From f6f885befbc74432ebd04cf956270cddda65ec06 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 3 Dec 2018 22:15:14 +0000 Subject: [PATCH 001/293] Introduce Coordinates::metric_type to switch between Field3D and Field2D storage for metric data --- include/bout/coordinates.hxx | 108 +++++++++++++++------------ src/mesh/coordinates.cxx | 140 +++++++++++++++++++---------------- 2 files changed, 135 insertions(+), 113 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 7922be9d0b..c88fb12dca 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -35,6 +35,9 @@ class Coordinates; #ifndef __COORDINATES_H__ #define __COORDINATES_H__ +#define METRIC_FIELD_TYPE Field2D +//#define METRIC_FIELD_TYPE Field3D + #include "mesh.hxx" #include "datafile.hxx" #include "utils.hxx" @@ -47,6 +50,8 @@ class Coordinates; */ class Coordinates { public: + using metric_type = METRIC_FIELD_TYPE; + /// Standard constructor from input Coordinates(Mesh *mesh); @@ -61,36 +66,38 @@ public: * Must be a better way so that Coordinates doesn't depend on Datafile */ void outputVars(Datafile &file); - - Field2D dx, dy; ///< Mesh spacing in x and y + + metric_type dx, dy; ///< Mesh spacing in x and y BoutReal dz; ///< Mesh spacing in Z BoutReal zlength() const { return dz * nz; } ///< Length of the Z domain. Used for FFTs /// True if corrections for non-uniform mesh spacing should be included in operators bool non_uniform; - Field2D d1_dx, d1_dy; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) - - Field2D J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz + metric_type d1_dx, + d1_dy; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) + + metric_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz + + metric_type Bxy; ///< Magnitude of B = nabla z times nabla x - Field2D Bxy; ///< Magnitude of B = nabla z times nabla x - /// Contravariant metric tensor (g^{ij}) - Field2D g11, g22, g33, g12, g13, g23; - + metric_type g11, g22, g33, g12, g13, g23; + /// Covariant metric tensor - Field2D g_11, g_22, g_33, g_12, g_13, g_23; - + metric_type g_11, g_22, g_33, g_12, g_13, g_23; + /// Christoffel symbol of the second kind (connection coefficients) - Field2D G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; - Field2D G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; - Field2D G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; - - Field2D G1, G2, G3; - - Field2D ShiftTorsion; ///< d pitch angle / dx. Needed for vector differentials (Curl) + metric_type G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; + metric_type G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; + metric_type G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; - Field2D IntShiftTorsion; ///< Integrated shear (I in BOUT notation) + metric_type G1, G2, G3; + + metric_type + ShiftTorsion; ///< d pitch angle / dx. Needed for vector differentials (Curl) + + metric_type IntShiftTorsion; ///< Integrated shear (I in BOUT notation) /// Calculate differential geometry quantities from the metric tensor int geometry(); @@ -100,31 +107,34 @@ public: // Operators - const Field2D DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); - const Field2D DDX(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { + const metric_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); + const metric_type DDX(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return DDX(f, outloc, DIFF_METHOD_STRING(method), region); }; - const Field2D DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); - const Field2D DDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { + const metric_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); + const metric_type DDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return DDY(f, outloc, DIFF_METHOD_STRING(method), region); }; - const Field2D DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); - const Field2D DDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { + const metric_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); + const metric_type DDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return DDZ(f, outloc, DIFF_METHOD_STRING(method), region); }; /// Gradient along magnetic field b.Grad(f) - const Field2D Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const Field2D Grad_par(const Field2D& var, CELL_LOC outloc, DIFF_METHOD method) { + const metric_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_type Grad_par(const Field2D& var, CELL_LOC outloc, DIFF_METHOD method) { return Grad_par(var, outloc, DIFF_METHOD_STRING(method)); }; @@ -135,11 +145,11 @@ public: }; /// Advection along magnetic field V*b.Grad(f) - const Field2D Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const Field2D Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { + const metric_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_type Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, DIFF_METHOD_STRING(method)); }; @@ -152,9 +162,9 @@ public: }; /// Divergence along magnetic field Div(b*f) = B.Grad(f/B) - const Field2D Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const Field2D Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { + const metric_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_type Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Div_par(f, outloc, DIFF_METHOD_STRING(method)); }; @@ -165,9 +175,9 @@ public: }; // Second derivative along magnetic field - const Field2D Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const Field2D Grad2_par2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { + const metric_type Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_type Grad2_par2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Grad2_par2(f, outloc, DIFF_METHOD_STRING(method)); }; @@ -180,17 +190,17 @@ public: // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code // since it makes use of the same coefficients and FFT routines - const Field2D Delp2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); + const metric_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Delp2(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); const FieldPerp Delp2(const FieldPerp &f, CELL_LOC outloc=CELL_DEFAULT); // Full parallel Laplacian operator on scalar field - // Laplace_par(f) = Div( b (b dot Grad(f)) ) - const Field2D Laplace_par(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); + // Laplace_par(f) = Div( b (b dot Grad(f)) ) + const metric_type Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); // Full Laplacian operator on scalar field - const Field2D Laplace(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); + const metric_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); private: diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 4d1891ebcf..21e6442234 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -123,7 +123,7 @@ Coordinates::Coordinates(Mesh *mesh) throw BoutException("Error in jacobian call"); // Attempt to read J from the grid file - Field2D Jcalc = J; + auto Jcalc = J; if (mesh->get(J, "J")) { output_warn.write("\tWARNING: Jacobian 'J' not found. Calculating from metric tensor\n"); J = Jcalc; @@ -136,7 +136,7 @@ Coordinates::Coordinates(Mesh *mesh) } // Attempt to read Bxy from the grid file - Field2D Bcalc = Bxy; + auto Bcalc = Bxy; if (mesh->get(Bxy, "Bxy")) { output_warn.write("\tWARNING: Magnitude of B field 'Bxy' not found. Calculating from " "metric tensor\n"); @@ -177,44 +177,47 @@ namespace { /// Boundary guard cells are set equal to the nearest grid point (equivalent to /// 2nd order accurate Neumann boundary condition). /// Corner guard cells are set to BoutNaN - Field2D interpolateAndNeumann(const Field2D &f, CELL_LOC location) { - Mesh* localmesh = f.getMesh(); - Field2D result = interp_to(f, location, RGN_NOBNDRY); - localmesh->communicate(result); - - // Copy nearest value into boundaries so that differential geometry terms can - // be interpolated if necessary - // Note: cannot use applyBoundary("neumann") here because applyBoundary() - // would try to create a new Coordinates object since we have not finished - // initializing yet, leading to an infinite recursion - for (auto bndry : localmesh->getBoundaries()) { - if (bndry->bx != 0) { - // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 - for(bndry->first(); !bndry->isDone(); bndry->next1d()) { - for (int i=0; ixstart; i++) - result(bndry->x+i*bndry->bx,bndry->y) = result(bndry->x+(i-1)*bndry->bx, bndry->y-bndry->by); - } +Coordinates::metric_type interpolateAndNeumann(const Coordinates::metric_type& f, + CELL_LOC location) { + Mesh* localmesh = f.getMesh(); + auto result = interp_to(f, location, RGN_NOBNDRY); + localmesh->communicate(result); + + // Copy nearest value into boundaries so that differential geometry terms can + // be interpolated if necessary + // Note: cannot use applyBoundary("neumann") here because applyBoundary() + // would try to create a new Coordinates object since we have not finished + // initializing yet, leading to an infinite recursion + for (auto bndry : localmesh->getBoundaries()) { + if (bndry->bx != 0) { + // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 + for (bndry->first(); !bndry->isDone(); bndry->next1d()) { + for (int i = 0; i < localmesh->xstart; i++) + result(bndry->x + i * bndry->bx, bndry->y) = + result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by); } - if (bndry->by != 0) { - // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 - for(bndry->first(); !bndry->isDone(); bndry->next1d()) { - for (int i=0; iystart; i++) - result(bndry->x,bndry->y+i*bndry->by) = result(bndry->x-bndry->bx, bndry->y+(i-1)*bndry->by); - } + } + if (bndry->by != 0) { + // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 + for (bndry->first(); !bndry->isDone(); bndry->next1d()) { + for (int i = 0; i < localmesh->ystart; i++) + result(bndry->x, bndry->y + i * bndry->by) = + result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by); } } + } - // Set corner guard cells - for (int i=0; ixstart; i++) { - for (int j=0; jystart; j++) { - result(i, j) = BoutNaN; - result(i, localmesh->LocalNy-1-j) = BoutNaN; - result(localmesh->LocalNx-1-i, j) = BoutNaN; - result(localmesh->LocalNx-1-i, localmesh->LocalNy-1-j) = BoutNaN; - } + // Set corner guard cells + for (int i = 0; i < localmesh->xstart; i++) { + for (int j = 0; j < localmesh->ystart; j++) { + result(i, j) = BoutNaN; + result(i, localmesh->LocalNy - 1 - j) = BoutNaN; + result(localmesh->LocalNx - 1 - i, j) = BoutNaN; + result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j) = BoutNaN; } + } - return result; + return result; } } @@ -442,7 +445,7 @@ int Coordinates::geometry() { OPTION(Options::getRoot(), non_uniform, true); - Field2D d2x, d2y; // d^2 x / d i^2 + Coordinates::metric_type d2x, d2y; // d^2 x / d i^2 // Read correction for non-uniform meshes if (localmesh->get(d2x, "d2x")) { output_warn.write( @@ -593,8 +596,8 @@ int Coordinates::jacobian() { TRACE("Coordinates::jacobian"); // calculate Jacobian using g^-1 = det[g^ij], J = sqrt(g) - Field2D g = g11 * g22 * g33 + 2.0 * g12 * g13 * g23 - g11 * g23 * g23 - - g22 * g13 * g13 - g33 * g12 * g12; + auto g = g11 * g22 * g33 + 2.0 * g12 * g13 * g23 - g11 * g23 * g23 - g22 * g13 * g13 + - g33 * g12 * g12; // Check that g is positive if (min(g) < 0.0) { @@ -623,21 +626,27 @@ int Coordinates::jacobian() { * *******************************************************************************/ -const Field2D Coordinates::DDX(const Field2D &f, CELL_LOC loc, const std::string &method, REGION region) { +const Coordinates::metric_type Coordinates::DDX(const Field2D& f, CELL_LOC loc, + const std::string& method, + REGION region) { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDX(f, loc, method, region) / dx; } -const Field2D Coordinates::DDY(const Field2D &f, CELL_LOC loc, const std::string &method, REGION region) { +const Coordinates::metric_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, + const std::string& method, + REGION region) { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDY(f, loc, method, region) / dy; } -const Field2D Coordinates::DDZ(MAYBE_UNUSED(const Field2D &f), CELL_LOC loc, - const std::string &UNUSED(method), REGION UNUSED(region)) { +const Coordinates::metric_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), + CELL_LOC loc, + const std::string& UNUSED(method), + REGION UNUSED(region)) { ASSERT1(location == loc || loc == CELL_DEFAULT); ASSERT1(f.getMesh() == localmesh); - auto result = Field2D(0.0, localmesh); + auto result = Coordinates::metric_type(0.0, localmesh); result.setLocation(location); return result; } @@ -647,8 +656,9 @@ const Field2D Coordinates::DDZ(MAYBE_UNUSED(const Field2D &f), CELL_LOC loc, ///////////////////////////////////////////////////////// // Parallel gradient -const Field2D Coordinates::Grad_par(const Field2D &var, MAYBE_UNUSED(CELL_LOC outloc), - const std::string &UNUSED(method)) { +const Coordinates::metric_type Coordinates::Grad_par(const Field2D& var, + MAYBE_UNUSED(CELL_LOC outloc), + const std::string& UNUSED(method)) { TRACE("Coordinates::Grad_par( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == var.getLocation())); @@ -667,9 +677,10 @@ const Field3D Coordinates::Grad_par(const Field3D &var, CELL_LOC outloc, // Vpar_Grad_par // vparallel times the parallel derivative along unperturbed B-field -const Field2D Coordinates::Vpar_Grad_par(const Field2D &v, const Field2D &f, - MAYBE_UNUSED(CELL_LOC outloc), - const std::string &UNUSED(method)) { +const Coordinates::metric_type +Coordinates::Vpar_Grad_par(const Field2D& v, const Field2D& f, + MAYBE_UNUSED(CELL_LOC outloc), + const std::string& UNUSED(method)) { ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); return VDDY(v, f) / sqrt(g_22); } @@ -683,14 +694,14 @@ const Field3D Coordinates::Vpar_Grad_par(const Field3D &v, const Field3D &f, CEL ///////////////////////////////////////////////////////// // Parallel divergence -const Field2D Coordinates::Div_par(const Field2D &f, CELL_LOC outloc, - const std::string &method) { +const Coordinates::metric_type Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, + const std::string& method) { TRACE("Coordinates::Div_par( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); // Need Bxy at location of f, which might be different from location of this // Coordinates object - Field2D Bxy_floc = f.getCoordinates()->Bxy; + auto Bxy_floc = f.getCoordinates()->Bxy; return Bxy * Grad_par(f / Bxy_floc, outloc, method); } @@ -702,7 +713,7 @@ const Field3D Coordinates::Div_par(const Field3D &f, CELL_LOC outloc, // Need Bxy at location of f, which might be different from location of this // Coordinates object - Field2D Bxy_floc = f.getCoordinates()->Bxy; + auto Bxy_floc = f.getCoordinates()->Bxy; if (!f.hasYupYdown()) { // No yup/ydown fields. The Grad_par operator will @@ -728,12 +739,14 @@ 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 std::string &method) { +const Coordinates::metric_type Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, + const std::string& 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, method) * DDY(f, outloc, method) / sg + D2DY2(f, outloc, method) / g_22; + auto sg = sqrt(g_22); + auto result = DDY(1. / sg, outloc, method) * DDY(f, outloc, method) / sg + + D2DY2(f, outloc, method) / g_22; return result; } @@ -745,12 +758,10 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc, const s } ASSERT1(location == outloc); - Field2D sg(localmesh); - Field3D result(localmesh), r2(localmesh); - - sg = sqrt(g_22); + auto sg = sqrt(g_22); sg = DDY(1. / sg, outloc, method) / sg; + Field3D result(localmesh), r2(localmesh); result = ::DDY(f, outloc, method); @@ -768,11 +779,11 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc, const s #include // Delp2 uses same coefficients as inversion code -const Field2D Coordinates::Delp2(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_type Coordinates::Delp2(const Field2D& f, CELL_LOC outloc) { TRACE("Coordinates::Delp2( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); - Field2D result = G1 * DDX(f, outloc) + g11 * D2DX2(f, outloc); + auto result = G1 * DDX(f, outloc) + g11 * D2DX2(f, outloc); return result; } @@ -899,7 +910,8 @@ const FieldPerp Coordinates::Delp2(const FieldPerp &f, CELL_LOC outloc) { return result; } -const Field2D Coordinates::Laplace_par(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_type Coordinates::Laplace_par(const Field2D& f, + CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * DDY(f, outloc) / J; } @@ -911,12 +923,12 @@ const Field3D Coordinates::Laplace_par(const Field3D &f, CELL_LOC outloc) { // Full Laplacian operator on scalar field -const Field2D Coordinates::Laplace(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_type Coordinates::Laplace(const Field2D& f, CELL_LOC outloc) { TRACE("Coordinates::Laplace( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); - Field2D result = - G1 * DDX(f, outloc) + G2 * DDY(f, outloc) + g11 * D2DX2(f, outloc) + g22 * D2DY2(f, outloc) + 2.0 * g12 * D2DXDY(f, outloc); + auto result = G1 * DDX(f, outloc) + G2 * DDY(f, outloc) + g11 * D2DX2(f, outloc) + + g22 * D2DY2(f, outloc) + 2.0 * g12 * D2DXDY(f, outloc); return result; } From 13b4e8343fd515041ad8588ee571a21acca8b6ee Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 3 Dec 2018 22:46:16 +0000 Subject: [PATCH 002/293] Slight tweak to coordinates handling of 3D --- include/bout/coordinates.hxx | 106 +++++++++++++++++++---------------- src/mesh/coordinates.cxx | 54 +++++++++--------- 2 files changed, 87 insertions(+), 73 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index c88fb12dca..1e2bddde95 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -35,8 +35,17 @@ class Coordinates; #ifndef __COORDINATES_H__ #define __COORDINATES_H__ -#define METRIC_FIELD_TYPE Field2D -//#define METRIC_FIELD_TYPE Field3D +#define COORDINATES_USE_3D 1 + +#ifdef COORDINATES_USE_3D +#define COORDINATES_FIELD_TYPE Field3D +#define COORDINATES_VECTOR_TYPE Vector3D +#else +#define COORDINATES_FIELD_TYPE Field2D +#define COORDINATES_VECTOR_TYPE Vector2D +#endif + +// #include "mesh.hxx" #include "datafile.hxx" @@ -50,7 +59,8 @@ class Coordinates; */ class Coordinates { public: - using metric_type = METRIC_FIELD_TYPE; + using metric_field_type = COORDINATES_FIELD_TYPE; + using metric_vector_type = COORDINATES_VECTOR_TYPE; /// Standard constructor from input Coordinates(Mesh *mesh); @@ -67,37 +77,37 @@ public: */ void outputVars(Datafile &file); - metric_type dx, dy; ///< Mesh spacing in x and y + metric_field_type dx, dy; ///< Mesh spacing in x and y BoutReal dz; ///< Mesh spacing in Z BoutReal zlength() const { return dz * nz; } ///< Length of the Z domain. Used for FFTs /// True if corrections for non-uniform mesh spacing should be included in operators bool non_uniform; - metric_type d1_dx, + metric_field_type d1_dx, d1_dy; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) - metric_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz + metric_field_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz - metric_type Bxy; ///< Magnitude of B = nabla z times nabla x + metric_field_type Bxy; ///< Magnitude of B = nabla z times nabla x /// Contravariant metric tensor (g^{ij}) - metric_type g11, g22, g33, g12, g13, g23; + metric_field_type g11, g22, g33, g12, g13, g23; /// Covariant metric tensor - metric_type g_11, g_22, g_33, g_12, g_13, g_23; + metric_field_type g_11, g_22, g_33, g_12, g_13, g_23; /// Christoffel symbol of the second kind (connection coefficients) - metric_type G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; - metric_type G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; - metric_type G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; + metric_field_type G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; + metric_field_type G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; + metric_field_type G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; - metric_type G1, G2, G3; + metric_field_type G1, G2, G3; - metric_type + metric_field_type ShiftTorsion; ///< d pitch angle / dx. Needed for vector differentials (Curl) - metric_type IntShiftTorsion; ///< Integrated shear (I in BOUT notation) + metric_field_type IntShiftTorsion; ///< Integrated shear (I in BOUT notation) /// Calculate differential geometry quantities from the metric tensor int geometry(); @@ -107,34 +117,35 @@ public: // Operators - const metric_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - REGION region = RGN_NOBNDRY); - const metric_type DDX(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { + const metric_field_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); + const metric_field_type DDX(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return DDX(f, outloc, DIFF_METHOD_STRING(method), region); }; - const metric_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - REGION region = RGN_NOBNDRY); - const metric_type DDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { + const metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); + const metric_field_type DDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return DDY(f, outloc, DIFF_METHOD_STRING(method), region); }; - const metric_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - REGION region = RGN_NOBNDRY); - const metric_type DDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { + const metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); + const metric_field_type DDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return DDZ(f, outloc, DIFF_METHOD_STRING(method), region); }; /// Gradient along magnetic field b.Grad(f) - const metric_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const metric_type Grad_par(const Field2D& var, CELL_LOC outloc, DIFF_METHOD method) { + const metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, + DIFF_METHOD method) { return Grad_par(var, outloc, DIFF_METHOD_STRING(method)); }; @@ -145,11 +156,11 @@ public: }; /// Advection along magnetic field V*b.Grad(f) - const metric_type Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const metric_type Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { + const metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, DIFF_METHOD_STRING(method)); }; @@ -162,9 +173,9 @@ public: }; /// Divergence along magnetic field Div(b*f) = B.Grad(f/B) - const metric_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const metric_type Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { + const metric_field_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Div_par(f, outloc, DIFF_METHOD_STRING(method)); }; @@ -175,9 +186,10 @@ public: }; // Second derivative along magnetic field - const metric_type Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - const metric_type Grad2_par2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { + const metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + const metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Grad2_par2(f, outloc, DIFF_METHOD_STRING(method)); }; @@ -190,17 +202,17 @@ public: // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code // since it makes use of the same coefficients and FFT routines - const metric_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); + const metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Delp2(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); const FieldPerp Delp2(const FieldPerp &f, CELL_LOC outloc=CELL_DEFAULT); // Full parallel Laplacian operator on scalar field // Laplace_par(f) = Div( b (b dot Grad(f)) ) - const metric_type Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); + const metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); // Full Laplacian operator on scalar field - const metric_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); + const metric_field_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); private: diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 21e6442234..8e3d076666 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -177,8 +177,8 @@ namespace { /// Boundary guard cells are set equal to the nearest grid point (equivalent to /// 2nd order accurate Neumann boundary condition). /// Corner guard cells are set to BoutNaN -Coordinates::metric_type interpolateAndNeumann(const Coordinates::metric_type& f, - CELL_LOC location) { +Coordinates::metric_field_type +interpolateAndNeumann(const Coordinates::metric_field_type& f, CELL_LOC location) { Mesh* localmesh = f.getMesh(); auto result = interp_to(f, location, RGN_NOBNDRY); localmesh->communicate(result); @@ -445,7 +445,7 @@ int Coordinates::geometry() { OPTION(Options::getRoot(), non_uniform, true); - Coordinates::metric_type d2x, d2y; // d^2 x / d i^2 + Coordinates::metric_field_type d2x, d2y; // d^2 x / d i^2 // Read correction for non-uniform meshes if (localmesh->get(d2x, "d2x")) { output_warn.write( @@ -626,27 +626,27 @@ int Coordinates::jacobian() { * *******************************************************************************/ -const Coordinates::metric_type Coordinates::DDX(const Field2D& f, CELL_LOC loc, - const std::string& method, - REGION region) { +const Coordinates::metric_field_type Coordinates::DDX(const Field2D& f, CELL_LOC loc, + const std::string& method, + REGION region) { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDX(f, loc, method, region) / dx; } -const Coordinates::metric_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, - const std::string& method, - REGION region) { +const Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, + const std::string& method, + REGION region) { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDY(f, loc, method, region) / dy; } -const Coordinates::metric_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), - CELL_LOC loc, - const std::string& UNUSED(method), - REGION UNUSED(region)) { +const Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), + CELL_LOC loc, + const std::string& UNUSED(method), + REGION UNUSED(region)) { ASSERT1(location == loc || loc == CELL_DEFAULT); ASSERT1(f.getMesh() == localmesh); - auto result = Coordinates::metric_type(0.0, localmesh); + auto result = Coordinates::metric_field_type(0.0, localmesh); result.setLocation(location); return result; } @@ -656,9 +656,9 @@ const Coordinates::metric_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), ///////////////////////////////////////////////////////// // Parallel gradient -const Coordinates::metric_type Coordinates::Grad_par(const Field2D& var, - MAYBE_UNUSED(CELL_LOC outloc), - const std::string& UNUSED(method)) { +const Coordinates::metric_field_type +Coordinates::Grad_par(const Field2D& var, MAYBE_UNUSED(CELL_LOC outloc), + const std::string& UNUSED(method)) { TRACE("Coordinates::Grad_par( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == var.getLocation())); @@ -677,7 +677,7 @@ const Field3D Coordinates::Grad_par(const Field3D &var, CELL_LOC outloc, // Vpar_Grad_par // vparallel times the parallel derivative along unperturbed B-field -const Coordinates::metric_type +const Coordinates::metric_field_type Coordinates::Vpar_Grad_par(const Field2D& v, const Field2D& f, MAYBE_UNUSED(CELL_LOC outloc), const std::string& UNUSED(method)) { @@ -694,8 +694,8 @@ const Field3D Coordinates::Vpar_Grad_par(const Field3D &v, const Field3D &f, CEL ///////////////////////////////////////////////////////// // Parallel divergence -const Coordinates::metric_type Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, - const std::string& method) { +const Coordinates::metric_field_type +Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Div_par( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -739,8 +739,8 @@ 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 Coordinates::metric_type Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, - const std::string& method) { +const Coordinates::metric_field_type +Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); @@ -779,7 +779,8 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc, const s #include // Delp2 uses same coefficients as inversion code -const Coordinates::metric_type Coordinates::Delp2(const Field2D& f, CELL_LOC outloc) { +const Coordinates::metric_field_type Coordinates::Delp2(const Field2D& f, + CELL_LOC outloc) { TRACE("Coordinates::Delp2( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -910,8 +911,8 @@ const FieldPerp Coordinates::Delp2(const FieldPerp &f, CELL_LOC outloc) { return result; } -const Coordinates::metric_type Coordinates::Laplace_par(const Field2D& f, - CELL_LOC outloc) { +const Coordinates::metric_field_type Coordinates::Laplace_par(const Field2D& f, + CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * DDY(f, outloc) / J; } @@ -923,7 +924,8 @@ const Field3D Coordinates::Laplace_par(const Field3D &f, CELL_LOC outloc) { // Full Laplacian operator on scalar field -const Coordinates::metric_type Coordinates::Laplace(const Field2D& f, CELL_LOC outloc) { +const Coordinates::metric_field_type Coordinates::Laplace(const Field2D& f, + CELL_LOC outloc) { TRACE("Coordinates::Laplace( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); From b476bad0f107a515de8bfeb9da0ead0000e95210 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 3 Dec 2018 23:06:30 +0000 Subject: [PATCH 003/293] Hacks to vecops to help support 3D metric types --- include/vecops.hxx | 12 ++-- src/field/vecops.cxx | 154 ++++++++++++++++++++++++++++++------------- 2 files changed, 114 insertions(+), 52 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 2cd611d177..2607814893 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -43,7 +43,7 @@ /// @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 -const Vector2D Grad(const Field2D &f, CELL_LOC outloc = CELL_DEFAULT); +const Coordinates::metric_vector_type Grad(const Field2D &f, CELL_LOC outloc = CELL_DEFAULT); const Vector3D Grad(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// Perpendicular gradient of scalar field \p f @@ -67,10 +67,10 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// @param[in] v The vector to differentiate /// @param[in] outloc The cell location where the result is desired /// -const Field2D Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); +const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); const Field3D Div(const Vector3D &v, CELL_LOC outloc = CELL_DEFAULT); -const Field2D Div(const Vector2D &v, const Field2D &f); +const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f); const Field3D Div(const Vector3D &v, const Field3D &f); const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, @@ -98,7 +98,7 @@ DEPRECATED(inline const Field3D Div(const Vector3D& v, const Field3D& f, /// /// @param[in] v The vector to differentiate /// -const Vector2D Curl(const Vector2D &v); +const Coordinates::metric_vector_type Curl(const Vector2D &v); const Vector3D Curl(const Vector3D &v); // Upwinding routines @@ -107,7 +107,7 @@ const Vector3D Curl(const Vector3D &v); /// /// 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 Coordinates::metric_field_type 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); @@ -115,7 +115,7 @@ 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 Coordinates::metric_vector_type 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); diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index a14855a5ab..2c5d73887e 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -36,7 +36,7 @@ * Gradient operators **************************************************************************/ -const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_vector_type Grad(const Field2D &f, CELL_LOC outloc) { TRACE("Grad( Field2D )"); SCOREP0(); CELL_LOC outloc_x, outloc_y, outloc_z; @@ -48,7 +48,7 @@ const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { outloc_x = outloc_y = outloc_z = outloc; } - Vector2D result(f.getMesh()); + Coordinates::metric_vector_type result(f.getMesh()); result.x = DDX(f, outloc_x); result.y = DDY(f, outloc_y); @@ -118,7 +118,7 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc) { * Divergence operators **************************************************************************/ -const Field2D Div(const Vector2D &v, CELL_LOC outloc) { +const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc) { TRACE("Div( Vector2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -128,12 +128,12 @@ const Field2D Div(const Vector2D &v, CELL_LOC outloc) { ASSERT1(outloc != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); - Field2D result(localmesh); + Coordinates::metric_field_type result(localmesh); Coordinates *metric = localmesh->getCoordinates(outloc); // get contravariant components of v - Vector2D vcn = v; + Coordinates::metric_vector_type vcn = v; vcn.toContravariant(); result = DDX(metric->J*vcn.x, outloc); @@ -175,7 +175,7 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { * Divergence operators for flux methods **************************************************************************/ -const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { TRACE("Div( Vector2D, Field2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -189,10 +189,10 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { Coordinates *metric = localmesh->getCoordinates(outloc); // get contravariant components of v - Vector2D vcn = v; + Coordinates::metric_vector_type vcn = v; vcn.toContravariant(); - Field2D result(localmesh); + Coordinates::metric_field_type result(localmesh); 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); @@ -241,7 +241,7 @@ const Field3D Div(const Vector3D &v, const Field3D &f) { * Curl operators **************************************************************************/ -const Vector2D Curl(const Vector2D &v) { +const Coordinates::metric_vector_type Curl(const Vector2D &v) { TRACE("Curl( Vector2D )"); @@ -250,11 +250,11 @@ const Vector2D Curl(const Vector2D &v) { auto metric = v.x.getCoordinates(); // Get covariant components of v - Vector2D vco = v; + Coordinates::metric_vector_type vco = v; vco.toCovariant(); // get components (curl(v))^j - Vector2D result(localmesh); + Coordinates::metric_vector_type result(localmesh); 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; @@ -300,10 +300,10 @@ const Vector3D Curl(const Vector3D &v) { /************************************************************************** * Upwinding operators **************************************************************************/ -const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f) { +const Coordinates::metric_field_type V_dot_Grad(const Vector2D &v, const Field2D &f) { TRACE("V_dot_Grad( Vector2D , Field2D )"); SCOREP0(); - Field2D result(f.getMesh()); + Coordinates::metric_field_type result(f.getMesh()); // Get contravariant components of v auto vcn = v; @@ -356,10 +356,83 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { return result; } +// // Here R is the deduced return type based on a promoting +// // operation (addition) between the two input types. +// template +// R V_dot_Grad(const T &v, const F &a) { +// AUTO_TRACE(); +// SCOREP0(); +// ASSERT1(v.getLocation() == a.getLocation()); +// ASSERT1(v.getLocation() != CELL_VSHIFT); + +// // Note by default R will describe a const vector type. By using +// // the following form of declaring result we ignore the const +// // qualifier here but keep it on the return type in the function +// // signature. +// auto result = R{v.x.getMesh()}; + +// auto metric = v.x.getCoordinates(); + +// auto vcn = v; +// vcn.toContravariant(); + +// if (a.covariant) { +// result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); +// BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { +// result.x[i] -= vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G2_11[i] * a.y[i] + metric->G3_11[i] * a.z[i]); +// result.x[i] -= vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); +// result.x[i] -= vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); +// } + +// result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); +// BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { +// result.y[i] -= vcn.x[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); +// result.y[i] -= vcn.y[i] * (metric->G1_22[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G3_22[i] * a.z[i]); +// result.y[i] -= vcn.z[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); +// } + +// result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); +// BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { +// result.z[i] -= vcn.x[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); +// result.z[i] -= vcn.y[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); +// result.z[i] -= vcn.z[i] * (metric->G1_33[i] * a.x[i] + metric->G2_33[i] * a.y[i] + metric->G3_33[i] * a.z[i]); +// } +// result.covariant = true; +// } else { +// result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); +// BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { +// result.x[i] += vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G1_12[i] * a.y[i] + metric->G1_13[i] * a.z[i]); +// result.x[i] += vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G1_22[i] * a.y[i] + metric->G1_23[i] * a.z[i]); +// result.x[i] += vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G1_23[i] * a.y[i] + metric->G1_33[i] * a.z[i]); +// } + +// result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); +// BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { +// result.y[i] += vcn.x[i] * (metric->G2_11[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G2_13[i] * a.z[i]); +// result.y[i] += vcn.y[i] * (metric->G2_12[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G2_23[i] * a.z[i]); +// result.y[i] += vcn.z[i] * (metric->G2_13[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G2_33[i] * a.z[i]); +// } + +// result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); +// BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { +// result.z[i] += vcn.x[i] * (metric->G3_11[i] * a.x[i] + metric->G3_12[i] * a.y[i] + metric->G3_13[i] * a.z[i]); +// result.z[i] += vcn.y[i] * (metric->G3_12[i] * a.x[i] + metric->G3_22[i] * a.y[i] + metric->G3_23[i] * a.z[i]); +// result.z[i] += vcn.z[i] * (metric->G3_13[i] * a.x[i] + metric->G3_23[i] * a.y[i] + metric->G3_33[i] * a.z[i]); +// } + +// result.covariant = false; +// } + +// result.setLocation(v.getLocation()); + +// return result; + +// }; + // Here R is the deduced return type based on a promoting // operation (addition) between the two input types. template -R V_dot_Grad(const T &v, const F &a) { +Coordinates::metric_vector_type V_dot_Grad(const T &v, const F &a) { AUTO_TRACE(); SCOREP0(); ASSERT1(v.getLocation() == a.getLocation()); @@ -369,7 +442,7 @@ R V_dot_Grad(const T &v, const F &a) { // the following form of declaring result we ignore the const // qualifier here but keep it on the return type in the function // signature. - auto result = R{v.x.getMesh()}; + Coordinates::metric_vector_type result = R{v.x.getMesh()}; auto metric = v.x.getCoordinates(); @@ -378,47 +451,36 @@ R V_dot_Grad(const T &v, const F &a) { if (a.covariant) { result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); - BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { - result.x[i] -= vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G2_11[i] * a.y[i] + metric->G3_11[i] * a.z[i]); - result.x[i] -= vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); - result.x[i] -= vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); - } + 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); - BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { - result.y[i] -= vcn.x[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); - result.y[i] -= vcn.y[i] * (metric->G1_22[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G3_22[i] * a.z[i]); - result.y[i] -= vcn.z[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); - } + 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); - BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { - result.z[i] -= vcn.x[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); - result.z[i] -= vcn.y[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); - result.z[i] -= vcn.z[i] * (metric->G1_33[i] * a.x[i] + metric->G2_33[i] * a.y[i] + metric->G3_33[i] * a.z[i]); - } + 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); - BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { - result.x[i] += vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G1_12[i] * a.y[i] + metric->G1_13[i] * a.z[i]); - result.x[i] += vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G1_22[i] * a.y[i] + metric->G1_23[i] * a.z[i]); - result.x[i] += vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G1_23[i] * a.y[i] + metric->G1_33[i] * a.z[i]); - } + 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); - BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { - result.y[i] += vcn.x[i] * (metric->G2_11[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G2_13[i] * a.z[i]); - result.y[i] += vcn.y[i] * (metric->G2_12[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G2_23[i] * a.z[i]); - result.y[i] += vcn.z[i] * (metric->G2_13[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G2_33[i] * a.z[i]); - } + 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); - BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { - result.z[i] += vcn.x[i] * (metric->G3_11[i] * a.x[i] + metric->G3_12[i] * a.y[i] + metric->G3_13[i] * a.z[i]); - result.z[i] += vcn.y[i] * (metric->G3_12[i] * a.x[i] + metric->G3_22[i] * a.y[i] + metric->G3_23[i] * a.z[i]); - result.z[i] += vcn.z[i] * (metric->G3_13[i] * a.x[i] + metric->G3_23[i] * a.y[i] + metric->G3_33[i] * a.z[i]); - } + 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; } @@ -430,7 +492,7 @@ R V_dot_Grad(const T &v, const F &a) { }; // Implement vector-vector operation in terms of templated routine above -const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { +const Coordinates::metric_vector_type V_dot_Grad(const Vector2D &v, const Vector2D &a) { return V_dot_Grad(v, a); } const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { From a81066ef3a781c103f9f3ced3b43370fd15b2b2e Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 08:43:55 +0000 Subject: [PATCH 004/293] Revert "Hacks to vecops to help support 3D metric types" This reverts commit b476bad0f107a515de8bfeb9da0ead0000e95210. --- include/vecops.hxx | 12 ++-- src/field/vecops.cxx | 154 +++++++++++++------------------------------ 2 files changed, 52 insertions(+), 114 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index 2607814893..2cd611d177 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -43,7 +43,7 @@ /// @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 -const Coordinates::metric_vector_type Grad(const Field2D &f, CELL_LOC outloc = CELL_DEFAULT); +const Vector2D Grad(const Field2D &f, CELL_LOC outloc = CELL_DEFAULT); const Vector3D Grad(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// Perpendicular gradient of scalar field \p f @@ -67,10 +67,10 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// @param[in] v The vector to differentiate /// @param[in] outloc The cell location where the result is desired /// -const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); +const Field2D Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); const Field3D Div(const Vector3D &v, CELL_LOC outloc = CELL_DEFAULT); -const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f); +const Field2D Div(const Vector2D &v, const Field2D &f); const Field3D Div(const Vector3D &v, const Field3D &f); const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, @@ -98,7 +98,7 @@ DEPRECATED(inline const Field3D Div(const Vector3D& v, const Field3D& f, /// /// @param[in] v The vector to differentiate /// -const Coordinates::metric_vector_type Curl(const Vector2D &v); +const Vector2D Curl(const Vector2D &v); const Vector3D Curl(const Vector3D &v); // Upwinding routines @@ -107,7 +107,7 @@ const Vector3D Curl(const Vector3D &v); /// /// The vector and the field must be at the same location, which /// cannot be CELL_VSHIFT -const Coordinates::metric_field_type V_dot_Grad(const Vector2D &v, const Field2D &f); +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); @@ -115,7 +115,7 @@ 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 Coordinates::metric_vector_type V_dot_Grad(const Vector2D &v, const Vector2D &a); +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); diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 2c5d73887e..a14855a5ab 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -36,7 +36,7 @@ * Gradient operators **************************************************************************/ -const Coordinates::metric_vector_type Grad(const Field2D &f, CELL_LOC outloc) { +const Vector2D Grad(const Field2D &f, CELL_LOC outloc) { TRACE("Grad( Field2D )"); SCOREP0(); CELL_LOC outloc_x, outloc_y, outloc_z; @@ -48,7 +48,7 @@ const Coordinates::metric_vector_type Grad(const Field2D &f, CELL_LOC outloc) { outloc_x = outloc_y = outloc_z = outloc; } - Coordinates::metric_vector_type result(f.getMesh()); + Vector2D result(f.getMesh()); result.x = DDX(f, outloc_x); result.y = DDY(f, outloc_y); @@ -118,7 +118,7 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc) { * Divergence operators **************************************************************************/ -const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc) { +const Field2D Div(const Vector2D &v, CELL_LOC outloc) { TRACE("Div( Vector2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -128,12 +128,12 @@ const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc) { ASSERT1(outloc != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); - Coordinates::metric_field_type result(localmesh); + Field2D result(localmesh); Coordinates *metric = localmesh->getCoordinates(outloc); // get contravariant components of v - Coordinates::metric_vector_type vcn = v; + Vector2D vcn = v; vcn.toContravariant(); result = DDX(metric->J*vcn.x, outloc); @@ -175,7 +175,7 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { * Divergence operators for flux methods **************************************************************************/ -const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { +const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { TRACE("Div( Vector2D, Field2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -189,10 +189,10 @@ const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, CE Coordinates *metric = localmesh->getCoordinates(outloc); // get contravariant components of v - Coordinates::metric_vector_type vcn = v; + Vector2D vcn = v; vcn.toContravariant(); - Coordinates::metric_field_type result(localmesh); + Field2D result(localmesh); 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); @@ -241,7 +241,7 @@ const Field3D Div(const Vector3D &v, const Field3D &f) { * Curl operators **************************************************************************/ -const Coordinates::metric_vector_type Curl(const Vector2D &v) { +const Vector2D Curl(const Vector2D &v) { TRACE("Curl( Vector2D )"); @@ -250,11 +250,11 @@ const Coordinates::metric_vector_type Curl(const Vector2D &v) { auto metric = v.x.getCoordinates(); // Get covariant components of v - Coordinates::metric_vector_type vco = v; + Vector2D vco = v; vco.toCovariant(); // get components (curl(v))^j - Coordinates::metric_vector_type result(localmesh); + Vector2D result(localmesh); 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; @@ -300,10 +300,10 @@ const Vector3D Curl(const Vector3D &v) { /************************************************************************** * Upwinding operators **************************************************************************/ -const Coordinates::metric_field_type V_dot_Grad(const Vector2D &v, const Field2D &f) { +const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f) { TRACE("V_dot_Grad( Vector2D , Field2D )"); SCOREP0(); - Coordinates::metric_field_type result(f.getMesh()); + Field2D result(f.getMesh()); // Get contravariant components of v auto vcn = v; @@ -356,83 +356,10 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { return result; } -// // Here R is the deduced return type based on a promoting -// // operation (addition) between the two input types. -// template -// R V_dot_Grad(const T &v, const F &a) { -// AUTO_TRACE(); -// SCOREP0(); -// ASSERT1(v.getLocation() == a.getLocation()); -// ASSERT1(v.getLocation() != CELL_VSHIFT); - -// // Note by default R will describe a const vector type. By using -// // the following form of declaring result we ignore the const -// // qualifier here but keep it on the return type in the function -// // signature. -// auto result = R{v.x.getMesh()}; - -// auto metric = v.x.getCoordinates(); - -// auto vcn = v; -// vcn.toContravariant(); - -// if (a.covariant) { -// result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); -// BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { -// result.x[i] -= vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G2_11[i] * a.y[i] + metric->G3_11[i] * a.z[i]); -// result.x[i] -= vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); -// result.x[i] -= vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); -// } - -// result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); -// BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { -// result.y[i] -= vcn.x[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); -// result.y[i] -= vcn.y[i] * (metric->G1_22[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G3_22[i] * a.z[i]); -// result.y[i] -= vcn.z[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); -// } - -// result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); -// BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { -// result.z[i] -= vcn.x[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); -// result.z[i] -= vcn.y[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); -// result.z[i] -= vcn.z[i] * (metric->G1_33[i] * a.x[i] + metric->G2_33[i] * a.y[i] + metric->G3_33[i] * a.z[i]); -// } -// result.covariant = true; -// } else { -// result.x = VDDX(vcn.x, a.x) + VDDY(vcn.y, a.x) + VDDZ(vcn.z, a.x); -// BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { -// result.x[i] += vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G1_12[i] * a.y[i] + metric->G1_13[i] * a.z[i]); -// result.x[i] += vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G1_22[i] * a.y[i] + metric->G1_23[i] * a.z[i]); -// result.x[i] += vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G1_23[i] * a.y[i] + metric->G1_33[i] * a.z[i]); -// } - -// result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); -// BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { -// result.y[i] += vcn.x[i] * (metric->G2_11[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G2_13[i] * a.z[i]); -// result.y[i] += vcn.y[i] * (metric->G2_12[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G2_23[i] * a.z[i]); -// result.y[i] += vcn.z[i] * (metric->G2_13[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G2_33[i] * a.z[i]); -// } - -// result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, a.z); -// BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { -// result.z[i] += vcn.x[i] * (metric->G3_11[i] * a.x[i] + metric->G3_12[i] * a.y[i] + metric->G3_13[i] * a.z[i]); -// result.z[i] += vcn.y[i] * (metric->G3_12[i] * a.x[i] + metric->G3_22[i] * a.y[i] + metric->G3_23[i] * a.z[i]); -// result.z[i] += vcn.z[i] * (metric->G3_13[i] * a.x[i] + metric->G3_23[i] * a.y[i] + metric->G3_33[i] * a.z[i]); -// } - -// result.covariant = false; -// } - -// result.setLocation(v.getLocation()); - -// return result; - -// }; - // Here R is the deduced return type based on a promoting // operation (addition) between the two input types. template -Coordinates::metric_vector_type V_dot_Grad(const T &v, const F &a) { +R V_dot_Grad(const T &v, const F &a) { AUTO_TRACE(); SCOREP0(); ASSERT1(v.getLocation() == a.getLocation()); @@ -442,7 +369,7 @@ Coordinates::metric_vector_type V_dot_Grad(const T &v, const F &a) { // the following form of declaring result we ignore the const // qualifier here but keep it on the return type in the function // signature. - Coordinates::metric_vector_type result = R{v.x.getMesh()}; + auto result = R{v.x.getMesh()}; auto metric = v.x.getCoordinates(); @@ -451,36 +378,47 @@ Coordinates::metric_vector_type V_dot_Grad(const T &v, const F &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->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); + BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { + result.x[i] -= vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G2_11[i] * a.y[i] + metric->G3_11[i] * a.z[i]); + result.x[i] -= vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); + result.x[i] -= vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); + } result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - 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); + BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { + result.y[i] -= vcn.x[i] * (metric->G1_12[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G3_12[i] * a.z[i]); + result.y[i] -= vcn.y[i] * (metric->G1_22[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G3_22[i] * a.z[i]); + result.y[i] -= vcn.z[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); + } result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, 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); - + BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { + result.z[i] -= vcn.x[i] * (metric->G1_13[i] * a.x[i] + metric->G2_13[i] * a.y[i] + metric->G3_13[i] * a.z[i]); + result.z[i] -= vcn.y[i] * (metric->G1_23[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G3_23[i] * a.z[i]); + result.z[i] -= vcn.z[i] * (metric->G1_33[i] * a.x[i] + metric->G2_33[i] * a.y[i] + metric->G3_33[i] * a.z[i]); + } 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->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); + BOUT_FOR(i, result.x.getRegion("RGN_ALL")) { + result.x[i] += vcn.x[i] * (metric->G1_11[i] * a.x[i] + metric->G1_12[i] * a.y[i] + metric->G1_13[i] * a.z[i]); + result.x[i] += vcn.y[i] * (metric->G1_12[i] * a.x[i] + metric->G1_22[i] * a.y[i] + metric->G1_23[i] * a.z[i]); + result.x[i] += vcn.z[i] * (metric->G1_13[i] * a.x[i] + metric->G1_23[i] * a.y[i] + metric->G1_33[i] * a.z[i]); + } result.y = VDDX(vcn.x, a.y) + VDDY(vcn.y, a.y) + VDDZ(vcn.z, a.y); - 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); + BOUT_FOR(i, result.y.getRegion("RGN_ALL")) { + result.y[i] += vcn.x[i] * (metric->G2_11[i] * a.x[i] + metric->G2_12[i] * a.y[i] + metric->G2_13[i] * a.z[i]); + result.y[i] += vcn.y[i] * (metric->G2_12[i] * a.x[i] + metric->G2_22[i] * a.y[i] + metric->G2_23[i] * a.z[i]); + result.y[i] += vcn.z[i] * (metric->G2_13[i] * a.x[i] + metric->G2_23[i] * a.y[i] + metric->G2_33[i] * a.z[i]); + } result.z = VDDX(vcn.x, a.z) + VDDY(vcn.y, a.z) + VDDZ(vcn.z, 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); + BOUT_FOR(i, result.z.getRegion("RGN_ALL")) { + result.z[i] += vcn.x[i] * (metric->G3_11[i] * a.x[i] + metric->G3_12[i] * a.y[i] + metric->G3_13[i] * a.z[i]); + result.z[i] += vcn.y[i] * (metric->G3_12[i] * a.x[i] + metric->G3_22[i] * a.y[i] + metric->G3_23[i] * a.z[i]); + result.z[i] += vcn.z[i] * (metric->G3_13[i] * a.x[i] + metric->G3_23[i] * a.y[i] + metric->G3_33[i] * a.z[i]); + } result.covariant = false; } @@ -492,7 +430,7 @@ Coordinates::metric_vector_type V_dot_Grad(const T &v, const F &a) { }; // Implement vector-vector operation in terms of templated routine above -const Coordinates::metric_vector_type V_dot_Grad(const Vector2D &v, const Vector2D &a) { +const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { return V_dot_Grad(v, a); } const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { From 74dc511a7e44e45dee540ed30e653f37562079ed Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 09:15:27 +0000 Subject: [PATCH 005/293] Hack Vector2D to use Field3D storage if metric is 3D --- include/bout/coordinates.hxx | 7 ++----- include/field.hxx | 1 - include/field3d.hxx | 3 ++- include/vecops.hxx | 14 +++++++------- include/vector2d.hxx | 12 +++++++----- src/field/field.cxx | 1 + src/field/vecops.cxx | 12 ++++++------ src/field/vector2d.cxx | 20 ++++++++++---------- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 1e2bddde95..7ccba79b55 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -35,8 +35,6 @@ class Coordinates; #ifndef __COORDINATES_H__ #define __COORDINATES_H__ -#define COORDINATES_USE_3D 1 - #ifdef COORDINATES_USE_3D #define COORDINATES_FIELD_TYPE Field3D #define COORDINATES_VECTOR_TYPE Vector3D @@ -45,10 +43,9 @@ class Coordinates; #define COORDINATES_VECTOR_TYPE Vector2D #endif -// +class Datafile; +class Mesh; -#include "mesh.hxx" -#include "datafile.hxx" #include "utils.hxx" #include diff --git a/include/field.hxx b/include/field.hxx index 13c288f635..3390c0bbc5 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -33,7 +33,6 @@ class Field; #include "bout_types.hxx" #include "stencils.hxx" -#include #include "boutexception.hxx" #include "unused.hxx" diff --git a/include/field3d.hxx b/include/field3d.hxx index f72d21f502..3b907bc10b 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -430,7 +430,8 @@ class Field3D : public Field, public FieldData { #endif friend class Vector3D; - + friend class Vector2D; + void applyBoundary(bool init=false) override; void applyBoundary(BoutReal t); void applyBoundary(const std::string &condition); diff --git a/include/vecops.hxx b/include/vecops.hxx index 2cd611d177..7c3738e1e3 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -29,10 +29,10 @@ #ifndef __VECOPS_H__ #define __VECOPS_H__ -#include "field2d.hxx" -#include "field3d.hxx" -#include "vector2d.hxx" -#include "vector3d.hxx" +class Field2D; +class Field3D; +class Vector2D; +class Vector3D; #include "bout/deprecated.hxx" @@ -67,10 +67,10 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /// @param[in] v The vector to differentiate /// @param[in] outloc The cell location where the result is desired /// -const Field2D Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); +const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT); const Field3D Div(const Vector3D &v, CELL_LOC outloc = CELL_DEFAULT); -const Field2D Div(const Vector2D &v, const Field2D &f); +const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f); const Field3D Div(const Vector3D &v, const Field3D &f); const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, @@ -107,7 +107,7 @@ const Vector3D Curl(const Vector3D &v); /// /// 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 Coordinates::metric_field_type 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); diff --git a/include/vector2d.hxx b/include/vector2d.hxx index 80040b76a2..18cf62d981 100644 --- a/include/vector2d.hxx +++ b/include/vector2d.hxx @@ -37,10 +37,12 @@ class Vector2D; #ifndef __VECTOR2D_H__ #define __VECTOR2D_H__ -#include "field2d.hxx" -class Field3D; //#include "field3d.hxx" +class Field2D; +class Field3D; class Vector3D; //#include "vector3d.hxx" +#include + /*! * A vector with three components (x,y,z) which only vary in 2D * (x and y). Implemented as a collection of three Field2D objects. @@ -51,7 +53,7 @@ class Vector2D : public FieldData { Vector2D(const Vector2D &f); ~Vector2D() override; - Field2D x, y, z; ///< components + Coordinates::metric_field_type x, y, z; ///< components bool covariant; ///< true if the components are covariant (default) @@ -122,7 +124,7 @@ class Vector2D : public FieldData { const Vector2D operator/(const Field2D &rhs) const; ///< Divides all components by \p rhs const Vector3D operator/(const Field3D &rhs) const; ///< Divides all components by \p rhs - const Field2D operator*(const Vector2D &rhs) const; ///< Dot product + const Coordinates::metric_field_type operator*(const Vector2D &rhs) const; ///< Dot product const Field3D operator*(const Vector3D &rhs) const; ///< Dot product /*! @@ -175,7 +177,7 @@ const Vector3D cross(const Vector2D & lhs, const Vector3D &rhs); * * |v| = sqrt( v dot v ) */ -const Field2D abs(const Vector2D &v, REGION region = RGN_ALL); +const Coordinates::metric_field_type abs(const Vector2D &v, REGION region = RGN_ALL); /*! * @brief Time derivative of 2D vector field diff --git a/src/field/field.cxx b/src/field/field.cxx index 3e4fd46987..8c2d44e8cd 100644 --- a/src/field/field.cxx +++ b/src/field/field.cxx @@ -31,6 +31,7 @@ #include #include #include +#include Field::Field(Mesh *localmesh) : fieldmesh(localmesh) { if (fieldmesh == nullptr) { diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index a14855a5ab..38455df794 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -118,7 +118,7 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc) { * Divergence operators **************************************************************************/ -const Field2D Div(const Vector2D &v, CELL_LOC outloc) { +const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc) { TRACE("Div( Vector2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -128,7 +128,7 @@ const Field2D Div(const Vector2D &v, CELL_LOC outloc) { ASSERT1(outloc != CELL_VSHIFT); Mesh *localmesh = v.x.getMesh(); - Field2D result(localmesh); + Coordinates::metric_field_type result(localmesh); Coordinates *metric = localmesh->getCoordinates(outloc); @@ -175,7 +175,7 @@ const Field3D Div(const Vector3D &v, CELL_LOC outloc) { * Divergence operators for flux methods **************************************************************************/ -const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { TRACE("Div( Vector2D, Field2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -192,7 +192,7 @@ const Field2D Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc) { Vector2D vcn = v; vcn.toContravariant(); - Field2D result(localmesh); + Coordinates::metric_field_type result(localmesh); 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); @@ -300,10 +300,10 @@ const Vector3D Curl(const Vector3D &v) { /************************************************************************** * Upwinding operators **************************************************************************/ -const Field2D V_dot_Grad(const Vector2D &v, const Field2D &f) { +const Coordinates::metric_field_type V_dot_Grad(const Vector2D &v, const Field2D &f) { TRACE("V_dot_Grad( Vector2D , Field2D )"); SCOREP0(); - Field2D result(f.getMesh()); + Coordinates::metric_field_type result(f.getMesh()); // Get contravariant components of v auto vcn = v; diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index 473805aaa7..0253d2de41 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -80,7 +80,7 @@ void Vector2D::toCovariant() { const auto y_at_z = interp_to(y, z.getLocation()); // multiply by g_{ij} - BOUT_FOR(i, localmesh->getRegion2D("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")){ x[i] = metric_x->g_11[i]*x[i] + metric_x->g_12[i]*y_at_x[i] + metric_x->g_13[i]*z_at_x[i]; y[i] = metric_y->g_22[i]*y[i] + metric_y->g_12[i]*x_at_y[i] + metric_y->g_23[i]*z_at_y[i]; z[i] = metric_z->g_33[i]*z[i] + metric_z->g_13[i]*x_at_z[i] + metric_z->g_23[i]*y_at_z[i]; @@ -89,10 +89,10 @@ void Vector2D::toCovariant() { const auto metric = localmesh->getCoordinates(location); // Need to use temporary arrays to store result - Field2D gx(localmesh), gy(localmesh), gz(localmesh); + Coordinates::metric_field_type gx(localmesh), gy(localmesh), gz(localmesh); gx.allocate(); gy.allocate(); gz.allocate(); - BOUT_FOR(i, localmesh->getRegion2D("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")){ gx[i] = metric->g_11[i]*x[i] + metric->g_12[i]*y[i] + metric->g_13[i]*z[i]; gy[i] = metric->g_22[i]*y[i] + metric->g_12[i]*x[i] + metric->g_23[i]*z[i]; gz[i] = metric->g_33[i]*z[i] + metric->g_13[i]*x[i] + metric->g_23[i]*y[i]; @@ -111,7 +111,7 @@ void Vector2D::toContravariant() { if(covariant) { // multiply by g^{ij} Mesh *localmesh = x.getMesh(); - Field2D gx(localmesh), gy(localmesh), gz(localmesh); + Coordinates::metric_field_type gx(localmesh), gy(localmesh), gz(localmesh); if (location == CELL_VSHIFT) { Coordinates *metric_x, *metric_y, *metric_z; @@ -133,7 +133,7 @@ void Vector2D::toContravariant() { const auto y_at_z = interp_to(y, z.getLocation()); // multiply by g_{ij} - BOUT_FOR(i, localmesh->getRegion2D("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")){ x[i] = metric_x->g11[i]*x[i] + metric_x->g12[i]*y_at_x[i] + metric_x->g13[i]*z_at_x[i]; y[i] = metric_y->g22[i]*y[i] + metric_y->g12[i]*x_at_y[i] + metric_y->g23[i]*z_at_y[i]; z[i] = metric_z->g33[i]*z[i] + metric_z->g13[i]*x_at_z[i] + metric_z->g23[i]*y_at_z[i]; @@ -143,10 +143,10 @@ void Vector2D::toContravariant() { const auto metric = localmesh->getCoordinates(location); // Need to use temporary arrays to store result - Field2D gx(localmesh), gy(localmesh), gz(localmesh); + Coordinates::metric_field_type gx(localmesh), gy(localmesh), gz(localmesh); gx.allocate(); gy.allocate(); gz.allocate(); - BOUT_FOR(i, localmesh->getRegion2D("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")){ gx[i] = metric->g11[i]*x[i] + metric->g12[i]*y[i] + metric->g13[i]*z[i]; gy[i] = metric->g22[i]*y[i] + metric->g12[i]*x[i] + metric->g23[i]*z[i]; gz[i] = metric->g33[i]*z[i] + metric->g13[i]*x[i] + metric->g23[i]*y[i]; @@ -369,11 +369,11 @@ const Vector3D Vector2D::operator/(const Field3D &rhs) const { ////////////////// DOT PRODUCT /////////////////// -const Field2D Vector2D::operator*(const Vector2D &rhs) const { +const Coordinates::metric_field_type Vector2D::operator*(const Vector2D &rhs) const { ASSERT2(location == rhs.getLocation()); Mesh *localmesh = x.getMesh(); - Field2D result(localmesh); + Coordinates::metric_field_type result(localmesh); if(rhs.covariant ^ covariant) { // Both different - just multiply components @@ -472,7 +472,7 @@ const Vector3D operator*(const Field3D &lhs, const Vector2D &rhs) { ***************************************************************/ // Return the magnitude of a vector -const Field2D abs(const Vector2D &v, REGION region) { +const Coordinates::metric_field_type abs(const Vector2D &v, REGION region) { return sqrt(v*v, region); } From f86fa84e28f76774e20d05cbba0976ad3f4ed7db Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 09:15:45 +0000 Subject: [PATCH 006/293] Datafile fixes for 3D Vector2D components --- src/fileio/datafile.cxx | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/fileio/datafile.cxx b/src/fileio/datafile.cxx index ba6b259395..4536967c2c 100644 --- a/src/fileio/datafile.cxx +++ b/src/fileio/datafile.cxx @@ -805,6 +805,19 @@ bool Datafile::read() { } // 2D vectors +#ifdef COORDINATES_USE_3D + for(const auto& var : v2d_arr) { + if(var.covar) { + // Reading covariant vector + read_f3d(var.name + "_x", &(var.ptr->x), var.save_repeat); + read_f3d(var.name + "_y", &(var.ptr->y), var.save_repeat); + read_f3d(var.name + "_z", &(var.ptr->z), var.save_repeat); + } else { + read_f3d(var.name + "x", &(var.ptr->x), var.save_repeat); + read_f3d(var.name + "y", &(var.ptr->y), var.save_repeat); + read_f3d(var.name + "z", &(var.ptr->z), var.save_repeat); + } +#else for(const auto& var : v2d_arr) { if(var.covar) { // Reading covariant vector @@ -816,7 +829,7 @@ bool Datafile::read() { read_f2d(var.name + "y", &(var.ptr->y), var.save_repeat); read_f2d(var.name + "z", &(var.ptr->z), var.save_repeat); } - +#endif var.ptr->covariant = var.covar; } @@ -933,6 +946,27 @@ bool Datafile::write() { } // 2D vectors +#ifdef COORDINATES_USE_3D + for(const auto& var : v2d_arr) { + if(var.covar) { + // Writing covariant vector + Vector2D v = *(var.ptr); + v.toCovariant(); + + write_f3d(var.name+"_x", &(v.x), var.save_repeat); + write_f3d(var.name+"_y", &(v.y), var.save_repeat); + write_f3d(var.name+"_z", &(v.z), var.save_repeat); + } else { + // Writing contravariant vector + Vector2D v = *(var.ptr); + v.toContravariant(); + + write_f3d(var.name+"x", &(v.x), var.save_repeat); + write_f3d(var.name+"y", &(v.y), var.save_repeat); + write_f3d(var.name+"z", &(v.z), var.save_repeat); + } + } +#else for(const auto& var : v2d_arr) { if(var.covar) { // Writing covariant vector @@ -952,7 +986,8 @@ bool Datafile::write() { write_f2d(var.name+"z", &(v.z), var.save_repeat); } } - +#endif + // 3D vectors for(const auto& var : v3d_arr) { if(var.covar) { From 35ca4e12c4c68bf642f93f6adba7672ff1ad3af1 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:02:24 +0000 Subject: [PATCH 007/293] Disable certain laplacian routines for 3D metrics --- .../laplace/impls/multigrid/multigrid_laplace.cxx | 10 +++++++--- src/invert/laplace/impls/serial_band/serial_band.cxx | 6 +++++- src/invert/laplace/invert_laplace.cxx | 5 ++++- src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx | 8 +++++++- src/invert/parderiv/impls/cyclic/cyclic.cxx | 5 +++++ 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index bb06c2b469..2899639476 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -40,7 +40,7 @@ BoutReal soltime=0.0,settime=0.0; LaplaceMultigrid::LaplaceMultigrid(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), A(0.0), C1(1.0), C2(1.0), D(1.0) { - + ASSERT1((std::same::value)); TRACE("LaplaceMultigrid::LaplaceMultigrid(Options *opt)"); A.setLocation(location); @@ -198,7 +198,7 @@ BOUT_OMP(master) } const FieldPerp LaplaceMultigrid::solve(const FieldPerp &b_in, const FieldPerp &x0) { - +#ifndef COORDINATES_USE_3D TRACE("LaplaceMultigrid::solve(const FieldPerp, const FieldPerp)"); ASSERT1(localmesh == b_in.getMesh() && localmesh == x0.getMesh()); @@ -543,10 +543,13 @@ BOUT_OMP(for) #endif return result; +#else + return FieldPerp{}; +#endif } void LaplaceMultigrid::generateMatrixF(int level) { - +#ifndef COORDINATES_USE_3D TRACE("LaplaceMultigrid::generateMatrixF(int)"); // Set (fine-level) matrix entries @@ -679,5 +682,6 @@ BOUT_OMP(for) } } } +#endif } diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index 46835d8174..98951099fc 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -40,6 +40,7 @@ LaplaceSerialBand::LaplaceSerialBand(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), Acoef(0.0), Ccoef(1.0), Dcoef(1.0) { + ASSERT1((std::same::value)); Acoef.setLocation(location); Ccoef.setLocation(location); Dcoef.setLocation(location); @@ -80,6 +81,7 @@ const FieldPerp LaplaceSerialBand::solve(const FieldPerp &b) { } const FieldPerp LaplaceSerialBand::solve(const FieldPerp &b, const FieldPerp &x0) { +#ifndef COORDINATES_USE_3D ASSERT1(localmesh == b.getMesh() && localmesh == x0.getMesh()); FieldPerp x(localmesh); @@ -419,6 +421,8 @@ const FieldPerp LaplaceSerialBand::solve(const FieldPerp &b, const FieldPerp &x0 irfft(&xk(ix, 0), ncz, x[ix]); } - return x; +#else + return FieldPerp{}; +#endif } diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index e120f86244..f74554011d 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -262,6 +262,7 @@ void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, dcomplex &a, dcomplex &b, dcomplex &c, const Field2D *ccoef, const Field2D *d, CELL_LOC loc) { +#ifndef COORDINATES_USE_3D /* Function: Laplacian::tridagCoef * Purpose: - Set the matrix components of A in Ax=b, solving * @@ -344,6 +345,7 @@ void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, a = dcomplex(coef1 - coef4,-kwave*coef3); b = dcomplex(-2.0*coef1 - SQ(kwave)*coef2,kwave*coef5); c = dcomplex(coef1 + coef4,kwave*coef3); +#endif } /// Sets the coefficients for parallel tridiagonal matrix inversion @@ -414,7 +416,7 @@ void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, const Field2D *a, const Field2D *ccoef, const Field2D *d, bool includeguards) { - +#ifndef COORDINATES_USE_3D ASSERT1(a->getLocation() == location); ASSERT1(ccoef->getLocation() == location); ASSERT1(d->getLocation() == location); @@ -729,6 +731,7 @@ void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, } } } +#endif } /********************************************************************************** diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 115c325267..926769b606 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -9,7 +9,7 @@ #include LaplaceXZcyclic::LaplaceXZcyclic(Mesh *m, Options *options, const CELL_LOC loc) : LaplaceXZ(m, options, loc), mesh(m) { - + ASSERT1((std::same::value)); // Number of Z Fourier modes, including DC nmode = (m->LocalNz) / 2 + 1; @@ -57,6 +57,7 @@ LaplaceXZcyclic::~LaplaceXZcyclic() { } void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { +#ifndef COORDINATES_USE_3D TRACE("LaplaceXZcyclic::setCoefs"); Timer timer("invert"); @@ -152,9 +153,11 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { } // Set coefficients in tridiagonal solver cr->setCoefs(acoef, bcoef, ccoef); +#endif } Field3D LaplaceXZcyclic::solve(const Field3D &rhs, const Field3D &x0) { +#ifndef COORDINATES_USE_3D Timer timer("invert"); Mesh *mesh = rhs.getMesh(); @@ -260,4 +263,7 @@ Field3D LaplaceXZcyclic::solve(const Field3D &rhs, const Field3D &x0) { } return result; +#else + return Field3D{}; +#endif } diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index e326aa5767..efa350d980 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -50,6 +50,7 @@ InvertParCR::InvertParCR(Options *opt, Mesh *mesh_in) : InvertPar(opt, mesh_in), A(1.0), B(0.0), C(0.0), D(0.0), E(0.0) { + ASSERT1((std::same::value)); // Number of k equations to solve for each x location nsys = 1 + (localmesh->LocalNz)/2; } @@ -58,6 +59,7 @@ InvertParCR::~InvertParCR() { } const Field3D InvertParCR::solve(const Field3D &f) { +#ifndef COORDINATES_USE_3D TRACE("InvertParCR::solve(Field3D)"); ASSERT1(localmesh == f.getMesh()); @@ -217,5 +219,8 @@ const Field3D InvertParCR::solve(const Field3D &f) { delete cr; return localmesh->fromFieldAligned(result); +#else + return Field3D{}; +#endif } From 3b5469834e5cc6b7775fa8d5093b04b1099ea881 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:02:42 +0000 Subject: [PATCH 008/293] Fix FCI for 3D metrics --- src/mesh/parallel/fci.cxx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 25002ffed3..9fed6239a4 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -214,11 +214,14 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) // Invert 2x2 matrix to get change in index BoutReal dx = (dZ_dz * dR - dR_dz * dZ) / det; BoutReal dz = (dR_dx * dZ - dZ_dx * dR) / det; - boundary->add_point(x, y, z, - x + dx, y + 0.5*dir, z + dz, // Intersection point in local index space - 0.5*coord.dy(x,y), //sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection - PI // Right-angle intersection - ); + boundary->add_point( + x, y, z, x + dx, y + 0.5 * dir, + z + dz, // Intersection point in local index space + 0.5 + * coord.dy(x, y, + z), // sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection + PI // Right-angle intersection + ); } //---------------------------------------- From 99a0930ce79ae160070845b5c6621ecd028dec35 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:19:08 +0000 Subject: [PATCH 009/293] Fix/disable difops for 3D metric --- include/difops.hxx | 100 +++++++++++++++----------- src/mesh/difops.cxx | 170 ++++++++++++++++++++++++++++---------------- 2 files changed, 166 insertions(+), 104 deletions(-) diff --git a/include/difops.hxx b/include/difops.hxx index 79c5328242..15a08285e0 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -53,15 +53,19 @@ * enabled) * @param[in] method The method to use. The default is set in the options. */ -const Field2D Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field2D Grad_par(const Field2D& var, const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Field2D Grad_par(const Field2D& var, CELL_LOC outloc, DIFF_METHOD method) { +const Coordinates::metric_field_type Grad_par(const Field2D& var, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(const Coordinates::metric_field_type Grad_par(const Field2D& var, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline const Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, + DIFF_METHOD method) { return Grad_par(var, outloc, DIFF_METHOD_STRING(method)); }; -DEPRECATED(inline const Field2D Grad_par(const Field2D& var, DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline const Coordinates::metric_field_type Grad_par(const Field2D& var, + DIFF_METHOD method, + CELL_LOC outloc)) { return Grad_par(var, outloc, DIFF_METHOD_STRING(method)); }; @@ -104,18 +108,18 @@ const Field3D Grad_parP(const Field3D& apar, const Field3D& f); * @param[in] method The numerical method to use. The default is set in the options * */ -const Field2D Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field2D Vpar_Grad_par(const Field2D& v, const Field2D& f, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Field2D Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { +const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(const Coordinates::metric_field_type Vpar_Grad_par( + const Field2D& v, const Field2D& f, const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline const Coordinates::metric_field_type +Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, DIFF_METHOD_STRING(method)); }; -DEPRECATED(inline const Field2D Vpar_Grad_par(const Field2D& v, const Field2D& f, - DIFF_METHOD method, CELL_LOC outloc)) { +DEPRECATED(inline const Coordinates::metric_field_type Vpar_Grad_par( + const Field2D& v, const Field2D& f, DIFF_METHOD method, CELL_LOC outloc)) { return Vpar_Grad_par(v, f, outloc, DIFF_METHOD_STRING(method)); }; @@ -146,15 +150,19 @@ DEPRECATED(inline const Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f * @param[in] method The numerical method to use * */ -const Field2D Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field2D Div_par(const Field2D& f, const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Field2D Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { +const Coordinates::metric_field_type Div_par(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(const Coordinates::metric_field_type Div_par(const Field2D& f, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline const Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Div_par(f, outloc, DIFF_METHOD_STRING(method)); }; -DEPRECATED(inline const Field2D Div_par(const Field2D& f, DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline const Coordinates::metric_field_type Div_par(const Field2D& f, + DIFF_METHOD method, + CELL_LOC outloc)) { return Div_par(f, outloc, DIFF_METHOD_STRING(method)); }; @@ -205,9 +213,11 @@ DEPRECATED(inline const Field3D Div_par_flux(const Field3D& v, const Field3D& f, * @param[in] f The field to be differentiated * @param[in] outloc The cell location of the result */ -const Field2D Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -inline const Field2D Grad2_par2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { +const Coordinates::metric_field_type Grad2_par2(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +inline const Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Grad2_par2(f, outloc, DIFF_METHOD_STRING(method)); }; @@ -222,14 +232,14 @@ inline const Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD m * These are a simple way to do staggered differencing */ const Field3D Grad_par_CtoL(const Field3D &var); -const Field2D Grad_par_CtoL(const Field2D &var); +const Coordinates::metric_field_type Grad_par_CtoL(const Field2D& var); const Field3D Vpar_Grad_par_LCtoC(const Field3D &v, const Field3D &f, REGION region=RGN_NOBNDRY); const Field3D Grad_par_LtoC(const Field3D &var); -const Field2D Grad_par_LtoC(const Field2D &var); +const Coordinates::metric_field_type Grad_par_LtoC(const Field2D& var); const Field3D Div_par_LtoC(const Field3D &var); -const Field2D Div_par_LtoC(const Field2D &var); +const Coordinates::metric_field_type Div_par_LtoC(const Field2D& var); const Field3D Div_par_CtoL(const Field3D &var); -const Field2D Div_par_CtoL(const Field2D &var); +const Coordinates::metric_field_type Div_par_CtoL(const Field2D& var); /*! * Parallel divergence of diffusive flux, K*Grad_par @@ -241,9 +251,11 @@ const Field2D Div_par_CtoL(const Field2D &var); * @param[in] kY The diffusion coefficient * @param[in] f The field whose gradient drives a flux */ -const Field2D Div_par_K_Grad_par(BoutReal kY, const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); const Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); -const Field2D Div_par_K_Grad_par(const Field2D &kY, const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type +Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); const Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); @@ -257,7 +269,8 @@ const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC o * * For the full perpendicular Laplacian, use Laplace_perp */ -const Field2D Delp2(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type Delp2(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); const Field3D Delp2(const Field3D &f, BoutReal zsmooth=-1.0, CELL_LOC outloc=CELL_DEFAULT); const FieldPerp Delp2(const FieldPerp &f, BoutReal zsmooth=-1.0, CELL_LOC outloc=CELL_DEFAULT); @@ -266,27 +279,31 @@ const FieldPerp Delp2(const FieldPerp &f, BoutReal zsmooth=-1.0, CELL_LOC outloc * * */ -const Field2D Laplace_perp(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type Laplace_perp(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace_perp(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); /*! * Parallel Laplacian operator * */ -const Field2D Laplace_par(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type Laplace_par(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); /*! * Full Laplacian operator (par + perp) */ -const Field2D Laplace(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type Laplace(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); const Field3D Laplace(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); /*! * Terms of form b0 x Grad(phi) dot Grad(A) * */ -const Field2D b0xGrad_dot_Grad(const Field2D &phi, const Field2D &A, CELL_LOC outloc=CELL_DEFAULT); +const Coordinates::metric_field_type +b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc = CELL_DEFAULT); /*! * Terms of form @@ -332,9 +349,10 @@ enum BRACKET_METHOD { * @param[in] solver Pointer to the time integration solver * */ -const Field2D bracket(const Field2D &f, const Field2D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); +const Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, + BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, + Solver* solver = nullptr); const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, Solver *solver = nullptr); diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index d271a4cda1..ada23b7ab9 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -45,11 +45,13 @@ * The parallel derivative along unperturbed B-field *******************************************************************************/ -const Field2D Grad_par(const Field2D &var, CELL_LOC outloc, const std::string &method) { +const Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, + const std::string& method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -const Field2D Grad_par(const Field2D &var, const std::string &method, CELL_LOC outloc) { +const Coordinates::metric_field_type +Grad_par(const Field2D& var, const std::string& method, CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } @@ -73,6 +75,7 @@ const Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC o *******************************************************************************/ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { +#ifndef COORDINATES_USE_3D ASSERT1(apar.getMesh() == f.getMesh()); ASSERT2(apar.getLocation() == f.getLocation()); @@ -159,6 +162,9 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { ASSERT2(result.getLocation() == f.getLocation()); return result; +#else + return Field3D{}; +#endif } /******************************************************************************* @@ -166,11 +172,15 @@ 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, CELL_LOC outloc, const std::string &method) { +const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc, + const std::string& method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -const Field2D Vpar_Grad_par(const Field2D &v, const Field2D &f, const std::string &method, CELL_LOC outloc) { +const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + const std::string& method, + CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } @@ -186,11 +196,13 @@ const Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, const std::strin * Div_par * parallel divergence operator B \partial_{||} (F/B) *******************************************************************************/ -const Field2D Div_par(const Field2D &f, CELL_LOC outloc, const std::string &method) { +const Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, + const std::string& method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -const Field2D Div_par(const Field2D &f, const std::string &method, CELL_LOC outloc) { +const Coordinates::metric_field_type Div_par(const Field2D& f, const std::string& method, + CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } @@ -227,12 +239,17 @@ const Field3D Div_par(const Field3D &f, const Field3D &v) { BoutReal vR = 0.5*(v(i,j,k) + v.yup()(i,j+1,k)); // Calculate flux at right boundary (y+1/2) - BoutReal fluxRight = fR * vR * (coord->J(i,j) + coord->J(i,j+1)) / (sqrt(coord->g_22(i,j))+ sqrt(coord->g_22(i,j+1))); - + BoutReal fluxRight = + fR * vR * (coord->J(i, j, k) + coord->J(i, j + 1, k)) + / (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j + 1, k))); + // Calculate at left boundary (y-1/2) - BoutReal fluxLeft = fL * vL * (coord->J(i,j) + coord->J(i,j-1)) / (sqrt(coord->g_22(i,j)) + sqrt(coord->g_22(i,j-1))); - - result(i,j,k) = (fluxRight - fluxLeft) / (coord->dy(i,j)*coord->J(i,j)); + BoutReal fluxLeft = + fL * vL * (coord->J(i, j, k) + coord->J(i, j - 1, k)) + / (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j - 1, k))); + + result(i, j, k) = + (fluxRight - fluxLeft) / (coord->dy(i, j, k) * coord->J(i, j, k)); } } @@ -246,7 +263,7 @@ const Field3D Div_par(const Field3D &f, const Field3D &v) { const Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { Coordinates *metric = f.getCoordinates(outloc); - Field2D Bxy_floc = f.getCoordinates()->Bxy; + auto Bxy_floc = f.getCoordinates()->Bxy; if (!f.hasYupYdown()) { return metric->Bxy*FDDY(v, f/Bxy_floc, outloc, method)/sqrt(metric->g_22); @@ -290,7 +307,10 @@ const Field3D Grad_par_CtoL(const Field3D &var) { for(int jx=0; jxLocalNx;jx++) { for(int jy=1;jyLocalNy;jy++) { for(int jz=0;jzLocalNz;jz++) { - result(jx, jy, jz) = 2.*(var(jx, jy, jz) - var.ydown()(jx, jy-1, jz)) / (metric->dy(jx, jy) * sqrt(metric->g_22(jx, jy)) + metric->dy(jx, jy-1) * sqrt(metric->g_22(jx, jy-1))); + result(jx, jy, jz) = + 2. * (var(jx, jy, jz) - var.ydown()(jx, jy - 1, jz)) + / (metric->dy(jx, jy, jz) * sqrt(metric->g_22(jx, jy, jz)) + + metric->dy(jx, jy - 1, jz) * sqrt(metric->g_22(jx, jy - 1, jz))); } } } @@ -301,7 +321,10 @@ const Field3D Grad_par_CtoL(const Field3D &var) { for(int jx=0; jxLocalNx;jx++) { for(int jy=1;jyLocalNy;jy++) { for(int jz=0;jzLocalNz;jz++) { - result(jx, jy, jz) = 2.*(var_fa(jx, jy, jz) - var_fa(jx, jy-1, jz)) / (metric->dy(jx, jy) * sqrt(metric->g_22(jx, jy)) + metric->dy(jx, jy-1) * sqrt(metric->g_22(jx, jy-1))); + result(jx, jy, jz) = + 2. * (var_fa(jx, jy, jz) - var_fa(jx, jy - 1, jz)) + / (metric->dy(jx, jy, jz) * sqrt(metric->g_22(jx, jy, jz)) + + metric->dy(jx, jy - 1, jz) * sqrt(metric->g_22(jx, jy - 1, jz))); } } } @@ -313,9 +336,9 @@ const Field3D Grad_par_CtoL(const Field3D &var) { return result; } -const Field2D Grad_par_CtoL(const Field2D &var) { +const Coordinates::metric_field_type Grad_par_CtoL(const Field2D& var) { const auto varMesh = var.getMesh(); - Field2D result(varMesh); + Coordinates::metric_field_type result(varMesh); result.allocate(); Coordinates *metric = var.getCoordinates(CELL_YLOW); @@ -427,9 +450,9 @@ const Field3D Grad_par_LtoC(const Field3D &var) { return result; } -const Field2D Grad_par_LtoC(const Field2D &var) { +const Coordinates::metric_field_type Grad_par_LtoC(const Field2D& var) { const auto varMesh = var.getMesh(); - Field2D result(varMesh); + Coordinates::metric_field_type result(varMesh); result.allocate(); Coordinates *metric = var.getCoordinates(CELL_CENTRE); @@ -443,7 +466,7 @@ const Field2D Grad_par_LtoC(const Field2D &var) { return result; } -const Field2D Div_par_LtoC(const Field2D &var) { +const Coordinates::metric_field_type Div_par_LtoC(const Field2D& var) { return var.getCoordinates(CELL_CENTRE)->Bxy * Grad_par_LtoC(var / var.getCoordinates(CELL_YLOW)->Bxy); } @@ -458,11 +481,12 @@ const Field3D Div_par_LtoC(const Field3D &var) { for (int jx = 0; jx < mesh->LocalNx; jx++) { for (int jy = 0; jy < mesh->LocalNy - 1; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { - result(jx, jy, jz) = metric->Bxy(jx, jy) * 2. * - (var.yup()(jx, jy + 1, jz) / metric->Bxy(jx, jy + 1) - - var(jx, jy, jz) / metric->Bxy(jx, jy)) / - (metric->dy(jx, jy) * sqrt(metric->g_22(jx, jy)) + - metric->dy(jx, jy - 1) * sqrt(metric->g_22(jx, jy - 1))); + result(jx, jy, jz) = + metric->Bxy(jx, jy, jz) * 2. + * (var.yup()(jx, jy + 1, jz) / metric->Bxy(jx, jy + 1, jz) + - var(jx, jy, jz) / metric->Bxy(jx, jy, jz)) + / (metric->dy(jx, jy, jz) * sqrt(metric->g_22(jx, jy, jz)) + + metric->dy(jx, jy - 1, jz) * sqrt(metric->g_22(jx, jy - 1, jz))); } } } @@ -472,7 +496,7 @@ const Field3D Div_par_LtoC(const Field3D &var) { return result; } -const Field2D Div_par_CtoL(const Field2D &var) { +const Coordinates::metric_field_type Div_par_CtoL(const Field2D& var) { return var.getCoordinates(CELL_CENTRE)->Bxy * Grad_par_CtoL(var / var.getCoordinates(CELL_YLOW)->Bxy); } @@ -487,11 +511,12 @@ const Field3D Div_par_CtoL(const Field3D &var) { for (int jx = 0; jx < mesh->LocalNx; jx++) { for (int jy = 1; jy < mesh->LocalNy; jy++) { for (int jz = 0; jz < mesh->LocalNz; jz++) { - result(jx, jy, jz) = metric->Bxy(jx, jy) * 2. * - (var(jx, jy, jz) / metric->Bxy(jx, jy) - - var.ydown()(jx, jy - 1, jz) / metric->Bxy(jx, jy - 1)) / - (metric->dy(jx, jy) * sqrt(metric->g_22(jx, jy)) + - metric->dy(jx, jy - 1) * sqrt(metric->g_22(jx, jy - 1))); + result(jx, jy, jz) = + metric->Bxy(jx, jy, jz) * 2. + * (var(jx, jy, jz) / metric->Bxy(jx, jy, jz) + - var.ydown()(jx, jy - 1, jz) / metric->Bxy(jx, jy - 1, jz)) + / (metric->dy(jx, jy, jz) * sqrt(metric->g_22(jx, jy, jz)) + + metric->dy(jx, jy - 1, jz) * sqrt(metric->g_22(jx, jy - 1, jz))); } } } @@ -510,7 +535,8 @@ const Field3D Div_par_CtoL(const Field3D &var) { * Note: For parallel Laplacian use LaplacePar *******************************************************************************/ -const Field2D Grad2_par2(const Field2D &f, CELL_LOC outloc, const std::string &method) { +const Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, + const std::string& method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } @@ -523,7 +549,8 @@ const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, const std::string &m * Parallel divergence of diffusive flux, K*Grad_par *******************************************************************************/ -const Field2D Div_par_K_Grad_par(BoutReal kY, const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, + CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } @@ -531,7 +558,8 @@ 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, CELL_LOC outloc) { +const Coordinates::metric_field_type +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); } @@ -552,7 +580,7 @@ const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC o * perpendicular Laplacian operator *******************************************************************************/ -const Field2D Delp2(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Delp2(f, outloc); } @@ -571,7 +599,7 @@ const FieldPerp Delp2(const FieldPerp &f, BoutReal UNUSED(zsmooth), CELL_LOC out * Laplace_perp = Laplace - Laplace_par *******************************************************************************/ -const Field2D Laplace_perp(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc) { return Laplace(f, outloc) - Laplace_par(f, outloc); } @@ -587,7 +615,7 @@ const Field3D Laplace_perp(const Field3D &f, CELL_LOC outloc) { * *******************************************************************************/ -const Field2D Laplace_par(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } @@ -600,7 +628,7 @@ const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { * Full Laplacian operator on scalar field *******************************************************************************/ -const Field2D Laplace(const Field2D &f, CELL_LOC outloc) { +const Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace(f, outloc); } @@ -614,8 +642,9 @@ const Field3D Laplace(const Field3D &f, CELL_LOC outloc) { * Used for ExB terms and perturbed B field using A_|| *******************************************************************************/ -const Field2D b0xGrad_dot_Grad(const Field2D &phi, const Field2D &A, CELL_LOC outloc) { - +const Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, + const Field2D& A, CELL_LOC outloc) { + TRACE("b0xGrad_dot_Grad( Field2D , Field2D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -625,15 +654,15 @@ const Field2D b0xGrad_dot_Grad(const Field2D &phi, const Field2D &A, CELL_LOC ou Coordinates *metric = phi.getCoordinates(outloc); // Calculate phi derivatives - Field2D dpdx = DDX(phi, outloc); - Field2D dpdy = DDY(phi, outloc); - + Coordinates::metric_field_type dpdx = DDX(phi, outloc); + Coordinates::metric_field_type dpdy = DDY(phi, outloc); + // Calculate advection velocity - Field2D vx = -metric->g_23*dpdy; - Field2D vy = metric->g_23*dpdx; + Coordinates::metric_field_type vx = -metric->g_23 * dpdy; + Coordinates::metric_field_type vy = metric->g_23 * dpdx; // Upwind A using these velocities - Field2D result = VDDX(vx, A, outloc) + VDDY(vy, A, outloc); + Coordinates::metric_field_type result = VDDX(vx, A, outloc) + VDDY(vy, A, outloc); result /= metric->J*sqrt(metric->g_22); ASSERT1(result.getLocation() == outloc); @@ -656,13 +685,13 @@ const Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC ou Coordinates *metric = phi.getCoordinates(outloc); // Calculate phi derivatives - Field2D dpdx = DDX(phi, outloc); - Field2D dpdy = DDY(phi, outloc); + Coordinates::metric_field_type dpdx = DDX(phi, outloc); + Coordinates::metric_field_type dpdy = DDY(phi, outloc); // Calculate advection velocity - Field2D vx = -metric->g_23 * dpdy; - Field2D vy = metric->g_23 * dpdx; - Field2D vz = metric->g_12 * dpdy - metric->g_22 * dpdx; + Coordinates::metric_field_type vx = -metric->g_23 * dpdy; + Coordinates::metric_field_type vy = metric->g_23 * dpdx; + Coordinates::metric_field_type vz = metric->g_12 * dpdy - metric->g_22 * dpdx; if(mesh->IncIntShear) { // BOUT-06 style differencing @@ -761,8 +790,9 @@ 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] *******************************************************************************/ -const Field2D bracket(const Field2D &f, const Field2D &g, BRACKET_METHOD method, - CELL_LOC outloc, Solver *UNUSED(solver)) { +const Coordinates::metric_field_type 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()); @@ -771,7 +801,7 @@ const Field2D bracket(const Field2D &f, const Field2D &g, BRACKET_METHOD method, } ASSERT1(f.getLocation() == g.getLocation() && outloc == f.getLocation()) - Field2D result(f.getMesh()); + Coordinates::metric_field_type result(f.getMesh()); if( (method == BRACKET_SIMPLE) || (method == BRACKET_ARAKAWA)) { // Use a subset of terms for comparison to BOUT-06 @@ -807,7 +837,8 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, if(!solver) throw BoutException("CTU method requires access to the solver"); - + +#ifndef COORDINATES_USE_3D result.allocate(); result.setLocation(outloc); @@ -815,7 +846,8 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, for(int x=mesh->xstart;x<=mesh->xend;x++) for(int y=mesh->ystart;y<=mesh->yend;y++) { for(int z=0;zdz); // Set stability condition - solver->setMaxTimestep(metric->dx(x,y) / (fabs(vx) + 1e-16)); - + solver->setMaxTimestep(metric->dx(x, y, z) / (fabs(vx) + 1e-16)); + // X differencing if(vx > 0.0) { gp = g(x,y); @@ -837,10 +869,13 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, gm = g(x,y); } - - result(x,y,z) = vx * (gp - gm) / metric->dx(x,y); + + result(x, y, z) = vx * (gp - gm) / metric->dx(x, y, z); } } +#else + throw BoutException("BRACKET_CTU not valid with 3D metrics yet."); +#endif break; } case BRACKET_ARAKAWA: { @@ -917,6 +952,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, break; } case BRACKET_ARAKAWA_OLD: { +#ifndef COORDINATES_USE_3D result.allocate(); result.setLocation(outloc); const int ncz = mesh->LocalNz; @@ -953,8 +989,10 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, } } } - - break; +#else + throw BoutException("BRACKET_ARAKAWA_OLD not valid with 3D metrics yet."); +#endif + break; } case BRACKET_SIMPLE: { // Use a subset of terms for comparison to BOUT-06 @@ -1032,7 +1070,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, case BRACKET_CTU: { // First order Corner Transport Upwind method // P.Collela JCP 87, 171-200 (1990) - +#ifndef COORDINATES_USE_3D if(!solver) throw BoutException("CTU method requires access to the solver"); @@ -1125,6 +1163,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, result(x, y, z) += vz(x, z) * (gp - gm) / metric->dz; } } +#else + throw BoutException("BRACKET_CTU not valid with 3D metrics yet."); +#endif break; } case BRACKET_ARAKAWA: { @@ -1223,7 +1264,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, } case BRACKET_ARAKAWA_OLD: { // Arakawa scheme for perpendicular flow - +#ifndef COORDINATES_USE_3D result.allocate(); result.setLocation(outloc); @@ -1271,6 +1312,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, } } } +#else + throw BoutException("BRACKET_ARAKAWA_OLD not valid with 3D metrics yet."); +#endif break; } case BRACKET_SIMPLE: { From a72ff1df52a25c8b5136ee048d56c51f38e2eada Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:35:32 +0000 Subject: [PATCH 010/293] Fix/disable boundary_standard --- src/mesh/boundary_standard.cxx | 131 +++++++++++++++++++++++++-------- 1 file changed, 101 insertions(+), 30 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 5e5c0a1c16..0d2367170b 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1452,6 +1452,7 @@ BoundaryOp* BoundaryNeumann_NonOrthogonal::clone(BoundaryRegion *region, const s } void BoundaryNeumann_NonOrthogonal::apply(Field2D &f) { +#ifndef COORDINATES_USE_3D Coordinates *metric = f.getCoordinates(); // Calculate derivatives for metric use mesh->communicate(f); @@ -1489,6 +1490,10 @@ void BoundaryNeumann_NonOrthogonal::apply(Field2D &f) { } } } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryNeumann_NonOrthogonal::apply(Field3D &f) { @@ -1499,19 +1504,23 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D &f) { Field3D dfdz = DDZ(f); // Loop over all elements and set equal to the next point in for(bndry->first(); !bndry->isDone(); bndry->next1d()) { - // Interpolate (linearly) metrics to halfway between last cell and boundary cell - BoutReal g11shift = 0.5*(metric->g11(bndry->x,bndry->y) + metric->g11(bndry->x-bndry->bx,bndry->y)); - BoutReal g12shift = 0.5*(metric->g12(bndry->x,bndry->y) + metric->g12(bndry->x-bndry->bx,bndry->y)); - BoutReal g13shift = 0.5*(metric->g13(bndry->x,bndry->y) + metric->g13(bndry->x-bndry->bx,bndry->y)); // 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++) { + // Interpolate (linearly) metrics to halfway between last cell and boundary cell + BoutReal g11shift = 0.5 * (metric->g11(bndry->x, bndry->y, z) + + metric->g11(bndry->x - bndry->bx, bndry->y, z)); + BoutReal g12shift = 0.5 * (metric->g12(bndry->x, bndry->y, z) + + metric->g12(bndry->x - bndry->bx, bndry->y, z)); + BoutReal g13shift = 0.5 * (metric->g13(bndry->x, bndry->y, z) + + metric->g13(bndry->x - bndry->bx, bndry->y, 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) { // x boundaries only - BoutReal delta = bndry->bx*metric->dx(bndry->x, bndry->y); + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, z); f(bndry->x, bndry->y, z) = f(bndry->x - bndry->bx, bndry->y, z) + delta/g11shift*(val - xshift); if (bndry->width == 2){ f(bndry->x + bndry->bx, bndry->y, z) = f(bndry->x - 2*bndry->bx, bndry->y, z) + 3.0*delta/g11shift*(val - xshift); @@ -1519,7 +1528,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D &f) { } else if(bndry->by != 0 && bndry->bx == 0) { // y boundaries only // no need to shift this b/c we want parallel nuemann not theta - BoutReal delta = bndry->by*metric->dy(bndry->x, bndry->y); + BoutReal delta = bndry->by * metric->dy(bndry->x, bndry->y, z); f(bndry->x, bndry->y, z) = f(bndry->x, bndry->y - bndry->by, z) + delta*val; if (bndry->width == 2){ f(bndry->x, bndry->y + bndry->by, z) = f(bndry->x, bndry->y - 2*bndry->by, z) + 3.0*delta*val; @@ -1556,7 +1565,7 @@ 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 - +#ifndef COORDINATES_USE_3D Coordinates *metric = f.getCoordinates(); bndry->first(); @@ -1785,9 +1794,10 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { 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); - - 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.; + val = fg->generate(xnorm, TWOPI * ynorm, TWOPI * zk / (mesh->LocalNz), t) + * metric->dx(bndry->x, bndry->y, zk); + + 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++) { @@ -1812,9 +1822,10 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { 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); - - 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.; + val = fg->generate(xnorm, TWOPI * ynorm, TWOPI * zk / (mesh->LocalNz), t) + * metric->dx(bndry->x - bndry->bx, bndry->y, zk); + + 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++) { @@ -1835,10 +1846,12 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { 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 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){ + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); + + if(fg){ val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; @@ -1862,8 +1875,9 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { 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 / (mesh->LocalNz), t) + * metric->dy(bndry->x, bndry->y, zk); + } 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 @@ -1887,9 +1901,10 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { + mesh->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); - - 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.; + val = fg->generate(xnorm, TWOPI * ynorm, TWOPI * zk / (mesh->LocalNz), t) + * metric->dy(bndry->x, bndry->y - bndry->by, zk); + + 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++) { @@ -1911,10 +1926,12 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { 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 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){ + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, kz); + + if(fg){ val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; @@ -1935,10 +1952,11 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell + mesh->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){ + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); + + if(fg){ val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); } f(bndry->x,bndry->y, zk) = f(bndry->x-bndry->bx, bndry->y-bndry->by, zk) + delta*val; @@ -1948,6 +1966,10 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { } } } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryNeumann::apply_ddt(Field2D &f) { @@ -1979,7 +2001,7 @@ void BoundaryNeumann_O4::apply(Field2D &f) { } void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { - +#ifndef COORDINATES_USE_3D // 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 bndry->first(); @@ -2029,6 +2051,10 @@ void BoundaryNeumann_O4::apply(Field2D &f,BoutReal t) { } } } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryNeumann_O4::apply(Field3D &f) { @@ -2060,9 +2086,10 @@ void BoundaryNeumann_O4::apply(Field3D &f,BoutReal t) { BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell + mesh->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++) { + BoutReal delta = bndry->bx * coords->dx(bndry->x, bndry->y, zk) + + bndry->by * coords->dy(bndry->x, bndry->y, zk); + if(fg){ val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); } @@ -2110,6 +2137,7 @@ BoundaryOp* BoundaryNeumann_4thOrder::clone(BoundaryRegion *region, const std::l } void BoundaryNeumann_4thOrder::apply(Field2D &f) { +#ifndef COORDINATES_USE_3D 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 @@ -2118,6 +2146,10 @@ void BoundaryNeumann_4thOrder::apply(Field2D &f) { f(bndry->x,bndry->y) = 12.*delta/11.*val + 17./22.*f(bndry->x-bndry->bx,bndry->y-bndry->by) + 9./22.*f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by) - 5./22.*f(bndry->x-3*bndry->bx,bndry->y-3*bndry->by) + 1./22.*f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by); f(bndry->x+bndry->bx,bndry->y+bndry->by) = -24.*delta*val + 27.*f(bndry->x,bndry->y) - 27.*f(bndry->x-bndry->bx,bndry->y-bndry->by) + f(bndry->x-2*bndry->bx,bndry->y-2*bndry->by); // The f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by) 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 } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryNeumann_4thOrder::apply(Field3D &f) { @@ -2126,7 +2158,8 @@ void BoundaryNeumann_4thOrder::apply(Field3D &f) { // 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++) { - BoutReal delta = -(bndry->bx*metric->dx(bndry->x,bndry->y)+bndry->by*metric->dy(bndry->x,bndry->y)); + BoutReal delta = -(bndry->bx * metric->dx(bndry->x, bndry->y, z) + + bndry->by * metric->dy(bndry->x, bndry->y, z)); 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 } @@ -2157,17 +2190,25 @@ BoundaryOp* BoundaryNeumannPar::clone(BoundaryRegion *region, const std::listfirst(); !bndry->isDone(); bndry->next()) f(bndry->x, bndry->y) = f(bndry->x - bndry->bx, bndry->y - bndry->by)*sqrt(metric->g_22(bndry->x, bndry->y)/metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryNeumannPar::apply(Field3D &f) { Coordinates *metric = f.getCoordinates(); for(bndry->first(); !bndry->isDone(); bndry->next()) 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)); + f(bndry->x, bndry->y, z) = + f(bndry->x - bndry->bx, bndry->y - bndry->by, z) + * sqrt(metric->g_22(bndry->x, bndry->y, z) + / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by, z)); } /////////////////////////////////////////////////////////////// @@ -2268,6 +2309,7 @@ BoundaryOp* BoundaryZeroLaplace::clone(BoundaryRegion *region, const std::listlocation != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { // Can't apply this boundary condition to non-X boundaries @@ -2287,9 +2329,14 @@ void BoundaryZeroLaplace::apply(Field2D &f) { x = bndry->x; y = bndry->y; }while(!bndry->isDone()); } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryZeroLaplace::apply(Field3D &f) { +#ifndef COORDINATES_USE_3D int ncz = mesh->LocalNz; Coordinates *metric = f.getCoordinates(); @@ -2340,6 +2387,10 @@ void BoundaryZeroLaplace::apply(Field3D &f) { y = bndry->y; } while (!bndry->isDone()); } +#else + throw BoutException( + "Applying boundary to Field3D not compatible with 3D metrics in ZeroLaplace case."); +#endif } /////////////////////////////////////////////////////////////// @@ -2354,6 +2405,7 @@ BoundaryOp *BoundaryZeroLaplace2::clone(BoundaryRegion *region, } void BoundaryZeroLaplace2::apply(Field2D &f) { +#ifndef COORDINATES_USE_3D if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { // Can't apply this boundary condition to non-X boundaries throw BoutException( @@ -2377,9 +2429,14 @@ void BoundaryZeroLaplace2::apply(Field2D &f) { y = bndry->y; } while (!bndry->isDone()); } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } void BoundaryZeroLaplace2::apply(Field3D &f) { +#ifndef COORDINATES_USE_3D int ncz = mesh->LocalNz; ASSERT0(ncz % 2 == 0); // Allocation assumes even number @@ -2428,6 +2485,10 @@ void BoundaryZeroLaplace2::apply(Field3D &f) { y = bndry->y; } while (!bndry->isDone()); } +#else + throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " + "ZeroLaplace2 case."); +#endif } /////////////////////////////////////////////////////////////// @@ -2471,6 +2532,7 @@ void BoundaryConstLaplace::apply(Field2D &f) { } void BoundaryConstLaplace::apply(Field3D &f) { +#ifndef COORDINATES_USE_3D if((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { // Can't apply this boundary condition to non-X boundaries throw BoutException("ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); @@ -2528,6 +2590,10 @@ void BoundaryConstLaplace::apply(Field3D &f) { x = bndry->x; y = bndry->y; }while(!bndry->isDone()); } +#else + throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " + "ConstLaplace case."); +#endif } /////////////////////////////////////////////////////////////// @@ -2544,6 +2610,7 @@ void BoundaryDivCurl::apply(Vector2D &UNUSED(f)) { } void BoundaryDivCurl::apply(Vector3D &var) { +#ifndef COORDINATES_USE_3D int jx, jy, jz, jzp, jzm; BoutReal tmp; @@ -2605,6 +2672,10 @@ void BoundaryDivCurl::apply(Vector3D &var) { 4.*metric->dx(jx,jy)*tmp ) / metric->J(jx+1,jy)*metric->g11(jx+1,jy); } } +#else + throw BoutException( + "Applying boundary to Vector3D not compatible with 3D metrics in DivCurl."); +#endif } /////////////////////////////////////////////////////////////// From 8f471b85893fcf901206d18e75490e218a345f5f Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:48:17 +0000 Subject: [PATCH 011/293] Fix coordinates for 3D metric --- include/bout/coordinates.hxx | 9 +++ src/mesh/coordinates.cxx | 123 ++++++++++++++++++++++------------- 2 files changed, 86 insertions(+), 46 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 7ccba79b55..cdea9a27b1 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -35,6 +35,9 @@ class Coordinates; #ifndef __COORDINATES_H__ #define __COORDINATES_H__ +#include "field2d.hxx" +#include "field3d.hxx" + #ifdef COORDINATES_USE_3D #define COORDINATES_FIELD_TYPE Field3D #define COORDINATES_VECTOR_TYPE Vector3D @@ -121,6 +124,8 @@ public: REGION region = RGN_NOBNDRY) { return DDX(f, outloc, DIFF_METHOD_STRING(method), region); }; + const Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); const metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -129,6 +134,8 @@ public: REGION region = RGN_NOBNDRY) { return DDY(f, outloc, DIFF_METHOD_STRING(method), region); }; + const Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); const metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -137,6 +144,8 @@ public: REGION region = RGN_NOBNDRY) { return DDZ(f, outloc, DIFF_METHOD_STRING(method), region); }; + const Field3D DDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); /// Gradient along magnetic field b.Grad(f) const metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 8e3d076666..652dc590ed 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -179,6 +179,7 @@ namespace { /// Corner guard cells are set to BoutNaN Coordinates::metric_field_type interpolateAndNeumann(const Coordinates::metric_field_type& f, CELL_LOC location) { +#ifndef COORDINATES_USE_3D Mesh* localmesh = f.getMesh(); auto result = interp_to(f, location, RGN_NOBNDRY); localmesh->communicate(result); @@ -218,6 +219,10 @@ interpolateAndNeumann(const Coordinates::metric_field_type& f, CELL_LOC location } return result; +#else + throw BoutException( + "Staggered coordinates locations not currently supported with 3D metrics."); +#endif } } @@ -491,29 +496,37 @@ int Coordinates::calcCovariant() { for (int jx = 0; jx < localmesh->LocalNx; jx++) { for (int jy = 0; jy < localmesh->LocalNy; jy++) { - // set elements of g - a(0, 0) = g11(jx, jy); - a(1, 1) = g22(jx, jy); - a(2, 2) = g33(jx, jy); - - a(0, 1) = a(1, 0) = g12(jx, jy); - a(1, 2) = a(2, 1) = g23(jx, jy); - a(0, 2) = a(2, 0) = g13(jx, jy); - - // invert - if (invert3x3(a)) { - output_error.write("\tERROR: metric tensor is singular at (%d, %d)\n", jx, jy); - return 1; +#ifndef COORDINATES_USE_3D + { + int jz = 0; +#else + for (int jz = 0; jz < localmesh->LocalNz; jz++) { // Inefficient for 2D metric type +#endif + // set elements of g + a(0, 0) = g11(jx, jy, jz); + a(1, 1) = g22(jx, jy, jz); + a(2, 2) = g33(jx, jy, jz); + + a(0, 1) = a(1, 0) = g12(jx, jy, jz); + a(1, 2) = a(2, 1) = g23(jx, jy, jz); + a(0, 2) = a(2, 0) = g13(jx, jy, jz); + + // invert + if (invert3x3(a)) { + output_error.write("\tERROR: metric tensor is singular at (%d, %d, %d)\n", jx, + jy, jz); + return 1; + } + + // put elements into g_{ij} + g_11(jx, jy, jz) = a(0, 0); + g_22(jx, jy, jz) = a(1, 1); + g_33(jx, jy, jz) = a(2, 2); + + g_12(jx, jy, jz) = a(0, 1); + g_13(jx, jy, jz) = a(0, 2); + g_23(jx, jy, jz) = a(1, 2); } - - // put elements into g_{ij} - g_11(jx, jy) = a(0, 0); - g_22(jx, jy) = a(1, 1); - g_33(jx, jy) = a(2, 2); - - g_12(jx, jy) = a(0, 1); - g_13(jx, jy) = a(0, 2); - g_23(jx, jy) = a(1, 2); } } @@ -551,29 +564,37 @@ int Coordinates::calcContravariant() { for (int jx = 0; jx < localmesh->LocalNx; jx++) { for (int jy = 0; jy < localmesh->LocalNy; jy++) { - // set elements of g - a(0, 0) = g_11(jx, jy); - a(1, 1) = g_22(jx, jy); - a(2, 2) = g_33(jx, jy); - - a(0, 1) = a(1, 0) = g_12(jx, jy); - a(1, 2) = a(2, 1) = g_23(jx, jy); - a(0, 2) = a(2, 0) = g_13(jx, jy); - - // invert - if (invert3x3(a)) { - output_error.write("\tERROR: metric tensor is singular at (%d, %d)\n", jx, jy); - return 1; +#ifndef COORDINATES_USE_3D + { + int jz = 0; +#else + for (int jz = 0; jz < localmesh->LocalNz; jz++) { // Inefficient for 2D metric type +#endif + // set elements of g + a(0, 0) = g_11(jx, jy, jz); + a(1, 1) = g_22(jx, jy, jz); + a(2, 2) = g_33(jx, jy, jz); + + a(0, 1) = a(1, 0) = g_12(jx, jy, jz); + a(1, 2) = a(2, 1) = g_23(jx, jy, jz); + a(0, 2) = a(2, 0) = g_13(jx, jy, jz); + + // invert + if (invert3x3(a)) { + output_error.write("\tERROR: metric tensor is singular at (%d, %d, %d)\n", jx, + jy, jz); + return 1; + } + + // put elements into g_{ij} + g11(jx, jy, jz) = a(0, 0); + g22(jx, jy, jz) = a(1, 1); + g33(jx, jy, jz) = a(2, 2); + + g12(jx, jy, jz) = a(0, 1); + g13(jx, jy, jz) = a(0, 2); + g23(jx, jy, jz) = a(1, 2); } - - // put elements into g_{ij} - g11(jx, jy) = a(0, 0); - g22(jx, jy) = a(1, 1); - g33(jx, jy) = a(2, 2); - - g12(jx, jy) = a(0, 1); - g13(jx, jy) = a(0, 2); - g23(jx, jy) = a(1, 2); } } @@ -632,6 +653,10 @@ const Coordinates::metric_field_type Coordinates::DDX(const Field2D& f, CELL_LOC ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDX(f, loc, method, region) / dx; } +const Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + return ::DDX(f, outloc, method, region); +}; const Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, const std::string& method, @@ -639,6 +664,10 @@ const Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDY(f, loc, method, region) / dy; } +const Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + return ::DDY(f, outloc, method, region); +}; const Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), CELL_LOC loc, @@ -650,8 +679,10 @@ const Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D result.setLocation(location); return result; } - -#include +const Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + return ::DDZ(f, outloc, method, region); +}; ///////////////////////////////////////////////////////// // Parallel gradient From 72d46465ed2b6d9c5df6406a904a432dd043afee Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:51:10 +0000 Subject: [PATCH 012/293] Fix parallel boundary for 3D metric --- src/mesh/parallel_boundary_op.cxx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mesh/parallel_boundary_op.cxx b/src/mesh/parallel_boundary_op.cxx index 1fdd82bcaa..827ea2c318 100644 --- a/src/mesh/parallel_boundary_op.cxx +++ b/src/mesh/parallel_boundary_op.cxx @@ -83,7 +83,6 @@ BoundaryOpPar* BoundaryOpPar_dirichlet::clone(BoundaryRegionPar *region, Field3D } void BoundaryOpPar_dirichlet::apply(Field3D &f, BoutReal t) { - Field3D& f_next = f.ynext(bndry->dir); Coordinates& coord = *(f.getCoordinates()); @@ -99,7 +98,7 @@ void BoundaryOpPar_dirichlet::apply(Field3D &f, BoutReal t) { // Scale the field and normalise to the desired value BoutReal y_prime = bndry->length; - BoutReal f2 = (f(x,y,z) - value) * (coord.dy(x, y) - y_prime) / y_prime; + BoutReal f2 = (f(x, y, z) - value) * (coord.dy(x, y, z) - y_prime) / y_prime; f_next(x, y+bndry->dir, z) = value - f2; } @@ -144,9 +143,9 @@ void BoundaryOpPar_dirichlet_O3::apply(Field3D &f, BoutReal t) { BoutReal fb = getValue(*bndry, t); BoutReal f1 = f_prev(x, y-bndry->dir, z); BoutReal f2 = f(x,y,z); - BoutReal l1 = coord.dy(x, y); + BoutReal l1 = coord.dy(x, y, z); BoutReal l2 = bndry->length; - BoutReal l3 = coord.dy(x, y) - l2; + BoutReal l3 = coord.dy(x, y, z) - l2; BoutReal denom = (l1*l1*l2 + l1*l2*l2); BoutReal term1 = (l2*l2*l3 + l2*l3*l3); @@ -196,7 +195,7 @@ void BoundaryOpPar_dirichlet_interp::apply(Field3D &f, BoutReal t) { BoutReal fs = getValue(*bndry, t); // Scale the field and normalise to the desired value - BoutReal dy = coord.dy(x, y); + BoutReal dy = coord.dy(x, y, z); BoutReal s = bndry->length*dy; f_next(x, y+bndry->dir, z) = f_prev(x, y-bndry->dir, z)*(1.-(2.*s/(dy+s))) @@ -244,7 +243,7 @@ void BoundaryOpPar_neumann::apply(Field3D &f, BoutReal t) { // Generate the boundary value BoutReal value = getValue(x, y, z, t); - BoutReal dy = coord.dy(x, y); + BoutReal dy = coord.dy(x, y, z); f_next(x, y+bndry->dir, z) = f(x, y, z) + bndry->dir*value*dy; } From 9776e929d3abf538df5e38ac11ea12ae67536230 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 11:59:13 +0000 Subject: [PATCH 013/293] Fix/disable FV ops for 3D metric --- src/mesh/fv_ops.cxx | 101 ++++++++++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 36 deletions(-) diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 51359cc34e..2243784c5f 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -10,6 +10,7 @@ namespace FV { // Div ( a Laplace_perp(f) ) -- Vorticity const Field3D Div_a_Laplace_perp(const Field3D &a, const Field3D &f) { +#ifndef COORDINATES_USE_3D ASSERT2(a.getLocation() == f.getLocation()); Mesh *mesh = a.getMesh(); @@ -112,6 +113,9 @@ namespace FV { } return result; +#else + throw BoutException("Not all FV:: ops currently support 3D metrics."); +#endif } const Field3D Div_par_K_Grad_par(const Field3D &Kin, const Field3D &fin, bool bndry_flux) { @@ -191,9 +195,8 @@ namespace FV { for(int i=mesh->xstart;i<=mesh->xend;i++) for(int j=mesh->ystart;j<=mesh->yend;j++) { - BoutReal dy3 = SQ(coord->dy(i,j))*coord->dy(i,j); for(int k=0;kLocalNz;k++) { - + BoutReal dy3 = SQ(coord->dy(i, j, k)) * coord->dy(i, j, k); // 3rd derivative at right boundary BoutReal d3fdx3 = ( @@ -202,12 +205,13 @@ namespace FV { + 3.*f(i,j, k) - f(i,j-1,k) ) / dy3; - - BoutReal flux = 0.5*(d(i,j,k) + d(i,j+1,k))*(coord->J(i,j) + coord->J(i,j+1)) * d3fdx3; - - result(i,j, k) += flux / (coord->J(i,j) * coord->dy(i,j)); - result(i,j+1,k) -= flux / (coord->J(i,j+1) * coord->dy(i,j+1)); - + + BoutReal flux = 0.5 * (d(i, j, k) + d(i, j + 1, k)) + * (coord->J(i, j, k) + coord->J(i, j + 1, k)) * d3fdx3; + + result(i, j, k) += flux / (coord->J(i, j, k) * coord->dy(i, j, k)); + result(i, j + 1, k) -= flux / (coord->J(i, j + 1, k) * coord->dy(i, j + 1, k)); + if(j == mesh->ystart && (!mesh->firstY())) { // Left cell boundary, no flux through boundaries d3fdx3 = ( @@ -216,11 +220,13 @@ namespace FV { + 3.*f(i,j-1,k) - f(i,j-2,k) ) / dy3; - - flux = 0.5*(d(i,j,k) + d(i,j-1,k))*(coord->J(i,j) + coord->J(i,j-1)) * d3fdx3; - - result(i,j, k) -= flux / (coord->J(i,j) * coord->dy(i,j)); - result(i,j-1,k) += flux / (coord->J(i,j-1) * coord->dy(i,j-1)); + + flux = 0.5 * (d(i, j, k) + d(i, j - 1, k)) + * (coord->J(i, j, k) + coord->J(i, j - 1, k)) * d3fdx3; + + result(i, j, k) -= flux / (coord->J(i, j, k) * coord->dy(i, j, k)); + result(i, j - 1, k) += + flux / (coord->J(i, j - 1, k) * coord->dy(i, j - 1, k)); } } } @@ -250,16 +256,20 @@ namespace FV { if (bndry_flux || (j != mesh->yend) || !has_upper_boundary) { // Calculate the fluxes - - // Right boundary common factors - BoutReal common_factor = 0.25 * - (coord->dy(i, j) + coord->dy(i, j + 1)) * - (coord->J(i, j) + coord->J(i, j + 1)); - - BoutReal factor_rc = common_factor / (coord->J(i,j) * coord->dy(i,j)); - BoutReal factor_rp = common_factor / (coord->J(i,j+1) * coord->dy(i,j+1)); - if ( j != mesh->yend || !has_upper_boundary ) { - for(int k=0;kLocalNz;k++) { + + if (j != mesh->yend || !has_upper_boundary) { + + for (int k = 0; k < mesh->LocalNz; k++) { + // Right boundary common factors + BoutReal common_factor = 0.25 + * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, j) + coord->J(i, j + 1, k)); + + BoutReal factor_rc = + common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); + BoutReal factor_rp = + common_factor / (coord->J(i, j + 1, k) * coord->dy(i, j + 1, k)); + // Not on domain boundary // 3rd derivative at right cell boundary @@ -278,6 +288,15 @@ namespace FV { // Use a one-sided difference formula for(int k=0;kLocalNz;k++) { + // Right boundary common factors + BoutReal common_factor = 0.25 + * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, j) + coord->J(i, j + 1, k)); + + BoutReal factor_rc = + common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); + BoutReal factor_rp = + common_factor / (coord->J(i, j + 1, k) * coord->dy(i, j + 1, k)); BoutReal d3fdx3 = -((16. / 5) * 0.5 * (f(i, j + 1, k) + f(i, j, k)) // Boundary value f_b @@ -297,16 +316,18 @@ namespace FV { if (bndry_flux || (j != mesh->ystart) || !has_lower_boundary) { // Calculate the fluxes - BoutReal common_factor = 0.25 * - (coord->dy(i, j) + coord->dy(i, j + 1)) * - (coord->J(i, j) + coord->J(i, j - 1)); - - BoutReal factor_lc = common_factor / (coord->J(i, j) * coord->dy(i, j)); - BoutReal factor_lm = common_factor / (coord->J(i, j - 1) * coord->dy(i, j - 1)); if ( j != mesh->ystart || !has_lower_boundary ) { for(int k=0;kLocalNz;k++) { - + BoutReal common_factor = 0.25 + * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, k) + coord->J(i, j - 1, k)); + + BoutReal factor_lc = + common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); + BoutReal factor_lm = + common_factor / (coord->J(i, j - 1, k) * coord->dy(i, j - 1, k)); + // Not on a domain boundary BoutReal d3fdx3 = (f(i, j + 1, k) - 3. * f(i, j, k) @@ -319,12 +340,20 @@ namespace FV { } else { // On a domain (Y) boundary for(int k=0;kLocalNz;k++) { - BoutReal d3fdx3 = -(-(16. / 5) * 0.5 * - (f(i, j - 1, k) + f(i, j, k)) // Boundary value f_b - + 6. * f(i, j, k) // f_0 - - 4. * f(i, j + 1, k) // f_1 - + (6. / 5) * f(i, j + 2, k) // f_2 - ); + BoutReal common_factor = 0.25 + * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, k) + coord->J(i, j - 1, k)); + + BoutReal factor_lc = + common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); + BoutReal factor_lm = + common_factor / (coord->J(i, j - 1, k) * coord->dy(i, j - 1, k)); + BoutReal d3fdx3 = + -(-(16. / 5) * 0.5 * (f(i, j - 1, k) + f(i, j, k)) // Boundary value f_b + + 6. * f(i, j, k) // f_0 + - 4. * f(i, j + 1, k) // f_1 + + (6. / 5) * f(i, j + 2, k) // f_2 + ); result(i, j , k) -= d3fdx3 * factor_lc; result(i, j - 1, k) += d3fdx3 * factor_lm; From 36bf6943a119b0667de29ff2b90900d725017103 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 12:02:21 +0000 Subject: [PATCH 014/293] Fix smoothing for 3D metric --- src/physics/smoothing.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/physics/smoothing.cxx b/src/physics/smoothing.cxx index 4a3bc507b4..9843ee4919 100644 --- a/src/physics/smoothing.cxx +++ b/src/physics/smoothing.cxx @@ -37,8 +37,9 @@ #include #include -#include #include +#include +#include // Smooth using simple 1-2-1 filter const Field3D smooth_x(const Field3D &f) { @@ -324,12 +325,17 @@ BoutReal Average_XY(const Field2D &var) { return Vol_Glb; } +BoutReal Average_XY(const Field3D& var) { + AUTO_TRACE(); + throw BoutException("Average_XY(Field3D) not yet implemented."); +} + BoutReal Vol_Integral(const Field2D &var) { Mesh *mesh = var.getMesh(); BoutReal Int_Glb; Coordinates *metric = var.getCoordinates(); - Field2D result = metric->J * var * metric->dx * metric->dy; + auto result = metric->J * var * metric->dx * metric->dy; Int_Glb = Average_XY(result); Int_Glb *= static_cast((mesh->GlobalNx-2*mesh->xstart)*mesh->GlobalNy)*PI * 2.; From 6769580ef73fa9d5eefebe5967bcb98b8f921209 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 12:18:38 +0000 Subject: [PATCH 015/293] Fix derivs for 3D metric --- include/derivs.hxx | 203 ++++++++++++++++++++++++++++----------------- src/sys/derivs.cxx | 117 ++++++++++++++------------ 2 files changed, 193 insertions(+), 127 deletions(-) diff --git a/include/derivs.hxx b/include/derivs.hxx index c167385a19..52468227a5 100644 --- a/include/derivs.hxx +++ b/include/derivs.hxx @@ -69,10 +69,11 @@ inline const Field3D DDX(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D DDX(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type +DDX(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY) { return DDX(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -107,10 +108,11 @@ inline const Field3D DDY(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D DDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type +DDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY) { return DDY(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -145,10 +147,11 @@ inline const Field3D DDZ(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D DDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type +DDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY) { return DDZ(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -223,10 +226,13 @@ inline const Field3D D2DX2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D2DX2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D2DX2(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D2DX2(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -261,10 +267,13 @@ inline const Field3D D2DY2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D2DY2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D2DY2(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D2DY2(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -299,10 +308,13 @@ inline const Field3D D2DZ2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D2DZ2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D2DZ2(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D2DZ2(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -339,10 +351,13 @@ inline const Field3D D4DX4(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D4DX4(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D4DX4(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D4DX4(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -377,10 +392,13 @@ inline const Field3D D4DY4(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D4DY4(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D4DY4(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D4DY4(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -415,10 +433,13 @@ inline const Field3D D4DZ4(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D4DZ4(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D4DZ4(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D4DZ4(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -455,10 +476,13 @@ inline const Field3D VDDX(const Field3D& v, const Field3D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return VDDX(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -495,10 +519,13 @@ inline const Field3D VDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return VDDY(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -535,10 +562,13 @@ inline const Field3D VDDZ(const Field3D& v, const Field3D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return VDDZ(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -555,10 +585,13 @@ inline const Field2D VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return VDDZ(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -595,10 +628,13 @@ inline const Field3D FDDX(const Field3D& v, const Field3D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return FDDX(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -635,10 +671,13 @@ inline const Field3D FDDY(const Field3D& v, const Field3D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return FDDY(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -675,10 +714,13 @@ inline const Field3D FDDZ(const Field3D& v, const Field3D& f, CELL_LOC outloc, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method, REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return FDDZ(v, f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -713,10 +755,13 @@ inline const Field3D D2DXDY(const Field3D& f, CELL_LOC outloc, DIFF_METHOD metho /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D2DXDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D2DXDY(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D2DXDY(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D2DXDY(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -751,10 +796,13 @@ inline const Field3D D2DXDZ(const Field3D& f, CELL_LOC outloc, DIFF_METHOD metho /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D2DXDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D2DXDZ(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D2DXDZ(f, outloc, DIFF_METHOD_STRING(method), region); }; @@ -789,10 +837,13 @@ inline const Field3D D2DYDZ(const Field3D& f, CELL_LOC outloc, DIFF_METHOD metho /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -const Field2D D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", REGION region = RGN_NOBNDRY); -inline const Field2D D2DYDZ(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, - REGION region = RGN_NOBNDRY) { +const Coordinates::metric_field_type D2DYDZ(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + REGION region = RGN_NOBNDRY); +inline const Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method, + REGION region = RGN_NOBNDRY) { return D2DYDZ(f, outloc, DIFF_METHOD_STRING(method), region); }; diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index c7ae870da7..dbfbd384af 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -73,7 +73,8 @@ const Field3D DDX(const Field3D &f, CELL_LOC outloc, const std::string &method, return result; } -const Field2D DDX(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type DDX(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } @@ -84,7 +85,8 @@ const Field3D DDY(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dy; } -const Field2D DDY(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { return f.getCoordinates(outloc)->DDY(f, outloc, method, region); } @@ -95,11 +97,9 @@ const Field3D DDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dz; } -const Field2D DDZ(const Field2D &f, CELL_LOC UNUSED(outloc), const std::string &UNUSED(method), - REGION UNUSED(region)) { - auto tmp = Field2D(0., f.getMesh()); - tmp.setLocation(f.getLocation()); - return tmp; +const Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + return f.getCoordinates(outloc)->DDZ(f, outloc, method, region); } const Vector3D DDZ(const Vector3D &v, CELL_LOC outloc, const std::string &method, REGION region) { @@ -170,10 +170,11 @@ const Field3D D2DX2(const Field3D &f, CELL_LOC outloc, const std::string &method return result; } -const Field2D D2DX2(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { Coordinates *coords = f.getCoordinates(outloc); - Field2D result = + auto result = bout::derivatives::index::D2DX2(f, outloc, method, region) / SQ(coords->dx); if(coords->non_uniform) { @@ -205,10 +206,11 @@ const Field3D D2DY2(const Field3D &f, CELL_LOC outloc, const std::string &method return result; } -const Field2D D2DY2(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { Coordinates *coords = f.getCoordinates(outloc); - Field2D result = + auto result = bout::derivatives::index::D2DY2(f, outloc, method, region) / SQ(coords->dy); if(coords->non_uniform) { // Correction for non-uniform f.getMesh() @@ -226,11 +228,10 @@ const Field3D D2DZ2(const Field3D &f, CELL_LOC outloc, const std::string &method / SQ(f.getCoordinates(outloc)->dz); } -const Field2D D2DZ2(const Field2D &f, CELL_LOC UNUSED(outloc), const std::string &UNUSED(method), - REGION UNUSED(region)) { - auto tmp = Field2D(0., f.getMesh()); - tmp.setLocation(f.getLocation()); - return tmp; +const Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + return bout::derivatives::index::D2DZ2(f, outloc, method, region) + / SQ(f.getCoordinates(outloc)->dz); } /******************************************************************************* @@ -242,7 +243,8 @@ const Field3D D4DX4(const Field3D &f, CELL_LOC outloc, const std::string &method / SQ(SQ(f.getCoordinates(outloc)->dx)); } -const Field2D D4DX4(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { return bout::derivatives::index::D4DX4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dx)); } @@ -252,7 +254,8 @@ const Field3D D4DY4(const Field3D &f, CELL_LOC outloc, const std::string &method / SQ(SQ(f.getCoordinates(outloc)->dy)); } -const Field2D D4DY4(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { return bout::derivatives::index::D4DY4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dy)); } @@ -262,7 +265,8 @@ const Field3D D4DZ4(const Field3D &f, CELL_LOC outloc, const std::string &method / SQ(SQ(f.getCoordinates(outloc)->dz)); } -const Field2D D4DZ4(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { return bout::derivatives::index::D4DZ4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dz)); } @@ -278,8 +282,9 @@ const Field2D D4DZ4(const Field2D &f, CELL_LOC outloc, const std::string &method * * ** Applies Neumann boundary in Y, communicates */ -const Field2D D2DXDY(const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { - Field2D dfdy = DDY(f, outloc, method, RGN_NOY); +const Coordinates::metric_field_type D2DXDY(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + auto dfdy = DDY(f, outloc, method, RGN_NOY); f.getMesh()->communicate(dfdy); return DDX(dfdy, outloc, method, region); } @@ -297,11 +302,10 @@ const Field3D D2DXDY(const Field3D &f, CELL_LOC outloc, const std::string &metho return DDX(dfdy, outloc, method, region); } -const Field2D D2DXDZ(const Field2D &f, CELL_LOC UNUSED(outloc), - const std::string &UNUSED(method), REGION UNUSED(region)) { - auto tmp = Field2D(0., f.getMesh()); - tmp.setLocation(f.getLocation()); - return tmp; +const Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + Field3D tmp{f}; + return D2DXDZ(tmp, outloc, method, region); } /// X-Z mixed derivative @@ -328,14 +332,14 @@ const Field3D D2DXDZ(const Field3D &f, CELL_LOC outloc, const std::string &metho return DDX(DDZ(f, outloc,method, region_inner),outloc,method,region);; } -const Field2D D2DYDZ(const Field2D &f, CELL_LOC UNUSED(outloc), - const std::string &UNUSED(method), REGION UNUSED(region)) { - auto tmp = Field2D(0., f.getMesh()); - tmp.setLocation(f.getLocation()); - return tmp; +const Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc, + const std::string& method, REGION region) { + Field3D tmp{f}; + return D2DYDZ(tmp, outloc, method, region); } const Field3D D2DYDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, REGION UNUSED(region)) { +#ifndef COORDINATES_USE_3D Coordinates *coords = f.getCoordinates(outloc); Field3D result(f.getMesh()); @@ -360,6 +364,9 @@ const Field3D D2DYDZ(const Field3D &f, CELL_LOC outloc, const std::string &metho // / (coords->dy[i.ym()])) // / coords->dz; } return result; +#else + throw BoutException("D2DYDZ not yet implemented for 3D metrics."); +#endif } /******************************************************************************* @@ -371,7 +378,9 @@ const Field3D D2DYDZ(const Field3D &f, CELL_LOC outloc, const std::string &metho ////////////// X DERIVATIVE ///////////////// /// Special case where both arguments are 2D. Output location ignored for now -const Field2D VDDX(const Field2D &v, const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { return bout::derivatives::index::VDDX(v, f, outloc, method, region) / f.getCoordinates(outloc)->dx; } @@ -385,7 +394,9 @@ const Field3D VDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const st ////////////// Y DERIVATIVE ///////////////// // special case where both are 2D -const Field2D VDDY(const Field2D &v, const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { return bout::derivatives::index::VDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; } @@ -399,21 +410,21 @@ const Field3D VDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const st ////////////// Z DERIVATIVE ///////////////// // special case where both are 2D -const Field2D VDDZ(const Field2D &v, const Field2D &UNUSED(f), CELL_LOC UNUSED(outloc), - const std::string &UNUSED(method), REGION UNUSED(region)) { - // Should we take location from v or f? - auto tmp = Field2D(0., v.getMesh()); - tmp.setLocation(v.getLocation()); - return tmp; +const Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { + return bout::derivatives::index::VDDZ(v, f, outloc, method, region) + / f.getCoordinates(outloc)->dz; } // Note that this is zero because no compression is included -const Field2D VDDZ(const Field3D &v, const Field2D &UNUSED(f), CELL_LOC UNUSED(outloc), - const std::string &UNUSED(method), REGION UNUSED(region)) { +const Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { // Should we take location from v or f? - auto tmp = Field2D(0., v.getMesh()); - tmp.setLocation(v.getLocation()); - return tmp; + Field3D tmp{f}; + return bout::derivatives::index::VDDZ(v, tmp, outloc, method, region) + / f.getCoordinates(outloc)->dz; } // general case @@ -425,7 +436,9 @@ const Field3D VDDZ(const Field3D &v, const Field3D &f, CELL_LOC outloc, const st /******************************************************************************* * Flux conserving schemes *******************************************************************************/ -const Field2D FDDX(const Field2D &v, const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { return bout::derivatives::index::FDDX(v, f, outloc, method, region) / f.getCoordinates(outloc)->dx; } @@ -437,7 +450,9 @@ const Field3D FDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const st ///////////////////////////////////////////////////////////////////////// -const Field2D FDDY(const Field2D &v, const Field2D &f, CELL_LOC outloc, const std::string &method, REGION region) { +const Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { return bout::derivatives::index::FDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; } @@ -449,12 +464,12 @@ const Field3D FDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const st ///////////////////////////////////////////////////////////////////////// -const Field2D FDDZ(const Field2D &v, const Field2D &UNUSED(f), CELL_LOC UNUSED(outloc), - const std::string &UNUSED(method), REGION UNUSED(region)) { +const Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method, + REGION region) { // Should we take location from v or f? - auto tmp = Field2D(0., v.getMesh()); - tmp.setLocation(v.getLocation()); - return tmp; + return bout::derivatives::index::FDDZ(v, f, outloc, method, region) + / f.getCoordinates(outloc)->dz; } const Field3D FDDZ(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method, REGION region) { From a5645af33a06f95b43fb0b3b804c0e815eb447e2 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 12:26:56 +0000 Subject: [PATCH 016/293] Fix to still work for 2D metrics --- src/mesh/boundary_standard.cxx | 2 +- src/sys/derivs.cxx | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 0d2367170b..e8b3bb4fd0 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1929,7 +1929,7 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { for(int zk=0;zkLocalNz;zk++) { BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) - + bndry->by * metric->dy(bndry->x, bndry->y, kz); + + bndry->by * metric->dy(bndry->x, bndry->y, zk); if(fg){ val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*zk/(mesh->LocalNz),t); diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index dbfbd384af..59dec07f96 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -304,8 +304,14 @@ const Field3D D2DXDY(const Field3D &f, CELL_LOC outloc, const std::string &metho const Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc, const std::string& method, REGION region) { +#ifdef COORDINATES_USE_3D Field3D tmp{f}; return D2DXDZ(tmp, outloc, method, region); +#else + Field2D tmp{0., f.getMesh()}; + tmp.setLocation(f.getLocation()); + return tmp; +#endif } /// X-Z mixed derivative @@ -334,8 +340,14 @@ const Field3D D2DXDZ(const Field3D &f, CELL_LOC outloc, const std::string &metho const Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc, const std::string& method, REGION region) { +#ifdef COORDINATES_USE_3D Field3D tmp{f}; return D2DYDZ(tmp, outloc, method, region); +#else + Field2D tmp{0, f.getMesh()}; + tmp.setLocation(f.getLocation()); + return tmp; +#endif } const Field3D D2DYDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, REGION UNUSED(region)) { @@ -422,9 +434,15 @@ const Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, REGION region) { // Should we take location from v or f? +#ifdef COORDINATES_USE_3D Field3D tmp{f}; return bout::derivatives::index::VDDZ(v, tmp, outloc, method, region) / f.getCoordinates(outloc)->dz; +#else + Field2D tmp{0., f.getMesh()}; + tmp.setLocation(f.getLocation()); + return tmp; +#endif } // general case From 1a5b670de711e433d2fde77fa014da831ea28bba Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 15:22:33 +0000 Subject: [PATCH 017/293] Fix location of `#endif` in boundary_standard --- src/mesh/boundary_standard.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index e8b3bb4fd0..4b650a50d2 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1754,6 +1754,10 @@ void BoundaryNeumann::apply(Field2D &f,BoutReal t) { } } } +#else + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif } @@ -1966,10 +1970,6 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { } } } -#else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); -#endif } void BoundaryNeumann::apply_ddt(Field2D &f) { From 9f5429ba23ef5e868352f5e50a580ada0f96aeec Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 15:22:46 +0000 Subject: [PATCH 018/293] Temporarily disable Vector2D unit tests when using 3D metric --- tests/unit/field/test_vector2d.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/field/test_vector2d.cxx b/tests/unit/field/test_vector2d.cxx index 5681bc6c12..ba13cd468c 100644 --- a/tests/unit/field/test_vector2d.cxx +++ b/tests/unit/field/test_vector2d.cxx @@ -1,3 +1,4 @@ +#ifndef COORDINATES_USE_3D #include "gtest/gtest.h" #include "bout/constants.hxx" @@ -498,3 +499,4 @@ TEST_F(Vector2DTest, DivideVector2DField3D) { EXPECT_TRUE(IsField3DEqualBoutReal(result.y, 2.0)); EXPECT_TRUE(IsField3DEqualBoutReal(result.z, 3.0)); } +#endif From 12d644ec415a3daca0b512dc608ecb3f63400f93 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 15:28:28 +0000 Subject: [PATCH 019/293] Tweaks to allow tests to compile with 3D metrics --- tests/MMS/wave-1d/wave.cxx | 4 ++-- .../test_multigrid_laplace.cxx | 14 ++++++++------ .../test-naulin-laplace/test_naulin_laplace.cxx | 14 ++++++++------ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/MMS/wave-1d/wave.cxx b/tests/MMS/wave-1d/wave.cxx index d2543a98b1..75ff82a518 100644 --- a/tests/MMS/wave-1d/wave.cxx +++ b/tests/MMS/wave-1d/wave.cxx @@ -31,8 +31,8 @@ const Field3D HLL(const Field3D &f, const Field3D &u, BoutReal SL, BoutReal SR) BoutReal fp = (SR*f(i,j,k) - SL*f(i+1,j,k) + SL*SR*(u(i+1,j,k) - u(i,j,k)) ) / (SR - SL); BoutReal fm = (SR*f(i-1,j,k) - SL*f(i,j,k) + SL*SR*(u(i,j,k) - u(i-1,j,k)) ) / (SR - SL); - - result(i,j,k) = (fm - fp) / coord->dx(i,j); + + result(i, j, k) = (fm - fp) / coord->dx(i, j, k); } return result; } diff --git a/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx b/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx index 748a85ae7e..0f977540ae 100644 --- a/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx +++ b/tests/integrated/test-multigrid_laplace/test_multigrid_laplace.cxx @@ -226,14 +226,16 @@ int main(int argc, char** argv) { x0 = 0.; 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->getCoordinates()->dx(mesh->xstart,mesh->ystart) - /sqrt(mesh->getCoordinates()->g_11(mesh->xstart,mesh->ystart)); + x0(mesh->xstart - 1, mesh->ystart, k) = + (f4(mesh->xstart, mesh->ystart, k) - f4(mesh->xstart - 1, mesh->ystart, k)) + / mesh->getCoordinates()->dx(mesh->xstart, mesh->ystart, k) + / sqrt(mesh->getCoordinates()->g_11(mesh->xstart, mesh->ystart, k)); 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->getCoordinates()->dx(mesh->xend,mesh->ystart) - /sqrt(mesh->getCoordinates()->g_11(mesh->xend,mesh->ystart)); + x0(mesh->xend + 1, mesh->ystart, k) = + (f4(mesh->xend + 1, mesh->ystart, k) - f4(mesh->xend, mesh->ystart, k)) + / mesh->getCoordinates()->dx(mesh->xend, mesh->ystart, k) + / sqrt(mesh->getCoordinates()->g_11(mesh->xend, mesh->ystart, k)); try { sol4 = invert->solve(sliceXZ(b4, mesh->ystart), sliceXZ(x0, mesh->ystart)); diff --git a/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx b/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx index b2873903ac..abaa146130 100644 --- a/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx +++ b/tests/integrated/test-naulin-laplace/test_naulin_laplace.cxx @@ -233,14 +233,16 @@ int main(int argc, char** argv) { x0 = 0.; 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->getCoordinates()->dx(mesh->xstart,mesh->ystart) - /sqrt(mesh->getCoordinates()->g_11(mesh->xstart,mesh->ystart)); + x0(mesh->xstart - 1, mesh->ystart, k) = + (f4(mesh->xstart, mesh->ystart, k) - f4(mesh->xstart - 1, mesh->ystart, k)) + / mesh->getCoordinates()->dx(mesh->xstart, mesh->ystart, k) + / sqrt(mesh->getCoordinates()->g_11(mesh->xstart, mesh->ystart, k)); 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->getCoordinates()->dx(mesh->xend,mesh->ystart) - /sqrt(mesh->getCoordinates()->g_11(mesh->xend,mesh->ystart)); + x0(mesh->xend + 1, mesh->ystart, k) = + (f4(mesh->xend + 1, mesh->ystart, k) - f4(mesh->xend, mesh->ystart, k)) + / mesh->getCoordinates()->dx(mesh->xend, mesh->ystart, k) + / sqrt(mesh->getCoordinates()->g_11(mesh->xend, mesh->ystart, k)); try { sol4 = invert->solve(b4, x0); From 85ed22b3ff6497f31dc76e09189b23b14767eaef Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 15:40:34 +0000 Subject: [PATCH 020/293] Tidy up defines in coordinates --- include/bout/coordinates.hxx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index cdea9a27b1..f8394cbec5 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -38,14 +38,6 @@ class Coordinates; #include "field2d.hxx" #include "field3d.hxx" -#ifdef COORDINATES_USE_3D -#define COORDINATES_FIELD_TYPE Field3D -#define COORDINATES_VECTOR_TYPE Vector3D -#else -#define COORDINATES_FIELD_TYPE Field2D -#define COORDINATES_VECTOR_TYPE Vector2D -#endif - class Datafile; class Mesh; @@ -59,8 +51,11 @@ class Mesh; */ class Coordinates { public: - using metric_field_type = COORDINATES_FIELD_TYPE; - using metric_vector_type = COORDINATES_VECTOR_TYPE; +#ifdef COORDINATES_USE_3D + using metric_field_type = Field3D; +#else + using metric_field_type = Field2D; +#endif /// Standard constructor from input Coordinates(Mesh *mesh); From 2cc3f57863f8b90433885aed8dc52fe320d08997 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 4 Dec 2018 16:40:22 +0000 Subject: [PATCH 021/293] Adding --metric-3d option to configure --- configure | 49 ++++++++++++++++++++++++++++--------------------- configure.ac | 9 +++++++++ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/configure b/configure index 80ae74f6ac..be46887f37 100755 --- a/configure +++ b/configure @@ -815,6 +815,7 @@ enable_shared enable_openmp with_openmp_schedule enable_pvode_openmp +enable_metric_3d with_gcov enable_code_coverage with_hdf5 @@ -1479,6 +1480,7 @@ Optional Features: --enable-shared Enable building bout++ into an shared object --enable-openmp Enable building with OpenMP support --enable-pvode-openmp Enable building PVODE with OpenMP support + --metric-3D=no/yes If yes use Field3D to store coordinates metric data --disable-openmp do not use OpenMP --enable-code-coverage Whether to enable code coverage support --disable-nls do not use Native Language Support @@ -2718,6 +2720,13 @@ else enable_pvode_openmp=no fi +# Check whether --enable-metric_3d was given. +if test "${enable_metric_3d+set}" = set; then : + enableval=$enable_metric_3d; +else + metric_3d=no +fi + @@ -6081,6 +6090,19 @@ fi fi +if test "x$metric_3d" != "xno"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using Field3D to store coordinates data" >&5 +$as_echo "$as_me: Using Field3D to store coordinates data" >&6;} + CXXFLAGS="$CXXFLAGS -DCOORDINATES_USE_3D=yes" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: Using Field2D to store coordinates data" >&5 +$as_echo "$as_me: Using Field2D to store coordinates data" >&6;} + +fi + ############################################################# # Build into shared object (pic) ############################################################# @@ -13348,21 +13370,16 @@ else /* end confdefs.h. */ #include -#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +$gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; -#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_domain_bindings) -#else -#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 -#endif -$gt_revision_test_code int main () { bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings ; return 0; @@ -14115,25 +14132,20 @@ else /* end confdefs.h. */ #include -#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +$gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); -#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) -#else -#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 -#endif -$gt_revision_test_code int main () { bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; @@ -14152,25 +14164,20 @@ rm -f core conftest.err conftest.$ac_objext \ /* end confdefs.h. */ #include -#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +$gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); -#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) -#else -#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 -#endif -$gt_revision_test_code int main () { bindtextdomain ("", ""); -return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; diff --git a/configure.ac b/configure.ac index 75222ab618..ccf91617b4 100644 --- a/configure.ac +++ b/configure.ac @@ -91,6 +91,8 @@ AC_ARG_WITH(openmp_schedule,[AS_HELP_STRING([--with-openmp-schedule=static/dynam [Set OpenMP schedule (default: static)])],,[with_openmp_schedule=static]) AC_ARG_ENABLE(pvode_openmp, [AS_HELP_STRING([--enable-pvode-openmp], [Enable building PVODE with OpenMP support])],,[enable_pvode_openmp=no]) +AC_ARG_ENABLE(metric_3d, [AS_HELP_STRING([--metric-3D=no/yes], + [If yes use Field3D to store coordinates metric data])],,[metric_3d=no]) AC_ARG_VAR(EXTRA_INCS,[Extra compile flags]) AC_ARG_VAR(EXTRA_LIBS,[Extra linking flags]) @@ -360,6 +362,13 @@ AS_IF([test "x$enable_backtrace" = "xyes" || test "x$enable_backtrace" = "xmaybe ]) ]) +AS_IF([test "x$metric_3d" != "xno"], [ + AC_MSG_NOTICE([Using Field3D to store coordinates data]) + CXXFLAGS="$CXXFLAGS -DCOORDINATES_USE_3D=yes" + ], [ + AC_MSG_NOTICE([Using Field2D to store coordinates data]) +]) + ############################################################# # Build into shared object (pic) ############################################################# From 7043fb635a53b6da0c619cf10b3d2ef92a638638 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Wed, 5 Dec 2018 15:10:28 +0000 Subject: [PATCH 022/293] Change from ASSERT to throw to avoid issue with brackets --- src/invert/laplace/impls/multigrid/multigrid_laplace.cxx | 5 ++++- src/invert/laplace/impls/serial_band/serial_band.cxx | 4 +++- src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx | 5 ++++- src/invert/parderiv/impls/cyclic/cyclic.cxx | 5 ++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index 2899639476..3b2c5a05b1 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -40,7 +40,10 @@ BoutReal soltime=0.0,settime=0.0; LaplaceMultigrid::LaplaceMultigrid(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), A(0.0), C1(1.0), C2(1.0), D(1.0) { - ASSERT1((std::same::value)); +#ifdef COORDINATES_USE_3D + throw BoutException("Laplace multigrid solver does not support 3D metric yet."); +#endif + TRACE("LaplaceMultigrid::LaplaceMultigrid(Options *opt)"); A.setLocation(location); diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index 98951099fc..e12c5b076f 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -40,7 +40,9 @@ LaplaceSerialBand::LaplaceSerialBand(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), Acoef(0.0), Ccoef(1.0), Dcoef(1.0) { - ASSERT1((std::same::value)); +#ifdef COORDINATES_USE_3D + throw BoutException("Laplacian serial band solver does not support 3D metric yet."); +#endif Acoef.setLocation(location); Ccoef.setLocation(location); Dcoef.setLocation(location); diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 926769b606..b6c0e218e4 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -9,7 +9,10 @@ #include LaplaceXZcyclic::LaplaceXZcyclic(Mesh *m, Options *options, const CELL_LOC loc) : LaplaceXZ(m, options, loc), mesh(m) { - ASSERT1((std::same::value)); +#ifdef COORDINATES_USE_3D + throw BoutException("LaplaceXZ cyclic solver does not support 3D metric yet."); +#endif + // Number of Z Fourier modes, including DC nmode = (m->LocalNz) / 2 + 1; diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index efa350d980..f2b9cda48a 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -50,7 +50,10 @@ InvertParCR::InvertParCR(Options *opt, Mesh *mesh_in) : InvertPar(opt, mesh_in), A(1.0), B(0.0), C(0.0), D(0.0), E(0.0) { - ASSERT1((std::same::value)); +#ifdef COORDINATES_USE_3D + throw BoutException("Parallel cyclic solver does not support 3D metric yet."); +#endif + // Number of k equations to solve for each x location nsys = 1 + (localmesh->LocalNz)/2; } From 49b1e35bded080ed6d45f10813b26c865bd697a1 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Thu, 6 Dec 2018 12:41:39 +0000 Subject: [PATCH 023/293] Fix for 3D coordinates derivatives --- src/mesh/coordinates.cxx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 652dc590ed..59ddffd90b 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -655,7 +655,16 @@ const Coordinates::metric_field_type Coordinates::DDX(const Field2D& f, CELL_LOC } const Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, const std::string& method, REGION region) { - return ::DDX(f, outloc, method, region); + + auto result = bout::derivatives::index::DDX(f, outloc, method, region); + result /= dx; + + if (f.getMesh()->IncIntShear) { + // Using BOUT-06 style shifting + result += IntShiftTorsion * DDZ(f, outloc, method, region); + } + + return result; }; const Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, @@ -666,7 +675,7 @@ const Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC } const Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, REGION region) { - return ::DDY(f, outloc, method, region); + return bout::derivatives::index::DDY(f, outloc, method, region) / dy; }; const Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), @@ -681,7 +690,7 @@ const Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D } const Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, const std::string& method, REGION region) { - return ::DDZ(f, outloc, method, region); + return bout::derivatives::index::DDZ(f, outloc, method, region) / dz; }; ///////////////////////////////////////////////////////// From 068dc38f4d4260e5a4b43e2a8d76447c67ddd05b Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Thu, 6 Dec 2018 13:41:59 +0000 Subject: [PATCH 024/293] Disable more Laplacian code and provide better notification --- src/invert/laplace/impls/cyclic/cyclic_laplace.cxx | 4 ++++ src/invert/laplace/invert_laplace.cxx | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index ff31e5a77b..3eb4f3ea6d 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -45,6 +45,10 @@ LaplaceCyclic::LaplaceCyclic(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), Acoef(0.0), Ccoef(1.0), Dcoef(1.0) { +#ifdef COORDINATES_USE_3D + throw BoutException("Laplacian cyclic solver does not support 3D metric yet."); +#endif + Acoef.setLocation(location); Ccoef.setLocation(location); Dcoef.setLocation(location); diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index f74554011d..9a98974b04 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -731,6 +731,8 @@ void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, } } } +#else + throw BoutException("Error: tridagMatrix does not yet work with 3D metric."); #endif } From f80d902c7588b67fa3a4456de0fe7e265ef8a874 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Thu, 6 Dec 2018 20:17:16 +0000 Subject: [PATCH 025/293] Reduce code duplication in derivatives --- src/sys/derivs.cxx | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index 59dec07f96..b07979d6b6 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -58,19 +58,7 @@ ////////////// X DERIVATIVE ///////////////// const Field3D DDX(const Field3D &f, CELL_LOC outloc, const std::string &method, REGION region) { - Field3D result = bout::derivatives::index::DDX(f, outloc, method, region); - Coordinates *coords = f.getCoordinates(outloc); - result /= coords->dx; - - if(f.getMesh()->IncIntShear) { - // Using BOUT-06 style shifting - result += coords->IntShiftTorsion * DDZ(f, outloc, method, region); - } - - ASSERT2(((outloc == CELL_DEFAULT) && (result.getLocation() == f.getLocation())) || - (result.getLocation() == outloc)); - - return result; + return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } const Coordinates::metric_field_type DDX(const Field2D& f, CELL_LOC outloc, @@ -81,8 +69,7 @@ const Coordinates::metric_field_type DDX(const Field2D& f, CELL_LOC outloc, ////////////// Y DERIVATIVE ///////////////// const Field3D DDY(const Field3D &f, CELL_LOC outloc, const std::string &method, REGION region) { - return bout::derivatives::index::DDY(f, outloc, method, region) - / f.getCoordinates(outloc)->dy; + return f.getCoordinates(outloc)->DDY(f, outloc, method, region); } const Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc, @@ -93,8 +80,7 @@ const Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc, ////////////// Z DERIVATIVE ///////////////// const Field3D DDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, REGION region) { - return bout::derivatives::index::DDZ(f, outloc, method, region) - / f.getCoordinates(outloc)->dz; + return f.getCoordinates(outloc)->DDZ(f, outloc, method, region); } const Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC outloc, From 72228d419324630aa5dd3a5c53ee7a550eb3d8f6 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 09:19:47 +0000 Subject: [PATCH 026/293] Fix configure options and report metric type in summary --- configure | 16 ++++++++++------ configure.ac | 12 +++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/configure b/configure index be46887f37..d3edce0b74 100755 --- a/configure +++ b/configure @@ -1480,7 +1480,8 @@ Optional Features: --enable-shared Enable building bout++ into an shared object --enable-openmp Enable building with OpenMP support --enable-pvode-openmp Enable building PVODE with OpenMP support - --metric-3D=no/yes If yes use Field3D to store coordinates metric data + --enable-metric-3d=no/yes + If yes use Field3D to store coordinates metric data --disable-openmp do not use OpenMP --enable-code-coverage Whether to enable code coverage support --disable-nls do not use Native Language Support @@ -2724,7 +2725,7 @@ fi if test "${enable_metric_3d+set}" = set; then : enableval=$enable_metric_3d; else - metric_3d=no + enable_metric_3d=no fi @@ -6090,16 +6091,18 @@ fi fi -if test "x$metric_3d" != "xno"; then : +if test "x$enable_metric_3d" != "xno"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: Using Field3D to store coordinates data" >&5 -$as_echo "$as_me: Using Field3D to store coordinates data" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Using Field3D to store coordinates data, this is experimental." >&5 +$as_echo "$as_me: WARNING: Using Field3D to store coordinates data, this is experimental." >&2;} CXXFLAGS="$CXXFLAGS -DCOORDINATES_USE_3D=yes" + METRIC_TYPE="3D" else { $as_echo "$as_me:${as_lineno-$LINENO}: Using Field2D to store coordinates data" >&5 $as_echo "$as_me: Using Field2D to store coordinates data" >&6;} + METRIC_TYPE="2D" fi @@ -17116,7 +17119,8 @@ $as_echo "$as_me: Scorep support : $HAS_SCOREP" >&6;} $as_echo "$as_me: OpenMP support : $HAS_OPENMP (schedule: $OPENMP_SCHEDULE)" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: Natural language support: $HAS_NLS (path: $localedir)" >&5 $as_echo "$as_me: Natural language support: $HAS_NLS (path: $localedir)" >&6;} - +{ $as_echo "$as_me:${as_lineno-$LINENO}: Metric type : $METRIC_TYPE" >&5 +$as_echo "$as_me: Metric type : $METRIC_TYPE" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: " >&5 $as_echo "$as_me: " >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: -------------------------------" >&5 diff --git a/configure.ac b/configure.ac index ccf91617b4..e274aceb8c 100644 --- a/configure.ac +++ b/configure.ac @@ -91,8 +91,8 @@ AC_ARG_WITH(openmp_schedule,[AS_HELP_STRING([--with-openmp-schedule=static/dynam [Set OpenMP schedule (default: static)])],,[with_openmp_schedule=static]) AC_ARG_ENABLE(pvode_openmp, [AS_HELP_STRING([--enable-pvode-openmp], [Enable building PVODE with OpenMP support])],,[enable_pvode_openmp=no]) -AC_ARG_ENABLE(metric_3d, [AS_HELP_STRING([--metric-3D=no/yes], - [If yes use Field3D to store coordinates metric data])],,[metric_3d=no]) +AC_ARG_ENABLE(metric_3d, [AS_HELP_STRING([--enable-metric-3d=no/yes], + [If yes use Field3D to store coordinates metric data])],,[enable_metric_3d=no]) AC_ARG_VAR(EXTRA_INCS,[Extra compile flags]) AC_ARG_VAR(EXTRA_LIBS,[Extra linking flags]) @@ -362,11 +362,13 @@ AS_IF([test "x$enable_backtrace" = "xyes" || test "x$enable_backtrace" = "xmaybe ]) ]) -AS_IF([test "x$metric_3d" != "xno"], [ - AC_MSG_NOTICE([Using Field3D to store coordinates data]) +AS_IF([test "x$enable_metric_3d" != "xno"], [ + AC_MSG_WARN([Using Field3D to store coordinates data, this is experimental.]) CXXFLAGS="$CXXFLAGS -DCOORDINATES_USE_3D=yes" + METRIC_TYPE="3D" ], [ AC_MSG_NOTICE([Using Field2D to store coordinates data]) + METRIC_TYPE="2D" ]) ############################################################# @@ -1309,7 +1311,7 @@ AC_MSG_NOTICE([ Lapack support : $HAS_LAPACK]) AC_MSG_NOTICE([ Scorep support : $HAS_SCOREP]) AC_MSG_NOTICE([ OpenMP support : $HAS_OPENMP (schedule: $OPENMP_SCHEDULE)]) AC_MSG_NOTICE([ Natural language support: $HAS_NLS (path: $localedir)]) - +AC_MSG_NOTICE([ Metric type : $METRIC_TYPE]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([-------------------------------]) AC_MSG_NOTICE([ Data analysis configuration ]) From abdddb3b7ad9f72f037d75627df353daa1f935b9 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 09:35:08 +0000 Subject: [PATCH 027/293] Fix test-griddata for 3D metric --- tests/integrated/test-griddata/runtest | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/integrated/test-griddata/runtest b/tests/integrated/test-griddata/runtest index 8a6a667a90..ae12812e3b 100755 --- a/tests/integrated/test-griddata/runtest +++ b/tests/integrated/test-griddata/runtest @@ -31,14 +31,18 @@ for nproc in [1]: Rxy = collect("Rxy", prefix=prefix, info=False) Bpxy = collect("Bpxy", prefix=prefix, info=False) dx = collect("dx", prefix=prefix, info=False) - + nx,ny = Rxy.shape + #Handle 3D metric case + if len(dx.shape) == 3: + dx = dx[:,:,0] + rwidth = 0.4 dr = float(rwidth) / nx # Test value of dx - if np.min(np.abs(dx - dr * Bpxy * Rxy)) > 1e-7: + if not np.allclose(dx, dr*Bpxy*Rxy, atol = 1e-7): print("Failed: dx does not match") exit(1) From ceb9312944ee7ed232ddae523f39f93fcf89d1b5 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 09:42:44 +0000 Subject: [PATCH 028/293] Fix dumping of Vector2D for 3D metrics --- src/fileio/datafile.cxx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/fileio/datafile.cxx b/src/fileio/datafile.cxx index 4536967c2c..1f1020eb90 100644 --- a/src/fileio/datafile.cxx +++ b/src/fileio/datafile.cxx @@ -657,6 +657,18 @@ void Datafile::add(Vector2D &f, const char *name, bool save_repeat) { if(floats) file->setLowPrecision(); +#ifdef COORDINATES_USE_3D + // Add variables to file + if (!file->addVarField3D(d.name + "_x", save_repeat)) { + throw BoutException("Failed to add Vector2D variable %s to Datafile", name); + } + if (!file->addVarField3D(d.name + "_y", save_repeat)) { + throw BoutException("Failed to add Vector2D variable %s to Datafile", name); + } + if (!file->addVarField3D(d.name + "_z", save_repeat)) { + throw BoutException("Failed to add Vector2D variable %s to Datafile", name); + } +#else // Add variables to file if (!file->addVarField2D(d.name + "_x", save_repeat)) { throw BoutException("Failed to add Vector2D variable %s to Datafile", name); @@ -667,6 +679,7 @@ void Datafile::add(Vector2D &f, const char *name, bool save_repeat) { if (!file->addVarField2D(d.name + "_z", save_repeat)) { throw BoutException("Failed to add Vector2D variable %s to Datafile", name); } +#endif if(openclose) { file->close(); From 28338117d7a219932f90a9a6036cc16468673db9 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 09:47:03 +0000 Subject: [PATCH 029/293] Fix test-io for 3D metric --- tests/integrated/test-io/runtest | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index 091de2e570..91864ef442 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -54,13 +54,19 @@ for nproc in [1,2,4]: for v in vars: stdout.write(" Checking variable "+v+" ... ") result = collect(v, path="data", info=False) - + # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - print("Fail, wrong shape") - success = False - continue - + if np.shape(bmk[v]) != np.shape(result): + if not ( + (v.startswith("v2d_")) and + np.shape(bmk[v]) == np.shape(result[:,:,:,0]) ): + + print("Fail, wrong shape") + success = False + continue + else: + result = result[:,:,:,0] + diff = np.max(np.abs(bmk[v] - result)) if diff > tol: print("Fail, maximum difference = "+str(diff)) From 84b4d07fcd3a7147c09fc6618a016e6abeb58655 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 10:28:16 +0000 Subject: [PATCH 030/293] Add metric-type to bout-config Add metric_3d test to requirements --- bin/bout-config.in | 8 ++++++++ configure | 4 +++- configure.ac | 1 + tests/requirements/metric_3d | 16 ++++++++++++++++ tests/requirements/requirements.py | 2 +- 5 files changed, 29 insertions(+), 2 deletions(-) create mode 100755 tests/requirements/metric_3d diff --git a/bin/bout-config.in b/bin/bout-config.in index 0cc85012ce..727ab56d17 100755 --- a/bin/bout-config.in +++ b/bin/bout-config.in @@ -43,6 +43,8 @@ has_nls="@HAS_NLS@" petsc_has_sundials="@PETSC_HAS_SUNDIALS@" +metric_type="@METRIC_TYPE@" + usage() { cat < $petsc_has_sundials" echo + echo " --metric-type -> $metric_type" } if test $# -eq 0; then @@ -238,6 +243,9 @@ while test $# -gt 0; do echo $has_nls ;; + --metric-type) + echo $metric_type + ;; --petsc-version) # TODO: Remove in next release diff --git a/configure b/configure index d3edce0b74..68fc341089 100755 --- a/configure +++ b/configure @@ -622,7 +622,8 @@ ac_includes_default="\ #endif" gt_needs= -ac_subst_vars='HAS_NLS +ac_subst_vars='METRIC_TYPE +HAS_NLS HAS_OPENMP SLEPC_ARCH SLEPC_DIR @@ -15765,6 +15766,7 @@ BOUT_INCLUDE_PATH=$PWD/include + ac_config_files="$ac_config_files bin/bout-config" diff --git a/configure.ac b/configure.ac index e274aceb8c..1cfa776167 100644 --- a/configure.ac +++ b/configure.ac @@ -1285,6 +1285,7 @@ AC_SUBST(SLEPC_DIR) AC_SUBST(SLEPC_ARCH) AC_SUBST(HAS_OPENMP) AC_SUBST(HAS_NLS) +AC_SUBST(METRIC_TYPE) AC_CONFIG_FILES([bin/bout-config]) AC_OUTPUT diff --git a/tests/requirements/metric_3d b/tests/requirements/metric_3d new file mode 100755 index 0000000000..38c2146d3b --- /dev/null +++ b/tests/requirements/metric_3d @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +# Tests if build has 3D metric + +import os +from sys import exit +from boututils.run_wrapper import shell + +selflocation = os.path.realpath(__file__) +selflocation = selflocation.rsplit("/", 1)[0] +status, out = shell(selflocation+"/../../bin/bout-config --metric-type", pipe=True) + +if "3D" in out: + exit(0) # True + +exit(1) # False diff --git a/tests/requirements/requirements.py b/tests/requirements/requirements.py index 1139f0877d..5189f9f678 100755 --- a/tests/requirements/requirements.py +++ b/tests/requirements/requirements.py @@ -37,7 +37,7 @@ def __init__(self, path=None, verbose=False): requirements_list = [x for x in os.listdir(path) if not (("#" in x) or ("~" in x) or (x[0] == ".") or (".py" in x))] - + if verbose: print("======= Requirement checks ========") From 86c4fd08958528ea78611abe51153124d102edbd Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 10:39:41 +0000 Subject: [PATCH 031/293] Disable Delp2(Field3D) when using 3D metrics --- src/mesh/coordinates.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 59ddffd90b..82fc88671b 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -831,6 +831,7 @@ const Coordinates::metric_field_type Coordinates::Delp2(const Field2D& f, const Field3D Coordinates::Delp2(const Field3D &f, CELL_LOC outloc) { TRACE("Coordinates::Delp2( Field3D )"); +#ifndef COORDINATES_USE_3D if (outloc == CELL_DEFAULT) { outloc = f.getLocation(); } @@ -896,6 +897,10 @@ const Field3D Coordinates::Delp2(const Field3D &f, CELL_LOC outloc) { ASSERT2(result.getLocation() == f.getLocation()); return result; +#else + throw BoutException("Delp2(Field3D) currently relies on the tridiagonal code that is " + "not supported with 3D metrics."); +#endif } const FieldPerp Coordinates::Delp2(const FieldPerp &f, CELL_LOC outloc) { From 896ea798bb04392411503f19145dc61b1123f5a1 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 10:39:59 +0000 Subject: [PATCH 032/293] Disable integrated tests known to not work with 3D metrics yet --- tests/integrated/test-delp2/runtest | 2 ++ tests/integrated/test-drift-instability-staggered/runtest | 2 +- tests/integrated/test-gyro/runtest | 2 ++ tests/integrated/test-interchange-instability/runtest | 3 +++ tests/integrated/test-invpar/runtest | 2 ++ tests/integrated/test-laplace/runtest | 2 ++ tests/integrated/test-multigrid_laplace/runtest | 2 ++ tests/integrated/test-naulin-laplace/runtest | 2 ++ 8 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/integrated/test-delp2/runtest b/tests/integrated/test-delp2/runtest index 1df61b0651..ff806a77bf 100755 --- a/tests/integrated/test-delp2/runtest +++ b/tests/integrated/test-delp2/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + from __future__ import print_function try: from builtins import str diff --git a/tests/integrated/test-drift-instability-staggered/runtest b/tests/integrated/test-drift-instability-staggered/runtest index 399f624850..52b7dc0645 100755 --- a/tests/integrated/test-drift-instability-staggered/runtest +++ b/tests/integrated/test-drift-instability-staggered/runtest @@ -1,3 +1,3 @@ #!/bin/sh - +#requires: not metric_3d ./runtest.py staggered diff --git a/tests/integrated/test-gyro/runtest b/tests/integrated/test-gyro/runtest index 516467759c..857b106933 100755 --- a/tests/integrated/test-gyro/runtest +++ b/tests/integrated/test-gyro/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # # Run the test, compare results against the benchmark # diff --git a/tests/integrated/test-interchange-instability/runtest b/tests/integrated/test-interchange-instability/runtest index 4a7242d52d..4343bf0677 100755 --- a/tests/integrated/test-interchange-instability/runtest +++ b/tests/integrated/test-interchange-instability/runtest @@ -1,9 +1,12 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # # Run the test, compare results against the benchmark # + from __future__ import print_function from __future__ import division nproc = 2 # Number of processors to run on diff --git a/tests/integrated/test-invpar/runtest b/tests/integrated/test-invpar/runtest index 3c1d24be74..ca0c4f1b6e 100755 --- a/tests/integrated/test-invpar/runtest +++ b/tests/integrated/test-invpar/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # # Run the test, check it completed successfully # diff --git a/tests/integrated/test-laplace/runtest b/tests/integrated/test-laplace/runtest index 81af3da736..7ba3ae92d7 100755 --- a/tests/integrated/test-laplace/runtest +++ b/tests/integrated/test-laplace/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # # Run the test, compare results against the benchmark # diff --git a/tests/integrated/test-multigrid_laplace/runtest b/tests/integrated/test-multigrid_laplace/runtest index c9eb8c7522..a85e9d19e2 100755 --- a/tests/integrated/test-multigrid_laplace/runtest +++ b/tests/integrated/test-multigrid_laplace/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # # Run the test, check the error # diff --git a/tests/integrated/test-naulin-laplace/runtest b/tests/integrated/test-naulin-laplace/runtest index b318fb5ded..ca3cbf4da8 100755 --- a/tests/integrated/test-naulin-laplace/runtest +++ b/tests/integrated/test-naulin-laplace/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # # Run the test, check the error # From 985a5cc4e9533742109ae98901b0c2477cb17e2e Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 10:42:26 +0000 Subject: [PATCH 033/293] Disable MMS tests known to not work with 3D metrics --- tests/MMS/wave-1d-y/runtest | 2 ++ tests/MMS/wave-1d/runtest | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/MMS/wave-1d-y/runtest b/tests/MMS/wave-1d-y/runtest index 168cea6807..7f5c70b0bd 100755 --- a/tests/MMS/wave-1d-y/runtest +++ b/tests/MMS/wave-1d-y/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # Python script to run and analyse MMS test from __future__ import division diff --git a/tests/MMS/wave-1d/runtest b/tests/MMS/wave-1d/runtest index f400d919c2..e41c5372ea 100755 --- a/tests/MMS/wave-1d/runtest +++ b/tests/MMS/wave-1d/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: not metric_3d + # Python script to run and analyse MMS test from __future__ import division From 591aaa54a259dc3406bd801dea8e45ef482652b8 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 10:49:23 +0000 Subject: [PATCH 034/293] Ensure Mesh::get routines have consistent interface In particular add communicate flag to Field2D and both Vector variants. Further add default flag to Vector routines --- include/bout/mesh.hxx | 18 +++++++++++++----- src/mesh/mesh.cxx | 34 ++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index c8c5d0a7d9..9271a77ed0 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -146,9 +146,11 @@ class Mesh { /// @param[out] var This will be set to the value. Will be allocated if needed /// @param[in] name Name of the variable to read /// @param[in] def The default value if not found + /// @param[in] communicate Should the field be communicated to fill guard cells? /// /// @returns zero if successful, non-zero on failure - int get(Field2D &var, const std::string &name, BoutReal def=0.0); + int get(Field2D& var, const std::string& name, BoutReal def = 0.0, + bool communicate = true); /// Get a Field3D from the input source /// @@ -169,9 +171,12 @@ class Mesh { /// /// @param[in] var This will be set to the value read /// @param[in] name The name of the vector. Individual fields are read based on this name by appending. See above + /// @param[in] def The default value if not found + /// @param[in] communicate Should the field be communicated to fill guard cells? /// - /// @returns zero always. - int get(Vector2D &var, const std::string &name); + /// @returns zero always. + int get(Vector2D& var, const std::string& name, BoutReal def = 0.0, + bool communicate = true); /// Get a Vector3D from the input source. /// If \p var is covariant then this gets three @@ -182,9 +187,12 @@ class Mesh { /// /// @param[in] var This will be set to the value read /// @param[in] name The name of the vector. Individual fields are read based on this name by appending. See above + /// @param[in] def The default value if not found + /// @param[in] communicate Should the field be communicated to fill guard cells? /// - /// @returns zero always. - int get(Vector3D &var, const std::string &name); + /// @returns zero always. + int get(Vector3D& var, const std::string& name, BoutReal def = 0.0, + bool communicate = true); /// Wrapper for GridDataSource::hasVar bool sourceHasVar(const std::string &name); diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index 73bca69767..48b2284745 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -68,7 +68,7 @@ int Mesh::get(BoutReal &rval, const std::string &name) { return 0; } -int Mesh::get(Field2D &var, const std::string &name, BoutReal def) { +int Mesh::get(Field2D& var, const std::string& name, BoutReal def, bool communicate) { TRACE("Loading 2D field: Mesh::get(Field2D, %s)", name.c_str()); // Ensure data allocated @@ -78,7 +78,9 @@ int Mesh::get(Field2D &var, const std::string &name, BoutReal def) { return 1; // Communicate to get guard cell data - Mesh::communicate(var); + if (communicate) { + Mesh::communicate(var); + } // Check that the data is valid checkData(var); @@ -110,43 +112,43 @@ int Mesh::get(Field3D &var, const std::string &name, BoutReal def, bool communic * Data get routines **************************************************************************/ -int Mesh::get(Vector2D &var, const std::string &name) { +int Mesh::get(Vector2D& var, const std::string& name, BoutReal def, bool communicate) { TRACE("Loading 2D vector: Mesh::get(Vector2D, %s)", name.c_str()); if(var.covariant) { output << _("\tReading covariant vector ") << name << endl; - get(var.x, name+"_x"); - get(var.y, name+"_y"); - get(var.z, name+"_z"); + get(var.x, name + "_x", def, communicate); + get(var.y, name + "_y", def, communicate); + get(var.z, name + "_z", def, communicate); }else { output << _("\tReading contravariant vector ") << name << endl; - get(var.x, name+"x"); - get(var.y, name+"y"); - get(var.z, name+"z"); + get(var.x, name + "x", def, communicate); + get(var.y, name + "y", def, communicate); + get(var.z, name + "z", def, communicate); } return 0; } -int Mesh::get(Vector3D &var, const std::string &name) { +int Mesh::get(Vector3D& var, const std::string& name, BoutReal def, bool communicate) { TRACE("Loading 3D vector: Mesh::get(Vector3D, %s)", name.c_str()); if(var.covariant) { output << _("\tReading covariant vector ") << name << endl; - get(var.x, name+"_x"); - get(var.y, name+"_y"); - get(var.z, name+"_z"); + get(var.x, name + "_x", def, communicate); + get(var.y, name + "_y", def, communicate); + get(var.z, name + "_z", def, communicate); }else { output << ("\tReading contravariant vector ") << name << endl; - get(var.x, name+"x"); - get(var.y, name+"y"); - get(var.z, name+"z"); + get(var.x, name + "x", def, communicate); + get(var.y, name + "y", def, communicate); + get(var.z, name + "z", def, communicate); } return 0; From 848c298d235e06a444f160e66121cb9708d0cee6 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 11:43:16 +0000 Subject: [PATCH 035/293] Use explicit communication in Coordinates constructor Used to avoid calls to calcYupYdown at this stage Furthermore, move call to geometry out of constructor and into the point at which we add the coordinates to the mesh. This allows us to use routines within `geometry` that try to get the coordinates out of the mesh. --- include/bout/mesh.hxx | 1 + src/mesh/coordinates.cxx | 92 +++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 44 deletions(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index 9271a77ed0..de0895943a 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -453,6 +453,7 @@ class Mesh { // Note that this can't be allocated here due to incomplete type // (circular dependency between Mesh and Coordinates) coords_map.emplace(location, createDefaultCoordinates(location)); + coords_map[location].get()->geometry(); return coords_map[location].get(); } } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 82fc88671b..cfd44f8fab 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -28,19 +28,15 @@ Coordinates::Coordinates(Mesh *mesh) G3_23(mesh), G1(mesh), G2(mesh), G3(mesh), ShiftTorsion(mesh), IntShiftTorsion(mesh), localmesh(mesh), location(CELL_CENTRE) { - if (mesh->get(dx, "dx")) { + if (mesh->get(dx, "dx", 1.0, false)) { output_warn.write("\tWARNING: differencing quantity 'dx' not found. Set to 1.0\n"); - dx = 1.0; } + mesh->communicateXZ(dx); - if (mesh->periodicX) { - mesh->communicate(dx); - } - - if (mesh->get(dy, "dy")) { + if (mesh->get(dy, "dy", 1.0, false)) { output_warn.write("\tWARNING: differencing quantity 'dy' not found. Set to 1.0\n"); - dy = 1.0; } + mesh->communicateXZ(dy); nz = mesh->LocalNz; @@ -64,14 +60,16 @@ Coordinates::Coordinates(Mesh *mesh) } // Diagonal components of metric tensor g^{ij} (default to 1) - mesh->get(g11, "g11", 1.0); - mesh->get(g22, "g22", 1.0); - mesh->get(g33, "g33", 1.0); + mesh->get(g11, "g11", 1.0, false); + mesh->get(g22, "g22", 1.0, false); + mesh->get(g33, "g33", 1.0, false); // Off-diagonal elements. Default to 0 - mesh->get(g12, "g12", 0.0); - mesh->get(g13, "g13", 0.0); - mesh->get(g23, "g23", 0.0); + mesh->get(g12, "g12", 0.0, false); + mesh->get(g13, "g13", 0.0, false); + mesh->get(g23, "g23", 0.0, false); + + mesh->communicateXZ(g11, g22, g33, g12, g13, g23); // Check input metrics if ((!finite(g11)) || (!finite(g22)) || (!finite(g33))) { @@ -93,12 +91,14 @@ Coordinates::Coordinates(Mesh *mesh) if (mesh->sourceHasVar("g_11") and mesh->sourceHasVar("g_22") and mesh->sourceHasVar("g_33") and mesh->sourceHasVar("g_12") and mesh->sourceHasVar("g_13") and mesh->sourceHasVar("g_23")) { - mesh->get(g_11, "g_11"); - mesh->get(g_22, "g_22"); - mesh->get(g_33, "g_33"); - mesh->get(g_12, "g_12"); - mesh->get(g_13, "g_13"); - mesh->get(g_23, "g_23"); + mesh->get(g_11, "g_11", 1.0, false); + mesh->get(g_22, "g_22", 1.0, false); + mesh->get(g_33, "g_33", 1.0, false); + mesh->get(g_12, "g_12", 0.0, false); + mesh->get(g_13, "g_13", 0.0, false); + mesh->get(g_23, "g_23", 0.0, false); + + mesh->communicateXZ(g_11, g_22, g_33, g_12, g_13, g_23); output_warn.write("\tWARNING! Covariant components of metric tensor set manually. " "Contravariant components NOT recalculated\n"); @@ -124,24 +124,28 @@ Coordinates::Coordinates(Mesh *mesh) // Attempt to read J from the grid file auto Jcalc = J; - if (mesh->get(J, "J")) { + if (mesh->get(J, "J", 0.0, false)) { output_warn.write("\tWARNING: Jacobian 'J' not found. Calculating from metric tensor\n"); J = Jcalc; } else { // Compare calculated and loaded values output_warn.write("\tMaximum difference in J is %e\n", max(abs(J - Jcalc))); + mesh->communicateXZ(J); + // Re-evaluate Bxy using new J Bxy = sqrt(g_22) / J; } // Attempt to read Bxy from the grid file auto Bcalc = Bxy; - if (mesh->get(Bxy, "Bxy")) { + if (mesh->get(Bxy, "Bxy", 0.0, false)) { output_warn.write("\tWARNING: Magnitude of B field 'Bxy' not found. Calculating from " "metric tensor\n"); Bxy = Bcalc; } else { + mesh->communicateXZ(Bxy); + output_warn.write("\tMaximum difference in Bxy is %e\n", max(abs(Bxy - Bcalc))); // Check Bxy if (!finite(Bxy)) { @@ -149,24 +153,18 @@ Coordinates::Coordinates(Mesh *mesh) } } - ////////////////////////////////////////////////////// - /// Calculate Christoffel symbols. Needs communication - if (geometry()) { - throw BoutException("Differential geometry failed\n"); - } - - if (mesh->get(ShiftTorsion, "ShiftTorsion")) { + if (mesh->get(ShiftTorsion, "ShiftTorsion", 0.0, false)) { output_warn.write("\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); - ShiftTorsion = 0.0; } + mesh->communicateXZ(ShiftTorsion); ////////////////////////////////////////////////////// if (mesh->IncIntShear) { - if (mesh->get(IntShiftTorsion, "IntShiftTorsion")) { + if (mesh->get(IntShiftTorsion, "IntShiftTorsion", 0.0, false)) { output_warn.write("\tWARNING: No Integrated torsion specified\n"); - IntShiftTorsion = 0.0; } + mesh->communicateXZ(IntShiftTorsion); } } @@ -275,12 +273,6 @@ Coordinates::Coordinates(Mesh *mesh, const CELL_LOC loc, const Coordinates* coor if (jacobian()) throw BoutException("Error in jacobian call"); - ////////////////////////////////////////////////////// - /// Calculate Christoffel symbols. Needs communication - if (geometry()) { - throw BoutException("Differential geometry failed\n"); - } - ShiftTorsion = interpolateAndNeumann(coords_in->ShiftTorsion, location); ////////////////////////////////////////////////////// @@ -314,6 +306,8 @@ void Coordinates::outputVars(Datafile &file) { int Coordinates::geometry() { TRACE("Coordinates::geometry"); + localmesh->communicate(dx, dy, g11, g22, g33, g12, g13, g23); + localmesh->communicate(g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); output_progress.write("Calculating differential geometry terms\n"); @@ -409,9 +403,15 @@ int Coordinates::geometry() { G3_23 = 0.5 * g13 * (DDZ(g_12) + DDY(g_13) - DDX(g_23)) + 0.5 * g23 * DDZ(g_22) + 0.5 * g33 * DDY(g_33); - G1 = (DDX(J * g11) + DDY(J * g12) + DDZ(J * g13)) / J; - G2 = (DDX(J * g12) + DDY(J * g22) + DDZ(J * g23)) / J; - G3 = (DDX(J * g13) + DDY(J * g23) + DDZ(J * g33)) / J; + auto tmp = J * g12; + localmesh->communicate(tmp); + G1 = (DDX(J * g11) + DDY(tmp) + DDZ(J * g13)) / J; + tmp = J * g22; + localmesh->communicate(tmp); + G2 = (DDX(J * g12) + DDY(tmp) + DDZ(J * g23)) / J; + tmp = J * g23; + localmesh->communicate(tmp); + G3 = (DDX(J * g13) + DDY(tmp) + DDZ(J * g33)) / J; // Communicate christoffel symbol terms output_progress.write("\tCommunicating connection terms\n"); @@ -452,19 +452,23 @@ int Coordinates::geometry() { Coordinates::metric_field_type d2x, d2y; // d^2 x / d i^2 // Read correction for non-uniform meshes - if (localmesh->get(d2x, "d2x")) { + if (localmesh->get(d2x, "d2x", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2x' not found. Calculating from dx\n"); d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) } else { + mesh->communicateXZ(d2x); d1_dx = -d2x / (dx * dx); } - if (localmesh->get(d2y, "d2y")) { + if (localmesh->get(d2y, "d2y", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) + auto tmp2 = 1. / dy; + localmesh->communicate(tmp2); + d1_dy = bout::derivatives::index::DDY(tmp2); // d/di(1/dy) } else { + mesh->communicateXZ(d2y); d1_dy = -d2y / (dy * dy); } From 6259c36f0ae92520ce83fe45b2a028408234071a Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 11:44:59 +0000 Subject: [PATCH 036/293] Avoid falling back on to/from field aligned in Grad_par routines --- src/mesh/coordinates.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index cfd44f8fab..a3c2d2ff79 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -788,8 +788,9 @@ Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& me TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); - auto sg = sqrt(g_22); - auto result = DDY(1. / sg, outloc, method) * DDY(f, outloc, method) / sg + auto invSg = 1.0 / sqrt(g_22); + localmesh->communicate(invSg); + auto result = DDY(invSg, outloc, method) * DDY(f, outloc, method) * invSg + D2DY2(f, outloc, method) / g_22; return result; @@ -803,7 +804,9 @@ const Field3D Coordinates::Grad2_par2(const Field3D &f, CELL_LOC outloc, const s ASSERT1(location == outloc); auto sg = sqrt(g_22); - sg = DDY(1. / sg, outloc, method) / sg; + auto invSg = 1.0 / sg; + localmesh->communicate(invSg); + sg = DDY(invSg, outloc, method) * invSg; Field3D result(localmesh), r2(localmesh); From 6c34d4c67ce1f411f9dbd88277af640e7c6ca646 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Sun, 9 Dec 2018 11:55:19 +0000 Subject: [PATCH 037/293] Remove some global mesh uses --- src/mesh/coordinates.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index a3c2d2ff79..d949ee9bdc 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -457,7 +457,7 @@ int Coordinates::geometry() { "\tWARNING: differencing quantity 'd2x' not found. Calculating from dx\n"); d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) } else { - mesh->communicateXZ(d2x); + localmesh->communicateXZ(d2x); d1_dx = -d2x / (dx * dx); } @@ -468,9 +468,10 @@ int Coordinates::geometry() { localmesh->communicate(tmp2); d1_dy = bout::derivatives::index::DDY(tmp2); // d/di(1/dy) } else { - mesh->communicateXZ(d2y); + localmesh->communicateXZ(d2y); d1_dy = -d2y / (dy * dy); } + localmesh->communicate(d1_dx, d1_dy); return 0; } From 5c03184d5d53c3cbdb9ad7544a0f28d29c1f4bde Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 10 Dec 2018 15:24:26 +0000 Subject: [PATCH 038/293] Move the calcWeights call to after the mask is set --- src/mesh/parallel/fci.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 9fed6239a4..973ba3841b 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -131,9 +131,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) interp_corner->setMask(corner_boundary_mask); interp_corner->calcWeights(xt_prime_corner, zt_prime_corner); - - interp->calcWeights(xt_prime, zt_prime); - + int ncz = mesh.LocalNz; BoutReal t_x, t_z; @@ -237,6 +235,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) } interp->setMask(boundary_mask); + interp->calcWeights(xt_prime, zt_prime); } const Field3D FCIMap::integrate(Field3D &f) const { From 09ac7259231ddc5a500a518cc119409ae9fdcb18 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 10 Dec 2018 15:24:57 +0000 Subject: [PATCH 039/293] Move validity checks sooner in loop --- src/mesh/parallel/fci.cxx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 973ba3841b..ddee1cd560 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -162,6 +162,16 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) t_x = xt_prime(x, y, z) - static_cast(i_corner(x, y, z)); t_z = zt_prime(x, y, z) - static_cast(k_corner(x, y, z)); + //---------------------------------------- + + // Check that t_x and t_z are in range + if ((t_x < 0.0) || (t_x > 1.0)) + throw BoutException("t_x=%e out of range at (%d,%d,%d)", t_x, x, y, z); + + if ((t_z < 0.0) || (t_z > 1.0)) + throw BoutException("t_z=%e out of range at (%d,%d,%d)", t_z, x, y, z); + + //---------------------------------------- // Boundary stuff // @@ -221,15 +231,6 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) PI // Right-angle intersection ); } - - //---------------------------------------- - - // Check that t_x and t_z are in range - if ((t_x < 0.0) || (t_x > 1.0)) - throw BoutException("t_x=%e out of range at (%d,%d,%d)", t_x, x, y, z); - - if ((t_z < 0.0) || (t_z > 1.0)) - throw BoutException("t_z=%e out of range at (%d,%d,%d)", t_z, x, y, z); } } } From 04faac472f283231a1ecaa99c89e4411476747a8 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 10 Dec 2018 17:07:51 +0000 Subject: [PATCH 040/293] Change how Zoidberg indicates boundaries Keep change of sign but don't force |value| to 1. --- tools/pylib/zoidberg/zoidberg.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index a7333d6762..966ea98271 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -101,8 +101,8 @@ def make_maps(grid, magnetic_field, quiet=False, **kwargs): # Get the indices into the forward poloidal grid if pol_forward is None: # No forward grid, so hit a boundary - xind = -1 - zind = -1 + xind *= -1 + zind *= -1 else: # Find the indices for these new locations on the forward poloidal grid xcoord = coord[:,:,0] @@ -111,8 +111,8 @@ def make_maps(grid, magnetic_field, quiet=False, **kwargs): # Check boundary defined by the field outside = magnetic_field.boundary.outside(xcoord, y_forward, zcoord) - xind[outside] = -1 - zind[outside] = -1 + xind[outside] *= -1 + zind[outside] *= -1 forward_xt_prime[:,j,:] = xind forward_zt_prime[:,j,:] = zind @@ -129,8 +129,8 @@ def make_maps(grid, magnetic_field, quiet=False, **kwargs): if pol_back is None: # Hit boundary - xind = -1 - zind = -1 + xind *= -1 + zind *= -1 else: # Find the indices for these new locations on the backward poloidal grid xcoord = coord[:,:,0] @@ -139,8 +139,8 @@ def make_maps(grid, magnetic_field, quiet=False, **kwargs): # Check boundary defined by the field outside = magnetic_field.boundary.outside(xcoord, y_back, zcoord) - xind[outside] = -1 - zind[outside] = -1 + xind[outside] *= -1 + zind[outside] *= -1 backward_xt_prime[:,j,:] = xind backward_zt_prime[:,j,:] = zind From 122c04be5e5ce9881c47a6136866906164d732dd Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Mon, 10 Dec 2018 17:10:54 +0000 Subject: [PATCH 041/293] Update FCIMap to account for change in Zoidberg and use it to allow interpolation in the boundary regions --- src/mesh/coordinates.cxx | 4 ++-- src/mesh/parallel/fci.cxx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index d949ee9bdc..220aeda7bc 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -443,7 +443,7 @@ int Coordinates::geometry() { com.add(G2); com.add(G3); - localmesh->communicate(com); + localmesh->communicateXZ(com); ////////////////////////////////////////////////////// /// Non-uniform meshes. Need to use DDX, DDY @@ -471,7 +471,7 @@ int Coordinates::geometry() { localmesh->communicateXZ(d2y); d1_dy = -d2y / (dy * dy); } - localmesh->communicate(d1_dx, d1_dy); + localmesh->communicateXZ(d1_dx, d1_dy); return 0; } diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index ddee1cd560..2154ed2c4b 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -143,7 +143,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) // The integer part of xt_prime, zt_prime are the indices of the cell // containing the field line end-point - i_corner(x, y, z) = static_cast(floor(xt_prime(x, y, z))); + i_corner(x, y, z) = static_cast(floor(std::abs(xt_prime(x, y, z)))); // z is periodic, so make sure the z-index wraps around if (zperiodic) { @@ -159,7 +159,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) // t_x, t_z are the normalised coordinates \in [0,1) within the cell // calculated by taking the remainder of the floating point index - t_x = xt_prime(x, y, z) - static_cast(i_corner(x, y, z)); + t_x = std::abs(xt_prime(x, y, z)) - static_cast(i_corner(x, y, z)); t_z = zt_prime(x, y, z) - static_cast(k_corner(x, y, z)); //---------------------------------------- @@ -182,7 +182,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) if (xt_prime(x, y, z) < 0.0) { // Hit a boundary - boundary_mask(x, y, z) = true; + boundary_mask(x, y, z) = false; // true; // Need to specify the index of the boundary intersection, but // this may not be defined in general. @@ -236,7 +236,7 @@ FCIMap::FCIMap(Mesh &mesh, int dir, bool zperiodic) } interp->setMask(boundary_mask); - interp->calcWeights(xt_prime, zt_prime); + interp->calcWeights(abs(xt_prime), zt_prime); } const Field3D FCIMap::integrate(Field3D &f) const { From 6c7d09e47b71934f8837121a1d07f42b582b40a8 Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 11 Dec 2018 09:43:40 +0000 Subject: [PATCH 042/293] Update zoidberg test --- tools/pylib/zoidberg/test_zoidberg.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pylib/zoidberg/test_zoidberg.py b/tools/pylib/zoidberg/test_zoidberg.py index d82c30f0e2..eff28188af 100644 --- a/tools/pylib/zoidberg/test_zoidberg.py +++ b/tools/pylib/zoidberg/test_zoidberg.py @@ -40,12 +40,12 @@ def test_make_maps_slab(): assert np.allclose(maps['backward_zt_prime'][:,y,:], identity_map_z) # The last forward map should hit a boundary - assert np.allclose(maps['forward_xt_prime'][:,-1,:], -1.0) - assert np.allclose(maps['forward_zt_prime'][:,-1,:], -1.0) + assert np.all(maps['forward_xt_prime'][:,-1,:] < 0.0) + assert np.all(maps['forward_zt_prime'][:,-1,:] < 0.0) # First backward map hits boundary - assert np.allclose(maps['backward_xt_prime'][:,0,:], -1.0) - assert np.allclose(maps['backward_zt_prime'][:,0,:], -1.0) + assert np.all(maps['backward_xt_prime'][:,0,:] < 0.0) + assert np.all(maps['backward_zt_prime'][:,0,:] < 0.0) def test_make_maps_straight_stellarator(): From a2395f39dcab8f6c79bf6d2ee5aba173ff9405fa Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 11 Dec 2018 10:07:22 +0000 Subject: [PATCH 043/293] Update Zoidberg test --- tools/pylib/zoidberg/test_zoidberg.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/pylib/zoidberg/test_zoidberg.py b/tools/pylib/zoidberg/test_zoidberg.py index eff28188af..440caf1b9e 100644 --- a/tools/pylib/zoidberg/test_zoidberg.py +++ b/tools/pylib/zoidberg/test_zoidberg.py @@ -40,12 +40,12 @@ def test_make_maps_slab(): assert np.allclose(maps['backward_zt_prime'][:,y,:], identity_map_z) # The last forward map should hit a boundary - assert np.all(maps['forward_xt_prime'][:,-1,:] < 0.0) - assert np.all(maps['forward_zt_prime'][:,-1,:] < 0.0) + assert np.all(np.signbit(maps['forward_xt_prime'][:,-1,:])) + assert np.all(np.signbit(maps['forward_zt_prime'][:,-1,:])) # First backward map hits boundary - assert np.all(maps['backward_xt_prime'][:,0,:] < 0.0) - assert np.all(maps['backward_zt_prime'][:,0,:] < 0.0) + assert np.all(np.signbit(maps['backward_xt_prime'][:,0,:])) + assert np.all(np.signbit(maps['backward_zt_prime'][:,0,:])) def test_make_maps_straight_stellarator(): From afbe5d715d5adcd6367fcb55f47a12c92dd87380 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 18 Dec 2018 11:12:54 +0100 Subject: [PATCH 044/293] Update petsc_laplace to work with 3D metrics --- .../laplace/impls/petsc/petsc_laplace.cxx | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index cafa8bb2d5..8e4575b8ed 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -399,24 +399,24 @@ const FieldPerp LaplacePetsc::solve(const FieldPerp &b, const FieldPerp &x0) { // Set values corresponding to nodes adjacent in x if( fourth_order ) { // Fourth Order Accuracy on Boundary - Element(i,x,z, 0, 0, -25.0 / (12.0*coords->dx(x,y)) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, 1, 0, 4.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, 2, 0, -3.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, 3, 0, 4.0 / (3.0*coords->dx(x,y)) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, 4, 0, -1.0 / (4.0*coords->dx(x,y)) / sqrt(coords->g_11(x,y)), MatA ); + Element(i,x,z, 0, 0, -25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 1, 0, 4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 2, 0, -3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 3, 0, 4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 4, 0, -1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); } else { -// // Second Order Accuracy on Boundary -// Element(i,x,z, 0, 0, -3.0 / (2.0*coords->dx(x,y)), MatA ); -// Element(i,x,z, 1, 0, 2.0 / coords->dx(x,y), MatA ); -// Element(i,x,z, 2, 0, -1.0 / (2.0*coords->dx(x,y)), MatA ); -// // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now -// // Element(i,x,z, 4, 0, 0.0, MatA ); - // Second Order Accuracy on Boundary, set half-way between grid points - Element(i,x,z, 0, 0, -1.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, 1, 0, 1.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, 2, 0, 0.0, MatA ); -// Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now -// Element(i,x,z, 4, 0, 0.0, MatA ); + // Second Order Accuracy on Boundary + // Element(i,x,z, 0, 0, -3.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, 1, 0, 2.0 / coords->dx(x,y), MatA ); + // Element(i,x,z, 2, 0, -1.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, 4, 0, 0.0, MatA ); + // Second Order Accuracy on Boundary, set half-way between grid points + Element(i,x,z, 0, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 1, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 2, 0, 0.0, MatA ); + // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, 4, 0, 0.0, MatA ); } } else { if (fourth_order) { @@ -470,11 +470,11 @@ const FieldPerp LaplacePetsc::solve(const FieldPerp &b, const FieldPerp &x0) { // Set the matrix coefficients Coeffs( x, y, z, A1, A2, A3, A4, A5 ); - BoutReal dx = coords->dx(x,y); - BoutReal dx2 = SQ(coords->dx(x,y)); + BoutReal dx = coords->dx(x,y,z); + BoutReal dx2 = SQ(coords->dx(x,y,z)); BoutReal dz = coords->dz; BoutReal dz2 = SQ(coords->dz); - BoutReal dxdz = coords->dx(x,y) * coords->dz; + BoutReal dxdz = coords->dx(x,y,z) * coords->dz; ASSERT3(finite(A1)); ASSERT3(finite(A2)); @@ -648,11 +648,11 @@ const FieldPerp LaplacePetsc::solve(const FieldPerp &b, const FieldPerp &x0) { // Set values corresponding to nodes adjacent in x if( fourth_order ) { // Fourth Order Accuracy on Boundary - Element(i,x,z, 0, 0, 25.0 / (12.0*coords->dx(x,y)) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, -1, 0, -4.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, -2, 0, 3.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, -3, 0, -4.0 / (3.0*coords->dx(x,y)) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, -4, 0, 1.0 / (4.0*coords->dx(x,y)) / sqrt(coords->g_11(x,y)), MatA ); + Element(i,x,z, 0, 0, 25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -1, 0, -4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -2, 0, 3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -3, 0, -4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -4, 0, 1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); } else { // // Second Order Accuracy on Boundary @@ -662,8 +662,8 @@ const FieldPerp LaplacePetsc::solve(const FieldPerp &b, const FieldPerp &x0) { // // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now // // Element(i,x,z, -4, 0, 0.0, MatA ); // Second Order Accuracy on Boundary, set half-way between grid points - Element(i,x,z, 0, 0, 1.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); - Element(i,x,z, -1, 0, -1.0 / coords->dx(x,y) / sqrt(coords->g_11(x,y)), MatA ); + Element(i,x,z, 0, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -1, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); Element(i,x,z, -2, 0, 0.0, MatA ); // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now // Element(i,x,z, -4, 0, 0.0, MatA ); @@ -934,16 +934,16 @@ 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 ) { - coef1 = coords->g11(x,y); // X 2nd derivative coefficient - coef2 = coords->g33(x,y); // Z 2nd derivative coefficient - coef3 = 2.*coords->g13(x,y); // X-Z mixed derivative coefficient + coef1 = coords->g11(x,y,z); // X 2nd derivative coefficient + coef2 = coords->g33(x,y,z); // Z 2nd derivative coefficient + coef3 = 2.*coords->g13(x,y,z); // X-Z mixed derivative coefficient coef4 = 0.0; coef5 = 0.0; // If global flag all_terms are set (true by default) if (all_terms) { - coef4 = coords->G1(x,y); // X 1st derivative - coef5 = coords->G3(x,y); // Z 1st derivative + coef4 = coords->G1(x,y,z); // X 1st derivative + coef5 = coords->G3(x,y,z); // Z 1st derivative ASSERT3(finite(coef4)); ASSERT3(finite(coef5)); @@ -952,13 +952,13 @@ void LaplacePetsc::Coeffs( int x, int y, int z, BoutReal &coef1, BoutReal &coef2 if(nonuniform) { // non-uniform mesh correction if((x != 0) && (x != (localmesh->LocalNx-1))) { - coef4 -= 0.5 * ( ( coords->dx(x+1,y) - coords->dx(x-1,y) ) / SQ(coords->dx(x,y)) ) * coef1; // BOUT-06 term + coef4 -= 0.5 * ( ( coords->dx(x+1,y,z) - coords->dx(x-1,y,z) ) / SQ(coords->dx(x,y,z)) ) * coef1; // BOUT-06 term } } if(localmesh->IncIntShear) { // d2dz2 term - coef2 += coords->g11(x,y) * coords->IntShiftTorsion(x,y) * coords->IntShiftTorsion(x,y); + coef2 += coords->g11(x,y,z) * coords->IntShiftTorsion(x,y,z) * coords->IntShiftTorsion(x,y,z); // Mixed derivative coef3 = 0.0; // This cancels out } @@ -988,19 +988,19 @@ void LaplacePetsc::Coeffs( int x, int y, int z, BoutReal &coef1, BoutReal &coef2 int zmm = z-2; // z minus 1 minus 1 if (zmm<0) zmm += meshz; // Fourth order discretization of C in x - ddx_C = (-C2(x+2,y,z) + 8.*C2(x+1,y,z) - 8.*C2(x-1,y,z) + C2(x-2,y,z)) / (12.*coords->dx(x,y)*(C1(x,y,z))); + ddx_C = (-C2(x+2,y,z) + 8.*C2(x+1,y,z) - 8.*C2(x-1,y,z) + C2(x-2,y,z)) / (12.*coords->dx(x,y,z)*(C1(x,y,z))); // Fourth order discretization of C in z ddz_C = (-C2(x,y,zpp) + 8.*C2(x,y,zp) - 8.*C2(x,y,zm) + C2(x,y,zmm)) / (12.*coords->dz*(C1(x,y,z))); } else { // Second order discretization of C in x - ddx_C = (C2(x+1,y,z) - C2(x-1,y,z)) / (2.*coords->dx(x,y)*(C1(x,y,z))); + ddx_C = (C2(x+1,y,z) - C2(x-1,y,z)) / (2.*coords->dx(x,y,z)*(C1(x,y,z))); // Second order discretization of C in z ddz_C = (C2(x,y,zp) - C2(x,y,zm)) / (2.*coords->dz*(C1(x,y,z))); } - coef4 += coords->g11(x,y) * ddx_C + coords->g13(x,y) * ddz_C; - coef5 += coords->g13(x,y) * ddx_C + coords->g33(x,y) * ddz_C; + coef4 += coords->g11(x,y,z) * ddx_C + coords->g13(x,y,z) * ddz_C; + coef5 += coords->g13(x,y,z) * ddx_C + coords->g33(x,y,z) * ddz_C; } } From 9230326a449a22f58486c2cebe53bc08680a07f1 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 18 Dec 2018 11:34:12 +0100 Subject: [PATCH 045/293] update assertions in petsc_laplace to those in next branch --- src/invert/laplace/impls/petsc/petsc_laplace.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index 8e4575b8ed..9666bc12dc 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -346,6 +346,8 @@ const FieldPerp LaplacePetsc::solve(const FieldPerp &b, const FieldPerp &x0) { TRACE("LaplacePetsc::solve"); ASSERT1(localmesh == b.getMesh() && localmesh == x0.getMesh()); + ASSERT1(b.getLocation() == location); + ASSERT1(x0.getLocation() == location); #if CHECK > 0 // Checking flags are set to something which is not implemented (see From 84637221e050d11b77655bfe2e9fcb87d76520ca Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 8 Jan 2019 10:48:22 +0100 Subject: [PATCH 046/293] Update laplacexy for 3D metrics --- src/invert/laplacexy/laplacexy.cxx | 169 +++++++++++++++-------------- 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index 5e5a5a4f93..89fd66df37 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -298,91 +298,92 @@ void LaplaceXY::setCoefs(const Field2D &A, const Field2D &B) { for(int x=mesh->xstart; x <= mesh->xend; x++) { for(int y=mesh->ystart;y<=mesh->yend;y++) { - // stencil entries - PetscScalar c, xm, xp, ym, yp; - - // XX component - - // Metrics on x+1/2 boundary - BoutReal J = 0.5*(coords->J(x,y) + coords->J(x+1,y)); - BoutReal g11 = 0.5*(coords->g11(x,y) + coords->g11(x+1,y)); - BoutReal dx = 0.5*(coords->dx(x,y) + coords->dx(x+1,y)); - BoutReal Acoef = 0.5*(A(x,y) + A(x+1,y)); - - BoutReal val = Acoef * J * g11 / (coords->J(x,y) * dx * coords->dx(x,y)); - xp = val; - c = -val; - - // Metrics on x-1/2 boundary - J = 0.5*(coords->J(x,y) + coords->J(x-1,y)); - g11 = 0.5*(coords->g11(x,y) + coords->g11(x-1,y)); - dx = 0.5*(coords->dx(x,y) + coords->dx(x-1,y)); - Acoef = 0.5*(A(x,y) + A(x-1,y)); - - val = Acoef * J * g11 / (coords->J(x,y) * dx * coords->dx(x,y)); - xm = val; - c -= val; - - c += B(x,y); - - // Put values into the preconditioner, X derivatives only - acoef(y - mesh->ystart, x - xstart) = xm; - bcoef(y - mesh->ystart, x - xstart) = c; - ccoef(y - mesh->ystart, x - xstart) = xp; - - if( include_y_derivs ) { - // YY component - // Metrics at y+1/2 - J = 0.5*(coords->J(x,y) + coords->J(x,y+1)); - BoutReal g_22 = 0.5*(coords->g_22(x,y) + coords->g_22(x,y+1)); - BoutReal g23 = 0.5*(coords->g23(x,y) + coords->g23(x,y+1)); - BoutReal g_23 = 0.5*(coords->g_23(x,y) + coords->g_23(x,y+1)); - BoutReal dy = 0.5*(coords->dy(x,y) + coords->dy(x,y+1)); - Acoef = 0.5*(A(x,y+1) + A(x,y)); - - val = -Acoef * J * g23 * g_23 / (g_22 * coords->J(x,y) * dy * coords->dy(x,y)); - yp = val; - c -= val; - - // Metrics at y-1/2 - J = 0.5*(coords->J(x,y) + coords->J(x,y-1)); - g_22 = 0.5*(coords->g_22(x,y) + coords->g_22(x,y-1)); - g23 = 0.5*(coords->g23(x,y) + coords->g23(x,y-1)); - g_23 = 0.5*(coords->g_23(x,y) + coords->g_23(x,y-1)); - dy = 0.5*(coords->dy(x,y) + coords->dy(x,y-1)); - Acoef = 0.5*(A(x,y-1) + A(x,y)); - - val = -Acoef * J * g23 * g_23 / (g_22 * coords->J(x,y) * dy * coords->dy(x,y)); - ym = val; - c -= val; + for(int z=0;z<=mesh->LocalNz;z++){ + // stencil entries + PetscScalar c, xm, xp, ym, yp; + + // XX component + + // Metrics on x+1/2 boundary + BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); + BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + BoutReal Acoef = 0.5*(A(x,y) + A(x+1,y)); + + BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xp = val; + c = -val; + + // Metrics on x-1/2 boundary + J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); + dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y) + A(x-1,y)); + + val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xm = val; + c -= val; + + c += B(x,y); + + // Put values into the preconditioner, X derivatives only + acoef(y - mesh->ystart, x - xstart) = xm; + bcoef(y - mesh->ystart, x - xstart) = c; + ccoef(y - mesh->ystart, x - xstart) = xp; + + if( include_y_derivs ) { + // YY component + // Metrics at y+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x,y+1,z)); + BoutReal g_22 = 0.5*(coords->g_22(x,y,z) + coords->g_22(x,y+1,z)); + BoutReal g23 = 0.5*(coords->g23(x,y,z) + coords->g23(x,y+1,z)); + BoutReal g_23 = 0.5*(coords->g_23(x,y,z) + coords->g_23(x,y+1,z)); + BoutReal dy = 0.5*(coords->dy(x,y,z) + coords->dy(x,y+1,z)); + Acoef = 0.5*(A(x,y+1) + A(x,y)); + + val = -Acoef * J * g23 * g_23 / (g_22 * coords->J(x,y,z) * dy * coords->dy(x,y,z)); + yp = val; + c -= val; + + // Metrics at y-1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x,y-1,z)); + g_22 = 0.5*(coords->g_22(x,y,z) + coords->g_22(x,y-1,z)); + g23 = 0.5*(coords->g23(x,y,z) + coords->g23(x,y-1,z)); + g_23 = 0.5*(coords->g_23(x,y,z) + coords->g_23(x,y-1,z)); + dy = 0.5*(coords->dy(x,y,z) + coords->dy(x,y-1,z)); + Acoef = 0.5*(A(x,y-1) + A(x,y)); + + val = -Acoef * J * g23 * g_23 / (g_22 * coords->J(x,y,z) * dy * coords->dy(x,y,z)); + ym = val; + c -= val; + + } + ///////////////////////////////////////////////// + // Now have a 5-point stencil for the Laplacian + + int row = globalIndex(x,y); + + // Set the centre (diagonal) + MatSetValues(MatA,1,&row,1,&row,&c,INSERT_VALUES); + + // X + 1 + int col = globalIndex(x+1, y); + MatSetValues(MatA,1,&row,1,&col,&xp,INSERT_VALUES); + + // X - 1 + col = globalIndex(x-1, y); + MatSetValues(MatA,1,&row,1,&col,&xm,INSERT_VALUES); + + if( include_y_derivs ) { + // Y + 1 + col = globalIndex(x, y+1); + MatSetValues(MatA,1,&row,1,&col,&yp,INSERT_VALUES); + + // Y - 1 + col = globalIndex(x, y-1); + MatSetValues(MatA,1,&row,1,&col,&ym,INSERT_VALUES); + } } - - ///////////////////////////////////////////////// - // Now have a 5-point stencil for the Laplacian - - int row = globalIndex(x,y); - - // Set the centre (diagonal) - MatSetValues(MatA,1,&row,1,&row,&c,INSERT_VALUES); - - // X + 1 - int col = globalIndex(x+1, y); - MatSetValues(MatA,1,&row,1,&col,&xp,INSERT_VALUES); - - // X - 1 - col = globalIndex(x-1, y); - MatSetValues(MatA,1,&row,1,&col,&xm,INSERT_VALUES); - - if( include_y_derivs ) { - // Y + 1 - col = globalIndex(x, y+1); - MatSetValues(MatA,1,&row,1,&col,&yp,INSERT_VALUES); - - // Y - 1 - col = globalIndex(x, y-1); - MatSetValues(MatA,1,&row,1,&col,&ym,INSERT_VALUES); - } - } } From e9bb061a1b05bb4b60394f70d5c2b88b7693313b Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 8 Jan 2019 12:09:00 +0100 Subject: [PATCH 047/293] Adding is3D() function to coordinates *checks if BOUT++ was compiled with 3D metrics --- include/bout/coordinates.hxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index f8394cbec5..d4743bac17 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -57,6 +57,14 @@ public: using metric_field_type = Field2D; #endif + bool is3D() { +#ifdef COORDINATES_USE_3D + return true; +#else + return false; +#endif + } + /// Standard constructor from input Coordinates(Mesh *mesh); From f5dccc9d29aad25198fd724748c23038be06421f Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 8 Jan 2019 12:16:03 +0100 Subject: [PATCH 048/293] Update LaplaceXZ for 3D metrics: * Remove assumption that off-diagonal components are small * Extend coordinate functions to 3D --- include/bout/invert/laplacexz.hxx | 3 +- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 297 ++++++++++++------ 2 files changed, 209 insertions(+), 91 deletions(-) diff --git a/include/bout/invert/laplacexz.hxx b/include/bout/invert/laplacexz.hxx index 1c7d84902d..2769b5322b 100644 --- a/include/bout/invert/laplacexz.hxx +++ b/include/bout/invert/laplacexz.hxx @@ -38,7 +38,8 @@ class LaplaceXZ { public: - LaplaceXZ(Mesh *UNUSED(m), Options *UNUSED(options), const CELL_LOC UNUSED(loc)) {} + LaplaceXZ(Mesh* UNUSED(m), Options* UNUSED(options), const CELL_LOC loc = CELL_CENTRE) + : location(loc) {} virtual ~LaplaceXZ() {} virtual void setCoefs(const Field2D &A, const Field2D &B) = 0; diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index 09d8b4ccc0..db4b47fc9c 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -177,9 +177,9 @@ LaplaceXZpetsc::LaplaceXZpetsc(Mesh *m, Options *opt, const CELL_LOC loc) for(int i=0;igetCoordinates(location); - - // NOTE: For now the X-Z terms are omitted, so check that they are small - ASSERT2(max(abs(coords->g13)) < 1e-5); for(int x=mesh->xstart; x <= mesh->xend; x++) { for(int z=0; z < mesh->LocalNz; z++) { - // stencil entries - PetscScalar c, xm, xp, zm, zp; - - // XX component - - // Metrics on x+1/2 boundary - BoutReal J = 0.5*(coords->J(x,y) + coords->J(x+1,y)); - BoutReal g11 = 0.5*(coords->g11(x,y) + coords->g11(x+1,y)); - BoutReal dx = 0.5*(coords->dx(x,y) + coords->dx(x+1,y)); - BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - BoutReal val = Acoef * J * g11 / (coords->J(x,y) * dx * coords->dx(x,y)); - xp = val; - c = -val; - - // Metrics on x-1/2 boundary - J = 0.5*(coords->J(x,y) + coords->J(x-1,y)); - g11 = 0.5*(coords->g11(x,y) + coords->g11(x-1,y)); - dx = 0.5*(coords->dx(x,y) + coords->dx(x-1,y)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - - val = Acoef * J * g11 / (coords->J(x,y) * dx * coords->dx(x,y)); - xm = val; - c -= val; - - // ZZ component - // Note that because metrics are constant in Z many terms cancel - - // Wrap around z-1 and z+1 indices - int zminus = (z - 1 + (mesh->LocalNz)) % (mesh->LocalNz); - int zplus = (z + 1) % (mesh->LocalNz); - - // Metrics on z+1/2 boundary - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = Acoef * coords->g33(x,y) / (coords->dz*coords->dz); - zp = val; - c -= val; - - // Metrics on z-1/2 boundary - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = Acoef * coords->g33(x,y) / (coords->dz*coords->dz); - zm = val; - c -= val; - - // B term - c += B(x,y,z); - - ///////////////////////////////////////////////// - // Now have a 5-point stencil for the Laplacian - - // Set the centre (diagonal) - MatSetValues(it.MatA, 1, &row, 1, &row, &c, INSERT_VALUES); - - // X + 1 - int col = row + (mesh->LocalNz); - MatSetValues(it.MatA, 1, &row, 1, &col, &xp, INSERT_VALUES); - - // X - 1 - col = row - (mesh->LocalNz); - MatSetValues(it.MatA, 1, &row, 1, &col, &xm, INSERT_VALUES); - - // Z + 1 - col = row + 1; - if(z == mesh->LocalNz-1) { - col -= mesh->LocalNz; // Wrap around - } - MatSetValues(it.MatA, 1, &row, 1, &col, &zp, INSERT_VALUES); - - // Z - 1 - col = row - 1; - if(z == 0) { - col += mesh->LocalNz; // Wrap around - } - MatSetValues(it.MatA, 1, &row, 1, &col, &zm, INSERT_VALUES); - - row++; + // stencil entries + PetscScalar c, xm, xp, zm, zp, xpzp, xpzm, xmzp, xmzm; + PetscScalar zpxp, zpxm, zmxp, zmxm; + + // XX component + + // Metrics on x+1/2 boundary + BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); + BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xp = val; + c = -val; + + // Metrics on x-1/2 boundary + J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); + dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xm = val; + c -= val; + + // ZZ component + // Metrics on z+1/2 boundary + // Wrap around z-1 and z+1 indices + int zminus = (z - 1 + (mesh->LocalNz)) % (mesh->LocalNz); + int zplus = (z + 1) % (mesh->LocalNz); + + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); + BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); + BoutReal dz = coords->dz; + Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + zp = val; + c -= val; + + // Metrics on z-1/2 boundary + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); + g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); + Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + zm = val; + c -= val; + + // XZ components + + // x+1/2, z+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); + dz = 4.0*coords->dz; + Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + xpzp = val; + c -= val; + + // x+1/2, z-1/2 + // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + xpzm = val; + c -= val; + + // x-1/2, z+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + xmzp = val; + c -= val; + + // x-1/2, z-1/2 + Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + xmzm = val; + c -= val; + + + // ZX components + // z+1/2, x+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); + g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + zpxp = val; + c -= val; + + //z+1/2, x-1/2 + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + zpxm = val; + c -= val; + + // z-1/2, x+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); + g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + zmxp = val; + c -= val; + + // z-1/2, x-1/2 + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + zmxm = val; + c -= val; + + + ///////////// OLDER CODE ///////////////// + // Note that because metrics are constant in Z many terms cancel + + // // Wrap around z-1 and z+1 indices + // // int zminus = (z - 1 + (mesh->LocalNz)) % (mesh->LocalNz); + // // int zplus = (z + 1) % (mesh->LocalNz); + + // // Metrics on z+1/2 boundary + // Acoef = 0.5*(A(x,y,z) + A(x,y,z+1)); + + // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); + // zp = val; + // c -= val; + + // // Metrics on z-1/2 boundary + // Acoef = 0.5*(A(x,y,z) + A(x,y,z-1)); + + // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); + // zm = val; + // c -= val; + ////////////////////////////////////////// + + + // B term + c += B(x,y,z); + + ///////////////////////////////////////////////// + // Now have a 5-point stencil for the Laplacian + + // Set the centre (diagonal) + MatSetValues(it.MatA,1,&row,1,&row,&c,INSERT_VALUES); + + // X + 1 + int col = row + (mesh->LocalNz); + MatSetValues(it.MatA,1,&row,1,&col,&xp,INSERT_VALUES); + + // X - 1 + col = row - (mesh->LocalNz); + MatSetValues(it.MatA,1,&row,1,&col,&xm,INSERT_VALUES); + + // Z + 1 + col = row + 1; + if(z == mesh->LocalNz-1) { + col -= mesh->LocalNz; // Wrap around + } + MatSetValues(it.MatA,1,&row,1,&col,&zp,INSERT_VALUES); + + int xzcol = col + (mesh->LocalNz); // X+1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzp,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxp,INSERT_VALUES); + + xzcol = col - (mesh->LocalNz); // X-1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzp,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxm,INSERT_VALUES); + + // Z - 1 + col = row - 1; + if(z == 0) { + col += mesh->LocalNz; // Wrap around + } + MatSetValues(it.MatA,1,&row,1,&col,&zm,INSERT_VALUES); + + xzcol = col + (mesh->LocalNz); // X+1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzm,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxp,INSERT_VALUES); + + xzcol = col - (mesh->LocalNz); // X-1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzm,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxm,INSERT_VALUES); + + row++; } } - + //////////////////////////////////////////////// // Outer X boundary (see note about BC in LaplaceXZ constructor) if(mesh->lastX()) { @@ -665,16 +781,17 @@ Field3D LaplaceXZpetsc::solve(const Field3D &bin, const Field3D &x0in) { // Set the inner points for(int x=mesh->xstart;x<= mesh->xend;x++) { for(int z=0; z < mesh->LocalNz; z++) { - PetscScalar val = x0(x,y,z); - VecSetValues( xs, 1, &ind, &val, INSERT_VALUES ); - - val = b(x,y,z); - VecSetValues( bs, 1, &ind, &val, INSERT_VALUES ); - ind++; + PetscScalar val = x0(x,y,z); + VecSetValues( xs, 1, &ind, &val, INSERT_VALUES ); + + val = b(x,y,z); + VecSetValues( bs, 1, &ind, &val, INSERT_VALUES ); + ind++; } } // Outer X boundary (see note about BC in LaplaceXZ constructor) + if(mesh->lastX()) { if (outer_boundary_flags & INVERT_AC_GRAD){ // Neumann 0 From dc099e606ed9da00239db4c148c6c264a5d2cd0a Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Wed, 9 Jan 2019 08:28:38 +0100 Subject: [PATCH 049/293] Make is3D() a Coordinates member function --- include/bout/coordinates.hxx | 11 +++-------- src/mesh/coordinates.cxx | 8 ++++++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index d4743bac17..e378d2b9a0 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -57,14 +57,6 @@ public: using metric_field_type = Field2D; #endif - bool is3D() { -#ifdef COORDINATES_USE_3D - return true; -#else - return false; -#endif - } - /// Standard constructor from input Coordinates(Mesh *mesh); @@ -118,6 +110,9 @@ public: int calcContravariant(); ///< Invert covariant metric to get contravariant int jacobian(); ///< Calculate J and Bxy + /// Return if the metrics are 3D + bool is3D(); + // Operators const metric_field_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 220aeda7bc..60b47d18df 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1000,3 +1000,11 @@ const Field3D Coordinates::Laplace(const Field3D &f, CELL_LOC outloc) { return result; } + + bool Coordinates::is3D() { +#ifdef COORDINATES_USE_3D + return true; +#else + return false; +#endif +} From 837ea897554646a91cbe1a10c4f551161831e45f Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 22 Jan 2019 13:30:27 +0100 Subject: [PATCH 050/293] Remove assertion for small off-diagonal metrics in LaplaceXZ-petsc * off-diagonal components are now calculated --- src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index df5e7f4c6a..b6ea742a97 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -373,9 +373,6 @@ 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 = localmesh->getCoordinates(location); - - // NOTE: For now the X-Z terms are omitted, so check that they are small - ASSERT2(max(abs(coords->g13)) < 1e-5); for(int x=localmesh->xstart; x <= localmesh->xend; x++) { for(int z=0; z < localmesh->LocalNz; z++) { From 5ee830759ba9c600f8b56cc078a1bb1320704002 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Tue, 22 Jan 2019 14:53:50 +0100 Subject: [PATCH 051/293] Update test for laplacexz * Add basic test for off-diagonal metrics * Add runtest --- tests/integrated/test-laplacexz/data/BOUT.inp | 19 +++++- tests/integrated/test-laplacexz/runtest | 61 +++++++++++++++++++ .../test-laplacexz/test-laplacexz.cxx | 19 ++++++ 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100755 tests/integrated/test-laplacexz/runtest diff --git a/tests/integrated/test-laplacexz/data/BOUT.inp b/tests/integrated/test-laplacexz/data/BOUT.inp index 89265fca24..0f5bff2f69 100644 --- a/tests/integrated/test-laplacexz/data/BOUT.inp +++ b/tests/integrated/test-laplacexz/data/BOUT.inp @@ -1,10 +1,14 @@ +f = gauss(x-0.5,0.05) * gauss(z-pi, 0.25) rhs = sin(x - z) rhs2 = rhs +MXG=1 +MYG=0 + [mesh] -nx = 36 -ny = 2 +nx = 34 +ny = 1 nz = 32 dx = 1 @@ -22,3 +26,14 @@ pctype = lu # Preconditioner. Direct "lu" or "ilu"; iterative "jacobi", "sor" # "superlu", "superlu_dist", "mumps", "cusparse" factor_package = superlu_dist +inner_boundary_flags = 0 +outer_boundary_flags = 0 + +[f] +bndry_all = dirichlet(0.0) +[g] +bndry_all = dirichlet(0.0) +[f2] +bndry_all = dirichlet(0.0) + + diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest new file mode 100755 index 0000000000..0077e13233 --- /dev/null +++ b/tests/integrated/test-laplacexz/runtest @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +# +# Run the test, compare results against the benchmark +# + +from __future__ import print_function +try: + from builtins import str +except: + pass + +tol = 1e-10 # Absolute tolerance + +from boututils.run_wrapper import shell, shell_safe, launch_safe, getmpirun +from boutdata.collect import collect +import numpy as np +from sys import stdout, exit + +MPIRUN = getmpirun() + +print("Making LaplaceXZ test") +shell("rm test-laplacexz") +shell_safe("make > make.log") + +print("Running LaplaceXZ test") +success = True + +for nproc in [1,2,4]: + nxpe = nproc + + cmd = "./test-laplacexz nxpe=" + str(nxpe) + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) + s, out = launch_safe(cmd, runcmd=MPIRUN, nproc=nproc, mthread=1, pipe=True) + with open("run.log."+str(nproc), "w") as f: + f.write(out) + + # Collect output data + f = collect('f', path="data", info=False) + f2 = collect('f2', path="data", info=False) + stdout.write(" Checking tolerance... ") + # Compare benchmark and output + if np.shape(f) != np.shape(f2): + print("Fail, wrong shape") + success = False + diff = np.max(np.abs(f2) - f) + if diff > tol: + print("Fail, maximum difference = "+str(diff)) + success = False + else: + print("Pass") + +if success: + print(" => LaplaceXZ inversion test passed") + exit(0) +else: + print(" => LaplaceXZ test failed") + exit(1) diff --git a/tests/integrated/test-laplacexz/test-laplacexz.cxx b/tests/integrated/test-laplacexz/test-laplacexz.cxx index 54e532f88e..ef4d558857 100644 --- a/tests/integrated/test-laplacexz/test-laplacexz.cxx +++ b/tests/integrated/test-laplacexz/test-laplacexz.cxx @@ -12,12 +12,31 @@ #include #include +#include int main(int argc, char** argv) { BoutInitialise(argc, argv); LaplaceXZ *inv = LaplaceXZ::create(mesh); + Coordinates *coord = mesh->getCoordinates(); + coord->g13 = 1.8; //test off-diagonal components with nonzero value + + // create some input field + Field3D f = FieldFactory::get()->create3D("f", Options::getRoot(), mesh); + + // Calculate the Laplacian with non-zero g13 + Field3D g = coord->g11*D2DX2(f) + coord->g13*D2DXDZ(f) + coord->g33*D2DZ2(f); + + inv->setCoefs(Field2D(1.0),Field2D(0.0)); + + Field3D f2 = inv->solve(g,0.0); // Invert the Laplacian. + + SAVE_ONCE3(f,f2,g); + + coord->g13 = 0.0; //reset to 0.0 for original laplacexz test + + // Now the normal test. output.write("Setting coefficients\n"); inv->setCoefs(Field3D(1.0),Field3D(0.0)); From 724fed77a39f04134a7d99a492c1b4eeb242f35e Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Wed, 23 Jan 2019 08:24:20 +0100 Subject: [PATCH 052/293] Make runtest in test-laplacexz require PETSc --- examples/blob2d-laplacexz/blob2d.cxx | 23 ++++++-- examples/blob2d-laplacexz/data/BOUT.inp | 5 +- include/difops.hxx | 7 +++ src/mesh/difops.cxx | 70 +++++++++++++++++++++++++ tests/integrated/test-laplacexz/runtest | 2 + 5 files changed, 100 insertions(+), 7 deletions(-) diff --git a/examples/blob2d-laplacexz/blob2d.cxx b/examples/blob2d-laplacexz/blob2d.cxx index a22f72adf8..7a59c71a1f 100644 --- a/examples/blob2d-laplacexz/blob2d.cxx +++ b/examples/blob2d-laplacexz/blob2d.cxx @@ -107,6 +107,7 @@ class Blob2D : public PhysicsModel { } int rhs(BoutReal t) { + Coordinates *coord = mesh->getCoordinates(); // Run communications //////////////////////////////////////////////////////////////////////////// @@ -136,8 +137,15 @@ class Blob2D : public PhysicsModel { ///////////////////////////////////////////////////////////////////////////// ddt(n) = -bracket(phi, n, BRACKET_SIMPLE) // ExB term - + 2 * DDZ(n) * (rho_s / R_c) // Curvature term - + D_n * Delp2(n); // Diffusion term + + 2 * DDZ(n) * (rho_s / R_c); // Curvature term + ddt(n) += D_n*Delp2(n, CELL_DEFAULT, false); + + // if(coord->is3D()){ + // ddt(n) += Div_Perp_Lap_FV(D_n, n); // Diffusion term + // }else{ + // ddt(n) += D_n*Delp2(n); + // } + if (compressible) { ddt(n) -= 2 * n * DDZ(phi) * (rho_s / R_c); // ExB Compression term } @@ -151,9 +159,14 @@ class Blob2D : public PhysicsModel { ///////////////////////////////////////////////////////////////////////////// ddt(omega) = -bracket(phi, omega, BRACKET_SIMPLE) // ExB term - + 2 * DDZ(n) * (rho_s / R_c) / n // Curvature term - + D_vort * Delp2(omega) / n // Viscous diffusion term - ; + + 2 * DDZ(n) * (rho_s / R_c) / n; // Curvature term + ddt(omega) += D_vort * Delp2(omega, CELL_DEFAULT, false)/n; // Viscous diffusion term + + // if(coord->is3D()){ + // ddt(omega) += Div_Perp_Lap_FV(D_vort ,omega) / n ; // Viscous diffusion term + // }else{ + // ddt(omega) += D_vort * Delp2(omega)/n; // Viscous diffusion term + // } if (sheath) { ddt(omega) += phi * (rho_s / L_par); diff --git a/examples/blob2d-laplacexz/data/BOUT.inp b/examples/blob2d-laplacexz/data/BOUT.inp index a11be5d365..70eb1360e8 100644 --- a/examples/blob2d-laplacexz/data/BOUT.inp +++ b/examples/blob2d-laplacexz/data/BOUT.inp @@ -9,12 +9,12 @@ NOUT = 50 # number of time-steps TIMESTEP = 1e2 # time between outputs MXG = 2 -MYG = 0 # No y derivatives, so no guard cells needed in y +MYG = 2 # No y derivatives, so no guard cells needed in y [mesh] nx = 68 -ny = 1 +ny = 2 nz = 64 dx = 2.0 @@ -71,6 +71,7 @@ factor_package = superlu_dist type = petsc inner_boundary_flags=2 + ################################################## # general settings for the model diff --git a/include/difops.hxx b/include/difops.hxx index 978599142b..e715d5eea7 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -320,6 +320,13 @@ const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field2D &A, CELL_LOC ou const Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); + +/*! + * X-Z Finite Volume diffusion operator + */ +const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); + + /*! * Poisson bracket methods */ diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index a9b431a22f..d9ef00c10a 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -785,6 +785,76 @@ const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC ou return result; } + +const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { + + Field3D result = 0.0; + + ////////////////////////////////////////// + // X-Z diffusion + // + // Z + // | + // + // o --- gU --- o + // | nU | + // | | + // gL nL nR gR -> X + // | | + // | nD | + // o --- gD --- o + // + Coordinates *coords = a.getCoordinates(outloc); + + + Field3D fs = f; + Field3D as = a; + + for(int i=mesh->xstart;i<=mesh->xend;i++) + for(int j=mesh->ystart;j<=mesh->yend;j++) + for(int k=0;kLocalNz;k++) { + + // wrap k-index around as Z is (currently) periodic. + int kp = (k+1) % (mesh->LocalNz); + int km = (k-1+mesh->LocalNz) % (mesh->LocalNz); + + // Calculate gradients on cell faces -- assumes constant grid spacing + + BoutReal gR = (coords->g11(i,j,k) + coords->g11(i+1,j,k)) * (fs(i+1,j,k) - fs(i,j,k))/(coords->dx(i+1,j,k) + coords->dx(i,j,k)) + + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(fs(i+1,j,kp) - fs(i+1,j,km) + fs(i,j,kp) - fs(i,j,km))/(4.*coords->dz); + + BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(fs(i,j,k) - fs(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) + + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(fs(i-1,j,kp) - fs(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4.*coords->dz); + + BoutReal gD = coords->g13(i,j,k)*(fs(i+1,j,km) - fs(i-1,j,km) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) + + coords->g33(i,j,k)*(fs(i,j,k) - fs(i,j,km))/coords->dz; + + BoutReal gU = coords->g13(i,j,k)*(fs(i+1,j,kp) - fs(i-1,j,kp) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) + + coords->g33(i,j,k)*(fs(i,j,kp) - fs(i,j,k))/coords->dz; + + + // Flow right + BoutReal flux = gR * 0.25*(coords->J(i+1,j,k) + coords->J(i,j,k)) *(as(i+1,j,k) + as(i,j,k)); + result(i,j,k) += flux / (coords->dx(i,j,k)*coords->J(i,j,k)); + + // Flow left + flux = gL * 0.25*(coords->J(i-1,j,k) + coords->J(i,j,k)) *(as(i-1,j,k) + as(i,j,k)); + result(i,j,k) -= flux / (coords->dx(i,j,k)*coords->J(i,j,k)); + + + // Flow up + flux = gU * 0.5*(as(i,j,k) + as(i,j,kp)) / coords->dz; + result(i,j,k) += flux; + + // Flow down + flux = gD * 0.5*(as(i,j,k) + as(i,j,km)) / coords->dz; + result(i,j,k) -= flux; + } + + return result; +} + + /******************************************************************************* * Poisson bracket * Terms of form b0 x Grad(f) dot Grad(g) / B = [f, g] diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index 0077e13233..b6597d9b8e 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +#requires: petsc + # # Run the test, compare results against the benchmark # From e66270c8da78fb6d6aa2759f700116089a64f61d Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Tue, 5 Feb 2019 09:49:36 +0000 Subject: [PATCH 053/293] Restore googletest submodule and disable a unit test --- externalpackages/googletest | 1 + tests/unit/mesh/test_coordinates.cxx | 3 +++ 2 files changed, 4 insertions(+) create mode 160000 externalpackages/googletest diff --git a/externalpackages/googletest b/externalpackages/googletest new file mode 160000 index 0000000000..4bab34d208 --- /dev/null +++ b/externalpackages/googletest @@ -0,0 +1 @@ +Subproject commit 4bab34d2084259cba67f3bfb51217c10d606e175 diff --git a/tests/unit/mesh/test_coordinates.cxx b/tests/unit/mesh/test_coordinates.cxx index 91781334b9..80501af8d8 100644 --- a/tests/unit/mesh/test_coordinates.cxx +++ b/tests/unit/mesh/test_coordinates.cxx @@ -34,6 +34,8 @@ TEST_F(CoordinatesTest, Jacobian) { EXPECT_TRUE(IsField3DEqualBoutReal(coords.Bxy, 1.0)); } +/// To do generalise these tests +#ifndef COORDINATES_USE_3D TEST_F(CoordinatesTest, CalcContravariant) { Coordinates coords{ mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{0.0}, Field2D{0.0}, @@ -71,3 +73,4 @@ TEST_F(CoordinatesTest, CalcCovariant) { EXPECT_TRUE(IsField2DEqualBoutReal(coords.g13, 0.0)); EXPECT_TRUE(IsField2DEqualBoutReal(coords.g23, 0.0)); } +#endif From e65fbc0d20071c375e197ea3c2db7b6afa15f12f Mon Sep 17 00:00:00 2001 From: David Dickinson Date: Fri, 26 Jul 2019 15:33:11 +0100 Subject: [PATCH 054/293] Add a bout_for hermite_spline interpolate --- src/mesh/interpolation/hermite_spline.cxx | 92 +++++++++++------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/mesh/interpolation/hermite_spline.cxx b/src/mesh/interpolation/hermite_spline.cxx index b0c425470a..55c52cb67d 100644 --- a/src/mesh/interpolation/hermite_spline.cxx +++ b/src/mesh/interpolation/hermite_spline.cxx @@ -121,52 +121,52 @@ Field3D HermiteSpline::interpolate(const Field3D &f) const { Field3D fxz = bout::derivatives::index::DDX(fz, CELL_DEFAULT, "DEFAULT"); localmesh->communicateXZ(fxz); - for (int x = localmesh->xstart; x <= localmesh->xend; x++) { - for (int y = localmesh->ystart; y <= localmesh->yend; y++) { - for (int z = 0; z < localmesh->LocalNz; z++) { - - if (skip_mask(x, y, z)) - continue; - - // Due to lack of guard cells in z-direction, we need to ensure z-index - // wraps around - int ncz = localmesh->LocalNz; - int z_mod = ((k_corner(x, y, z) % ncz) + ncz) % ncz; - int z_mod_p1 = (z_mod + 1) % ncz; - - int y_next = y + y_offset; - - // Interpolate f in X at Z - BoutReal f_z = f(i_corner(x, y, z), y_next, z_mod) * h00_x(x, y, z) + - f(i_corner(x, y, z) + 1, y_next, z_mod) * h01_x(x, y, z) + - fx(i_corner(x, y, z), y_next, z_mod) * h10_x(x, y, z) + - fx(i_corner(x, y, z) + 1, y_next, z_mod) * h11_x(x, y, z); - - // Interpolate f in X at Z+1 - BoutReal f_zp1 = f(i_corner(x, y, z), y_next, z_mod_p1) * h00_x(x, y, z) + - f(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h01_x(x, y, z) + - fx(i_corner(x, y, z), y_next, z_mod_p1) * h10_x(x, y, z) + - fx(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h11_x(x, y, z); - - // Interpolate fz in X at Z - BoutReal fz_z = fz(i_corner(x, y, z), y_next, z_mod) * h00_x(x, y, z) + - fz(i_corner(x, y, z) + 1, y_next, z_mod) * h01_x(x, y, z) + - fxz(i_corner(x, y, z), y_next, z_mod) * h10_x(x, y, z) + - fxz(i_corner(x, y, z) + 1, y_next, z_mod) * h11_x(x, y, z); - - // Interpolate fz in X at Z+1 - BoutReal fz_zp1 = fz(i_corner(x, y, z), y_next, z_mod_p1) * h00_x(x, y, z) + - fz(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h01_x(x, y, z) + - fxz(i_corner(x, y, z), y_next, z_mod_p1) * h10_x(x, y, z) + - fxz(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h11_x(x, y, z); - - // Interpolate in Z - f_interp(x, y_next, z) = +f_z * h00_z(x, y, z) + f_zp1 * h01_z(x, y, z) + - fz_z * h10_z(x, y, z) + fz_zp1 * h11_z(x, y, z); - - ASSERT2(finite(f_interp(x, y_next, z))); - } - } + // Due to lack of guard cells in z-direction, we need to ensure z-index + // wraps around + const int ncz = localmesh->LocalNz; + + BOUT_FOR(i, f.getRegion("RGN_NOBNDRY")) { + const int x = i.x(), y = i.y(), z = i.z(); + + if (skip_mask(x, y, z)) + continue; + + // Can these be replaced with i.zp() etc? + const int z_mod = ((k_corner(x, y, z) % ncz) + ncz) % ncz; + const int z_mod_p1 = (z_mod + 1) % ncz; + + // Could this use `yp/ym` or `ypp/ymm`? + const int y_next = y + y_offset; + + // Interpolate f in X at Z + const BoutReal f_z = f(i_corner(x, y, z), y_next, z_mod) * h00_x[i] + + f(i_corner(x, y, z) + 1, y_next, z_mod) * h01_x[i] + + fx(i_corner(x, y, z), y_next, z_mod) * h10_x[i] + + fx(i_corner(x, y, z) + 1, y_next, z_mod) * h11_x[i]; + + // Interpolate f in X at Z+1 + const BoutReal f_zp1 = f(i_corner(x, y, z), y_next, z_mod_p1) * h00_x[i] + + f(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h01_x[i] + + fx(i_corner(x, y, z), y_next, z_mod_p1) * h10_x[i] + + fx(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h11_x[i]; + + // Interpolate fz in X at Z + const BoutReal fz_z = fz(i_corner(x, y, z), y_next, z_mod) * h00_x[i] + + fz(i_corner(x, y, z) + 1, y_next, z_mod) * h01_x[i] + + fxz(i_corner(x, y, z), y_next, z_mod) * h10_x[i] + + fxz(i_corner(x, y, z) + 1, y_next, z_mod) * h11_x[i]; + + // Interpolate fz in X at Z+1 + const BoutReal fz_zp1 = fz(i_corner(x, y, z), y_next, z_mod_p1) * h00_x[i] + + fz(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h01_x[i] + + fxz(i_corner(x, y, z), y_next, z_mod_p1) * h10_x[i] + + fxz(i_corner(x, y, z) + 1, y_next, z_mod_p1) * h11_x[i]; + + // Interpolate in Z + f_interp(x, y_next, z) = +f_z * h00_z[i] + f_zp1 * h01_z[i] + + fz_z * h10_z[i] + fz_zp1 * h11_z[i]; + + ASSERT2(finite(f_interp(x, y_next, z))); } return f_interp; } From c7567fc77f2d455b81b3d9f0730a7097aeb9d957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 26 Jan 2020 10:58:26 +0000 Subject: [PATCH 055/293] enable flags do not need yes/no --enable-fu means enable fu and --disable-fu means disable fu. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1a1b396f23..2c28fadff4 100644 --- a/configure.ac +++ b/configure.ac @@ -91,7 +91,7 @@ AC_ARG_WITH(openmp_schedule,[AS_HELP_STRING([--with-openmp-schedule=static/dynam [Set OpenMP schedule (default: static)])],,[with_openmp_schedule=static]) AC_ARG_ENABLE(pvode_openmp, [AS_HELP_STRING([--enable-pvode-openmp], [Enable building PVODE with OpenMP support])],,[enable_pvode_openmp=no]) -AC_ARG_ENABLE(metric_3d, [AS_HELP_STRING([--enable-metric-3d=no/yes], +AC_ARG_ENABLE(metric_3d, [AS_HELP_STRING([--enable-metric-3d], [If yes use Field3D to store coordinates metric data])],,[enable_metric_3d=no]) AC_ARG_VAR(EXTRA_INCS,[Extra compile flags]) From 1cd6da416773fc27ad87f36f62b56183f4bbf30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 11 Feb 2020 15:10:18 +0000 Subject: [PATCH 056/293] fix derivative function signature provide DD? for coordinates for Field3D --- include/bout/coordinates.hxx | 9 +++++++++ src/mesh/coordinates.cxx | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 921e526709..c965acdcba 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -196,6 +196,15 @@ public: const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, metric_field_type, Field2D); + Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + + Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + + Field3D DDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + /// Gradient along magnetic field b.Grad(f) metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 2b241a4905..3660de5782 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1245,7 +1245,7 @@ Coordinates::metric_field_type Coordinates::DDX(const Field2D& f, CELL_LOC loc, ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDX(f, loc, method, region) / dx; } -const Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, +Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { auto result = bout::derivatives::index::DDX(f, outloc, method, region); @@ -1266,7 +1266,7 @@ Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, return bout::derivatives::index::DDY(f, loc, method, region) / dy; } -const Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, +Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::DDY(f, outloc, method, region) / dy; }; @@ -1282,7 +1282,7 @@ Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), } return zeroFrom(f).setLocation(loc); } -const Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, +Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::DDZ(f, outloc, method, region) / dz; }; From b16650dd91effd6201178268e78e0e9fe737d74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 11 Feb 2020 15:10:49 +0000 Subject: [PATCH 057/293] dx can be 3d field Thus 3rd argument is required --- src/mesh/boundary_standard.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 082d465cb4..fa760e26a1 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -2108,9 +2108,9 @@ void BoundaryNeumann::apply(Field3D &f,BoutReal t) { BoutReal ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell + mesh->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++) { + BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y, zk)+bndry->by*metric->dy(bndry->x,bndry->y, zk); if(fg){ val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*(zk - 0.5)/(mesh->LocalNz),t); } From e81a292f6b6e6dd0aad2816546b96c82a6fc2da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 11 Feb 2020 15:12:00 +0000 Subject: [PATCH 058/293] Provide 2D and 3D version of inter/extrapolate --- src/mesh/coordinates.cxx | 119 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 3660de5782..6775018bd9 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -26,7 +26,7 @@ namespace { /// Boundary guard cells are set by extrapolating from the grid, like /// 'free_o3' boundary conditions /// Corner guard cells are set to BoutNaN -Coordinates::metric_field_type interpolateAndExtrapolate(const Coordinates::metric_field_type& f, CELL_LOC location, +Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, bool extrapolate_x = true, bool extrapolate_y = true, bool no_extra_interpolate = false) { @@ -129,6 +129,123 @@ Coordinates::metric_field_type interpolateAndExtrapolate(const Coordinates::metr return result; } +Field3D interpolateAndExtrapolate(const Field3D& f, CELL_LOC location, + bool extrapolate_x = true, bool extrapolate_y = true, + bool no_extra_interpolate = false) { + + Mesh* localmesh = f.getMesh(); + auto result = interp_to(f, location, "RGN_NOBNDRY"); + // Ensure result's data is unique. Otherwise result might be a duplicate of + // f (if no interpolation is needed, e.g. if interpolation is in the + // z-direction); then f would be communicated. Since this function is used + // on geometrical quantities that might not be periodic in y even on closed + // field lines (due to dependence on integrated shear), we don't want to + // communicate f. We will sort out result's boundary guard cells below, but + // not f's so we don't want to change f. + result.allocate(); + localmesh->communicate(result); + + // Extrapolate into boundaries (if requested) so that differential geometry + // terms can be interpolated if necessary + // Note: cannot use applyBoundary("free_o3") here because applyBoundary() + // would try to create a new Coordinates object since we have not finished + // initializing yet, leading to an infinite recursion. + // Also, here we interpolate for the boundary points at xstart/ystart and + // (xend+1)/(yend+1) instead of extrapolating. + for (auto& bndry : localmesh->getBoundaries()) { + if ((extrapolate_x and bndry->bx != 0) or (extrapolate_y and bndry->by != 0)) { + int extrap_start = 0; + if (not no_extra_interpolate) { + // Can use no_extra_interpolate argument to skip the extra interpolation when we + // want to extrapolate the Christoffel symbol terms which come from derivatives so + // don't have the extra point set already + if ((location == CELL_XLOW) && (bndry->bx > 0)) { + extrap_start = 1; + } else if ((location == CELL_YLOW) && (bndry->by > 0)) { + extrap_start = 1; + } + } + for (bndry->first(); !bndry->isDone(); bndry->next1d()) { + // interpolate extra boundary point that is missed by interp_to, if + // necessary. + // Only interpolate this point if we are actually changing location. E.g. + // when we use this function to extrapolate J and Bxy on staggered grids, + // this point should already be set correctly because the metric + // components have been interpolated to here. + if (extrap_start > 0 and f.getLocation() != location) { + ASSERT1(bndry->bx == 0 or localmesh->xstart > 1); + ASSERT1(bndry->by == 0 or localmesh->ystart > 1); + // note that either bx or by is >0 here + for (int zi=0; zi < localmesh->LocalNz; ++zi){ + result(bndry->x, bndry->y, zi) = + (9. * (f(bndry->x - bndry->bx, bndry->y - bndry->by, zi) + f(bndry->x, bndry->y, zi)) + - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, zi) + - f(bndry->x + bndry->bx, bndry->y + bndry->by, zi)) + / 16.; + } + + // set boundary guard cells + if ((bndry->bx != 0 && localmesh->GlobalNx - 2 * bndry->width >= 3) + || (bndry->by != 0 + && localmesh->GlobalNy - 2 * bndry->width + >= 3)) + { + if (bndry->bx != 0 && localmesh->LocalNx == 1 && bndry->width == 1) { + throw BoutException( + "Not enough points in the x-direction on this " + "processor for extrapolation needed to use staggered grids. " + "Increase number of x-guard cells MXG or decrease number of " + "processors in the x-direction NXPE."); + } + if (bndry->by != 0 && localmesh->LocalNy == 1 && bndry->width == 1) { + throw BoutException( + "Not enough points in the y-direction on this " + "processor for extrapolation needed to use staggered grids. " + "Increase number of y-guard cells MYG or decrease number of " + "processors in the y-direction NYPE."); + } + // extrapolate into boundary guard cells if there are enough grid points + for (int i = extrap_start; i < bndry->width; i++) { + int xi = bndry->x + i * bndry->bx; + int yi = bndry->y + i * bndry->by; + for (int zi=0; zi < localmesh->LocalNz; ++zi){ + result(xi, yi, zi) = 3.0 * result(xi - bndry->bx, yi - bndry->by, zi) + - 3.0 * result(xi - 2 * bndry->bx, yi - 2 * bndry->by, zi) + + result(xi - 3 * bndry->bx, yi - 3 * bndry->by, zi); + } + } + } else { + // not enough grid points to extrapolate, set equal to last grid point + for (int i = extrap_start; i < bndry->width; i++) { + for (int zi = 0; zi < localmesh->LocalNz; ++zi){ + result(bndry->x + i * bndry->bx, bndry->y + i * bndry->by, zi) = + result(bndry->x - bndry->bx, bndry->y - bndry->by, zi); + } + } + } + } + } + } + + // Set corner guard cells + for (int i = 0; i < localmesh->xstart; i++) { + for (int j = 0; j < localmesh->ystart; j++) { + for (int zi = 0; zi < localmesh->LocalNz; ++zi){ + result(i, j, zi) = BoutNaN; + result(i, localmesh->LocalNy - 1 - j, zi) = BoutNaN; + result(localmesh->LocalNx - 1 - i, j, zi) = BoutNaN; + result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, zi) = BoutNaN; + } + } + } + + return result; + //throw BoutException("NotImplemented (3D)"); + } +} + + + // If the CELL_CENTRE variable was read, the staggered version is required to // also exist for consistency void checkStaggeredGet(Mesh* mesh, const std::string& name, const std::string& suffix) { From 5c3b51a0696ce5f9d9ca5eec9bcc3f091c22d2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 11 Feb 2020 15:12:49 +0000 Subject: [PATCH 059/293] getAtLoc should take metric_field_type --- 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 6775018bd9..977a5c5db9 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -256,7 +256,7 @@ void checkStaggeredGet(Mesh* mesh, const std::string& name, const std::string& s } // convenience function for repeated code -void getAtLoc(Mesh* mesh, Field2D &var, const std::string& name, +void getAtLoc(Mesh* mesh, Coordinates::metric_field_type &var, const std::string& name, const std::string& suffix, CELL_LOC location, BoutReal default_value = 0.) { checkStaggeredGet(mesh, name, suffix); From c5ba486604973f1b534c2fc1c4b37bdc027f528f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 13 Feb 2020 14:04:32 +0000 Subject: [PATCH 060/293] ensure quiet script isn't to verbose on error --- tests/unit/quiet.sh | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/unit/quiet.sh b/tests/unit/quiet.sh index f702cff791..1b29fd53e2 100755 --- a/tests/unit/quiet.sh +++ b/tests/unit/quiet.sh @@ -1,9 +1,7 @@ #!/usr/bin/env bash -set -o pipefail -for cmd in $@ -do - $cmd | awk '{ +function _awk () { + awk '{ if (match($0,"^$")) { empty=1 #print "empty", $0 @@ -43,5 +41,11 @@ do } if (out) print $0 -}' || exit +}' +} + +set -o pipefail +for cmd in $@ +do + $cmd | _awk || exit done From 40af75626e917dae492db6e5c9d862f752c74d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 14 Feb 2020 17:49:52 +0000 Subject: [PATCH 061/293] Fix tests/integrated/test-io/runtest after merge broke it --- tests/integrated/test-io/runtest | 68 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index a90dc68521..b6e36d70cd 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -52,7 +52,6 @@ for nproc in [1,2,4]: extra_args = "" cmd = "./test_io" + extra_args - # TODO: INDENT BELOW # On some machines need to delete dmp files first # or data isn't written correctly @@ -76,40 +75,39 @@ for nproc in [1,2,4]: # Collect output data for v in vars: - stdout.write(" Checking variable "+v+" ... ") - result = collect(v, path="data", info=False) - - # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - if not ( - (v.startswith("v2d_")) and - np.shape(bmk[v]) == np.shape(result[:,:,:,0]) ): - - print("Fail, wrong shape") - success = False - continue - else: - result = result[:,:,:,0] - - diff = np.max(np.abs(bmk[v] - result)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - continue - - if v in field_vars: - # Check cell location - if "cell_location" not in result.attributes: - print("Fail: {0} has no cell_location attribute".format(v)) - success = False - continue - - if result.attributes["cell_location"] != "CELL_CENTRE": - print("Fail: Expecting cell_location == CELL_CENTRE, but got {0}".format(result.attributes["cell_location"])) - success = False - continue - - print("Pass") + stdout.write(" Checking variable "+v+" ... ") + result = collect(v, path="data", info=False) + + # Compare benchmark and output + if np.shape(bmk[v]) != np.shape(result): + if not ( + (v.startswith("v2d_")) and + np.shape(bmk[v]) == np.shape(result[:,:,:,0]) ): + print("Fail, wrong shape") + success = False + continue + else: + result = result[:,:,:,0] + + diff = np.max(np.abs(bmk[v] - result)) + if diff > tol: + print("Fail, maximum difference = "+str(diff)) + success = False + continue + + if v in field_vars: + # Check cell location + if "cell_location" not in result.attributes: + print("Fail: {0} has no cell_location attribute".format(v)) + success = False + continue + + if result.attributes["cell_location"] != "CELL_CENTRE": + print("Fail: Expecting cell_location == CELL_CENTRE, but got {0}".format(result.attributes["cell_location"])) + success = False + continue + + print("Pass") if success: print(" => All I/O tests passed") From 3f2ed05758b43fe129ba72a16464ee4c624b8136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 15 Feb 2020 16:12:32 +0000 Subject: [PATCH 062/293] Better debug messages for fields compatibility Rather then failing with fields are not compatible, the error now contains information about which part is not compatible, and what the specific missmatched types are. --- include/bout/fv_ops.hxx | 6 +- include/field.hxx | 32 +++++++++ include/utils.hxx | 4 ++ include/where.hxx | 8 +-- src/field/field3d.cxx | 8 +-- src/field/gen_fieldops.jinja | 4 +- src/field/generated_fieldops.cxx | 120 +++++++++++++++---------------- src/mesh/difops.cxx | 12 ++-- src/mesh/fv_ops.cxx | 2 +- src/solver/solver.cxx | 2 +- src/sys/options.cxx | 6 +- 11 files changed, 120 insertions(+), 84 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index b0fcc92cd7..d46f79a0e9 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -182,8 +182,8 @@ namespace FV { const Field3D Div_par(const Field3D &f_in, const Field3D &v_in, const Field3D &wave_speed_in, bool fixflux=true) { - ASSERT1(areFieldsCompatible(f_in, v_in)); - ASSERT1(areFieldsCompatible(f_in, wave_speed_in)); + ASSERT1_FIELDS_COMPATIBLE(f_in, v_in); + ASSERT1_FIELDS_COMPATIBLE(f_in, wave_speed_in); Mesh* mesh = f_in.getMesh(); @@ -354,7 +354,7 @@ namespace FV { template const Field3D Div_f_v(const Field3D &n_in, const Vector3D &v, bool bndry_flux) { ASSERT1(n_in.getLocation() == v.getLocation()); - ASSERT1(areFieldsCompatible(n_in, v.x)); + ASSERT1_FIELDS_COMPATIBLE(n_in, v.x); Mesh* mesh = n_in.getMesh(); diff --git a/include/field.hxx b/include/field.hxx index e3b4ac6d61..84b7013ec8 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -191,6 +191,38 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { areDirectionsCompatible(field1.getDirections(), field2.getDirections()); } +#if CHECKLEVEL >= 1 +#define ASSERT1_FIELDS_COMPATIBLE(field1, field2) \ + if ((field1).getLocation() != (field2).getLocation()){ \ + throw BoutException("Error in %s:%d\nFields at different position:" \ + "`%s` at %s, `%s` at %s",__FILE__,__LINE__, \ + #field1, toString((field1).getLocation()).c_str(), \ + #field2, toString((field2).getLocation()).c_str()); \ + } \ + if ((field1).getCoordinates() != (field2).getCoordinates()){ \ + throw BoutException("Error in %s:%d\nFields have different coordinates:" \ + "`%s` at %p, `%s` at %p",__FILE__,__LINE__, \ + #field1, (field1).getCoordinates(), \ + #field2, (field2).getCoordinates()); \ + } \ + if ((field1).getMesh() != (field2).getMesh()){ \ + throw BoutException("Error in %s:%d\nFields are on different Meshes:" \ + "`%s` at %p, `%s` at %p",__FILE__,__LINE__, \ + #field1, (field1).getMesh(), \ + #field2, (field2).getMesh()); \ + } \ + if (!areDirectionsCompatible((field1).getDirections(), \ + (field2).getDirections())){ \ + throw BoutException("Error in %s:%d\nFields at different directions:" \ + "`%s` at %s, `%s` at %s",__FILE__,__LINE__, \ + #field1, toString((field1).getDirections()).c_str(), \ + #field2, toString((field2).getDirections()).c_str()); \ + } + +#else +#define ASSERT1_FIELDS_COMPATIBLE(field1, field2); +#endif + /// Return an empty shell field of some type derived from Field, with metadata /// copied and a data array that is allocated but not initialised. template diff --git a/include/utils.hxx b/include/utils.hxx index 735f422ca3..ff578f6de0 100644 --- a/include/utils.hxx +++ b/include/utils.hxx @@ -491,6 +491,10 @@ inline std::string toString(const bool& val) { return "false"; } +inline std::string toString(const DirectionTypes& dir) { + return "{"+toString(dir.y)+", "+toString(dir.z)+"}"; +} + /// Convert a time stamp to a string /// This uses std::localtime and std::put_time std::string toString(const time_t& time); diff --git a/include/where.hxx b/include/where.hxx index 1a3a7aff18..a024f67dc1 100644 --- a/include/where.hxx +++ b/include/where.hxx @@ -40,8 +40,8 @@ template > auto where(const T& test, const U& gt0, const V& le0) -> ResultType { - ASSERT1(areFieldsCompatible(test, gt0)); - ASSERT1(areFieldsCompatible(test, le0)); + ASSERT1_FIELDS_COMPATIBLE(test, gt0); + ASSERT1_FIELDS_COMPATIBLE(test, le0); ResultType result{emptyFrom(test)}; @@ -53,7 +53,7 @@ auto where(const T& test, const U& gt0, const V& le0) -> ResultType { template > auto where(const T& test, const U& gt0, BoutReal le0) -> ResultType { - ASSERT1(areFieldsCompatible(test, gt0)); + ASSERT1_FIELDS_COMPATIBLE(test, gt0); ResultType result{emptyFrom(test)}; @@ -65,7 +65,7 @@ auto where(const T& test, const U& gt0, BoutReal le0) -> ResultType { template > auto where(const T& test, BoutReal gt0, const V& le0) -> ResultType { - ASSERT1(areFieldsCompatible(test, le0)); + ASSERT1_FIELDS_COMPATIBLE(test, le0); ResultType result{emptyFrom(test)}; diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index ea9527fe05..74c3b80b9e 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -282,7 +282,7 @@ Field3D & Field3D::operator=(const Field2D &rhs) { /// Make sure there's a unique array to copy data into allocate(); - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); /// Copy data BOUT_FOR(i, rhs.getRegion("RGN_ALL")) { @@ -297,7 +297,7 @@ Field3D & Field3D::operator=(const Field2D &rhs) { void Field3D::operator=(const FieldPerp &rhs) { TRACE("Field3D = FieldPerp"); - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); /// Check that the data is allocated ASSERT1(rhs.isAllocated()); @@ -610,7 +610,7 @@ Field3D pow(const Field3D &lhs, const Field2D &rhs, const std::string& rgn) { // Check if the inputs are allocated checkData(lhs); checkData(rhs); - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); // Define and allocate the output result Field3D result{emptyFrom(lhs)}; @@ -626,7 +626,7 @@ FieldPerp pow(const Field3D &lhs, const FieldPerp &rhs, const std::string& rgn) checkData(lhs); checkData(rhs); - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; diff --git a/src/field/gen_fieldops.jinja b/src/field/gen_fieldops.jinja index 42e420767a..249245b21c 100644 --- a/src/field/gen_fieldops.jinja +++ b/src/field/gen_fieldops.jinja @@ -1,7 +1,7 @@ // Provide the C++ wrapper for {{operator_name}} of {{lhs}} and {{rhs}} {{out}} operator{{operator}}(const {{lhs.passByReference}}, const {{rhs.passByReference}}) { {% if lhs != "BoutReal" and rhs != "BoutReal" %} - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); {% endif %} {{out.field_type}} {{out.name}}{emptyFrom({{lhs.name if lhs.field_type == out.field_type else rhs.name}})}; @@ -61,7 +61,7 @@ // otherwise just call the non-inplace version if (data.unique()) { {% if lhs != "BoutReal" and rhs != "BoutReal" %} - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); {% endif %} {% if (lhs == "Field3D") %} diff --git a/src/field/generated_fieldops.cxx b/src/field/generated_fieldops.cxx index 1058c42340..91fe31f3d1 100644 --- a/src/field/generated_fieldops.cxx +++ b/src/field/generated_fieldops.cxx @@ -8,7 +8,7 @@ // Provide the C++ wrapper for multiplication of Field3D and Field3D Field3D operator*(const Field3D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -27,7 +27,7 @@ Field3D& Field3D::operator*=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -48,7 +48,7 @@ Field3D& Field3D::operator*=(const Field3D& rhs) { // Provide the C++ wrapper for division of Field3D and Field3D Field3D operator/(const Field3D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -67,7 +67,7 @@ Field3D& Field3D::operator/=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -88,7 +88,7 @@ Field3D& Field3D::operator/=(const Field3D& rhs) { // Provide the C++ wrapper for addition of Field3D and Field3D Field3D operator+(const Field3D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -107,7 +107,7 @@ Field3D& Field3D::operator+=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -128,7 +128,7 @@ Field3D& Field3D::operator+=(const Field3D& rhs) { // Provide the C++ wrapper for subtraction of Field3D and Field3D Field3D operator-(const Field3D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -147,7 +147,7 @@ Field3D& Field3D::operator-=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -168,7 +168,7 @@ Field3D& Field3D::operator-=(const Field3D& rhs) { // Provide the C++ wrapper for multiplication of Field3D and Field2D Field3D operator*(const Field3D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -192,7 +192,7 @@ Field3D& Field3D::operator*=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -218,7 +218,7 @@ Field3D& Field3D::operator*=(const Field2D& rhs) { // Provide the C++ wrapper for division of Field3D and Field2D Field3D operator/(const Field3D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -243,7 +243,7 @@ Field3D& Field3D::operator/=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -270,7 +270,7 @@ Field3D& Field3D::operator/=(const Field2D& rhs) { // Provide the C++ wrapper for addition of Field3D and Field2D Field3D operator+(const Field3D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -294,7 +294,7 @@ Field3D& Field3D::operator+=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -320,7 +320,7 @@ Field3D& Field3D::operator+=(const Field2D& rhs) { // Provide the C++ wrapper for subtraction of Field3D and Field2D Field3D operator-(const Field3D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(lhs)}; checkData(lhs); @@ -344,7 +344,7 @@ Field3D& Field3D::operator-=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); // Delete existing parallel slices. We don't copy parallel slices, so any // that currently exist will be incorrect. @@ -370,7 +370,7 @@ Field3D& Field3D::operator-=(const Field2D& rhs) { // Provide the C++ wrapper for multiplication of Field3D and FieldPerp FieldPerp operator*(const Field3D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -390,7 +390,7 @@ FieldPerp operator*(const Field3D& lhs, const FieldPerp& rhs) { // Provide the C++ wrapper for division of Field3D and FieldPerp FieldPerp operator/(const Field3D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -410,7 +410,7 @@ FieldPerp operator/(const Field3D& lhs, const FieldPerp& rhs) { // Provide the C++ wrapper for addition of Field3D and FieldPerp FieldPerp operator+(const Field3D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -430,7 +430,7 @@ FieldPerp operator+(const Field3D& lhs, const FieldPerp& rhs) { // Provide the C++ wrapper for subtraction of Field3D and FieldPerp FieldPerp operator-(const Field3D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -596,7 +596,7 @@ Field3D& Field3D::operator-=(const BoutReal rhs) { // Provide the C++ wrapper for multiplication of Field2D and Field3D Field3D operator*(const Field2D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(rhs)}; checkData(lhs); @@ -617,7 +617,7 @@ Field3D operator*(const Field2D& lhs, const Field3D& rhs) { // Provide the C++ wrapper for division of Field2D and Field3D Field3D operator/(const Field2D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(rhs)}; checkData(lhs); @@ -638,7 +638,7 @@ Field3D operator/(const Field2D& lhs, const Field3D& rhs) { // Provide the C++ wrapper for addition of Field2D and Field3D Field3D operator+(const Field2D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(rhs)}; checkData(lhs); @@ -659,7 +659,7 @@ Field3D operator+(const Field2D& lhs, const Field3D& rhs) { // Provide the C++ wrapper for subtraction of Field2D and Field3D Field3D operator-(const Field2D& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field3D result{emptyFrom(rhs)}; checkData(lhs); @@ -680,7 +680,7 @@ Field3D operator-(const Field2D& lhs, const Field3D& rhs) { // Provide the C++ wrapper for multiplication of Field2D and Field2D Field2D operator*(const Field2D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field2D result{emptyFrom(lhs)}; checkData(lhs); @@ -699,7 +699,7 @@ Field2D& Field2D::operator*=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -716,7 +716,7 @@ Field2D& Field2D::operator*=(const Field2D& rhs) { // Provide the C++ wrapper for division of Field2D and Field2D Field2D operator/(const Field2D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field2D result{emptyFrom(lhs)}; checkData(lhs); @@ -735,7 +735,7 @@ Field2D& Field2D::operator/=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -752,7 +752,7 @@ Field2D& Field2D::operator/=(const Field2D& rhs) { // Provide the C++ wrapper for addition of Field2D and Field2D Field2D operator+(const Field2D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field2D result{emptyFrom(lhs)}; checkData(lhs); @@ -771,7 +771,7 @@ Field2D& Field2D::operator+=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -788,7 +788,7 @@ Field2D& Field2D::operator+=(const Field2D& rhs) { // Provide the C++ wrapper for subtraction of Field2D and Field2D Field2D operator-(const Field2D& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); Field2D result{emptyFrom(lhs)}; checkData(lhs); @@ -807,7 +807,7 @@ Field2D& Field2D::operator-=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -824,7 +824,7 @@ Field2D& Field2D::operator-=(const Field2D& rhs) { // Provide the C++ wrapper for multiplication of Field2D and FieldPerp FieldPerp operator*(const Field2D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -844,7 +844,7 @@ FieldPerp operator*(const Field2D& lhs, const FieldPerp& rhs) { // Provide the C++ wrapper for division of Field2D and FieldPerp FieldPerp operator/(const Field2D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -864,7 +864,7 @@ FieldPerp operator/(const Field2D& lhs, const FieldPerp& rhs) { // Provide the C++ wrapper for addition of Field2D and FieldPerp FieldPerp operator+(const Field2D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -884,7 +884,7 @@ FieldPerp operator+(const Field2D& lhs, const FieldPerp& rhs) { // Provide the C++ wrapper for subtraction of Field2D and FieldPerp FieldPerp operator-(const Field2D& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(rhs)}; checkData(lhs); @@ -1034,7 +1034,7 @@ Field2D& Field2D::operator-=(const BoutReal rhs) { // Provide the C++ wrapper for multiplication of FieldPerp and Field3D FieldPerp operator*(const FieldPerp& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1057,7 +1057,7 @@ FieldPerp& FieldPerp::operator*=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1080,7 +1080,7 @@ FieldPerp& FieldPerp::operator*=(const Field3D& rhs) { // Provide the C++ wrapper for division of FieldPerp and Field3D FieldPerp operator/(const FieldPerp& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1103,7 +1103,7 @@ FieldPerp& FieldPerp::operator/=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1126,7 +1126,7 @@ FieldPerp& FieldPerp::operator/=(const Field3D& rhs) { // Provide the C++ wrapper for addition of FieldPerp and Field3D FieldPerp operator+(const FieldPerp& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1149,7 +1149,7 @@ FieldPerp& FieldPerp::operator+=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1172,7 +1172,7 @@ FieldPerp& FieldPerp::operator+=(const Field3D& rhs) { // Provide the C++ wrapper for subtraction of FieldPerp and Field3D FieldPerp operator-(const FieldPerp& lhs, const Field3D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1195,7 +1195,7 @@ FieldPerp& FieldPerp::operator-=(const Field3D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1218,7 +1218,7 @@ FieldPerp& FieldPerp::operator-=(const Field3D& rhs) { // Provide the C++ wrapper for multiplication of FieldPerp and Field2D FieldPerp operator*(const FieldPerp& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1241,7 +1241,7 @@ FieldPerp& FieldPerp::operator*=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1264,7 +1264,7 @@ FieldPerp& FieldPerp::operator*=(const Field2D& rhs) { // Provide the C++ wrapper for division of FieldPerp and Field2D FieldPerp operator/(const FieldPerp& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1287,7 +1287,7 @@ FieldPerp& FieldPerp::operator/=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1310,7 +1310,7 @@ FieldPerp& FieldPerp::operator/=(const Field2D& rhs) { // Provide the C++ wrapper for addition of FieldPerp and Field2D FieldPerp operator+(const FieldPerp& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1333,7 +1333,7 @@ FieldPerp& FieldPerp::operator+=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1356,7 +1356,7 @@ FieldPerp& FieldPerp::operator+=(const Field2D& rhs) { // Provide the C++ wrapper for subtraction of FieldPerp and Field2D FieldPerp operator-(const FieldPerp& lhs, const Field2D& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1379,7 +1379,7 @@ FieldPerp& FieldPerp::operator-=(const Field2D& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1402,7 +1402,7 @@ FieldPerp& FieldPerp::operator-=(const Field2D& rhs) { // Provide the C++ wrapper for multiplication of FieldPerp and FieldPerp FieldPerp operator*(const FieldPerp& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1421,7 +1421,7 @@ FieldPerp& FieldPerp::operator*=(const FieldPerp& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1438,7 +1438,7 @@ FieldPerp& FieldPerp::operator*=(const FieldPerp& rhs) { // Provide the C++ wrapper for division of FieldPerp and FieldPerp FieldPerp operator/(const FieldPerp& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1457,7 +1457,7 @@ FieldPerp& FieldPerp::operator/=(const FieldPerp& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1474,7 +1474,7 @@ FieldPerp& FieldPerp::operator/=(const FieldPerp& rhs) { // Provide the C++ wrapper for addition of FieldPerp and FieldPerp FieldPerp operator+(const FieldPerp& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1493,7 +1493,7 @@ FieldPerp& FieldPerp::operator+=(const FieldPerp& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); @@ -1510,7 +1510,7 @@ FieldPerp& FieldPerp::operator+=(const FieldPerp& rhs) { // Provide the C++ wrapper for subtraction of FieldPerp and FieldPerp FieldPerp operator-(const FieldPerp& lhs, const FieldPerp& rhs) { - ASSERT1(areFieldsCompatible(lhs, rhs)); + ASSERT1_FIELDS_COMPATIBLE(lhs, rhs); FieldPerp result{emptyFrom(lhs)}; checkData(lhs); @@ -1529,7 +1529,7 @@ FieldPerp& FieldPerp::operator-=(const FieldPerp& rhs) { // only if data is unique we update the field // otherwise just call the non-inplace version if (data.unique()) { - ASSERT1(areFieldsCompatible(*this, rhs)); + ASSERT1_FIELDS_COMPATIBLE(*this, rhs); checkData(*this); checkData(rhs); diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 7ed0281968..9ba2f8846a 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -76,7 +76,7 @@ const Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC o const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { #ifndef COORDINATES_USE_3D - ASSERT1(areFieldsCompatible(apar, f)); + ASSERT1_FIELDS_COMPATIBLE(apar, f); ASSERT1(f.hasParallelSlices()); Mesh *mesh = apar.getMesh(); @@ -213,7 +213,7 @@ const Field3D Div_par(const Field3D &f, const std::string &method, CELL_LOC outl } const Field3D Div_par(const Field3D& f, const Field3D& v) { - ASSERT1(areFieldsCompatible(f, v)); + ASSERT1_FIELDS_COMPATIBLE(f, v); ASSERT1(f.hasParallelSlices()); ASSERT1(v.hasParallelSlices()); @@ -616,7 +616,7 @@ const Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, Solver* UNUSED(solver)) { TRACE("bracket(Field2D, Field2D)"); - ASSERT1(areFieldsCompatible(f, g)); + ASSERT1_FIELDS_COMPATIBLE(f, g); if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); } @@ -639,7 +639,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *solver) { TRACE("bracket(Field3D, Field2D)"); - ASSERT1(areFieldsCompatible(f, g)); + ASSERT1_FIELDS_COMPATIBLE(f, g); if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); } @@ -827,7 +827,7 @@ const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *solver) { TRACE("bracket(Field2D, Field3D)"); - ASSERT1(areFieldsCompatible(f, g)); + ASSERT1_FIELDS_COMPATIBLE(f, g); if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); } @@ -864,7 +864,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *solver) { TRACE("Field3D, Field3D"); - ASSERT1(areFieldsCompatible(f, g)); + ASSERT1_FIELDS_COMPATIBLE(f, g); if (outloc == CELL_DEFAULT) { outloc = g.getLocation(); } diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index f570391936..b67a9771d7 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -234,7 +234,7 @@ namespace FV { } const Field3D D4DY4(const Field3D &d_in, const Field3D &f_in) { - ASSERT1(areFieldsCompatible(d_in, f_in)); + ASSERT1_FIELDS_COMPATIBLE(d_in, f_in); Mesh* mesh = d_in.getMesh(); diff --git a/src/solver/solver.cxx b/src/solver/solver.cxx index aa0c27db4f..c6fbe2d098 100644 --- a/src/solver/solver.cxx +++ b/src/solver/solver.cxx @@ -1275,7 +1275,7 @@ void Solver::post_rhs(BoutReal UNUSED(t)) { // Make sure 3D fields are at the correct cell location, etc. for (MAYBE_UNUSED(const auto& f) : f3d) { - ASSERT1(areFieldsCompatible(*f.var, *f.F_var)); + ASSERT1_FIELDS_COMPATIBLE(*f.var, *f.F_var); } // Apply boundary conditions to the time-derivatives diff --git a/src/sys/options.cxx b/src/sys/options.cxx index 0683cd2f17..5dca75ae6a 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -339,7 +339,7 @@ template <> Field3D Options::as(const Field3D& similar_to) const { Field3D stored_value = bout::utils::get(value); // Check that meta-data is consistent - ASSERT1(areFieldsCompatible(stored_value, similar_to)); + ASSERT1_FIELDS_COMPATIBLE(stored_value, similar_to); return stored_value; } @@ -348,7 +348,7 @@ template <> Field3D Options::as(const Field3D& similar_to) const { const auto& stored_value = bout::utils::get(value); // Check that meta-data is consistent - ASSERT1(areFieldsCompatible(stored_value, similar_to)); + ASSERT1_FIELDS_COMPATIBLE(stored_value, similar_to); return Field3D(stored_value); } @@ -403,7 +403,7 @@ template <> Field2D Options::as(const Field2D& similar_to) const { Field2D stored_value = bout::utils::get(value); // Check that meta-data is consistent - ASSERT1(areFieldsCompatible(stored_value, similar_to)); + ASSERT1_FIELDS_COMPATIBLE(stored_value, similar_to); return stored_value; } From 4c06a94a76668e1128300055f3ac54a91babfd44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 15 Feb 2020 16:25:18 +0000 Subject: [PATCH 063/293] Ensure coordinates can be constructed interp_to, communicate() and to/fromFieldAligned require that the coordinates have been constructed. * Thus some care has to be taken, to e.g. only call communicateXZ rather then communicate. Otherwise communicate might also calculate the parallel fields, which fails because coordinate is not valid. * While calling interp_to, we need to ensure fields are fieldaligned if the direction is Y. * the free to/from fieldaligned function read the fields coordinate system. While in the constructor, this hasn't been yet set. But we already now it, so we can directly call it, if we have created the parallel transform. * create3D tries to interpolate from fieldAligned. This doesn't work in the constructor, and we need to do this manually (done in interpolateAndExtrapolate) with maybeFromFieldAligned --- include/bout/coordinates.hxx | 16 ++ src/field/field3d.cxx | 7 + src/field/field_factory.cxx | 36 +-- src/mesh/coordinates.cxx | 425 +++++++++++++++++++---------------- 4 files changed, 277 insertions(+), 207 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index c965acdcba..8b4e084f37 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -283,6 +283,22 @@ private: /// Set the parallel (y) transform from the options file. /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); + template + inline T maybeFromFieldAligned(const T& f, const std::string& region = "RGN_ALL") { + static_assert(bout::utils::is_Field::value, "fromFieldAligned only works on Fields"); + ASSERT1(location == f.getLocation()); + ASSERT1(localmesh == f.getMesh()); + if (f.getDirectionY() != YDirectionType::Standard){ + return this->getParallelTransform().fromFieldAligned(f, region); + } + return f; + } + + /// A wrapper for index:DDY derivative that is able to tranform + /// fields before the constructor is finished. + Coordinates::metric_field_type indexDDY(const Coordinates::metric_field_type& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + }; /* diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 74c3b80b9e..32459b5cb8 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -204,6 +204,13 @@ Field3D &Field3D::ynext(int dir) { } bool Field3D::requiresTwistShift(bool twist_shift_enabled) { + // Workaround for 3D coordinates. + // We need to communicate in the coordinates constructure in that + // case a Field3D, but coordinates isn't valid yet. As such we + // disable twist-shift in that case. + if (getCoordinates() == nullptr){ + return false; + } return getCoordinates()->getParallelTransform().requiresTwistShift(twist_shift_enabled, getDirectionY()); } diff --git a/src/field/field_factory.cxx b/src/field/field_factory.cxx index d7f3c00eed..696d90cdfc 100644 --- a/src/field/field_factory.cxx +++ b/src/field/field_factory.cxx @@ -226,14 +226,19 @@ Field3D FieldFactory::create3D(FieldGeneratorPtr gen, Mesh* localmesh, CELL_LOC if (transform_from_field_aligned) { auto coords = result.getCoordinates(); if (coords == nullptr) { - throw BoutException("Unable to transform result: Mesh does not have Coordinates set"); - } - if (coords->getParallelTransform().canToFromFieldAligned()) { - // Transform from field aligned coordinates, to be compatible with - // older BOUT++ inputs. This is not a particularly "nice" solution. - result = fromFieldAligned(result, "RGN_ALL"); + // Should not lead to issues. If called from the coordinates + // constructor, then this is expected, and the result will be + // transformed. Otherwise, if the field is used untransformed, + // the inconsistency will be detected. + output_warn.write("Skipping parallel transformation - coordinates not set!\n"); } else { - result.setDirectionY(YDirectionType::Standard); + if (coords->getParallelTransform().canToFromFieldAligned()) { + // Transform from field aligned coordinates, to be compatible with + // older BOUT++ inputs. This is not a particularly "nice" solution. + result = fromFieldAligned(result, "RGN_ALL"); + } else { + result.setDirectionY(YDirectionType::Standard); + } } } @@ -309,12 +314,17 @@ FieldPerp FieldFactory::createPerp(FieldGeneratorPtr gen, Mesh* localmesh, CELL_ if (transform_from_field_aligned) { auto coords = result.getCoordinates(); if (coords == nullptr) { - throw BoutException("Unable to transform result: Mesh does not have Coordinates set"); - } - if (coords->getParallelTransform().canToFromFieldAligned()) { - // Transform from field aligned coordinates, to be compatible with - // older BOUT++ inputs. This is not a particularly "nice" solution. - result = fromFieldAligned(result, "RGN_ALL"); + // Should not lead to issues. If called from the coordinates + // constructor, then this is expected, and the result will be + // transformed. Otherwise, if the field is used untransformed, + // the inconsistency will be detected. + output_warn.write("Skipping parallel transformation - coordinates not set!\n"); + } else { + if (coords->getParallelTransform().canToFromFieldAligned()) { + // Transform from field aligned coordinates, to be compatible with + // older BOUT++ inputs. This is not a particularly "nice" solution. + result = fromFieldAligned(result, "RGN_ALL"); + } } } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 977a5c5db9..6047bce036 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -26,9 +26,9 @@ namespace { /// Boundary guard cells are set by extrapolating from the grid, like /// 'free_o3' boundary conditions /// Corner guard cells are set to BoutNaN -Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, - bool extrapolate_x = true, bool extrapolate_y = true, - bool no_extra_interpolate = false) { +Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* UNUSED(pt) = nullptr) { Mesh* localmesh = f.getMesh(); Field2D result = interp_to(f, location, "RGN_NOBNDRY"); @@ -40,7 +40,7 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); - localmesh->communicate(result); + localmesh->communicateXZ(result); // Extrapolate into boundaries (if requested) so that differential geometry // terms can be interpolated if necessary @@ -129,12 +129,27 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, return result; } -Field3D interpolateAndExtrapolate(const Field3D& f, CELL_LOC location, - bool extrapolate_x = true, bool extrapolate_y = true, - bool no_extra_interpolate = false) { +#define interpolateAndExtrapolate(a,b,c,d,e) _interpolateAndExtrapolate(a, b, c, d, e, transform.get()) - Mesh* localmesh = f.getMesh(); - auto result = interp_to(f, location, "RGN_NOBNDRY"); + Field3D _interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* pt) { + + Mesh* localmesh = f_.getMesh(); + Field3D result; + // Cannot use normal ifs, so that f is const + const Field3D f = (f_.getDirectionY() == YDirectionType::Standard ? f_ : + (f_.getCoordinates() == nullptr ? pt->fromFieldAligned(f_) : fromFieldAligned(f_))); + + if (location == CELL_YLOW){ + auto f_aligned = f.getCoordinates() == nullptr ? + pt->toFieldAligned(f, "RGN_NOX") : toFieldAligned(f, "RGN_NOX"); + result = interp_to(f_aligned, location, "RGN_NOBNDRY"); + result = result.getCoordinates() == nullptr ? + pt->fromFieldAligned(result, "RGN_NOBNDRY") : fromFieldAligned(result, "RGN_NOBNDRY"); + } else { + result = interp_to(f, location, "RGN_NOBNDRY"); + } // Ensure result's data is unique. Otherwise result might be a duplicate of // f (if no interpolation is needed, e.g. if interpolation is in the // z-direction); then f would be communicated. Since this function is used @@ -143,7 +158,7 @@ Field3D interpolateAndExtrapolate(const Field3D& f, CELL_LOC location, // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); - localmesh->communicate(result); + localmesh->communicateXZ(result); // Extrapolate into boundaries (if requested) so that differential geometry // terms can be interpolated if necessary @@ -182,8 +197,9 @@ Field3D interpolateAndExtrapolate(const Field3D& f, CELL_LOC location, - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, zi) - f(bndry->x + bndry->bx, bndry->y + bndry->by, zi)) / 16.; - } + } + } // set boundary guard cells if ((bndry->bx != 0 && localmesh->GlobalNx - 2 * bndry->width >= 3) || (bndry->by != 0 @@ -241,7 +257,6 @@ Field3D interpolateAndExtrapolate(const Field3D& f, CELL_LOC location, return result; //throw BoutException("NotImplemented (3D)"); - } } @@ -260,7 +275,7 @@ void getAtLoc(Mesh* mesh, Coordinates::metric_field_type &var, const std::string const std::string& suffix, CELL_LOC location, BoutReal default_value = 0.) { checkStaggeredGet(mesh, name, suffix); - mesh->get(var, name+suffix, default_value); + mesh->get(var, name+suffix, default_value, false); var.setLocation(location); } @@ -286,7 +301,15 @@ std::string getLocationSuffix(CELL_LOC location) { } } } -} + + template + void communicate(T & t, Ts&... ts) { + FieldGroup g(t,ts...); + t.getMesh()->communicateXZ(g); + } + + +}// anonymous namespace Coordinates::Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2D J, Field2D Bxy, Field2D g11, Field2D g22, Field2D g33, Field2D g12, @@ -340,15 +363,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) "cells. Set option extrapolate_y=false to disable this.\n")); } - mesh->get(dx, "dx", 1.0); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y); - - if (mesh->periodicX) { - mesh->communicate(dx); - } - - mesh->get(dy, "dy", 1.0); - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y); + mesh->get(dx, "dx", 1.0, false); + mesh->get(dy, "dy", 1.0, false); nz = mesh->LocalNz; @@ -364,17 +380,32 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) mesh->get(dz, "dz", default_dz); } + // required early for differentiation. + setParallelTransform(options); + + dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false); + + if (mesh->periodicX) { + communicate(dx); + } + + dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false); + +#define GET(a,b) \ + mesh->get(a, #a, b, false); \ + a = maybeFromFieldAligned(a); + // Diagonal components of metric tensor g^{ij} (default to 1) - mesh->get(g11, "g11", 1.0, false); - mesh->get(g22, "g22", 1.0, false); - mesh->get(g33, "g33", 1.0, false); + GET(g11, 1.0); + GET(g22, 1.0); + GET(g33, 1.0); // Off-diagonal elements. Default to 0 - mesh->get(g12, "g12", 0.0, false); - mesh->get(g13, "g13", 0.0, false); - mesh->get(g23, "g23", 0.0, false); - - mesh->communicateXZ(g11, g22, g33, g12, g13, g23); + GET(g12, 0.0); + GET(g13, 0.0); + GET(g23, 0.0); + + communicate(g11, g22, g33, g12, g13, g23); // Check input metrics // Diagonal metric components should be finite @@ -401,14 +432,16 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // Check that all components are present if (std::all_of(begin(covariant_component_names), end(covariant_component_names), source_has_component)) { - mesh->get(g_11, "g_11", 1.0, false); - mesh->get(g_22, "g_22", 1.0, false); - mesh->get(g_33, "g_33", 1.0, false); - mesh->get(g_12, "g_12", 0.0, false); - mesh->get(g_13, "g_13", 0.0, false); - mesh->get(g_23, "g_23", 0.0, false); + GET(g_11, 1.0); + GET(g_22, 1.0); + GET(g_33, 1.0); + GET(g_12, 0.0); + GET(g_13, 0.0); + GET(g_23, 0.0); - mesh->communicateXZ(g_11, g_22, g_33, g_12, g_13, g_23); +#undef GET + + communicate(g_11, g_22, g_33, g_12, g_13, g_23); output_warn.write("\tWARNING! Covariant components of metric tensor set manually. " "Contravariant components NOT recalculated\n"); @@ -429,12 +462,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) } // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y); - g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y); - g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y); - g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y); - g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y); - g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y); + g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false); + g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false); + g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false); + g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false); + g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false); + g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false); // Check covariant metrics // Diagonal metric components should be finite @@ -460,12 +493,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) output_warn.write("\tWARNING: Jacobian 'J' not found. Calculating from metric tensor\n"); J = Jcalc; } else { - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false); // Compare calculated and loaded values output_warn.write("\tMaximum difference in J is %e\n", max(abs(J - Jcalc))); - mesh->communicateXZ(J); + communicate(J); // Re-evaluate Bxy using new J Bxy = sqrt(g_22) / J; @@ -478,8 +511,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) "metric tensor\n"); Bxy = Bcalc; } else { - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false); output_warn.write("\tMaximum difference in Bxy is %e\n", max(abs(Bxy - Bcalc))); // Check Bxy bout::checkFinite(Bxy, "Bxy", "RGN_NOCORNERS"); @@ -492,12 +525,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) throw BoutException("Differential geometry failed\n"); } - if (mesh->get(ShiftTorsion, "ShiftTorsion")) { + if (mesh->get(ShiftTorsion, "ShiftTorsion", 0.0, false)) { output_warn.write( "\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); ShiftTorsion = 0.0; } - ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y); + ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false); ////////////////////////////////////////////////////// @@ -505,13 +538,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) if (mesh->get(IntShiftTorsion, "IntShiftTorsion", 0.0, false)) { output_warn.write("\tWARNING: No Integrated torsion specified\n"); } - IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y); + IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; } - setParallelTransform(options); } // use anonymous namespace so this utility function is not available outside this file @@ -522,11 +554,26 @@ namespace { /// 2nd order accurate Neumann boundary condition). /// Corner guard cells are set to BoutNaN Coordinates::metric_field_type -interpolateAndNeumann(const Coordinates::metric_field_type& f, CELL_LOC location) { +interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAYBE_UNUSED(CELL_LOC location), ParallelTransform * pt) { #ifndef COORDINATES_USE_3D +#define COORDS_ITER_Z int z=0; +#else +#define COORDS_ITER_Z for (int z=0;zLocalNz;++z) + //throw BoutException( + // "Staggered coordinates locations not currently supported with 3D metrics."); +#endif Mesh* localmesh = f.getMesh(); - auto result = interp_to(f, location, RGN_NOBNDRY); - localmesh->communicate(result); + Coordinates::metric_field_type result; + if (location == CELL_YLOW){ + auto f_aligned = f.getCoordinates() == nullptr ? + pt->toFieldAligned(f, "RGN_NOX") : toFieldAligned(f, "RGN_NOX"); + result = interp_to(f_aligned, location, "RGN_NOBNDRY"); + result = result.getCoordinates() == nullptr ? + pt->fromFieldAligned(result, "RGN_NOBNDRY") : fromFieldAligned(result, "RGN_NOBNDRY"); + } else { + result = interp_to(f, location, "RGN_NOBNDRY"); + } + communicate(result); // Copy nearest value into boundaries so that differential geometry terms can // be interpolated if necessary @@ -538,16 +585,22 @@ interpolateAndNeumann(const Coordinates::metric_field_type& f, CELL_LOC location // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->xstart; i++) - result(bndry->x + i * bndry->bx, bndry->y) = - result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by); + COORDS_ITER_Z + { + result(bndry->x + i * bndry->bx, bndry->y, z) = + result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); + } } } if (bndry->by != 0) { // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->ystart; i++) - result(bndry->x, bndry->y + i * bndry->by) = - result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by); + COORDS_ITER_Z + { + result(bndry->x, bndry->y + i * bndry->by, z) = + result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); + } } } } @@ -555,37 +608,18 @@ interpolateAndNeumann(const Coordinates::metric_field_type& f, CELL_LOC location // Set corner guard cells for (int i = 0; i < localmesh->xstart; i++) { for (int j = 0; j < localmesh->ystart; j++) { - result(i, j) = BoutNaN; - result(i, localmesh->LocalNy - 1 - j) = BoutNaN; - result(localmesh->LocalNx - 1 - i, j) = BoutNaN; - result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j) = BoutNaN; + COORDS_ITER_Z + { + result(i, j, z) = BoutNaN; + result(i, localmesh->LocalNy - 1 - j, z) = BoutNaN; + result(localmesh->LocalNx - 1 - i, j, z) = BoutNaN; + result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, z) = BoutNaN; + } } } return result; -#else - throw BoutException( - "Staggered coordinates locations not currently supported with 3D metrics."); -#endif - } - - // If the CELL_CENTRE variable was read, the staggered version is required to - // also exist for consistency - void checkStaggeredGet(Mesh* mesh, std::string name, std::string suffix) { - if (mesh->sourceHasVar(name) != mesh->sourceHasVar(name+suffix)) { - throw BoutException("Attempting to read staggered fields from grid, but " + name - + " is not present in both CELL_CENTRE and staggered versions."); - } - } - - // convenience function for repeated code - void getAtLoc(Mesh* mesh, Coordinates::metric_field_type &var, std::string name, std::string suffix, - CELL_LOC location, BoutReal default_value = 0.) { - - checkStaggeredGet(mesh, name, suffix); - mesh->get(var, name+suffix, default_value); - var.setLocation(location); - } +} } Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, @@ -610,6 +644,8 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, bool extrapolate_x = true; bool extrapolate_y = true; + setParallelTransform(options); + if (!force_interpolate_from_centre && mesh->sourceHasVar("dx"+suffix)) { extrapolate_x = not mesh->sourceHasXBoundaryGuards(); @@ -626,29 +662,29 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } getAtLoc(mesh, dx, "dx", suffix, location, 1.0); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y); + dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false); if (mesh->periodicX) { - mesh->communicate(dx); + communicate(dx); } getAtLoc(mesh, dy, "dy", suffix, location, 1.0); - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y); + dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false); // grid data source has staggered fields, so read instead of interpolating // Diagonal components of metric tensor g^{ij} (default to 1) getAtLoc(mesh, g11, "g11", suffix, location, 1.0); - g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y); + g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false); getAtLoc(mesh, g22, "g22", suffix, location, 1.0); - g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y); + g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false); getAtLoc(mesh, g33, "g33", suffix, location, 1.0); - g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y); + g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false); getAtLoc(mesh, g12, "g12", suffix, location, 0.0); - g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y); + g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false); getAtLoc(mesh, g13, "g13", suffix, location, 0.0); - g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y); + g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false); getAtLoc(mesh, g23, "g23", suffix, location, 0.0); - g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y); + g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false); /// Find covariant metric components auto covariant_component_names = {"g_11", "g_22", "g_33", "g_12", "g_13", "g_23"}; @@ -688,12 +724,12 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y); - g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y); - g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y); - g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y); - g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y); - g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y); + g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false); + g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false); + g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false); + g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false); + g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false); + g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false); /// Calculate Jacobian and Bxy if (jacobian()) { @@ -701,23 +737,23 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } checkStaggeredGet(mesh, "ShiftTorsion", suffix); - if (mesh->get(ShiftTorsion, "ShiftTorsion"+suffix)) { + if (mesh->get(ShiftTorsion, "ShiftTorsion"+suffix, 0.0, false)) { output_warn.write("\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); ShiftTorsion = 0.0; } ShiftTorsion.setLocation(location); - ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y); + ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false); ////////////////////////////////////////////////////// if (mesh->IncIntShear) { checkStaggeredGet(mesh, "IntShiftTorsion", suffix); - if (mesh->get(IntShiftTorsion, "IntShiftTorsion"+suffix)) { + if (mesh->get(IntShiftTorsion, "IntShiftTorsion"+suffix, 0.0, false)) { output_warn.write("\tWARNING: No Integrated torsion specified\n"); IntShiftTorsion = 0.0; } IntShiftTorsion.setLocation(location); - IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y); + IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; @@ -725,42 +761,42 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } else { // Interpolate fields from coords_in - dx = interpolateAndExtrapolate(coords_in->dx, location); - dy = interpolateAndExtrapolate(coords_in->dy, location); + dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false); + dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false); // Diagonal components of metric tensor g^{ij} - g11 = interpolateAndExtrapolate(coords_in->g11, location); - g22 = interpolateAndExtrapolate(coords_in->g22, location); - g33 = interpolateAndExtrapolate(coords_in->g33, location); + g11 = interpolateAndExtrapolate(coords_in->g11, location, true, true, false); + g22 = interpolateAndExtrapolate(coords_in->g22, location, true, true, false); + g33 = interpolateAndExtrapolate(coords_in->g33, location, true, true, false); // Off-diagonal elements. - g12 = interpolateAndExtrapolate(coords_in->g12, location); - g13 = interpolateAndExtrapolate(coords_in->g13, location); - g23 = interpolateAndExtrapolate(coords_in->g23, location); + g12 = interpolateAndExtrapolate(coords_in->g12, location, true, true, false); + g13 = interpolateAndExtrapolate(coords_in->g13, location, true, true, false); + g23 = interpolateAndExtrapolate(coords_in->g23, location, true, true, false); // 3x3 matrix inversion can exaggerate small interpolation errors, so it is // more robust to interpolate and extrapolate derived quantities directly, // rather than deriving from interpolated/extrapolated covariant metric // components - g_11 = interpolateAndExtrapolate(coords_in->g_11, location); - g_22 = interpolateAndExtrapolate(coords_in->g_22, location); - g_33 = interpolateAndExtrapolate(coords_in->g_33, location); - g_12 = interpolateAndExtrapolate(coords_in->g_12, location); - g_13 = interpolateAndExtrapolate(coords_in->g_13, location); - g_23 = interpolateAndExtrapolate(coords_in->g_23, location); + g_11 = interpolateAndExtrapolate(coords_in->g_11, location, true, true, false); + g_22 = interpolateAndExtrapolate(coords_in->g_22, location, true, true, false); + g_33 = interpolateAndExtrapolate(coords_in->g_33, location, true, true, false); + g_12 = interpolateAndExtrapolate(coords_in->g_12, location, true, true, false); + g_13 = interpolateAndExtrapolate(coords_in->g_13, location, true, true, false); + g_23 = interpolateAndExtrapolate(coords_in->g_23, location, true, true, false); - J = interpolateAndExtrapolate(coords_in->J, location); - Bxy = interpolateAndExtrapolate(coords_in->Bxy, location); + J = interpolateAndExtrapolate(coords_in->J, location, true, true, false); + Bxy = interpolateAndExtrapolate(coords_in->Bxy, location, true, true, false); bout::checkFinite(J, "The Jacobian", "RGN_NOCORNERS"); bout::checkPositive(J, "The Jacobian", "RGN_NOCORNERS"); bout::checkFinite(Bxy, "Bxy", "RGN_NOCORNERS"); bout::checkPositive(Bxy, "Bxy", "RGN_NOCORNERS"); - ShiftTorsion = interpolateAndExtrapolate(coords_in->ShiftTorsion, location); + ShiftTorsion = interpolateAndExtrapolate(coords_in->ShiftTorsion, location, true, true, false); if (mesh->IncIntShear) { - IntShiftTorsion = interpolateAndExtrapolate(coords_in->IntShiftTorsion, location); + IntShiftTorsion = interpolateAndExtrapolate(coords_in->IntShiftTorsion, location, true, true, false); } } @@ -787,12 +823,12 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); - ShiftTorsion = interpolateAndNeumann(coords_in->ShiftTorsion, location); + ShiftTorsion = interpolateAndNeumann(coords_in->ShiftTorsion, location, transform.get()); ////////////////////////////////////////////////////// if (mesh->IncIntShear) { - IntShiftTorsion = interpolateAndNeumann(coords_in->IntShiftTorsion, location); + IntShiftTorsion = interpolateAndNeumann(coords_in->IntShiftTorsion, location, transform.get()); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; @@ -802,8 +838,6 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, if (geometry(false, force_interpolate_from_centre)) { throw BoutException("Differential geometry failed while constructing staggered Coordinates"); } - - setParallelTransform(options); } void Coordinates::outputVars(Datafile& file) { @@ -840,8 +874,8 @@ void Coordinates::outputVars(Datafile& file) { int Coordinates::geometry(bool recalculate_staggered, bool force_interpolate_from_centre) { TRACE("Coordinates::geometry"); - localmesh->communicate(dx, dy, g11, g22, g33, g12, g13, g23); - localmesh->communicate(g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); + communicate(dx, dy, g11, g22, g33, g12, g13, g23, + g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); output_progress.write("Calculating differential geometry terms\n"); @@ -881,6 +915,7 @@ int Coordinates::geometry(bool recalculate_staggered, bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); + // Calculate Christoffel symbol terms (18 independent values) // Note: This calculation is completely general: metric // tensor can be 2D or 3D. For 2D, all DDZ terms are zero @@ -944,46 +979,22 @@ int Coordinates::geometry(bool recalculate_staggered, + 0.5 * g33 * DDY(g_33); auto tmp = J * g12; - localmesh->communicate(tmp); + communicate(tmp); G1 = (DDX(J * g11) + DDY(tmp) + DDZ(J * g13)) / J; tmp = J * g22; - localmesh->communicate(tmp); + communicate(tmp); G2 = (DDX(J * g12) + DDY(tmp) + DDZ(J * g23)) / J; tmp = J * g23; - localmesh->communicate(tmp); + communicate(tmp); G3 = (DDX(J * g13) + DDY(tmp) + DDZ(J * g33)) / J; // Communicate christoffel symbol terms output_progress.write("\tCommunicating connection terms\n"); - FieldGroup com; - - com.add(G1_11); - com.add(G1_22); - com.add(G1_33); - com.add(G1_12); - com.add(G1_13); - com.add(G1_23); - - com.add(G2_11); - com.add(G2_22); - com.add(G2_33); - com.add(G2_12); - com.add(G2_13); - com.add(G2_23); - - com.add(G3_11); - com.add(G3_22); - com.add(G3_33); - com.add(G3_12); - com.add(G3_13); - com.add(G3_23); - - com.add(G1); - com.add(G2); - com.add(G3); - - localmesh->communicateXZ(com); + communicate(G1_11, G1_22, G1_33, G1_12, G1_13, G1_23, + G2_11, G2_22, G2_33, G2_12, G2_13, G2_23, + G3_11, G3_22, G3_33, G3_12, G3_13, G3_23, + G1, G2, G3); // Set boundary guard cells of Christoffel symbol terms // Ideally, when location is staggered, we would set the upper/outer boundary point @@ -1034,65 +1045,65 @@ int Coordinates::geometry(bool recalculate_staggered, bool extrapolate_x = not localmesh->sourceHasXBoundaryGuards(); bool extrapolate_y = not localmesh->sourceHasYBoundaryGuards(); - if (localmesh->get(d2x, "d2x"+suffix)) { + if (localmesh->get(d2x, "d2x"+suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2x' not found. Calculating from dx\n"); d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) - localmesh->communicate(d1_dx); + communicate(d1_dx); d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true); } else { d2x.setLocation(location); // set boundary cells if necessary - d2x = interpolateAndExtrapolate(d2x, location, extrapolate_x, extrapolate_y); + d2x = interpolateAndExtrapolate(d2x, location, extrapolate_x, extrapolate_y, false); d1_dx = -d2x / (dx * dx); } - if (localmesh->get(d2y, "d2y"+suffix)) { + if (localmesh->get(d2y, "d2y"+suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) + d1_dy = indexDDY(1. / dy); // d/di(1/dy) - localmesh->communicate(d1_dy); + communicate(d1_dy); d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true); } else { d2y.setLocation(location); // set boundary cells if necessary - d2y = interpolateAndExtrapolate(d2y, location, extrapolate_x, extrapolate_y); + d2y = interpolateAndExtrapolate(d2y, location, extrapolate_x, extrapolate_y, false); d1_dy = -d2y / (dy * dy); } } else { - if (localmesh->get(d2x, "d2x")) { + if (localmesh->get(d2x, "d2x", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2x' not found. Calculating from dx\n"); d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) - localmesh->communicate(d1_dx); + communicate(d1_dx); d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true); } else { // Shift d2x to our location - d2x = interpolateAndExtrapolate(d2x, location); + d2x = interpolateAndExtrapolate(d2x, location, true, true, false); d1_dx = -d2x / (dx * dx); } - if (localmesh->get(d2y, "d2y")) { + if (localmesh->get(d2y, "d2y", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) + d1_dy = indexDDY(1. / dy); // d/di(1/dy) - localmesh->communicate(d1_dy); + communicate(d1_dy); d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true); } else { // Shift d2y to our location - d2y = interpolateAndExtrapolate(d2y, location); + d2y = interpolateAndExtrapolate(d2y, location, true, true, false); d1_dy = -d2y / (dy * dy); } } - localmesh->communicateXZ(d1_dx, d1_dy); + communicate(d1_dx, d1_dy); if (location == CELL_CENTRE && recalculate_staggered) { // Re-calculate interpolated Coordinates at staggered locations @@ -1234,7 +1245,7 @@ int Coordinates::jacobian() { J = 1. / sqrt(g); // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false); // Check jacobian bout::checkFinite(J, "The Jacobian", "RGN_NOCORNERS"); @@ -1246,7 +1257,7 @@ int Coordinates::jacobian() { bout::checkPositive(g_22, "g_22", "RGN_NOCORNERS"); Bxy = sqrt(g_22) / J; - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false); bout::checkFinite(Bxy, "Bxy", "RGN_NOCORNERS"); bout::checkPositive(Bxy, "Bxy", "RGN_NOCORNERS"); @@ -1256,29 +1267,42 @@ int Coordinates::jacobian() { namespace { // Utility function for fixing up guard cells of zShift -void fixZShiftGuards(Field2D& zShift) { + void fixZShiftGuards(Field2D& zShift) { auto localmesh = zShift.getMesh(); // extrapolate into boundary guard cells if necessary - zShift = interpolateAndExtrapolate(zShift, zShift.getLocation(), + zShift = _interpolateAndExtrapolate(zShift, zShift.getLocation(), not localmesh->sourceHasXBoundaryGuards(), - not localmesh->sourceHasYBoundaryGuards()); + not localmesh->sourceHasYBoundaryGuards(), + false); // make sure zShift has been communicated - localmesh->communicate(zShift); + communicate(zShift); // Correct guard cells for discontinuity of zShift at poloidal branch cut for (int x = 0; x < localmesh->LocalNx; x++) { const auto lower = localmesh->hasBranchCutLower(x); if (lower.first) { for (int y = 0; y < localmesh->ystart; y++) { - zShift(x, y) -= lower.second; + int z=0; +// #ifdef COORDINATES_USE_3D +// for (;zLocalNz; ++z) +// #endif + { + zShift(x, y, z) -= lower.second; + } } } const auto upper = localmesh->hasBranchCutUpper(x); if (upper.first) { for (int y = localmesh->yend + 1; y < localmesh->LocalNy; y++) { - zShift(x, y) += upper.second; + int z=0; +// #ifdef COORDINATES_USE_3D +// for (;zLocalNz; ++z) +// #endif + { + zShift(x, y, z) += upper.second; + } } } } @@ -1307,9 +1331,9 @@ void Coordinates::setParallelTransform(Options* options) { if (localmesh->sourceHasVar("dx"+suffix)) { // Grid file has variables at this location, so should be able to read checkStaggeredGet(localmesh, "zShift", suffix); - if (localmesh->get(zShift, "zShift"+suffix)) { + if (localmesh->get(zShift, "zShift"+suffix, 0.0, false)) { // No zShift variable. Try qinty in BOUT grid files - if (localmesh->get(zShift, "qinty"+suffix)) { + if (localmesh->get(zShift, "qinty"+suffix, 0.0, false)) { // Failed to find either variable, cannot use ShiftedMetric throw BoutException("Could not read zShift"+suffix+" from grid file"); } @@ -1317,9 +1341,9 @@ void Coordinates::setParallelTransform(Options* options) { zShift.setLocation(location); } else { Field2D zShift_centre; - if (localmesh->get(zShift_centre, "zShift")) { + if (localmesh->get(zShift_centre, "zShift", 0.0, false)) { // No zShift variable. Try qinty in BOUT grid files - if (localmesh->get(zShift_centre, "qinty")) { + if (localmesh->get(zShift_centre, "qinty", 0.0, false)) { // Failed to find either variable, cannot use ShiftedMetric throw BoutException("Could not read zShift"+suffix+" from grid file"); } @@ -1327,7 +1351,7 @@ void Coordinates::setParallelTransform(Options* options) { fixZShiftGuards(zShift_centre); - zShift = interpolateAndExtrapolate(zShift_centre, location); + zShift = interpolateAndExtrapolate(zShift_centre, location, true, true, false); } fixZShiftGuards(zShift); @@ -1384,12 +1408,11 @@ Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, } Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { - return bout::derivatives::index::DDY(f, outloc, method, region) / dy; + const std::string& method, const std::string& region) { + return indexDDY(f, outloc, method, region)/dy; }; -Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), - MAYBE_UNUSED(CELL_LOC loc), +Coordinates::metric_field_type Coordinates::DDZ(const Field2D& f, CELL_LOC loc, const std::string& UNUSED(method), const std::string& UNUSED(region)) { ASSERT1(location == loc || loc == CELL_DEFAULT); @@ -1400,7 +1423,7 @@ Coordinates::metric_field_type Coordinates::DDZ(MAYBE_UNUSED(const Field2D& f), return zeroFrom(f).setLocation(loc); } Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::DDZ(f, outloc, method, region) / dz; }; @@ -1491,7 +1514,7 @@ Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& me ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); auto invSg = 1.0 / sqrt(g_22); - localmesh->communicate(invSg); + communicate(invSg); auto result = DDY(invSg, outloc, method) * DDY(f, outloc, method) * invSg + D2DY2(f, outloc, method) / g_22; @@ -1508,7 +1531,7 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, auto sg = sqrt(g_22); auto invSg = 1.0 / sg; - localmesh->communicate(invSg); + communicate(invSg); sg = DDY(invSg, outloc, method) * invSg; Field3D result = ::DDY(f, outloc, method); @@ -1703,6 +1726,20 @@ Field3D Coordinates::Laplace(const Field3D& f, CELL_LOC outloc) { return result; } +// must be member function so we use the member to/from field aligned +Coordinates::metric_field_type Coordinates::indexDDY(const Coordinates::metric_field_type& f, CELL_LOC outloc, + const std::string& method, const std::string& region){ +#ifdef COORDINATES_USE_3D + if (!f.hasParallelSlices()){ + const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); + const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); + } +#endif + return bout::derivatives::index::DDY(f, outloc, method, region); + } + bool Coordinates::is3D() { #ifdef COORDINATES_USE_3D return true; From 2f9375d1c54424e544135524c0f27188d7d3509e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 12:02:18 +0000 Subject: [PATCH 064/293] Ajust boutcore interface for 3d metric fields --- tools/pylib/_boutcore_build/boutcore.pyx.in | 24 ++++++++--------- tools/pylib/_boutcore_build/boutcpp.pxd.in | 22 ++++++++-------- tools/pylib/_boutcore_build/common.sh | 29 +++++++++++++++++++-- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/tools/pylib/_boutcore_build/boutcore.pyx.in b/tools/pylib/_boutcore_build/boutcore.pyx.in index 21577c7bcc..72673cee53 100755 --- a/tools/pylib/_boutcore_build/boutcore.pyx.in +++ b/tools/pylib/_boutcore_build/boutcore.pyx.in @@ -822,18 +822,18 @@ cdef class Coordinates: """ cdef c.Coordinates * cobj cdef c.bool isSelfOwned - cdef public Field2D dx, dy + cdef public $metric_field dx, dy cdef public double dz - cdef public Field2D J - cdef public Field2D Bxy - cdef public Field2D g11, g22, g33, g12, g13, g23 - cdef public Field2D g_11, g_22, g_33, g_12, g_13, g_23 - cdef public Field2D G1_11, G1_22, G1_33, G1_12, G1_13, G1_23 - cdef public Field2D G2_11, G2_22, G2_33, G2_12, G2_13, G2_23 - cdef public Field2D G3_11, G3_22, G3_33, G3_12, G3_13, G3_23 - cdef public Field2D G1, G2, G3 - cdef public Field2D ShiftTorsion - cdef public Field2D IntShiftTorsion + cdef public $metric_field J + cdef public $metric_field Bxy + cdef public $metric_field g11, g22, g33, g12, g13, g23 + cdef public $metric_field g_11, g_22, g_33, g_12, g_13, g_23 + cdef public $metric_field G1_11, G1_22, G1_33, G1_12, G1_13, G1_23 + cdef public $metric_field G2_11, G2_22, G2_33, G2_12, G2_13, G2_23 + cdef public $metric_field G3_11, G3_22, G3_33, G3_12, G3_13, G3_23 + cdef public $metric_field G1, G2, G3 + cdef public $metric_field ShiftTorsion + cdef public $metric_field IntShiftTorsion def __init__(self): self.cobj = NULL @@ -843,7 +843,7 @@ cdef class Coordinates: EOF for f in "dx" "dy" "J" "Bxy" "g11" "g22" "g33" "g12" "g13" "g23" "g_11" "g_22" "g_33" "g_12" "g_13" "g_23" "G1_11" "G1_22" "G1_33" "G1_12" "G1_13" "G1_23" "G2_11" "G2_22" "G2_33" "G2_12" "G2_13" "G2_23" "G3_11" "G3_22" "G3_33" "G3_12" "G3_13" "G3_23" "G1" "G2" "G3" "ShiftTorsion" "IntShiftTorsion" do - echo " self.${f} = f2dFromPtr(&self.cobj.${f})" + echo " self.${f} = ${metric_fdd}FromPtr(&self.cobj.${f})" done for f in "dz" do diff --git a/tools/pylib/_boutcore_build/boutcpp.pxd.in b/tools/pylib/_boutcore_build/boutcpp.pxd.in index a06d4f321e..8090fffa0d 100755 --- a/tools/pylib/_boutcore_build/boutcpp.pxd.in +++ b/tools/pylib/_boutcore_build/boutcpp.pxd.in @@ -82,18 +82,18 @@ cdef extern from "bout/mesh.hxx": cdef extern from "bout/coordinates.hxx": cppclass Coordinates: Coordinates() - Field2D dx, dy + $metric_field dx, dy double dz - Field2D J - Field2D Bxy - Field2D g11, g22, g33, g12, g13, g23 - Field2D g_11, g_22, g_33, g_12, g_13, g_23 - Field2D G1_11, G1_22, G1_33, G1_12, G1_13, G1_23 - Field2D G2_11, G2_22, G2_33, G2_12, G2_13, G2_23 - Field2D G3_11, G3_22, G3_33, G3_12, G3_13, G3_23 - Field2D G1, G2, G3 - Field2D ShiftTorsion - Field2D IntShiftTorsion + $metric_field J + $metric_field Bxy + $metric_field g11, g22, g33, g12, g13, g23 + $metric_field g_11, g_22, g_33, g_12, g_13, g_23 + $metric_field G1_11, G1_22, G1_33, G1_12, G1_13, G1_23 + $metric_field G2_11, G2_22, G2_33, G2_12, G2_13, G2_23 + $metric_field G3_11, G3_22, G3_33, G3_12, G3_13, G3_23 + $metric_field G1, G2, G3 + $metric_field ShiftTorsion + $metric_field IntShiftTorsion int geometry() int calcCovariant() int calcContravariant() diff --git a/tools/pylib/_boutcore_build/common.sh b/tools/pylib/_boutcore_build/common.sh index 7f5a12acc0..a449f13a5b 100644 --- a/tools/pylib/_boutcore_build/common.sh +++ b/tools/pylib/_boutcore_build/common.sh @@ -19,12 +19,34 @@ makelist () { start="$spacing" ; i=$(( i + 1 )) done ; } +# What is the metric type? +coords_is() { + if grep ^BOUT_FLAGS ../../../make.config| grep COORDINATES_USE_3D -q + then + echo "f3d" + else + echo "f2d" + fi ; } + +name_of_fdd() { + case $1 in + f3d) + echo "Field3D" + ;; + f2d) + echo "Field2D" + ;; + *) + echo "unexpected fdd" + exit 4; + esac ; } + # Set variables for Vectors and Fields setvars() { case $1 in Vector2D) - field=Field2D - fdd=f2d + fdd=$(coords_is) + field=$(name_of_fdd $fdd) vdd=v2d fheader=vector2d ;; @@ -55,3 +77,6 @@ setvars() { vecs="Vector3D Vector2D" fields="Field3D Field2D" + +metric_fdd=$(coords_is) +metric_field=$(name_of_fdd $metric_fdd) From 76c375e66674a638ec52fe0a7a191581b880e2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 13:50:58 +0000 Subject: [PATCH 065/293] Skip tests that require features not ported Some features aren't available with 3d metrics. Tests that require them have to be disabled. --- tests/MMS/bracket/runtest | 1 + tests/MMS/spatial/fci/runtest | 3 +-- tests/integrated/test-snb/runtest | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/MMS/bracket/runtest b/tests/MMS/bracket/runtest index ac316316db..e9ff74457d 100755 --- a/tests/MMS/bracket/runtest +++ b/tests/MMS/bracket/runtest @@ -13,6 +13,7 @@ import numpy as np #Requires: boutcore #requires: not make +#requires: not metric_3d import boutcore as bc diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index dfbca4e505..910b4de162 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -2,8 +2,7 @@ # # Python script to run and analyse MMS test # -from __future__ import division -from __future__ import print_function +#requires not metric_3d from boututils.run_wrapper import shell_safe, launch_safe from boutdata.collect import collect diff --git a/tests/integrated/test-snb/runtest b/tests/integrated/test-snb/runtest index f283dfc8ab..6aaee40a22 100755 --- a/tests/integrated/test-snb/runtest +++ b/tests/integrated/test-snb/runtest @@ -1,4 +1,6 @@ #!/bin/sh +#requires: not metric_3d + make ./test_snb From ce4ceef9ec133745ebb7b8600fe171ddcad4e0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 17:39:33 +0000 Subject: [PATCH 066/293] Fix unit tests Some ajustments. Vector2D contains sometimes Field3D. Also we can construct a Field3D without coordinates. --- tests/unit/field/test_field_factory.cxx | 2 +- tests/unit/mesh/data/test_gridfromoptions.cxx | 41 +++++++++++------- tests/unit/solver/test_solver.cxx | 42 ++++++++++++------- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/tests/unit/field/test_field_factory.cxx b/tests/unit/field/test_field_factory.cxx index 23ccdeaef7..b5d8423cac 100644 --- a/tests/unit/field/test_field_factory.cxx +++ b/tests/unit/field/test_field_factory.cxx @@ -603,7 +603,7 @@ TEST_F(FieldFactoryTest, RequireMesh) { TEST_F(FieldFactoryTest, CreateOnMeshWithoutCoordinates) { static_cast(mesh)->setCoordinates(nullptr); - EXPECT_THROW(factory.create3D("x"), BoutException); + EXPECT_NO_THROW(factory.create3D("x")); } TEST_F(FieldFactoryTest, CleanCache) { diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index 0efa5be4b7..d483bbf162 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -62,6 +62,12 @@ class GridFromOptionsTest : public ::testing::Test { return index.x() + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; }, &mesh_from_options); + expected_metric = +#ifdef COORDINATES_USE_3D + expected_3d; +#else + expected_2d; +#endif } ~GridFromOptionsTest() override { @@ -82,6 +88,7 @@ class GridFromOptionsTest : public ::testing::Test { std::string expected_string{"x + y + z + 3"}; Field2D expected_2d; Field3D expected_3d; + Coordinates::metric_field_type expected_metric; FakeMesh mesh_from_options{nx, ny, nz}; }; @@ -336,12 +343,12 @@ TEST_F(GridFromOptionsTest, CoordinatesCentre) { mesh_from_options.communicate(expected_2d); - EXPECT_TRUE(IsFieldEqual(coords->g11, expected_2d + 5.)); - EXPECT_TRUE(IsFieldEqual(coords->g22, expected_2d + 4.)); - EXPECT_TRUE(IsFieldEqual(coords->g33, expected_2d + 3.)); - EXPECT_TRUE(IsFieldEqual(coords->g12, expected_2d + 2.)); - EXPECT_TRUE(IsFieldEqual(coords->g13, expected_2d + 1.)); - EXPECT_TRUE(IsFieldEqual(coords->g23, expected_2d)); + EXPECT_TRUE(IsFieldEqual(coords->g11, expected_metric + 5.)); + EXPECT_TRUE(IsFieldEqual(coords->g22, expected_metric + 4.)); + EXPECT_TRUE(IsFieldEqual(coords->g33, expected_metric + 3.)); + EXPECT_TRUE(IsFieldEqual(coords->g12, expected_metric + 2.)); + EXPECT_TRUE(IsFieldEqual(coords->g13, expected_metric + 1.)); + EXPECT_TRUE(IsFieldEqual(coords->g23, expected_metric)); } TEST_F(GridFromOptionsTest, CoordinatesZlow) { @@ -349,12 +356,12 @@ TEST_F(GridFromOptionsTest, CoordinatesZlow) { mesh_from_options.communicate(expected_2d); - EXPECT_TRUE(IsFieldEqual(coords->g11, expected_2d + 5.)); - EXPECT_TRUE(IsFieldEqual(coords->g22, expected_2d + 4.)); - EXPECT_TRUE(IsFieldEqual(coords->g33, expected_2d + 3.)); - EXPECT_TRUE(IsFieldEqual(coords->g12, expected_2d + 2.)); - EXPECT_TRUE(IsFieldEqual(coords->g13, expected_2d + 1.)); - EXPECT_TRUE(IsFieldEqual(coords->g23, expected_2d)); + EXPECT_TRUE(IsFieldEqual(coords->g11, expected_metric + 5.)); + EXPECT_TRUE(IsFieldEqual(coords->g22, expected_metric + 4.)); + EXPECT_TRUE(IsFieldEqual(coords->g33, expected_metric + 3.)); + EXPECT_TRUE(IsFieldEqual(coords->g12, expected_metric + 2.)); + EXPECT_TRUE(IsFieldEqual(coords->g13, expected_metric + 1.)); + EXPECT_TRUE(IsFieldEqual(coords->g23, expected_metric)); } TEST_F(GridFromOptionsTest, CoordinatesXlowInterp) { @@ -366,8 +373,8 @@ TEST_F(GridFromOptionsTest, CoordinatesXlowInterp) { auto coords = mesh_from_options.getCoordinates(CELL_XLOW); - Field2D expected_xlow = makeField( - [](Field2D::ind_type& index) { + Coordinates::metric_field_type expected_xlow = makeField( + [](Coordinates::metric_field_type::ind_type& index) { return index.x() - 0.5 + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; }, &mesh_from_options); @@ -419,6 +426,7 @@ TEST_F(GridFromOptionsTest, CoordinatesXlowRead) { } TEST_F(GridFromOptionsTest, CoordinatesYlowInterp) { +#ifndef COORDINATES_USE_3D // *_ylow fields not present in options, Coordinates will be interpolated // from CELL_CENTRE @@ -441,9 +449,11 @@ TEST_F(GridFromOptionsTest, CoordinatesYlowInterp) { EXPECT_TRUE(IsFieldEqual(coords->g12, expected_ylow + 2., "RGN_NOBNDRY", this_tolerance)); EXPECT_TRUE(IsFieldEqual(coords->g13, expected_ylow + 1., "RGN_NOBNDRY", this_tolerance)); EXPECT_TRUE(IsFieldEqual(coords->g23, expected_ylow, "RGN_NOBNDRY", this_tolerance)); +#endif } TEST_F(GridFromOptionsTest, CoordinatesYlowRead) { +#ifndef COORDINATES_USE_3D // *_ylow fields added to options, will be read to initialise Coordinates // Note '(2*pi*11 - y)' here because FakeMesh::GlobalY(int jy) returns jy, not a @@ -478,9 +488,11 @@ TEST_F(GridFromOptionsTest, CoordinatesYlowRead) { EXPECT_TRUE(IsFieldEqual(coords->g12, expected_ylow + 2., "RGN_ALL", this_tolerance)); EXPECT_TRUE(IsFieldEqual(coords->g13, expected_ylow + 1., "RGN_ALL", this_tolerance)); EXPECT_TRUE(IsFieldEqual(coords->g23, expected_ylow, "RGN_ALL", this_tolerance)); +#endif } TEST_F(GridFromOptionsTest, CoordinatesZlowRead) { +#ifndef COORDINATES_USE_3D // Grids are axisymmetric, so CELL_ZLOW Coordinates will be read from // CELL_CENTRE variables @@ -492,4 +504,5 @@ TEST_F(GridFromOptionsTest, CoordinatesZlowRead) { EXPECT_TRUE(IsFieldEqual(coords->g12, expected_2d + 2.)); EXPECT_TRUE(IsFieldEqual(coords->g13, expected_2d + 1.)); EXPECT_TRUE(IsFieldEqual(coords->g23, expected_2d)); +#endif } diff --git a/tests/unit/solver/test_solver.cxx b/tests/unit/solver/test_solver.cxx index fba99fb75e..e91518df59 100644 --- a/tests/unit/solver/test_solver.cxx +++ b/tests/unit/solver/test_solver.cxx @@ -256,22 +256,27 @@ TEST_F(SolverTest, AddVector2D) { Vector2D vector1{}, vector2{}; EXPECT_NO_THROW(solver.add(vector1, "vector")); - EXPECT_EQ(solver.n2Dvars(), 3); - EXPECT_EQ(solver.n3Dvars(), 0); +#ifndef COORDINATES_USE_3D + int n2d=3, n3d=0; +#else + int n2d=0, n3d=3; +#endif + EXPECT_EQ(solver.n2Dvars(), n2d); + EXPECT_EQ(solver.n3Dvars(), n3d); EXPECT_TRUE(IsFieldEqual(vector1.x, 5.0)); EXPECT_TRUE(IsFieldEqual(vector1.y, 6.0)); EXPECT_TRUE(IsFieldEqual(vector1.z, 7.0)); #if CHECK > 0 EXPECT_THROW(solver.add(vector2, "vector"), BoutException); - EXPECT_EQ(solver.n2Dvars(), 3); - EXPECT_EQ(solver.n3Dvars(), 0); + EXPECT_EQ(solver.n2Dvars(), n2d); + EXPECT_EQ(solver.n3Dvars(), n3d); #endif vector2.covariant = false; EXPECT_NO_THROW(solver.add(vector2, "another_vector")); - EXPECT_EQ(solver.n2Dvars(), 6); - EXPECT_EQ(solver.n3Dvars(), 0); + EXPECT_EQ(solver.n2Dvars(), n2d*2); + EXPECT_EQ(solver.n3Dvars(), n3d*2); EXPECT_TRUE(IsFieldEqual(vector2.x, 8.0)); EXPECT_TRUE(IsFieldEqual(vector2.y, 9.0)); EXPECT_TRUE(IsFieldEqual(vector2.z, 10.0)); @@ -382,29 +387,34 @@ TEST_F(SolverTest, ConstraintVector2D) { Vector2D vector1{}, vector2{}; EXPECT_NO_THROW(solver.constraint(vector1, vector1, "vector")); - EXPECT_EQ(solver.n2Dvars(), 3); - EXPECT_EQ(solver.n3Dvars(), 0); +#ifndef COORDINATES_USE_3D + int n2d=3, n3d=0; +#else + int n2d=0, n3d=3; +#endif + EXPECT_EQ(solver.n2Dvars(), n2d); + EXPECT_EQ(solver.n3Dvars(), n3d); #if CHECK > 0 EXPECT_THROW(solver.constraint(vector2, vector2, "vector"), BoutException); - EXPECT_EQ(solver.n2Dvars(), 3); - EXPECT_EQ(solver.n3Dvars(), 0); + EXPECT_EQ(solver.n2Dvars(), n2d); + EXPECT_EQ(solver.n3Dvars(), n3d); EXPECT_THROW(solver.constraint(vector2, vector2, ""), BoutException); - EXPECT_EQ(solver.n2Dvars(), 3); - EXPECT_EQ(solver.n3Dvars(), 0); + EXPECT_EQ(solver.n2Dvars(), n2d); + EXPECT_EQ(solver.n3Dvars(), n3d); solver.changeHasConstraints(false); EXPECT_THROW(solver.constraint(vector2, vector2, "some_other_name"), BoutException); - EXPECT_EQ(solver.n2Dvars(), 3); - EXPECT_EQ(solver.n3Dvars(), 0); + EXPECT_EQ(solver.n2Dvars(), n2d); + EXPECT_EQ(solver.n3Dvars(), n3d); solver.changeHasConstraints(true); #endif vector2.covariant = false; EXPECT_NO_THROW(solver.constraint(vector2, vector2, "another_vector")); - EXPECT_EQ(solver.n2Dvars(), 6); - EXPECT_EQ(solver.n3Dvars(), 0); + EXPECT_EQ(solver.n2Dvars(), n2d*2); + EXPECT_EQ(solver.n3Dvars(), n3d*2); const auto expected_names = std::vector{"vector", "another_vector"}; EXPECT_EQ(solver.listVector2DNames(), expected_names); From ad343d01b75e2974a4592b28b3fc38a5f4ecdd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 17:41:14 +0000 Subject: [PATCH 067/293] Fix more errors from merge The only appeared in 2D version --- include/bout/coordinates.hxx | 13 +++++++--- src/mesh/coordinates.cxx | 47 ++++++++++++++++++++++++------------ src/mesh/difops.cxx | 5 ++-- src/mesh/parallel/fci.cxx | 2 +- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 8b4e084f37..adc974de2d 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -283,9 +283,8 @@ private: /// Set the parallel (y) transform from the options file. /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); - template - inline T maybeFromFieldAligned(const T& f, const std::string& region = "RGN_ALL") { - static_assert(bout::utils::is_Field::value, "fromFieldAligned only works on Fields"); + + inline Field3D maybeFromFieldAligned(const Field3D& f, const std::string& region = "RGN_ALL") { ASSERT1(location == f.getLocation()); ASSERT1(localmesh == f.getMesh()); if (f.getDirectionY() != YDirectionType::Standard){ @@ -294,10 +293,16 @@ private: return f; } + inline Field2D maybeFromFieldAligned(const Field2D& f, const std::string& UNUSED(region) = "RGN_ALL") { + return f; + } + /// A wrapper for index:DDY derivative that is able to tranform /// fields before the constructor is finished. - Coordinates::metric_field_type indexDDY(const Coordinates::metric_field_type& f, CELL_LOC outloc = CELL_DEFAULT, + Coordinates::metric_field_type indexDDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + Field3D indexDDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); }; diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 6047bce036..bf8463d6cf 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -564,13 +564,16 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY #endif Mesh* localmesh = f.getMesh(); Coordinates::metric_field_type result; +#ifdef COORDINATES_USE_3D if (location == CELL_YLOW){ auto f_aligned = f.getCoordinates() == nullptr ? pt->toFieldAligned(f, "RGN_NOX") : toFieldAligned(f, "RGN_NOX"); result = interp_to(f_aligned, location, "RGN_NOBNDRY"); result = result.getCoordinates() == nullptr ? pt->fromFieldAligned(result, "RGN_NOBNDRY") : fromFieldAligned(result, "RGN_NOBNDRY"); - } else { + } else +#endif + { result = interp_to(f, location, "RGN_NOBNDRY"); } communicate(result); @@ -584,23 +587,25 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY if (bndry->bx != 0) { // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { - for (int i = 0; i < localmesh->xstart; i++) + for (int i = 0; i < localmesh->xstart; i++){ COORDS_ITER_Z - { + { result(bndry->x + i * bndry->bx, bndry->y, z) = result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); } + } } } if (bndry->by != 0) { // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { - for (int i = 0; i < localmesh->ystart; i++) + for (int i = 0; i < localmesh->ystart; i++) { COORDS_ITER_Z { result(bndry->x, bndry->y + i * bndry->by, z) = result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); } + } } } } @@ -1726,21 +1731,33 @@ Field3D Coordinates::Laplace(const Field3D& f, CELL_LOC outloc) { return result; } -// must be member function so we use the member to/from field aligned -Coordinates::metric_field_type Coordinates::indexDDY(const Coordinates::metric_field_type& f, CELL_LOC outloc, - const std::string& method, const std::string& region){ +Coordinates::metric_field_type Coordinates::indexDDY(const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region){ #ifdef COORDINATES_USE_3D - if (!f.hasParallelSlices()){ - const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; - Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); - } + if (!f.hasParallelSlices()){ + const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); + const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); + } #endif - return bout::derivatives::index::DDY(f, outloc, method, region); + return bout::derivatives::index::DDY(f, outloc, method, region); +} + +Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, + const std::string& method, const std::string& region){ +#ifdef COORDINATES_USE_3D + if (!f.hasParallelSlices()){ + const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); + const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); } +#endif + return bout::derivatives::index::DDY(f, outloc, method, region); +} - bool Coordinates::is3D() { +bool Coordinates::is3D() { #ifdef COORDINATES_USE_3D return true; #else diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 9ba2f8846a..bca01b0952 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -660,10 +660,11 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, throw BoutException("CTU method requires access to the solver"); #ifndef COORDINATES_USE_3D - + const int ncz = mesh->LocalNz; + for(int x=mesh->xstart;x<=mesh->xend;x++) for(int y=mesh->ystart;y<=mesh->yend;y++) { - for (int z = 0; z < mesh->LocalNz; z++) { + for (int z = 0; z < ncz; z++) { int zm = (z - 1 + ncz) % ncz; int zp = (z + 1) % ncz; diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index a5299f74d1..00dffcbe15 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -264,7 +264,7 @@ FCIMap::FCIMap(Mesh& mesh, int offset_, BoundaryRegionPar* boundary, bool zperio BoutReal dz = (dR_dx * dZ - dZ_dx * dR) / det; boundary->add_point(x, y, z, x + dx, y + 0.5*offset, z + dz, // Intersection point in local index space - 0.5*(*coord.dy(x,y)), //sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection + 0.5*coord.dy(x,y,z), //sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection PI // Right-angle intersection ); } From d22e1d7558a754f379160980bf9c523a62484ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 17:41:37 +0000 Subject: [PATCH 068/293] Set c++ version not in setup This is deprecated, so drop it. --- tools/pylib/_boutcore_build/setup.py.in | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/pylib/_boutcore_build/setup.py.in b/tools/pylib/_boutcore_build/setup.py.in index ddd2d19a0f..5a2e4efd92 100644 --- a/tools/pylib/_boutcore_build/setup.py.in +++ b/tools/pylib/_boutcore_build/setup.py.in @@ -14,7 +14,6 @@ os.environ["CC"] = "$(bout-config --cc)" setup( ext_modules = cythonize("boutcore.pyx", - language="c++", # generate C++ code ) ) EOF From dd7f1eddcbbbbbac600f75ef0fd09bbd9acfaac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 20:56:34 +0000 Subject: [PATCH 069/293] fix googletest version --- externalpackages/googletest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externalpackages/googletest b/externalpackages/googletest index 4bab34d208..8b6d3f9c4a 160000 --- a/externalpackages/googletest +++ b/externalpackages/googletest @@ -1 +1 @@ -Subproject commit 4bab34d2084259cba67f3bfb51217c10d606e175 +Subproject commit 8b6d3f9c4a774bef3081195d422993323b6bb2e0 From 6effa24b28a3746a7aa3ea73225e6437dc002eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 17 Feb 2020 21:00:57 +0000 Subject: [PATCH 070/293] Add travis metric_3d test --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7ba9df2027..6a65fb46bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,6 +81,10 @@ matrix: - *default_env - CONFIGURE_OPTIONS="--enable-openmp --with-petsc --with-slepc --with-sundials=$HOME/local" - OMP_NUM_THREADS=2 + - env: + - *default_env + - CONFIGURE_OPTIONS="--enable-metric-3d --enable-shared" + - SCRIPT_FLAGS="-uim -t python -t shared" #CMAKE - env: - *default_env From 4553c0de0e225dadcbd8ca537b34b8e1ec9f3cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 18 Feb 2020 10:51:31 +0000 Subject: [PATCH 071/293] Fix various tests Make e.g. sure we always use 3 indices for metric fields. --- examples/conducting-wall-mode/cwm.cxx | 8 +++--- examples/elm-pb/elm_pb.cxx | 6 +++-- examples/gyro-gem/gem.cxx | 2 +- examples/lapd-drift/lapd_drift.cxx | 21 ++++++++-------- examples/laplacexy/laplace_perp/test.cxx | 2 +- examples/orszag-tang/mhd.cxx | 4 +-- include/bout/fv_ops.hxx | 25 +++++++++++++++---- include/vecops.hxx | 9 +++++++ .../integrated/test-compile-examples/runtest | 5 ++-- .../integrated/test-drift-instability/runtest | 1 + tests/integrated/test-fieldgroupComm/runtest | 1 + tests/integrated/test-io_hdf5/runtest | 3 +++ 12 files changed, 60 insertions(+), 27 deletions(-) diff --git a/examples/conducting-wall-mode/cwm.cxx b/examples/conducting-wall-mode/cwm.cxx index 8ce3fbb38d..d76eb9dd1f 100644 --- a/examples/conducting-wall-mode/cwm.cxx +++ b/examples/conducting-wall-mode/cwm.cxx @@ -304,8 +304,8 @@ class CWM : public PhysicsModel { for (int jz = 0; jz < mesh->LocalNz; jz++) { var(xrup.ind, jy, jz) = var(xrup.ind, jy - 1, jz) - + coord->dy(xrup.ind, jy) - * sqrt(coord->g_22(xrup.ind, jy)) + + coord->dy(xrup.ind, jy, jz) + * sqrt(coord->g_22(xrup.ind, jy, jz)) * value(xrup.ind, jy, jz); } } @@ -319,8 +319,8 @@ class CWM : public PhysicsModel { for (int jz = 0; jz < mesh->LocalNz; jz++) { var(xrdn.ind, jy, jz) = var(xrdn.ind, jy + 1, jz) - - coord->dy(xrdn.ind, jy) - * sqrt(coord->g_22(xrdn.ind, jy)) + - coord->dy(xrdn.ind, jy, jz) + * sqrt(coord->g_22(xrdn.ind, jy, jz)) * value(xrdn.ind, jy, jz); } } diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index 3c3308f14a..d008b7986a 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -24,9 +24,11 @@ class ELMpb : public PhysicsModel { // 2D inital profiles Field2D J0, P0; // Current and pressure Vector2D b0xcv; // Curvature term - Field2D beta, gradparB; // Used for Vpar terms + Field2D beta; // Used for Vpar terms + Coordinates::metric_field_type gradparB; Field2D phi0; // When diamagnetic terms used - Field2D U0, Psixy, x; // 0th vorticity of equilibrium flow, + Field2D Psixy, x; // 0th vorticity of equilibrium flow, + Coordinates::metric_field_type U0; // radial flux coordinate, normalized radial flux coordinate bool constn0; diff --git a/examples/gyro-gem/gem.cxx b/examples/gyro-gem/gem.cxx index d50888f696..97b58e9ad2 100644 --- a/examples/gyro-gem/gem.cxx +++ b/examples/gyro-gem/gem.cxx @@ -57,7 +57,7 @@ class GEM : public PhysicsModel { Vector3D B0vec; // Equilibrium B field vector Field2D logB; // For curvature - Field2D Grad_par_logB; // Grad_par(log(B)) + Coordinates::metric_field_type Grad_par_logB; // Grad_par(log(B)) Field2D Ni0, Ne0; // Gyro-center densities Field2D Ti0, Te0; // Starting isotropic temperatures diff --git a/examples/lapd-drift/lapd_drift.cxx b/examples/lapd-drift/lapd_drift.cxx index 0198d96be8..0514904e8e 100644 --- a/examples/lapd-drift/lapd_drift.cxx +++ b/examples/lapd-drift/lapd_drift.cxx @@ -20,7 +20,8 @@ class LAPDdrift : public PhysicsModel { private: // 2D initial profiles - Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, rho0, Ajpar0, src_ni0; + Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, Ajpar0, src_ni0; + Coordinates::metric_field_type rho0; Vector2D b0xcv; // for curvature terms // 3D evolving fields @@ -725,7 +726,7 @@ class LAPDdrift : public PhysicsModel { /****************SPECIAL DIFFERENTIAL OPERATORS******************/ - const Field2D Perp_Grad_dot_Grad(const Field2D &p, const Field2D &f) { + Coordinates::metric_field_type Perp_Grad_dot_Grad(const Field2D &p, const Field2D &f) { return DDX(p)*DDX(f)*mesh->getCoordinates()->g11; } @@ -735,8 +736,8 @@ class LAPDdrift : public PhysicsModel { // ExB terms. These routines allow comparisons with BOUT-06 // if bout_exb=true is set in BOUT.inp ///////////////////////////////////////////////////////////////// - const Field2D vE_Grad(const Field2D &f, const Field2D &p) { - Field2D result; + Coordinates::metric_field_type vE_Grad(const Field2D &f, const Field2D &p) { + Coordinates::metric_field_type result; if (bout_exb) { // Use a subset of terms for comparison to BOUT-06 result = 0.0; @@ -768,20 +769,20 @@ class LAPDdrift : public PhysicsModel { (f(jx+1,jy) - f(jx-1,jy)) - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* (f(jx,jy) - f(jx,jy)) ) - / (coord->dx(jx,jy) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz); // J+x BoutReal Jpx = 0.25*( f(jx+1,jy)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - f(jx-1,jy)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - f(jx,jy)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + f(jx,jy)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz); // Jx+ BoutReal Jxp = 0.25*( f(jx+1,jy)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - f(jx-1,jy)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - f(jx-1,jy)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + f(jx+1,jy)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz); result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } @@ -829,20 +830,20 @@ class LAPDdrift : public PhysicsModel { (f(jx+1,jy,jz) - f(jx-1,jy,jz)) - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* (f(jx,jy,jzp) - f(jx,jy,jzm)) ) - / (coord->dx(jx,jy) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz); // J+x BoutReal Jpx = 0.25*( f(jx+1,jy,jz)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - f(jx-1,jy,jz)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - f(jx,jy,jzp)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + f(jx,jy,jzm)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz); // Jx+ BoutReal Jxp = 0.25*( f(jx+1,jy,jzp)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - f(jx-1,jy,jzm)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - f(jx-1,jy,jzp)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + f(jx+1,jy,jzm)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz); result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } diff --git a/examples/laplacexy/laplace_perp/test.cxx b/examples/laplacexy/laplace_perp/test.cxx index d81936a599..075f54de21 100644 --- a/examples/laplacexy/laplace_perp/test.cxx +++ b/examples/laplacexy/laplace_perp/test.cxx @@ -57,7 +57,7 @@ int main(int argc, char** argv) { mesh->communicate(solved); // Now differentiate using Laplace_perp - Field2D result = Laplace_perp(solved); + auto result = Laplace_perp(solved); // Write fields to output SAVE_ONCE3(input, solved, result); diff --git a/examples/orszag-tang/mhd.cxx b/examples/orszag-tang/mhd.cxx index acaaca8efa..e590694430 100644 --- a/examples/orszag-tang/mhd.cxx +++ b/examples/orszag-tang/mhd.cxx @@ -47,8 +47,8 @@ class MHD : public PhysicsModel { bout_solve(B, "B"); 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); + output.write("dx[0,0] = %e, dy[0,0] = %e, dz = %e\n", coord->dx(0, 0, 0), + coord->dy(0, 0, 0), coord->dz); SAVE_REPEAT(divB); diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index d46f79a0e9..ef88c8c1e6 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -204,7 +204,7 @@ namespace FV { Coordinates *coord = f_in.getCoordinates(); Field3D result{zeroFrom(f)}; - + // Only need one guard cell, so no need to communicate fluxes // Instead calculate in guard cells to preserve fluxes int ys = mesh->ystart-1; @@ -231,11 +231,11 @@ namespace FV { for (int j = ys; j <= ye; j++) { // Pre-calculate factors which multiply fluxes - +#ifndef COORDINATES_USE_3D // For right cell boundaries BoutReal common_factor = (coord->J(i, j) + coord->J(i, j + 1)) / (sqrt(coord->g_22(i, j)) + sqrt(coord->g_22(i, j + 1))); - + BoutReal flux_factor_rc = common_factor / (coord->dy(i, j) * coord->J(i, j)); BoutReal flux_factor_rp = common_factor / (coord->dy(i, j + 1) * coord->J(i, j + 1)); @@ -245,14 +245,29 @@ namespace FV { BoutReal flux_factor_lc = common_factor / (coord->dy(i, j) * coord->J(i, j)); BoutReal flux_factor_lm = common_factor / (coord->dy(i, j - 1) * coord->J(i, j - 1)); - +#endif for (int k = 0; k < mesh->LocalNz; k++) { +#ifdef COORDINATES_USE_3D + // For right cell boundaries + BoutReal common_factor = (coord->J(i, j, k) + coord->J(i, j + 1, k)) / + (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j + 1, k))); + + BoutReal flux_factor_rc = common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); + BoutReal flux_factor_rp = common_factor / (coord->dy(i, j + 1, k) * coord->J(i, j + 1, k)); + + // For left cell boundaries + common_factor = (coord->J(i, j, k) + coord->J(i, j - 1, k)) / + (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j - 1, k))); + + BoutReal flux_factor_lc = common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); + BoutReal flux_factor_lm = common_factor / (coord->dy(i, j - 1, k) * coord->J(i, j - 1, k)); +#endif //////////////////////////////////////////// // Reconstruct f at the cell faces // This calculates s.R and s.L for the Right and Left // face values on this cell - + // Reconstruct f at the cell faces Stencil1D s; s.c = f(i, j, k); diff --git a/include/vecops.hxx b/include/vecops.hxx index 312062b499..991f220417 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -35,6 +35,15 @@ class Vector2D; class Vector3D; #include "bout/deprecated.hxx" +#include "bout_types.hxx" +#include "bout/coordinates.hxx" +// Those are needed because we implement functions here. +// They can be dropped if we remove the deprecated wrappers. +#include "field2d.hxx" +#include "field3d.hxx" +#include "vector2d.hxx" +#include "vector3d.hxx" + /// Gradient of scalar field \p f, returning a covariant vector /// diff --git a/tests/integrated/test-compile-examples/runtest b/tests/integrated/test-compile-examples/runtest index 9a77d6d04b..31650adeab 100755 --- a/tests/integrated/test-compile-examples/runtest +++ b/tests/integrated/test-compile-examples/runtest @@ -23,9 +23,10 @@ do if test $ex -gt 0 then - echo $(basename $dir) failed + dir=${dir#../../../examples/} + echo $dir failed error=1 - failed="$failed\n$(basename $dir) failed" + failed="$failed\n$dir failed" fi fi done diff --git a/tests/integrated/test-drift-instability/runtest b/tests/integrated/test-drift-instability/runtest index 80f2b98b4e..d583941dc3 100755 --- a/tests/integrated/test-drift-instability/runtest +++ b/tests/integrated/test-drift-instability/runtest @@ -1,5 +1,6 @@ #!/bin/sh #requires: all_tests +#requires: not metric_3d ./runtest.py diff --git a/tests/integrated/test-fieldgroupComm/runtest b/tests/integrated/test-fieldgroupComm/runtest index b1e75767eb..ac8d4c61db 100755 --- a/tests/integrated/test-fieldgroupComm/runtest +++ b/tests/integrated/test-fieldgroupComm/runtest @@ -5,6 +5,7 @@ # #requires: all_tests +#requires: not metric_3d # Variables to compare from __future__ import print_function diff --git a/tests/integrated/test-io_hdf5/runtest b/tests/integrated/test-io_hdf5/runtest index ec6e65c076..067ffbc9e6 100755 --- a/tests/integrated/test-io_hdf5/runtest +++ b/tests/integrated/test-io_hdf5/runtest @@ -7,6 +7,9 @@ #requires: all_tests #Requires: hdf5 +# in metric_3d the vector2d contains 3d fields +#requires: not metric_3d + from boututils.run_wrapper import shell, shell_safe, launch_safe from boutdata.collect import collect import numpy as np From 3fea776c174e6215a98e61888b3e2e2029010ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 18 Feb 2020 11:55:08 +0000 Subject: [PATCH 072/293] skip tests/integrated/test-laplacexz on travis The petsc installation on travis is missing superlu_dist --- tests/integrated/test-laplacexz/runtest | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index b6597d9b8e..4657ef4800 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -1,6 +1,8 @@ #!/usr/bin/env python3 #requires: petsc +# travis doesn't have superlu_dist +#requires: not travis # # Run the test, compare results against the benchmark From c51441bdd4b31452299ad7afab5b529cef667ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 26 Feb 2020 15:46:37 +0000 Subject: [PATCH 073/293] fix requires in options-netcdf test No test should ever `require: False` as there is no way to include this test. --- tests/integrated/test-options-netcdf/runtest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-options-netcdf/runtest b/tests/integrated/test-options-netcdf/runtest index 52db45d900..a56177dafb 100755 --- a/tests/integrated/test-options-netcdf/runtest +++ b/tests/integrated/test-options-netcdf/runtest @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Note: This test requires NCDF4, whereas on Travis NCDF is used -#requires: False +#requires: not travis from boututils.datafile import DataFile from boututils.run_wrapper import shell From 8fa459057a0f4388da799a1a1db1856575c91935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 26 Feb 2020 16:11:31 +0000 Subject: [PATCH 074/293] Drop argument for --enable-metric Is not needed, dropping is easier to use and more consistent with other options --- configure | 3 +-- configure.ac | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 8b5638d8a9..b01dbf7fec 100755 --- a/configure +++ b/configure @@ -1483,8 +1483,7 @@ Optional Features: --enable-shared Enable building bout++ into an shared object --enable-openmp Enable building with OpenMP support --enable-pvode-openmp Enable building PVODE with OpenMP support - --enable-metric-3d=no/yes - If yes use Field3D to store coordinates metric data + --enable-metric-3d Use Field3D to store coordinates metric data --disable-openmp do not use OpenMP --enable-code-coverage Whether to enable code coverage support --disable-nls do not use Native Language Support diff --git a/configure.ac b/configure.ac index 0e145990ab..3ce4ace799 100644 --- a/configure.ac +++ b/configure.ac @@ -92,7 +92,7 @@ AC_ARG_WITH(openmp_schedule,[AS_HELP_STRING([--with-openmp-schedule=static/dynam AC_ARG_ENABLE(pvode_openmp, [AS_HELP_STRING([--enable-pvode-openmp], [Enable building PVODE with OpenMP support])],,[enable_pvode_openmp=no]) AC_ARG_ENABLE(metric_3d, [AS_HELP_STRING([--enable-metric-3d], - [If yes use Field3D to store coordinates metric data])],,[enable_metric_3d=no]) + [Use Field3D to store coordinates metric data])],,[enable_metric_3d=no]) AC_ARG_VAR(EXTRA_INCS,[Extra compile flags]) AC_ARG_VAR(EXTRA_LIBS,[Extra linking flags]) From b6257e956261114f97f14ca53f62907b43bfec50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 26 Feb 2020 16:11:59 +0000 Subject: [PATCH 075/293] Ignore some additional files --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index e23b756987..01a1bfcff2 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,8 @@ src/.libfast .BOUT.pid.* build/ build*/ +/tests/integrated/test-griddata-yboundary-guards/test_griddata +/tests/integrated/test-laplacexz/test-laplacexz +/tests/integrated/test-twistshift-staggered/test-twistshift +/tests/integrated/test-twistshift/test-twistshift +/tests/integrated/test-griddata-yboundary-guards/*/*.nc From 34a62cdae9359694444c5f357875ae22795acee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 26 Feb 2020 18:59:45 +0000 Subject: [PATCH 076/293] Only transform if possible If the parallel transform cannot transform, do not transform. --- include/bout/coordinates.hxx | 8 +++++++- src/mesh/coordinates.cxx | 39 +++++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index adc974de2d..17cd167122 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -288,7 +288,13 @@ private: ASSERT1(location == f.getLocation()); ASSERT1(localmesh == f.getMesh()); if (f.getDirectionY() != YDirectionType::Standard){ - return this->getParallelTransform().fromFieldAligned(f, region); + if (this->getParallelTransform().canToFromFieldAligned()){ + return this->getParallelTransform().fromFieldAligned(f, region); + } else { + Field3D f_ = f; + f_.setDirectionY(YDirectionType::Standard); + return f_; + } } return f; } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index bf8463d6cf..52f4673856 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -133,20 +133,35 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, Field3D _interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* pt) { + bool no_extra_interpolate, ParallelTransform* pt_) { Mesh* localmesh = f_.getMesh(); Field3D result; + Field3D f = f_; + ParallelTransform * pt_f; + if (f.getCoordinates() == nullptr) { + pt_f = pt_; + } else { + pt_f = & f.getCoordinates()->getParallelTransform(); + } // Cannot use normal ifs, so that f is const - const Field3D f = (f_.getDirectionY() == YDirectionType::Standard ? f_ : - (f_.getCoordinates() == nullptr ? pt->fromFieldAligned(f_) : fromFieldAligned(f_))); - + if (f.getDirectionY() != YDirectionType::Standard) { + if (pt_f->canToFromFieldAligned()) { + f = pt_f->fromFieldAligned(f); + } else { + f.setDirectionY(YDirectionType::Standard); + } + } if (location == CELL_YLOW){ - auto f_aligned = f.getCoordinates() == nullptr ? - pt->toFieldAligned(f, "RGN_NOX") : toFieldAligned(f, "RGN_NOX"); + auto f_aligned = pt_f->toFieldAligned(f, "RGN_NOX"); result = interp_to(f_aligned, location, "RGN_NOBNDRY"); - result = result.getCoordinates() == nullptr ? - pt->fromFieldAligned(result, "RGN_NOBNDRY") : fromFieldAligned(result, "RGN_NOBNDRY"); + ParallelTransform * pt_result; + if (result.getCoordinates() == nullptr){ + pt_result = pt_; + } else { + pt_result = & result.getCoordinates()->getParallelTransform(); + } + result = pt_result->fromFieldAligned(result, "RGN_NOBNDRY"); } else { result = interp_to(f, location, "RGN_NOBNDRY"); } @@ -1749,7 +1764,13 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, #ifdef COORDINATES_USE_3D if (!f.hasParallelSlices()){ const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + Field3D f_aligned; + if (transform->canToFromFieldAligned()){ + f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + } else { + f_aligned = f; + f_aligned.setDirectionY(YDirectionType::Aligned); + } Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); } From c224bbd1cc87eabab274d9dab0ebba1951a2483d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 27 Feb 2020 00:39:28 +0000 Subject: [PATCH 077/293] Add bout_config to expose configure status to python Some tests need to know wether the metric field is 2d or 3d. Exposing the whole state might be usefull. --- .gitignore | 4 + configure | 3 + configure.ac | 1 + tools/pylib/boututils/bout_config.py.in | 293 ++++++++++++++++++++++++ 4 files changed, 301 insertions(+) create mode 100644 tools/pylib/boututils/bout_config.py.in diff --git a/.gitignore b/.gitignore index 01a1bfcff2..5042929cb7 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,7 @@ build*/ /tests/integrated/test-twistshift-staggered/test-twistshift /tests/integrated/test-twistshift/test-twistshift /tests/integrated/test-griddata-yboundary-guards/*/*.nc +/tests/integrated/test-options-netcdf/*.nc +/tests/integrated/test-options-netcdf/test-options-netcdf +/tests/integrated/test-options-netcdf/*.ini +/tools/pylib/boututils/bout_config.py diff --git a/configure b/configure index b01dbf7fec..2a1d4a6f5c 100755 --- a/configure +++ b/configure @@ -15788,6 +15788,8 @@ MPARK_VARIANT_INCLUDE_PATH=$PWD/externalpackages/mpark.variant/include ac_config_files="$ac_config_files bin/bout-config" +ac_config_files="$ac_config_files tools/pylib/boututils/bout_config.py" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -16518,6 +16520,7 @@ do "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; "make.config") CONFIG_FILES="$CONFIG_FILES make.config" ;; "bin/bout-config") CONFIG_FILES="$CONFIG_FILES bin/bout-config" ;; + "tools/pylib/boututils/bout_config.py") CONFIG_FILES="$CONFIG_FILES tools/pylib/boututils/bout_config.py" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/configure.ac b/configure.ac index 3ce4ace799..d3e1fde93d 100644 --- a/configure.ac +++ b/configure.ac @@ -1315,6 +1315,7 @@ AC_SUBST(METRIC_TYPE) AC_SUBST(HAS_FFTW) AC_CONFIG_FILES([bin/bout-config]) +AC_CONFIG_FILES([tools/pylib/boututils/bout_config.py]) AC_OUTPUT chmod a+x bin/bout-config diff --git a/tools/pylib/boututils/bout_config.py.in b/tools/pylib/boututils/bout_config.py.in new file mode 100644 index 0000000000..c53d4cce2c --- /dev/null +++ b/tools/pylib/boututils/bout_config.py.in @@ -0,0 +1,293 @@ +"""Functions for getting the config used for compiling BOUT++ + +""" + +_yesno = {'"yes"': True, '"no"': False} + +_cc='@MPICXX@' +_cxx='@MPICXX@' +_ld='@MPICXX@' +_checks="@CHECK_LEVEL@" +_cflags='@CONFIG_CFLAGS@' +_libs='@CONFIG_LDFLAGS@' + +_version="@BOUT_VERSION@" +_git="@GIT_REVISION@" +_idlpath="@IDLCONFIGPATH@" +_pythonpath="@PYTHONCONFIGPATH@" + +_has_netcdf="@HAS_NETCDF@" +_has_pnetcdf="@HAS_PNETCDF@" +_has_hdf5="@HAS_HDF5@" +_has_pvode="@HAS_PVODE@" +_has_cvode="@HAS_CVODE@" +_has_ida="@HAS_IDA@" +_has_lapack="@HAS_LAPACK@" +_has_petsc="@HAS_PETSC@" +_has_slepc="@HAS_SLEPC@" +_has_mumps="@HAS_MUMPS@" +_has_arkode="@HAS_ARKODE@" +_has_openmp="@HAS_OPENMP@" +_has_nls="@HAS_NLS@" +_has_fftw="@HAS_FFTW@" + +_petsc_has_sundials="@PETSC_HAS_SUNDIALS@" + +_metric_type="@METRIC_TYPE@" +def has_netcdf(): + """Return 'yes' / 'no' whether has_netcdf is available + + """ + return _has_netcdf + +def hasNetcdf(): + """Return True / False whether has_netcdf is available + + """ + return _yesno[_has_netcdf] + +def has_pnetcdf(): + """Return 'yes' / 'no' whether has_pnetcdf is available + + """ + return _has_pnetcdf + +def hasPnetcdf(): + """Return True / False whether has_pnetcdf is available + + """ + return _yesno[_has_pnetcdf] + +def has_hdf5(): + """Return 'yes' / 'no' whether has_hdf5 is available + + """ + return _has_hdf5 + +def hasHdf5(): + """Return True / False whether has_hdf5 is available + + """ + return _yesno[_has_hdf5] + +def has_pvode(): + """Return 'yes' / 'no' whether has_pvode is available + + """ + return _has_pvode + +def hasPvode(): + """Return True / False whether has_pvode is available + + """ + return _yesno[_has_pvode] + +def has_cvode(): + """Return 'yes' / 'no' whether has_cvode is available + + """ + return _has_cvode + +def hasCvode(): + """Return True / False whether has_cvode is available + + """ + return _yesno[_has_cvode] + +def has_ida(): + """Return 'yes' / 'no' whether has_ida is available + + """ + return _has_ida + +def hasIda(): + """Return True / False whether has_ida is available + + """ + return _yesno[_has_ida] + +def has_lapack(): + """Return 'yes' / 'no' whether has_lapack is available + + """ + return _has_lapack + +def hasLapack(): + """Return True / False whether has_lapack is available + + """ + return _yesno[_has_lapack] + +def has_petsc(): + """Return 'yes' / 'no' whether has_petsc is available + + """ + return _has_petsc + +def hasPetsc(): + """Return True / False whether has_petsc is available + + """ + return _yesno[_has_petsc] + +def has_slepc(): + """Return 'yes' / 'no' whether has_slepc is available + + """ + return _has_slepc + +def hasSlepc(): + """Return True / False whether has_slepc is available + + """ + return _yesno[_has_slepc] + +def has_mumps(): + """Return 'yes' / 'no' whether has_mumps is available + + """ + return _has_mumps + +def hasMumps(): + """Return True / False whether has_mumps is available + + """ + return _yesno[_has_mumps] + +def has_arkode(): + """Return 'yes' / 'no' whether has_arkode is available + + """ + return _has_arkode + +def hasArkode(): + """Return True / False whether has_arkode is available + + """ + return _yesno[_has_arkode] + +def has_openmp(): + """Return 'yes' / 'no' whether has_openmp is available + + """ + return _has_openmp + +def hasOpenmp(): + """Return True / False whether has_openmp is available + + """ + return _yesno[_has_openmp] + +def has_nls(): + """Return 'yes' / 'no' whether has_nls is available + + """ + return _has_nls + +def hasNls(): + """Return True / False whether has_nls is available + + """ + return _yesno[_has_nls] + +def has_fftw(): + """Return 'yes' / 'no' whether has_fftw is available + + """ + return _has_fftw + +def hasFftw(): + """Return True / False whether has_fftw is available + + """ + return _yesno[_has_fftw] + +def petsc_has_sundials(): + """Return 'yes' / 'no' whether petsc_has_sundials is available + + """ + return _petsc_has_sundials + +def petscHasSundials(): + """Return True / False whether petsc_has_sundials is available + + """ + return _yesno[_petsc_has_sundials] + +def cc(): + """Option for cc + + """ + return _cc + +def cxx(): + """Option for cxx + + """ + return _cxx + +def ld(): + """Option for ld + + """ + return _ld + +def checks(): + """Option for checks + + """ + return _checks + +def cflags(): + """Option for cflags + + """ + return _cflags + +def libs(): + """Option for libs + + """ + return _libs + +def metric_type(): + """Option for metric_type + + """ + return _metric_type + +def version(): + """Option for version + + """ + return _version + +def git(): + """Option for git + + """ + return _git + +def idlpath(): + """Option for idlpath + + """ + return _idlpath + +def pythonpath(): + """Option for pythonpath + + """ + return _pythonpath + +def isMetric2D(): + """Is the metric 2D? + + """ + return _metric_type == "2D" + +def isMetric3D(): + """Is the metric 3D? + + """ + return _metric_type == "3D" From 068c0e24ec136d4477d79c9fbe214ace9233c226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 27 Feb 2020 00:40:11 +0000 Subject: [PATCH 078/293] generate appropriate field Use new boututils.bout_config for checking metric field type. --- tests/MMS/spatial/fci/runtest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index 910b4de162..cbf3581c30 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -2,10 +2,10 @@ # # Python script to run and analyse MMS test # -#requires not metric_3d from boututils.run_wrapper import shell_safe, launch_safe from boutdata.collect import collect +import boututils.bout_config as conf from numpy import array, log, polyfit, linspace, arange @@ -74,7 +74,7 @@ for nslice in nslices: grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) # Make and write maps maps = zb.make_maps(grid, field, nslice=nslice, quiet=True) - zb.write_maps(grid, field, maps, new_names=False, metric2d=True, quiet=True) + zb.write_maps(grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True) args = (" MZ={} MYG={} fci:y_periodic={} mesh:ddy:first={}" .format(n, nslice, yperiodic, method_orders[nslice]["name"])) From 07e08dd1337213d16ea74bd2003550da00b39cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 27 Feb 2020 01:13:41 +0000 Subject: [PATCH 079/293] Fix io test for 3D metrics --- tests/MMS/wave-1d-y/runtest | 2 - tests/MMS/wave-1d/runtest | 2 - tests/integrated/test-io/runtest | 76 ++++++++++++++++++-------------- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/tests/MMS/wave-1d-y/runtest b/tests/MMS/wave-1d-y/runtest index 12643fb7a8..ea332f79cd 100755 --- a/tests/MMS/wave-1d-y/runtest +++ b/tests/MMS/wave-1d-y/runtest @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -#requires: not metric_3d - # Python script to run and analyse MMS test from __future__ import division diff --git a/tests/MMS/wave-1d/runtest b/tests/MMS/wave-1d/runtest index 35771da93e..39278d500a 100755 --- a/tests/MMS/wave-1d/runtest +++ b/tests/MMS/wave-1d/runtest @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -#requires: not metric_3d - # Python script to run and analyse MMS test from __future__ import division diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index b6e36d70cd..cd4887f306 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -14,6 +14,7 @@ except: from boututils.run_wrapper import shell, shell_safe, launch_safe from boutdata.collect import collect +import boututils.bout_config as conf import numpy as np from sys import stdout, exit @@ -36,6 +37,46 @@ bmk = {} for v in vars: bmk[v] = collect(v, path="data", prefix="benchmark.out", info=False) +def check_output(): + success = True + for v in vars: + stdout.write(" Checking variable "+v+" ... ") + result = collect(v, path="data", info=False) + + # Compare benchmark and output + if np.shape(bmk[v]) != np.shape(result): + if (conf.isMetric3D() and v.startswith('v2d') + and bmk[v].shape == result.shape[:-1]): + result = result[...,0] + else: + print("Fail, wrong shape") + print(v,bmk[v].shape, result.shape) + success = False + continue + + diff = np.max(np.abs(bmk[v] - result)) + if diff > tol: + print("Fail, maximum difference = "+str(diff)) + success = False + continue + + if v in field_vars: + # Check cell location + if "cell_location" not in result.attributes: + print("Fail: {0} has no cell_location attribute".format(v)) + success = False + continue + + if result.attributes["cell_location"] != "CELL_CENTRE": + print("Fail: Expecting cell_location == CELL_CENTRE, but got {0}".format(result.attributes["cell_location"])) + success = False + continue + + print("Pass") + + return success + + print("Running I/O test") success = True for nproc in [1,2,4]: @@ -74,40 +115,7 @@ for nproc in [1,2,4]: print("Pass") # Collect output data - for v in vars: - stdout.write(" Checking variable "+v+" ... ") - result = collect(v, path="data", info=False) - - # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - if not ( - (v.startswith("v2d_")) and - np.shape(bmk[v]) == np.shape(result[:,:,:,0]) ): - print("Fail, wrong shape") - success = False - continue - else: - result = result[:,:,:,0] - - diff = np.max(np.abs(bmk[v] - result)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - continue - - if v in field_vars: - # Check cell location - if "cell_location" not in result.attributes: - print("Fail: {0} has no cell_location attribute".format(v)) - success = False - continue - - if result.attributes["cell_location"] != "CELL_CENTRE": - print("Fail: Expecting cell_location == CELL_CENTRE, but got {0}".format(result.attributes["cell_location"])) - success = False - continue - - print("Pass") + success = success and check_output() if success: print(" => All I/O tests passed") From 71a1591e7910e19a73f43b06678dd0d20b0d4e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 27 Feb 2020 01:17:15 +0000 Subject: [PATCH 080/293] cyclic solver not available with 3d metrics --- tests/integrated/test-invertable-operator/runtest | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-invertable-operator/runtest b/tests/integrated/test-invertable-operator/runtest index 11b366f804..6a956c9cb0 100755 --- a/tests/integrated/test-invertable-operator/runtest +++ b/tests/integrated/test-invertable-operator/runtest @@ -1,6 +1,7 @@ #!/usr/bin/env python3 #requires: petsc +#requires: not metric_3d # # Run the test, compare results against expected value From 30649509e2a59cc043f95393f51a059022776947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 27 Feb 2020 01:27:54 +0000 Subject: [PATCH 081/293] Delp2 uses no-fft with 3d metric With 3D metrics the FFTs aren't implemented. We might do in the future, thus we do not want user code to change, if the would prefere FFTs as they get available. --- src/mesh/coordinates.cxx | 9 ++++----- tests/integrated/test-delp2/runtest | 2 -- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 52f4673856..392b81cdaf 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1580,7 +1580,7 @@ Coordinates::metric_field_type Coordinates::Delp2(const Field2D& f, return result; } -Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, bool useFFT) { +Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(bool useFFT)) { TRACE("Coordinates::Delp2( Field3D )"); if (outloc == CELL_DEFAULT) { @@ -1598,8 +1598,8 @@ Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, bool useFFT) { Field3D result{emptyFrom(f).setLocation(outloc)}; - if (useFFT) { #ifndef COORDINATES_USE_3D + if (useFFT) { int ncz = localmesh->LocalNz; // Allocate memory @@ -1634,10 +1634,9 @@ Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, bool useFFT) { irfft(&delft(jx, 0), ncz, &result(jx, jy, 0)); } } -#else - throw BoutException("Delp2(Field3D) currently only works when passed useFFT=False."); + } else #endif - } else { + { result = G1 * ::DDX(f, outloc) + G3 * ::DDZ(f, outloc) + g11 * ::D2DX2(f, outloc) + g33 * ::D2DZ2(f, outloc) + 2 * g13 * ::D2DXDZ(f, outloc); }; diff --git a/tests/integrated/test-delp2/runtest b/tests/integrated/test-delp2/runtest index 65562587df..fb98b4b6a4 100755 --- a/tests/integrated/test-delp2/runtest +++ b/tests/integrated/test-delp2/runtest @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -#requires: not metric_3d - from __future__ import print_function try: from builtins import str From ca8c53385f823bb5ee1992d3064d922d51c64ae9 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Fri, 28 Feb 2020 10:35:53 +0100 Subject: [PATCH 082/293] Implement BOUT_FOR in div_f_v Add DC function for Field2D Implement RGN_UPPER/LOWER_Y_THIN regions --- include/bout/fv_ops.hxx | 217 ++++++++++++++++++---------------------- include/field2d.hxx | 7 ++ src/mesh/mesh.cxx | 15 +++ 3 files changed, 122 insertions(+), 117 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index ef88c8c1e6..53491b3608 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -387,110 +387,98 @@ namespace FV { Field3D vx = v.x; Field3D vz = v.z; Field3D n = n_in; - - // X-Z advection - for(int i=mesh->xstart;i<=mesh->xend;i++) - for(int j=mesh->ystart;j<=mesh->yend;j++) - for(int k=0;kLocalNz;k++) { - int kp = (k+1) % (mesh->LocalNz); - int kpp = (kp+1) % (mesh->LocalNz); - int km = (k-1+mesh->LocalNz) % (mesh->LocalNz); - int kmm = (km-1+mesh->LocalNz) % (mesh->LocalNz); - - // Calculate velocities - BoutReal vU = 0.5*(vz(i,j,kp) + vz(i,j,k))*coord->J(i,j); - BoutReal vD = 0.5*(vz(i,j,km) + vz(i,j,k))*coord->J(i,j); - BoutReal vL = 0.25*(vx(i-1,j,k) + vx(i,j,k))*(coord->J(i-1,j) + coord->J(i,j)); - BoutReal vR = 0.25*(vx(i+1,j,k) + vx(i,j,k))*(coord->J(i+1,j) + coord->J(i,j)); - - // X direction - Stencil1D s; - s.c = n(i, j,k); - s.m = n(i-1,j,k); - s.mm = n(i-2,j,k); - s.p = n(i+1,j,k); - s.pp = n(i+2,j,k); - - cellboundary(s); - - if((i==mesh->xend) && (mesh->lastX())) { - // At right boundary in X + + BOUT_FOR(i,result.getRegion("RGN_NOBNDRY")){ + // Calculate velocities + BoutReal vU = 0.25*(vz[i.zp()] + vz[i])*(coord->J[i.zp()] + coord->J[i]); + BoutReal vD = 0.25*(vz[i.zm()] + vz[i])*(coord->J[i.zm()] + coord->J[i]); + BoutReal vL = 0.25*(vx[i.xm()] + vx[i])*(coord->J[i.xm()] + coord->J[i]); + BoutReal vR = 0.25*(vx[i.xp()] + vx[i])*(coord->J[i.xp()] + coord->J[i]); + + // X direction + Stencil1D s; + s.c = n[i]; + s.m = n[i.xm()]; + s.mm = n[i.xmm()]; + s.p = n[i.xp()]; + s.pp = n[i.xpp()]; + + cellboundary(s); + + if ((i.x()==mesh->xend) && (mesh->lastX())) { + // At right boundary in X + if(bndry_flux) { + BoutReal flux; + if(vR > 0.0) { + // Flux to boundary + flux = vR * s.R; + }else { + // Flux in from boundary + flux = vR * 0.5*(n[i.xp()] + n[i]); + } + result[i] += flux / (coord->dx[i] * coord->J[i]); + result[i.xp()] -= flux / (coord->dx[i.xp()] * coord->J[i.xp()]); + } + }else { + // Not at a boundary + if(vR > 0.0) { + // Flux out into next cell + BoutReal flux = vR * s.R; + result[i] += flux / (coord->dx[i] * coord->J[i]); + result[i.xp()] -= flux / (coord->dx[i.xp()] * coord->J[i.xp()]); + } + } + + // Left side - if(bndry_flux) { - BoutReal flux; - if(vR > 0.0) { - // Flux to boundary - flux = vR * s.R; - }else { - // Flux in from boundary - flux = vR * 0.5*(n(i+1,j,k) + n(i,j,k)); - } - result(i,j,k) += flux / (coord->dx(i,j) * coord->J(i,j)); - result(i+1,j,k) -= flux / (coord->dx(i+1,j) * coord->J(i+1,j)); - } - }else { - // Not at a boundary - if(vR > 0.0) { - // Flux out into next cell - BoutReal flux = vR * s.R; - result(i,j,k) += flux / (coord->dx(i,j) * coord->J(i,j)); - result(i+1,j,k) -= flux / (coord->dx(i+1,j) * coord->J(i+1,j)); - } - } + if((i.x()==mesh->xstart) && (mesh->firstX())) { + // At left boundary in X - // Left side - - if((i==mesh->xstart) && (mesh->firstX())) { - // At left boundary in X - - if(bndry_flux) { - BoutReal flux; - - if(vL < 0.0) { - // Flux to boundary - flux = vL * s.L; - - }else { - // Flux in from boundary - flux = vL * 0.5*(n(i-1,j,k) + n(i,j,k)); - } - result(i,j,k) -= flux / (coord->dx(i,j) * coord->J(i,j)); - result(i-1,j,k) += flux / (coord->dx(i-1,j) * coord->J(i-1,j)); - } - }else { - // Not at a boundary - - if(vL < 0.0) { - BoutReal flux = vL * s.L; - result(i,j,k) -= flux / (coord->dx(i,j) * coord->J(i,j)); - result(i-1,j,k) += flux / (coord->dx(i-1,j) * coord->J(i-1,j)); - } - } - - /// NOTE: Need to communicate fluxes - - // Z direction - s.m = n(i,j,km); - s.mm = n(i,j,kmm); - s.p = n(i,j,kp); - s.pp = n(i,j,kpp); - - cellboundary(s); - - if(vU > 0.0) { - BoutReal flux = vU * s.R / (coord->J(i,j)*coord->dz); - result(i,j,k) += flux; - result(i,j,kp) -= flux; - } - if(vD < 0.0) { - BoutReal flux = vD * s.L / (coord->J(i,j)*coord->dz); - result(i,j,k) -= flux; - result(i,j,km) += flux; - } + if(bndry_flux) { + BoutReal flux; + if(vL < 0.0) { + // Flux to boundary + flux = vL * s.L; + }else { + // Flux in from boundary + flux = vL * 0.5*(n[i.xm()] + n[i]); + } + result[i] -= flux / (coord->dx[i] * coord->J[i]); + result[i.xm()] += flux / (coord->dx[i.xm()] * coord->J[i.xm()]); + } + }else { + // Not at a boundary + if(vL < 0.0) { + BoutReal flux = vL * s.L; + result[i] -= flux / (coord->dx[i] * coord->J[i]); + result[i.xm()] += flux / (coord->dx[i.xm()] * coord->J[i.xm()]); + } + } + + /// NOTE: Need to communicate fluxes - } - communicateFluxes(result); + // Z direction + s.m = n[i.zm()]; + s.mm = n[i.zmm()]; + s.p = n[i.zp()]; + s.pp = n[i.zpp()]; + + cellboundary(s); + + if(vU > 0.0) { + BoutReal flux = vU * s.R; + result[i] += flux / (coord->J[i]*coord->dz); + result[i.zp()] -= flux / (coord->J[i.zp()]*coord->dz); + } + if(vD < 0.0) { + BoutReal flux = vD * s.L; + result[i] -= flux / (coord->J[i]*coord->dz);; + result[i.zm()] += flux / (coord->J[i.zm()]*coord->dz);; + } + } + communicateFluxes(result); + // Y advection // Currently just using simple centered differences // so no fluxes need to be exchanged @@ -500,24 +488,19 @@ namespace FV { Field3D yresult = 0.0; yresult.setDirectionY(YDirectionType::Aligned); - for(int i=mesh->xstart;i<=mesh->xend;i++) - for(int j=mesh->ystart;j<=mesh->yend;j++) - for(int k=0;kLocalNz;k++) { - - // Y velocities on y boundaries - BoutReal vU = 0.25*(vy(i,j,k) + vy(i,j+1,k))*(coord->J(i,j) + coord->J(i,j+1)); - BoutReal vD = 0.25*(vy(i,j,k) + vy(i,j-1,k))*(coord->J(i,j) + coord->J(i,j-1)); - - // n (advected quantity) on y boundaries - // Note: Use unshifted n_in variable - BoutReal nU = 0.5*(n(i,j,k) + n(i,j+1,k)); - BoutReal nD = 0.5*(n(i,j,k) + n(i,j-1,k)); - - yresult(i,j,k) = (nU*vU - nD*vD) / (coord->J(i,j)*coord->dy(i,j)); - } - + BOUT_FOR(i,result.getRegion("RGN_NOBNDRY")){ + // Y velocities on y boundaries + BoutReal vU = 0.25*(vy[i] + vy[i.yp()])*(coord->J[i] + coord->J[i.yp()]); + BoutReal vD = 0.25*(vy[i] + vy[i.ym()])*(coord->J[i] + coord->J[i.ym()]); + + // n (advected quantity) on y boundaries + // Note: Use unshifted n_in variable + BoutReal nU = 0.5*(n[i] + n[i.yp()]); + BoutReal nD = 0.5*(n[i] + n[i.ym()]); + + yresult[i] = (nU*vU - nD*vD) / (coord->J[i]*coord->dy[i]); + } return result + fromFieldAligned(yresult, "RGN_NOBNDRY"); } } - #endif // __FV_OPS_H__ diff --git a/include/field2d.hxx b/include/field2d.hxx index 1d4176029d..cb5c150a96 100644 --- a/include/field2d.hxx +++ b/include/field2d.hxx @@ -377,6 +377,13 @@ void invalidateGuards(Field2D &var); inline void invalidateGuards(Field2D &UNUSED(var)) {} #endif +/// Average in the Z direction +/// Field2D has no Z direction -- return input +/// @param[in] f Variable to average +inline Field2D DC(const Field2D &f) { + return f; +} + /// Returns a reference to the time-derivative of a field \p f /// /// Wrapper around member function f.timeDeriv() diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index e74b370ec6..cb83f15bd7 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -467,6 +467,14 @@ void Mesh::createDefaultRegions(){ (getRegion3D("RGN_NOBNDRY") + getRegion3D("RGN_XGUARDS") + getRegion3D("RGN_YGUARDS") + getRegion3D("RGN_ZGUARDS")).unique()); + addRegion3D("RGN_UPPER_Y_THIN", + Region(xstart, xend, yend + 1, yend + 1, 0, LocalNz - 1, LocalNy, LocalNz, + maxregionblocksize)); + addRegion3D("RGN_LOWER_Y_THIN", + Region(xstart, xend, ystart + 1, ystart + 1, 0, LocalNz - 1, LocalNy, LocalNz, + maxregionblocksize)); + + //2D regions addRegion2D("RGN_ALL", Region(0, LocalNx - 1, 0, LocalNy - 1, 0, 0, LocalNy, 1, maxregionblocksize)); @@ -495,6 +503,13 @@ void Mesh::createDefaultRegions(){ (getRegion2D("RGN_NOBNDRY") + getRegion2D("RGN_XGUARDS") + getRegion2D("RGN_YGUARDS") + getRegion2D("RGN_ZGUARDS")).unique()); + addRegion2D("RGN_UPPER_Y_THIN", + Region(xstart, xend, yend + 1, yend + 1, 0, -1, LocalNy, 1, + maxregionblocksize)); + addRegion2D("RGN_LOWER_Y_THIN", + Region(xstart, xend, ystart + 1, ystart + 1, 0, -1, LocalNy, 1, + maxregionblocksize)); + // Perp regions addRegionPerp("RGN_ALL", Region(0, LocalNx - 1, 0, 0, 0, LocalNz - 1, 1, LocalNz, maxregionblocksize)); From 30533724c5693dda3e0b5d4cb871af2c2d576a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 09:36:04 +0000 Subject: [PATCH 083/293] If we cannot transform, calculate slices --- src/mesh/coordinates.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 392b81cdaf..a03921a442 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1767,8 +1767,8 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, if (transform->canToFromFieldAligned()){ f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; } else { - f_aligned = f; - f_aligned.setDirectionY(YDirectionType::Aligned); + f.calcParallelSlices(); + return bout::derivatives::index::DDY(f, outloc, method, region); } Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); From 932dfe0afb0b344a5048cede05ee360ecb899ddf Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Fri, 28 Feb 2020 10:54:47 +0100 Subject: [PATCH 084/293] Use local transform in indexDDY --- src/mesh/coordinates.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index a03921a442..0dd4eba735 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1767,8 +1767,9 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, if (transform->canToFromFieldAligned()){ f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; } else { - f.calcParallelSlices(); - return bout::derivatives::index::DDY(f, outloc, method, region); + Field3D f_parallel = f; + transform->calcParallelSlices(f_parallel); + return bout::derivatives::index::DDY(f_parallel, outloc, method, region); } Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); From 21e64d5284625bc07a18115cc2e94dee9817cf9b Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Fri, 28 Feb 2020 14:38:40 +0100 Subject: [PATCH 085/293] Nearly implement dz as a FieldXD some tests are broken (Zshift issues?) --- include/bout/coordinates.hxx | 18 ++++-- include/field2d.hxx | 2 + include/field3d.hxx | 2 + src/field/field2d.cxx | 10 ++++ src/field/field3d.cxx | 12 +++- src/field/fieldgenerators.cxx | 6 +- .../laplace/impls/cyclic/cyclic_laplace.cxx | 9 +-- src/invert/laplace/impls/pdd/pdd.cxx | 3 +- .../laplace/impls/petsc/petsc_laplace.cxx | 12 ++-- .../laplace/impls/serial_tri/serial_tri.cxx | 3 +- .../laplace/impls/shoot/shoot_laplace.cxx | 3 +- src/invert/laplace/impls/spt/spt.cxx | 3 +- src/invert/laplace/invert_laplace.cxx | 6 +- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 20 +++---- src/mesh/coordinates.cxx | 34 +++++------ src/mesh/data/gridfromfile.cxx | 6 +- src/mesh/difops.cxx | 56 +++++++++---------- tests/MMS/diffusion/diffusion.cxx | 4 +- tests/MMS/wave-1d/wave.cxx | 12 ++-- .../integrated/test-yupdown/test_yupdown.cxx | 2 +- .../unit/mesh/parallel/test_shiftedmetric.cxx | 2 +- tests/unit/mesh/test_coordinates.cxx | 2 +- 22 files changed, 129 insertions(+), 98 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 17cd167122..8d4db2aedb 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -88,15 +88,25 @@ public: */ void outputVars(Datafile &file); - metric_field_type dx, dy; ///< Mesh spacing in x and y - BoutReal dz; ///< Mesh spacing in Z + metric_field_type dx, dy, dz; ///< Mesh spacing in x and y + // BoutReal dz; ///< Mesh spacing in Z - BoutReal zlength() const { return dz * nz; } ///< Length of the Z domain. Used for FFTs + Field2D zlength() const { +#ifdef COORDINATES_USE_3D + Field2D result(0.,(Mesh * ) this); + BOUT_FOR_SERIAL(i, dz.getRegion("RGN_ALL")) { + result[i] += dz[i]; + } + return result; +#else + return dz * nz; +#endif + } ///< Length of the Z domain. Used for FFTs /// True if corrections for non-uniform mesh spacing should be included in operators bool non_uniform; metric_field_type d1_dx, - d1_dy; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) + d1_dy, d1_dz; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) metric_field_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz diff --git a/include/field2d.hxx b/include/field2d.hxx index cb5c150a96..e9941de2b0 100644 --- a/include/field2d.hxx +++ b/include/field2d.hxx @@ -260,6 +260,8 @@ class Field2D : public Field, public FieldData { int byteSize() const override { return sizeof(BoutReal); } // Just one BoutReal int BoutRealSize() const override { return 1; } + bool isConst(const std::string& region) const; + #if CHECK > 0 void doneComms() override { bndry_xin = bndry_xout = bndry_yup = bndry_ydown = true; } #else diff --git a/include/field3d.hxx b/include/field3d.hxx index 83ea810c45..2137f8f511 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -459,6 +459,8 @@ class Field3D : public Field, public FieldData { int byteSize() const override { return sizeof(BoutReal); } // Just one BoutReal int BoutRealSize() const override { return 1; } + bool isConst(const std::string& region) const; + /// Visitor pattern support void accept(FieldVisitor &v) override { v.accept(*this); } diff --git a/src/field/field2d.cxx b/src/field/field2d.cxx index 9e2ba75492..b1b1a188ad 100644 --- a/src/field/field2d.cxx +++ b/src/field/field2d.cxx @@ -94,6 +94,16 @@ Field2D::Field2D(Array data_in, Mesh* localmesh, CELL_LOC datalocation setLocation(datalocation); } +bool Field2D::isConst(const std::string & region) const { + auto element = (*this)[this->getRegion(region).begin()[0]]; + BOUT_FOR_SERIAL(i, this->getRegion(region)){ + if ((*this)[i] != element){ + return false; + } + } + return true; +} + Field2D::~Field2D() { delete deriv; } Field2D& Field2D::allocate() { diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 32459b5cb8..90ed4b0ea3 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -756,7 +756,7 @@ void shiftZ(Field3D &var, int jx, int jy, double zangle) { rfft(&(var(jx,jy,0)), ncz, v.begin()); // Forward FFT - BoutReal zlength = var.getCoordinates()->zlength(); + BoutReal zlength = var.getCoordinates()->zlength()(jx, jy); // Apply phase shift for(int jz=1;jz<=ncz/2;jz++) { @@ -848,3 +848,13 @@ std::ostream& operator<<(std::ostream &out, const Field3D &value) { out << toString(value); return out; } + +bool Field3D::isConst(const std::string & region) const { + auto element = (*this)[this->getRegion(region).begin()[0]]; + BOUT_FOR_SERIAL(i, this->getRegion(region)){ + if ((*this)[i] != element){ + return false; + } + } + return true; +} diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 892bf2d6b2..02197d0e2a 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -188,16 +188,18 @@ BoutReal FieldBallooning::generate(double x, double y, double z, double t) { (mesh->xend - mesh->xstart); int jx = ROUND((x - mesh->GlobalX(0)) / dx); + ASSERT1(coords->zlength().isConst("RGN_ALL")); + if(mesh->periodicY(jx, ts)) { // Start with the value at this point BoutReal value = arg->generate(x,y,z,t); for(int i=1; i<= ball_n; i++) { // y - i * 2pi - value += arg->generate(x,y - i*TWOPI,z + i*ts*TWOPI/coords->zlength(),t); + value += arg->generate(x,y - i*TWOPI,z + i*ts*TWOPI/coords->zlength()(0,0),t); // y + i * 2pi - value += arg->generate(x,y + i*TWOPI,z - i*ts*TWOPI/coords->zlength(),t); + value += arg->generate(x,y + i*TWOPI,z - i*ts*TWOPI/coords->zlength()(0,0),t); } return value; } diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index e401160c91..2e9eacc5ad 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -118,6 +118,7 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { outbndry = 1; if(dst) { + ASSERT1(coords->dz.isConst("RGN_ALL")); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = @@ -147,7 +148,7 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { // including boundary conditions BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { - BoutReal zlen = coords->dz * (localmesh->LocalNz - 3); + BoutReal zlen = coords->dz(0,0,0) * (localmesh->LocalNz - 3); BoutReal kwave = kz * 2.0 * PI / (2. * zlen); // wave number is 1/[rad]; DST has extra 2. @@ -215,7 +216,7 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { // including boundary conditions BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { - BoutReal kwave = kz * 2.0 * PI / (coords->zlength()); // wave number is 1/[rad] + BoutReal kwave = kz * 2.0 * PI / (coords->zlength()(0,0)); // wave number is 1/[rad] tridagMatrix(&a(kz, 0), &b(kz, 0), &c(kz, 0), &bcmplx(kz, 0), jy, kz, // True for the component constant (DC) in Z kwave, // Z wave number @@ -349,7 +350,7 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { int iy = ys + ind / nmode; int kz = ind % nmode; - BoutReal zlen = coords->dz * (localmesh->LocalNz - 3); + BoutReal zlen = coords->dz(0,0,0) * (localmesh->LocalNz - 3); BoutReal kwave = kz * 2.0 * PI / (2. * zlen); // wave number is 1/[rad]; DST has extra 2. @@ -430,7 +431,7 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { int iy = ys + ind / nmode; int kz = ind % nmode; - BoutReal kwave = kz * 2.0 * PI / (coords->zlength()); // wave number is 1/[rad] + BoutReal kwave = kz * 2.0 * PI / (coords->zlength()(0,0)); // wave number is 1/[rad] tridagMatrix(&a3D(ind, 0), &b3D(ind, 0), &c3D(ind, 0), &bcmplx3D(ind, 0), iy, kz, // True for the component constant (DC) in Z kwave, // Z wave number diff --git a/src/invert/laplace/impls/pdd/pdd.cxx b/src/invert/laplace/impls/pdd/pdd.cxx index 5a07ed4cde..3e0c935310 100644 --- a/src/invert/laplace/impls/pdd/pdd.cxx +++ b/src/invert/laplace/impls/pdd/pdd.cxx @@ -165,7 +165,8 @@ 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 / coords->zlength(); + ASSERT1(coords->zlength().isConst("RGN_ALL")); + BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); /// 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 f2ac5b0c77..319b053025 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -473,10 +473,10 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { Coeffs( x, y, z, A1, A2, A3, A4, A5 ); BoutReal dx = coords->dx(x,y,z); - BoutReal dx2 = SQ(coords->dx(x,y,z)); - BoutReal dz = coords->dz; - BoutReal dz2 = SQ(coords->dz); - BoutReal dxdz = coords->dx(x,y,z) * coords->dz; + BoutReal dx2 = SQ(dx); + BoutReal dz = coords->dz(x,y,z); + BoutReal dz2 = SQ(dz); + BoutReal dxdz = dx * dz; ASSERT3(finite(A1)); ASSERT3(finite(A2)); @@ -992,13 +992,13 @@ void LaplacePetsc::Coeffs( int x, int y, int z, BoutReal &coef1, BoutReal &coef2 // Fourth order discretization of C in x ddx_C = (-C2(x+2,y,z) + 8.*C2(x+1,y,z) - 8.*C2(x-1,y,z) + C2(x-2,y,z)) / (12.*coords->dx(x,y,z)*(C1(x,y,z))); // Fourth order discretization of C in z - ddz_C = (-C2(x,y,zpp) + 8.*C2(x,y,zp) - 8.*C2(x,y,zm) + C2(x,y,zmm)) / (12.*coords->dz*(C1(x,y,z))); + ddz_C = (-C2(x,y,zpp) + 8.*C2(x,y,zp) - 8.*C2(x,y,zm) + C2(x,y,zmm)) / (12.*coords->dz(x,y,z)*(C1(x,y,z))); } else { // Second order discretization of C in x ddx_C = (C2(x+1,y,z) - C2(x-1,y,z)) / (2.*coords->dx(x,y,z)*(C1(x,y,z))); // Second order discretization of C in z - ddz_C = (C2(x,y,zp) - C2(x,y,zm)) / (2.*coords->dz*(C1(x,y,z))); + ddz_C = (C2(x,y,zp) - C2(x,y,zm)) / (2.*coords->dz(x,y,z)*(C1(x,y,z))); } coef4 += coords->g11(x,y,z) * ddx_C + coords->g13(x,y,z) * ddz_C; diff --git a/src/invert/laplace/impls/serial_tri/serial_tri.cxx b/src/invert/laplace/impls/serial_tri/serial_tri.cxx index 12a1d0d410..5010c6bcb6 100644 --- a/src/invert/laplace/impls/serial_tri/serial_tri.cxx +++ b/src/invert/laplace/impls/serial_tri/serial_tri.cxx @@ -83,7 +83,8 @@ FieldPerp LaplaceSerialTri::solve(const FieldPerp& b, const FieldPerp& x0) { int ncz = localmesh->LocalNz; // No of z pnts int ncx = localmesh->LocalNx; // No of x pnts - BoutReal kwaveFactor = 2.0 * PI / coords->zlength(); + ASSERT1(coords->zlength().isConst("RGN_ALL")); + BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); // 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 b31a710455..06141e857e 100644 --- a/src/invert/laplace/impls/shoot/shoot_laplace.cxx +++ b/src/invert/laplace/impls/shoot/shoot_laplace.cxx @@ -129,11 +129,12 @@ FieldPerp LaplaceShoot::solve(const FieldPerp& rhs) { // kc and kp now set to result at x and x+1 respectively // Use b at x to get km at x-1 // Loop inwards from edge + ASSERT1(coords->zlength().isConst("RGN_ALL")); for(int ix=xe; ix >= xs; ix--) { rfft(rhs[ix], localmesh->LocalNz, std::begin(rhsk)); for(int kz=0; kzzlength()); // wave number is 1/[rad] + BoutReal kwave=kz*2.0*PI/(coords->zlength()(0,0)); // wave number is 1/[rad] // Get the coefficients dcomplex a,b,c; diff --git a/src/invert/laplace/impls/spt/spt.cxx b/src/invert/laplace/impls/spt/spt.cxx index 1960d38928..8c9361b08b 100644 --- a/src/invert/laplace/impls/spt/spt.cxx +++ b/src/invert/laplace/impls/spt/spt.cxx @@ -291,7 +291,8 @@ int LaplaceSPT::start(const FieldPerp &b, SPT_data &data) { data.bk(kz, ix) = dc1d[kz]; } - BoutReal kwaveFactor = 2.0 * PI / coords->zlength(); + ASSERT1(coords->zlength().isConst("RGN_ALL")); + BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); /// 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 000238b350..3c6cfdae6d 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -250,8 +250,7 @@ void Laplacian::tridagCoefs(int jx, int jy, int jz, ASSERT1(ccoef == nullptr || ccoef->getLocation() == loc); ASSERT1(d == nullptr || d->getLocation() == loc); - - BoutReal kwave=jz*2.0*PI/coords->zlength(); // wave number is 1/[rad] + BoutReal kwave=jz*2.0*PI/coords->zlength()(jx,jy); // wave number is 1/[rad] tridagCoefs(jx, jy, kwave, a, b, c, @@ -365,9 +364,10 @@ void Laplacian::tridagMatrix(dcomplex **avec, dcomplex **bvec, dcomplex **cvec, const Field2D *a, const Field2D *ccoef, const Field2D *d) { + ASSERT3(coords->zlength().isConst("RGN_ALL")); BOUT_OMP(parallel for) for(int kz = 0; kz <= maxmode; kz++) { - BoutReal kwave=kz*2.0*PI/coords->zlength(); // wave number is 1/[rad] + BoutReal kwave=kz*2.0*PI/coords->zlength()(0,jy); // wave number is 1/[rad] tridagMatrix(avec[kz], bvec[kz], cvec[kz], bk[kz], diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index 243c1fb036..5a31271c3d 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -418,7 +418,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); - BoutReal dz = coords->dz; + const BoutReal dz = coords->dz(x,y,z); // Metrics on z+1/2 boundary Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); @@ -440,10 +440,10 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // x+1/2, z+1/2 J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); - dz = 4.0*coords->dz; + const BoutReal fourdz= 4.*dz; Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - val = Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); xpzp = val; c -= val; @@ -452,7 +452,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - val = - Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); xpzm = val; c -= val; @@ -461,14 +461,14 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - val = - Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); xmzp = val; c -= val; // x-1/2, z-1/2 Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - val = Acoef * J * g13 / (coords->J(x,y,z) * dz * coords->dx(x,y,z)); + val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); xmzm = val; c -= val; @@ -480,7 +480,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - val = Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); zpxp = val; c -= val; @@ -488,7 +488,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); zpxm = val; c -= val; @@ -498,7 +498,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); zmxp = val; c -= val; @@ -506,7 +506,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - val = Acoef * J * g13 / (coords->J(x,y,z) * dx * coords->dz); + val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); zmxm = val; c -= val; diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 0dd4eba735..008205f356 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -347,7 +347,7 @@ Coordinates::Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2 } Coordinates::Coordinates(Mesh* mesh, Options* options) - : dx(1, mesh), dy(1, mesh), dz(1), d1_dx(mesh), d1_dy(mesh), J(1, mesh), Bxy(1, mesh), + : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1, mesh), Bxy(1, mesh), // Identity metric tensor g11(1, mesh), g22(1, mesh), g33(1, mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), g_11(1, mesh), g_22(1, mesh), g_33(1, mesh), g_12(0, mesh), g_13(0, mesh), @@ -392,12 +392,13 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) const auto default_dz = (zmax - zmin) * TWOPI / nz; - mesh->get(dz, "dz", default_dz); + mesh->get(dz, "dz", default_dz, false); } // required early for differentiation. setParallelTransform(options); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false); dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false); if (mesh->periodicX) { @@ -644,7 +645,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, const Coordinates* coords_in, bool force_interpolate_from_centre) - : dx(1, mesh), dy(1, mesh), dz(1), d1_dx(mesh), d1_dy(mesh), J(1, mesh), Bxy(1, mesh), + : dx(1, mesh), dy(1, mesh), dz(1, mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1, mesh), Bxy(1, mesh), // Identity metric tensor g11(1, mesh), g22(1, mesh), g33(1, mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), g_11(1, mesh), g_22(1, mesh), g_33(1, mesh), g_12(0, mesh), g_13(0, mesh), @@ -658,8 +659,6 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, nz = mesh->LocalNz; - dz = coords_in->dz; - // Default to true in case staggered quantities are not read from file bool extrapolate_x = true; bool extrapolate_y = true; @@ -681,6 +680,9 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, "cells\n")); } + getAtLoc(mesh, dz, "dz", suffix, location, 1.0); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false); + getAtLoc(mesh, dx, "dx", suffix, location, 1.0); dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false); @@ -783,6 +785,7 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false); dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false); + dz = interpolateAndExtrapolate(coords_in->dz, location, true, true, false); // Diagonal components of metric tensor g^{ij} g11 = interpolateAndExtrapolate(coords_in->g11, location, true, true, false); @@ -905,7 +908,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (min(abs(dy)) < 1e-8) throw BoutException("dy magnitude less than 1e-8"); - if (fabs(dz) < 1e-8) + if (min(abs(dz)) < 1e-8) throw BoutException("dz magnitude less than 1e-8"); // Check input metrics @@ -1304,25 +1307,13 @@ namespace { const auto lower = localmesh->hasBranchCutLower(x); if (lower.first) { for (int y = 0; y < localmesh->ystart; y++) { - int z=0; -// #ifdef COORDINATES_USE_3D -// for (;zLocalNz; ++z) -// #endif - { - zShift(x, y, z) -= lower.second; - } + zShift(x, y) -= lower.second; } } const auto upper = localmesh->hasBranchCutUpper(x); if (upper.first) { for (int y = localmesh->yend + 1; y < localmesh->LocalNy; y++) { - int z=0; -// #ifdef COORDINATES_USE_3D -// for (;zLocalNz; ++z) -// #endif - { - zShift(x, y, z) += upper.second; - } + zShift(x, y) += upper.second; } } } @@ -1376,8 +1367,9 @@ void Coordinates::setParallelTransform(Options* options) { fixZShiftGuards(zShift); + ASSERT1(zlength().isConst("RGN_ALL")); transform = bout::utils::make_unique(*localmesh, location, zShift, - zlength()); + zlength()(0,0)); } else if (ptstr == "fci") { diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index 217c49cb3a..0fb07cb334 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -566,7 +566,8 @@ bool GridFile::readgrid_3dvar_fft(Mesh *m, const std::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->getCoordinates(var.getLocation())->zlength(); + ASSERT1(m->getCoordinates(var.getLocation())->zlength().isConst("RGN_ALL")); + BoutReal zlength = m->getCoordinates(var.getLocation())->zlength()(0,0); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi @@ -697,7 +698,8 @@ bool GridFile::readgrid_perpvar_fft(Mesh *m, const std::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->getCoordinates(var.getLocation())->zlength(); + ASSERT1(m->getCoordinates(var.getLocation())->zlength().isConst("RGN_ALL")); + BoutReal zlength = m->getCoordinates(var.getLocation())->zlength()(0,0); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index bca01b0952..eae299e797 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -75,7 +75,6 @@ const Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC o *******************************************************************************/ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { -#ifndef COORDINATES_USE_3D ASSERT1_FIELDS_COMPATIBLE(apar, f); ASSERT1(f.hasParallelSlices()); @@ -93,66 +92,66 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { for(int x=1;x<=mesh->LocalNx-2;x++) for(int y=1;y<=mesh->LocalNy-2;y++) for(int z=0;zdy(x, y+1) + metric->dy(x, y) + 0.5*metric->dy(x, y-1)); + gys(x, y, z) = (f.yup()(x, y+1, z) - f.ydown()(x, y-1, z))/(0.5*metric->dy(x, y+1, z) + metric->dy(x, y, z) + 0.5*metric->dy(x, y-1, z)); } for(int x=1;x<=mesh->LocalNx-2;x++) { for(int y=mesh->ystart;y<=mesh->yend;y++) { - BoutReal by = 1./sqrt(metric->g_22(x, y)); for(int z=0;zg_22(x, y, z)); // Z indices zm and zp int zm = (z - 1 + ncz) % ncz; int zp = (z + 1) % ncz; // bx = -DDZ(apar) - BoutReal bx = (apar(x, y, zm) - apar(x, y, zp))/(2.*metric->dz); + BoutReal bx = (apar(x, y, zm) - apar(x, y, zp))/(0.5*metric->dz(x, y, zm) + metric->dz(x, y, z) + 0.5*metric->dz(x, y, zp)); // bz = DDX(f) - BoutReal bz = (apar(x+1, y, z) - apar(x-1, y, z))/(0.5*metric->dx(x-1, y) + metric->dx(x, y) + 0.5*metric->dx(x+1, y)); + BoutReal bz = (apar(x+1, y, z) - apar(x-1, y, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)); // Now calculate (bx*d/dx + by*d/dy + bz*d/dz) f // Length dl for predictor - BoutReal dl = fabs(metric->dx(x, y)) / (fabs(bx) + 1e-16); - dl = BOUTMIN(dl, fabs(metric->dy(x, y)) / (fabs(by) + 1e-16)); - dl = BOUTMIN(dl, metric->dz / (fabs(bz) + 1e-16)); + BoutReal dl = fabs(metric->dx(x, y, z)) / (fabs(bx) + 1e-16); + dl = BOUTMIN(dl, fabs(metric->dy(x, y, z)) / (fabs(by) + 1e-16)); + dl = BOUTMIN(dl, fabs(metric->dz(x, y, z)) / (fabs(bz) + 1e-16)); BoutReal fp, fm; // X differencing fp = f(x+1, y, z) - + (0.25*dl/metric->dz) * bz * (f(x+1, y, zm) - f(x+1, y, zp)) + + (0.25*dl/metric->dz(x, y, z)) * bz * (f(x+1, y, zm) - f(x+1, y, zp)) - 0.5*dl * by * gys(x+1, y, z); fm = f(x-1, y, z) - + (0.25*dl/metric->dz) * bz * (f(x-1, y, zm) - f(x-1, y, zp)) + + (0.25*dl/metric->dz(x, y, z)) * bz * (f(x-1, y, zm) - f(x-1, y, zp)) - 0.5*dl * by * gys(x-1, y, z); - result(x, y, z) = bx * (fp - fm) / (0.5*metric->dx(x-1, y) + metric->dx(x, y) + 0.5*metric->dx(x+1, y)); + result(x, y, z) = bx * (fp - fm) / (0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)); // Z differencing fp = f(x, y, zp) - + (0.25*dl/metric->dx(x, y)) * bx * (f(x-1, y, zp) - f(x+1, y, zp)) + + (0.25*dl/metric->dx(x, y, z)) * bx * (f(x-1, y, zp) - f(x+1, y, zp)) - 0.5*dl * by * gys(x, y, zp); fm = f(x, y, zm) - + (0.25*dl/metric->dx(x, y)) * bx * (f(x-1,y,zm) - f(x+1, y, zm)) + + (0.25*dl/metric->dx(x, y, z)) * bx * (f(x-1,y,zm) - f(x+1, y, zm)) - 0.5*dl * by * gys(x, y, zm); - result(x, y, z) += bz * (fp - fm) / (2.*metric->dz); + result(x, y, z) += bz * (fp - fm) / (0.5*metric->dz(x, y, zm) + metric->dz(x, y, z) + 0.5*metric->dz(x, y, zp)); // Y differencing fp = f.yup()(x,y+1,z) - - 0.5*dl * bx * (f.yup()(x+1, y+1, z) - f.yup()(x-1, y+1, z))/(0.5*metric->dx(x-1, y) + metric->dx(x, y) + 0.5*metric->dx(x+1, y)) + - 0.5*dl * bx * (f.yup()(x+1, y+1, z) - f.yup()(x-1, y+1, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)) - + (0.25*dl/metric->dz) * bz * (f.yup()(x,y+1,zm) - f.yup()(x,y+1,zp)); + + (0.25*dl/metric->dz(x,y,z)) * bz * (f.yup()(x,y+1,zm) - f.yup()(x,y+1,zp)); fm = f.ydown()(x,y-1,z) - - 0.5*dl * bx * (f.ydown()(x+1, y-1, z) - f.ydown()(x-1, y-1, z))/(0.5*metric->dx(x-1, y) + metric->dx(x, y) + 0.5*metric->dx(x+1, y)) - + (0.25*dl/metric->dz) * bz * (f.ydown()(x,y-1,zm) - f.ydown()(x,y-1,zp)); + - 0.5*dl * bx * (f.ydown()(x+1, y-1, z) - f.ydown()(x-1, y-1, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)) + + (0.25*dl/metric->dz(x,y,z)) * bz * (f.ydown()(x,y-1,zm) - f.ydown()(x,y-1,zp)); - result(x,y,z) += by * (fp - fm) / (0.5*metric->dy(x,y-1) + metric->dy(x,y) + 0.5*metric->dy(x,y+1)); + result(x,y,z) += by * (fp - fm) / (0.5*metric->dy(x,y-1, z) + metric->dy(x,y,z) + 0.5*metric->dy(x,y+1,z)); } } } @@ -160,9 +159,6 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { ASSERT2(result.getLocation() == f.getLocation()); return result; -#else - return Field3D{}; -#endif } /******************************************************************************* @@ -572,16 +568,16 @@ const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outlo // Calculate gradients on cell faces -- assumes constant grid spacing BoutReal gR = (coords->g11(i,j,k) + coords->g11(i+1,j,k)) * (fs(i+1,j,k) - fs(i,j,k))/(coords->dx(i+1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(fs(i+1,j,kp) - fs(i+1,j,km) + fs(i,j,kp) - fs(i,j,km))/(4.*coords->dz); + + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(fs(i+1,j,kp) - fs(i+1,j,km) + fs(i,j,kp) - fs(i,j,km))/(4.*coords->dz(i,j,k)); BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(fs(i,j,k) - fs(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(fs(i-1,j,kp) - fs(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4.*coords->dz); + + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(fs(i-1,j,kp) - fs(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4*coords->dz(i,j,k)); BoutReal gD = coords->g13(i,j,k)*(fs(i+1,j,km) - fs(i-1,j,km) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(fs(i,j,k) - fs(i,j,km))/coords->dz; + + coords->g33(i,j,k)*(fs(i,j,k) - fs(i,j,km))/coords->dz(i,j,k); BoutReal gU = coords->g13(i,j,k)*(fs(i+1,j,kp) - fs(i-1,j,kp) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(fs(i,j,kp) - fs(i,j,k))/coords->dz; + + coords->g33(i,j,k)*(fs(i,j,kp) - fs(i,j,k))/coords->dz(i,j,k); // Flow right @@ -594,12 +590,12 @@ const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outlo // Flow up - flux = gU * 0.5*(as(i,j,k) + as(i,j,kp)) / coords->dz; - result(i,j,k) += flux; + flux = gU * 0.25*(coords->J(i,j,k) + coords->J(i,j,kp)) *(as(i,j,k) + as(i,j,kp)); + result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); // Flow down - flux = gD * 0.5*(as(i,j,k) + as(i,j,km)) / coords->dz; - result(i,j,k) -= flux; + flux = gD * 0.25*(coords->J(i,j,km) + coords->J(i,j,k)) *(as(i,j,km) + as(i,j,k)); + result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); } return result; diff --git a/tests/MMS/diffusion/diffusion.cxx b/tests/MMS/diffusion/diffusion.cxx index c764a7ee2c..3c7e59bead 100644 --- a/tests/MMS/diffusion/diffusion.cxx +++ b/tests/MMS/diffusion/diffusion.cxx @@ -77,7 +77,7 @@ int physics_init(bool UNUSED(restarting)) { for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ for (int zk = 0; zk < mesh->LocalNz; zk++) { output.write("Initial condition at %d,%d,%d\n", xi, yj, zk); - N(xi, yj, zk) = MS(0.,mesh->GlobalX(xi)*Lx,mesh->GlobalY(yj)*Ly,coord->dz*zk); + N(xi, yj, zk) = MS(0.,mesh->GlobalX(xi)*Lx,mesh->GlobalY(yj)*Ly,coord->dz(xi, yj, zk)*zk); } } } @@ -141,7 +141,7 @@ void solution(Field3D &f, BoutReal t, BoutReal UNUSED(D)) { x = mesh->GlobalX(xi); y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - z = coord->dz*zk; + z = coord->dz(xi, yj, zk)*zk; output.write("Solution at %d,%d,%d\n", xi, yj, zk); f(xi, yj, zk) = MS(t,x,y,z); } diff --git a/tests/MMS/wave-1d/wave.cxx b/tests/MMS/wave-1d/wave.cxx index 69ef04d313..90332010ed 100644 --- a/tests/MMS/wave-1d/wave.cxx +++ b/tests/MMS/wave-1d/wave.cxx @@ -102,8 +102,8 @@ class Wave1D : public PhysicsModel { for (int xi = mesh->xstart; xi < mesh->xend +1; xi++){ for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ for (int zk = 0; zk < mesh->LocalNz; zk++) { - f(xi, yj, zk) = MS_f(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz*zk); - g(xi, yj, zk) = MS_g(0.,0.5*(mesh->GlobalX(xi)+mesh->GlobalX(xi-1)),mesh->GlobalY(yj),coord->dz*zk); + f(xi, yj, zk) = MS_f(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz(xi,yj,zk)*zk); + g(xi, yj, zk) = MS_g(0.,0.5*(mesh->GlobalX(xi)+mesh->GlobalX(xi-1)),mesh->GlobalY(yj),coord->dz(xi,yj,zk)*zk); } } } @@ -111,8 +111,8 @@ class Wave1D : public PhysicsModel { for (int xi = mesh->xstart; xi < mesh->xend +1; xi++){ for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ for (int zk = 0; zk < mesh->LocalNz; zk++) { - f(xi, yj, zk) = MS_f(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz*zk); - g(xi, yj, zk) = MS_g(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz*zk); + f(xi, yj, zk) = MS_f(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz(xi,yj,zk)*zk); + g(xi, yj, zk) = MS_g(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz(xi,yj,zk)*zk); } } } @@ -201,7 +201,7 @@ const Field3D Wave1D::solution_f(BoutReal t) { BoutReal x = mesh->GlobalX(xi); BoutReal y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal z = coord->dz*zk; + BoutReal z = coord->dz(xi,yj,zk)*zk; S(xi, yj, zk) = MS_f(t,x,y,z); } } @@ -261,7 +261,7 @@ const Field3D Wave1D::solution_g(BoutReal t) { } BoutReal y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal z = coord->dz*zk; + BoutReal z = coord->dz(xi,yj,zk)*zk; S(xi, yj, zk) = MS_g(t,x,y,z); } } diff --git a/tests/integrated/test-yupdown/test_yupdown.cxx b/tests/integrated/test-yupdown/test_yupdown.cxx index dc1d09e971..a76c1bb7ed 100644 --- a/tests/integrated/test-yupdown/test_yupdown.cxx +++ b/tests/integrated/test-yupdown/test_yupdown.cxx @@ -34,7 +34,7 @@ int main(int argc, char** argv) { Field2D zShift; mesh->get(zShift, "zShift"); - ShiftedMetric s(*mesh, CELL_CENTRE, zShift, mesh->getCoordinates()->zlength()); + ShiftedMetric s(*mesh, CELL_CENTRE, zShift, mesh->getCoordinates()->zlength()(0,0)); // Read variable from mesh Field3D var; diff --git a/tests/unit/mesh/parallel/test_shiftedmetric.cxx b/tests/unit/mesh/parallel/test_shiftedmetric.cxx index b589af68d6..6a2aa56eff 100644 --- a/tests/unit/mesh/parallel/test_shiftedmetric.cxx +++ b/tests/unit/mesh/parallel/test_shiftedmetric.cxx @@ -44,7 +44,7 @@ class ShiftedMetricTest : public ::testing::Test { auto coords = mesh->getCoordinates(); coords->setParallelTransform( bout::utils::make_unique(*mesh, CELL_CENTRE, zShift, - coords->zlength())); + coords->zlength()(0,0))); Field3D input_temp{mesh}; diff --git a/tests/unit/mesh/test_coordinates.cxx b/tests/unit/mesh/test_coordinates.cxx index ca77bc7fe2..6c604b93a5 100644 --- a/tests/unit/mesh/test_coordinates.cxx +++ b/tests/unit/mesh/test_coordinates.cxx @@ -24,7 +24,7 @@ TEST_F(CoordinatesTest, ZLength) { Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, false}; - EXPECT_DOUBLE_EQ(coords.zlength(), 7.0); + EXPECT_TRUE(IsFieldEqual(coords.zlength(), 7.0)); } TEST_F(CoordinatesTest, Jacobian) { From e4f0c883ebbf703db02f7a9e91a0dacacb3f018d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 20:34:45 +0000 Subject: [PATCH 086/293] fix bad cast --- include/bout/coordinates.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 8d4db2aedb..4037cbb7d0 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -93,7 +93,7 @@ public: Field2D zlength() const { #ifdef COORDINATES_USE_3D - Field2D result(0.,(Mesh * ) this); + Field2D result(0.,localmesh); BOUT_FOR_SERIAL(i, dz.getRegion("RGN_ALL")) { result[i] += dz[i]; } From c939e39add2f27efb85096e67bdd96294f16f21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 20:36:46 +0000 Subject: [PATCH 087/293] Fix indexing in fv_ops.hxx --- include/bout/fv_ops.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 53491b3608..9aa2ec7ee5 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -467,13 +467,13 @@ namespace FV { if(vU > 0.0) { BoutReal flux = vU * s.R; - result[i] += flux / (coord->J[i]*coord->dz); - result[i.zp()] -= flux / (coord->J[i.zp()]*coord->dz); + result[i] += flux / (coord->J[i]*coord->dz[i]); + result[i.zp()] -= flux / (coord->J[i.zp()]*coord->dz[i.zp()]); } if(vD < 0.0) { BoutReal flux = vD * s.L; - result[i] -= flux / (coord->J[i]*coord->dz);; - result[i.zm()] += flux / (coord->J[i.zm()]*coord->dz);; + result[i] -= flux / (coord->J[i]*coord->dz[i]);; + result[i.zm()] += flux / (coord->J[i.zm()]*coord->dz[i.zm()]);; } } From 74e284956d3bafc8d2a53ea27b5432c8d96f5c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 20:37:19 +0000 Subject: [PATCH 088/293] improve error messages --- include/bout/fv_ops.hxx | 2 +- tests/integrated/test-twistshift-staggered/runtest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 9aa2ec7ee5..08ab7d10bf 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -379,7 +379,7 @@ namespace FV { if(v.covariant) { // Got a covariant vector instead - throw BoutException("Div_f_v_XPPM passed a covariant v"); + throw BoutException("Div_f_v passed a covariant v"); } Field3D result{zeroFrom(n_in)}; diff --git a/tests/integrated/test-twistshift-staggered/runtest b/tests/integrated/test-twistshift-staggered/runtest index ed5567fbda..0c0d05d8f9 100755 --- a/tests/integrated/test-twistshift-staggered/runtest +++ b/tests/integrated/test-twistshift-staggered/runtest @@ -31,7 +31,7 @@ def test1(ylower, yupper): if numpy.any(numpy.abs(test_aligned[:, yupper, :] - test_aligned[:, ylower, :]) < 1.e-6): success = False print("Fail - test_aligned should not be periodic jy=%i and jy=%i should be " - "different", yupper, ylower) + "different"%( yupper, ylower)) test1(0,-4) test1(1,-3) test1(2,-2) From 06d6cfbad816845af3dfab46990aee340191d593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 20:37:44 +0000 Subject: [PATCH 089/293] Do not make fields non-const --- src/mesh/coordinates.cxx | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 008205f356..f039a0182d 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -116,16 +116,6 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, } } - // Set corner guard cells - for (int i = 0; i < localmesh->xstart; i++) { - for (int j = 0; j < localmesh->ystart; j++) { - result(i, j) = BoutNaN; - result(i, localmesh->LocalNy - 1 - j) = BoutNaN; - result(localmesh->LocalNx - 1 - i, j) = BoutNaN; - result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j) = BoutNaN; - } - } - return result; } @@ -258,17 +248,6 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, } } - // Set corner guard cells - for (int i = 0; i < localmesh->xstart; i++) { - for (int j = 0; j < localmesh->ystart; j++) { - for (int zi = 0; zi < localmesh->LocalNz; ++zi){ - result(i, j, zi) = BoutNaN; - result(i, localmesh->LocalNy - 1 - j, zi) = BoutNaN; - result(localmesh->LocalNx - 1 - i, j, zi) = BoutNaN; - result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, zi) = BoutNaN; - } - } - } return result; //throw BoutException("NotImplemented (3D)"); From 236fd8edf5deff022cac4c35f13b0a8f59afdd34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 21:01:19 +0000 Subject: [PATCH 090/293] Set d1_dz --- src/mesh/coordinates.cxx | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index f039a0182d..3c66776289 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1038,7 +1038,7 @@ int Coordinates::geometry(bool recalculate_staggered, OPTION(Options::getRoot(), non_uniform, true); - Coordinates::metric_field_type d2x(localmesh), d2y(localmesh); // d^2 x / d i^2 + Coordinates::metric_field_type d2x(localmesh), d2y(localmesh), d2z(localmesh); // d^2 x / d i^2 // Read correction for non-uniform meshes std::string suffix = getLocationSuffix(location); @@ -1076,6 +1076,21 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = -d2y / (dy * dy); } + + if (localmesh->get(d2z, "d2z"+suffix, 0.0, false)) { + output_warn.write( + "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); + d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) + + communicate(d1_dz); + d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true); + } else { + d2z.setLocation(location); + // set boundary cells if necessary + d2z = interpolateAndExtrapolate(d2z, location, extrapolate_x, extrapolate_y, false); + + d1_dz = -d2z / (dz * dz); + } } else { if (localmesh->get(d2x, "d2x", 0.0, false)) { output_warn.write( @@ -1104,8 +1119,22 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = -d2y / (dy * dy); } + + if (localmesh->get(d2z, "d2z", 0.0, false)) { + output_warn.write( + "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); + d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) + + communicate(d1_dz); + d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true); + } else { + // Shift d2z to our location + d2z = interpolateAndExtrapolate(d2z, location, true, true, false); + + d1_dz = -d2z / (dz * dz); + } } - communicate(d1_dx, d1_dy); + communicate(d1_dx, d1_dy, d1_dz); if (location == CELL_CENTRE && recalculate_staggered) { // Re-calculate interpolated Coordinates at staggered locations From 0dab643c6a55b7cc55ce99f841d6be56bd2eaf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 22:11:29 +0000 Subject: [PATCH 091/293] Fix most tests --- .../impls/multigrid/multigrid_laplace.cxx | 11 ++++---- .../laplace/impls/serial_band/serial_band.cxx | 13 ++++++--- .../impls/cyclic/laplacexz-cyclic.cxx | 3 +- src/invert/parderiv/impls/cyclic/cyclic.cxx | 11 ++++---- src/mesh/boundary_standard.cxx | 8 +++--- src/mesh/coordinates.cxx | 9 +++++- src/mesh/difops.cxx | 28 +++++++++---------- src/mesh/fv_ops.cxx | 10 +++---- 8 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index 564c5f83f3..414c463a7d 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -575,17 +575,18 @@ BOUT_OMP(for collapse(2)) int k2 = k-1; int k2p = (k2+1)%Nz_global; int k2m = (k2+Nz_global-1)%Nz_global; - + + BoutReal dz = coords->dz(i2, yindex); BoutReal ddx_C = (C2(i2+1, yindex, k2) - C2(i2-1, yindex, k2))/2./coords->dx(i2, yindex)/C1(i2, yindex, k2); - BoutReal ddz_C = (C2(i2, yindex, k2p) - C2(i2, yindex, k2m)) /2./coords->dz/C1(i2, yindex, k2); + BoutReal ddz_C = (C2(i2, yindex, k2p) - C2(i2, yindex, k2m)) /2./dz/C1(i2, yindex, k2); BoutReal ddx = D(i2, yindex, k2)*coords->g11(i2, yindex)/coords->dx(i2, yindex)/coords->dx(i2, yindex); // coefficient of 2nd derivative stencil (x-direction) - BoutReal ddz = D(i2, yindex, k2)*coords->g33(i2, yindex)/coords->dz/coords->dz; + BoutReal ddz = D(i2, yindex, k2)*coords->g33(i2, yindex)/SQ(dz); // coefficient of 2nd derivative stencil (z-direction) - BoutReal dxdz = D(i2, yindex, k2)*2.*coords->g13(i2, yindex)/coords->dx(i2, yindex)/coords->dz; + BoutReal dxdz = D(i2, yindex, k2)*2.*coords->g13(i2, yindex)/coords->dx(i2, yindex)/dz; // coefficient of mixed derivative stencil (could assume zero, at least initially, // if easier; then check this is true in constructor) @@ -601,7 +602,7 @@ BOUT_OMP(for collapse(2)) BoutReal dzd = (D(i2, yindex, k2)*coords->G3(i2, yindex) + coords->g33(i2, yindex)*ddz_C + coords->g13(i2, yindex)*ddx_C // (could assume zero, at least initially, if easier; then check this is true in constructor) - )/coords->dz; // coefficient of 1st derivative stencil (z-direction) + )/dz; // coefficient of 1st derivative stencil (z-direction) int ic = i*(llz+2)+k; mat[ic*9] = dxdz/4.; diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index d166400108..ee93ff0d0e 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -125,11 +125,12 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { // solve differential equation in x BoutReal coef1=0.0, coef2=0.0, coef3=0.0, coef4=0.0, - coef5=0.0, coef6=0.0, kwave; + coef5=0.0, coef6=0.0; + Field2D kwave_; ///////// PERFORM INVERSION ///////// // shift freqs according to FFT convention - kwave=iz*2.0*PI/coords->zlength(); // wave number is 1/[rad] + kwave_=iz*2.0*PI/coords->zlength(); // wave number is 1/[rad] // set bk1d for(int ix=0;ixLocalNx;ix++) @@ -138,6 +139,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { // Fill in interior points for(int ix=xstart;ix<=xend;ix++) { + BoutReal kwave = kwave_(ix, jy); #ifdef SECONDORDER // Use second-order differencing. Useful for testing the tridiagonal solver // with different boundary conditions @@ -199,6 +201,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { int ix = 1; + auto kwave = kwave_(ix,jy); coef1=coords->g11(ix,jy)/(SQ(coords->dx(ix,jy))); coef2=coords->g33(ix,jy); coef3= kwave * coords->g13(ix,jy)/(2. * coords->dx(ix,jy)); @@ -319,7 +322,8 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { // Enforce zero laplacian for 2nd and 4th-order int ix = 1; - + + auto kwave = kwave_(ix,jy); coef1=coords->g11(ix,jy)/(12.* SQ(coords->dx(ix,jy))); coef2=coords->g33(ix,jy); @@ -365,7 +369,8 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { coef1=coords->g11(ix,jy)/(12.* SQ(coords->dx(ix,jy))); coef2=coords->g33(ix,jy); - + + auto kwave = kwave_(ix,jy); coef3= kwave * coords->g13(ix,jy)/(2. * coords->dx(ix,jy)); coef4 = Acoef(ix,jy); diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 1951fc44e3..777af53101 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -76,9 +76,10 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { ASSERT2(max(abs(coord->g13)) < 1e-5); int ind = 0; + ASSERT1(coord->zlength().isConst("RGN_ALL")); for(int y=localmesh->ystart; y <= localmesh->yend; y++) { for(int kz = 0; kz < nmode; kz++) { - BoutReal kwave=kz*2.0*PI/(coord->zlength()); + BoutReal kwave=kz*2.0*PI/(coord->zlength()(0,0)); if(localmesh->firstX()) { // Inner X boundary diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 52c69d412e..1eeb4bcbc3 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -96,6 +96,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { auto b = Matrix(nsys, size); auto c = Matrix(nsys, size); + ASSERT1(coord->zlength().isConst("RGN_ALL")); // Loop over flux-surfaces for (surf.first(); !surf.isDone(); surf.next()) { int x = surf.xpos; @@ -126,7 +127,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { // Set up tridiagonal system for(int k=0; kzlength(); // wave number is 1/[rad] + BoutReal kwave=k*2.0*PI/coord->zlength()(0,0); // wave number is 1/[rad] for (int y = 0; y < localmesh->LocalNy - 2 * localmesh->ystart; y++) { BoutReal acoef = A(x, y + localmesh->ystart); // Constant @@ -137,8 +138,8 @@ const Field3D InvertParCR::solve(const Field3D &f) { BoutReal ecoef = E(x, y + localmesh->ystart); // ddy bcoef /= SQ(coord->dy(x, y + localmesh->ystart)); - ccoef /= coord->dy(x, y + localmesh->ystart) * coord->dz; - dcoef /= SQ(coord->dz); + ccoef /= coord->dy(x, y + localmesh->ystart) * coord->dz(x, y + localmesh->ystart); + dcoef /= SQ(coord->dz(x, y + localmesh->ystart)); ecoef /= coord->dy(x, y + localmesh->ystart); // const d2dy2 d2dydz d2dz2 ddy @@ -158,14 +159,14 @@ const Field3D InvertParCR::solve(const Field3D &f) { MPI_Comm_size(surf.communicator(), &np); if(rank == 0) { for(int k=0; kzlength(); // wave number is 1/[rad] + BoutReal kwave=k*2.0*PI/coord->zlength()(0,0); // wave number is 1/[rad] dcomplex phase(cos(kwave*ts) , -sin(kwave*ts)); a(k, 0) *= phase; } } if(rank == np-1) { for(int k=0; kzlength(); // wave number is 1/[rad] + BoutReal kwave=k*2.0*PI/coord->zlength()(0,0); // wave number is 1/[rad] dcomplex phase(cos(kwave*ts) , sin(kwave*ts)); c(k, localmesh->LocalNy - 2 * localmesh->ystart - 1) *= phase; } diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index fa760e26a1..8749b3739d 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -2574,7 +2574,7 @@ void BoundaryZeroLaplace::apply(Field3D &f) { BoutReal coef = -1.0 * sqrt(metric->g33(x, y) / metric->g11(x, y)) * metric->dx(x, y); for (int jz = 1; jz <= ncz / 2; jz++) { - BoutReal kwave = jz * 2.0 * PI / metric->zlength(); // wavenumber in [rad^-1] + BoutReal kwave = jz * 2.0 * PI / metric->zlength()(x,y); // wavenumber in [rad^-1] c0[jz] *= exp(coef * kwave); // The decaying solution only } // Reverse FFT @@ -2780,7 +2780,7 @@ void BoundaryConstLaplace::apply(Field3D &f) { // kz != 0 solution BoutReal coef = -1.0*sqrt(metric->g33(x-bx,y) / metric->g11(x-bx,y))*metric->dx(x-bx,y); for(int jz=1;jz<=ncz/2;jz++) { - BoutReal kwave=jz*2.0*PI/metric->zlength(); // wavenumber in [rad^-1] + BoutReal kwave=jz*2.0*PI/metric->zlength()(x,y); // wavenumber in [rad^-1] c0[jz] *= exp(coef*kwave); // The decaying solution only // Add the particular solution c2[jz] = c0[jz] - c1[jz]/(metric->g33(x-bx,y)*kwave*kwave); @@ -2850,7 +2850,7 @@ void BoundaryDivCurl::apply(Vector3D &var) { // dB_z / dx = dB_x / dz - tmp = (var.x(jx-1,jy,jzp) - var.x(jx-1,jy,jzm)) / (2.*metric->dz); + tmp = (var.x(jx-1,jy,jzp) - var.x(jx-1,jy,jzm)) / (2.*metric->dz(jx-1,jy,jz)); 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) @@ -2868,7 +2868,7 @@ void BoundaryDivCurl::apply(Vector3D &var) { / (metric->dy(jx-1,jy-1) + metric->dy(jx-1,jy)); // second (d/dy) tmp -= (metric->J(jx-1,jy)*metric->g13(jx-1,jy)*(var.x(jx-1,jy,jzp) - var.x(jx-1,jy,jzm)) + metric->J(jx-1,jy)*metric->g23(jx-1,jy)*(var.y(jx-1,jy,jzp) - var.y(jx-1,jy,jzm)) + - metric->J(jx-1,jy)*metric->g33(jx-1,jy)*(var.z(jx-1,jy,jzp) - var.z(jx-1,jy,jzm))) / (2.*metric->dz); + metric->J(jx-1,jy)*metric->g33(jx-1,jy)*(var.z(jx-1,jy,jzp) - var.z(jx-1,jy,jzm))) / (2.*metric->dz(jx,jy,jz)); 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); diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 3c66776289..0209b8f61a 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1077,11 +1077,11 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = -d2y / (dy * dy); } +#ifdef COORDINATES_USE_3D if (localmesh->get(d2z, "d2z"+suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) - communicate(d1_dz); d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true); } else { @@ -1091,6 +1091,9 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dz = -d2z / (dz * dz); } +#else + d1_dz = 0; +#endif } else { if (localmesh->get(d2x, "d2x", 0.0, false)) { output_warn.write( @@ -1120,6 +1123,7 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = -d2y / (dy * dy); } +#ifdef COORDINATES_USE_3D if (localmesh->get(d2z, "d2z", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); @@ -1133,6 +1137,9 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dz = -d2z / (dz * dz); } +#else + d1_dz = 0; +#endif } communicate(d1_dx, d1_dy, d1_dz); diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index eae299e797..674db5f2f4 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -667,7 +667,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, BoutReal gp, gm; // Vx = DDZ(f) - BoutReal vx = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz); + BoutReal vx = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz(x,y,z)); // Set stability condition solver->setMaxTimestep(metric->dx(x, y, z) / (fabs(vx) + 1e-16)); @@ -696,11 +696,11 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, // Arakawa scheme for perpendicular flow. Here as a test #ifndef COORDINATES_USE_3D - const BoutReal fac = 1.0 / (12 * metric->dz); const int ncz = mesh->LocalNz; BOUT_FOR(j2D, result.getRegion2D("RGN_NOBNDRY")) { // Get constants for this iteration + const BoutReal fac = 1.0 / (12 * metric->dz[j2D]); const BoutReal spacingFactor = fac / metric->dx[j2D]; const int jy = j2D.y(), jx = j2D.x(); const int xm = jx - 1, xp = jx + 1; @@ -769,11 +769,11 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, case BRACKET_ARAKAWA_OLD: { #ifndef COORDINATES_USE_3D const int ncz = mesh->LocalNz; - const BoutReal partialFactor = 1.0/(12 * metric->dz); BOUT_OMP(parallel for) for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ - const BoutReal spacingFactor = partialFactor / metric->dx(jx,jy); + const BoutReal partialFactor = 1.0/(12 * metric->dz(jx,jy)); + const BoutReal spacingFactor = partialFactor / metric->dx(jx,jy); for (int jz = 0; jz < mesh->LocalNz; jz++) { const int jzp = jz+1 < ncz ? jz + 1 : 0; //Above is alternative to const int jzp = (jz + 1) % ncz; @@ -904,13 +904,13 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, int zp = (z + 1) % ncz; // Vx = DDZ(f) - vx(x,z) = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz); + vx(x,z) = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz(x,y,z)); // Vz = -DDX(f) vz(x,z) = (f(x-1,y,z) - f(x+1,y,z))/(0.5*metric->dx(x-1,y) + metric->dx(x,y) + 0.5*metric->dx(x+1,y)); // Set stability condition solver->setMaxTimestep(fabs(metric->dx(x,y)) / (fabs(vx(x,z)) + 1e-16)); - solver->setMaxTimestep(metric->dz / (fabs(vz(x,z)) + 1e-16)); + solver->setMaxTimestep(metric->dz(x,y) / (fabs(vz(x,z)) + 1e-16)); } } @@ -926,23 +926,23 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, // X differencing if (vx(x, z) > 0.0) { gp = g(x, y, z) + - (0.5 * dt / metric->dz) * ((vz(x, z) > 0) + (0.5 * dt / metric->dz(x,y)) * ((vz(x, z) > 0) ? vz(x, z) * (g(x, y, zm) - g(x, y, z)) : vz(x, z) * (g(x, y, z) - g(x, y, zp))); gm = g(x - 1, y, z) + - (0.5 * dt / metric->dz) * + (0.5 * dt / metric->dz(x,y)) * ((vz(x, z) > 0) ? vz(x, z) * (g(x - 1, y, zm) - g(x - 1, y, z)) : vz(x, z) * (g(x - 1, y, z) - g(x - 1, y, zp))); } else { gp = g(x + 1, y, z) + - (0.5 * dt / metric->dz) * + (0.5 * dt / metric->dz(x,y)) * ((vz(x, z) > 0) ? vz(x, z) * (g(x + 1, y, zm) - g(x + 1, y, z)) : vz[x][z] * (g(x + 1, y, z) - g(x + 1, y, zp))); gm = g(x, y, z) + - (0.5 * dt / metric->dz) * ((vz(x, z) > 0) + (0.5 * dt / metric->dz(x,y)) * ((vz(x, z) > 0) ? vz(x, z) * (g(x, y, zm) - g(x, y, z)) : vz(x, z) * (g(x, y, z) - g(x, y, zp))); } @@ -972,7 +972,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, : vx(x, z) * (g(x, y, z) - g(x + 1, y, z))); } - result(x, y, z) += vz(x, z) * (gp - gm) / metric->dz; + result(x, y, z) += vz(x, z) * (gp - gm) / metric->dz(x,y); } } #else @@ -984,7 +984,6 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, // Arakawa scheme for perpendicular flow #ifndef COORDINATES_USE_3D const int ncz = mesh->LocalNz; - const BoutReal partialFactor = 1.0/(12 * metric->dz); // We need to discard const qualifier in order to manipulate // storage array directly @@ -992,6 +991,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, Field3D g_temp = g; BOUT_FOR(j2D, result.getRegion2D("RGN_NOBNDRY")) { + const BoutReal partialFactor = 1.0/(12 * metric->dz[j2D]); const BoutReal spacingFactor = partialFactor / metric->dx[j2D]; const int jy = j2D.y(), jx = j2D.x(); const int xm = jx - 1, xp = jx + 1; @@ -1079,7 +1079,6 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, #ifndef COORDINATES_USE_3D const int ncz = mesh->LocalNz; - const BoutReal partialFactor = 1.0 / (12 * metric->dz); // We need to discard const qualifier in order to manipulate // storage array directly @@ -1089,7 +1088,8 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, BOUT_OMP(parallel for) for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ - const BoutReal spacingFactor = partialFactor / metric->dx(jx, jy); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx,jy) + * metric->dx(jx, jy)); const BoutReal *Fxm = f_temp(jx-1, jy); const BoutReal *Fx = f_temp(jx, jy); const BoutReal *Fxp = f_temp(jx+1, jy); diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index b67a9771d7..1dfa951f28 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -96,7 +96,7 @@ namespace FV { // Calculate Z derivative at y boundary BoutReal dfdz = 0.25 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) / - coord->dz; + coord->dz(i, j);// is this at right location? // Y derivative BoutReal dfdy = 2. * (fup(i, j + 1, k) - fc(i, j, k)) / @@ -112,7 +112,7 @@ namespace FV { // Calculate flux between j and j-1 dfdz = 0.25 * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) / - coord->dz; + coord->dz(i,j);// is this at right location? dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) / (coord->dy(i, j) + coord->dy(i, j - 1)); @@ -144,15 +144,15 @@ namespace FV { BoutReal fout = 0.5 * (ac(i, j, k) + ac(i, j, kp)) * coord->g33(i, j) * ( // df/dz - (fc(i, j, kp) - fc(i, j, k)) / coord->dz + (fc(i, j, kp) - fc(i, j, k)) / coord->dz(i, j, k) // - g_yz * df/dy / SQ(J*B) - coef * (fup(i, j + 1, k) + fup(i, j + 1, kp) - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); - yzresult(i, j, k) += fout / coord->dz; - yzresult(i, j, kp) -= fout / coord->dz; + yzresult(i, j, k) += fout / coord->dz(i,j,k); + yzresult(i, j, kp) -= fout / coord->dz(i,j,k); } } } From 571b1ab230b684cb181c208a5489340391c41f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 23:45:18 +0000 Subject: [PATCH 092/293] update examples for non-const dz --- .gitignore | 1 + examples/elm-pb/elm_pb.cxx | 2 +- examples/lapd-drift/lapd_drift.cxx | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 5042929cb7..99563e579a 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ build*/ /tests/integrated/test-options-netcdf/test-options-netcdf /tests/integrated/test-options-netcdf/*.ini /tools/pylib/boututils/bout_config.py +/tests/integrated/test-snb/test_snb diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index d008b7986a..2b2ce8de75 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -642,7 +642,7 @@ class ELMpb : public PhysicsModel { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal angle = rmp_m * pol_angle(jx, jy) - + rmp_n * ((BoutReal)jz) * mesh->getCoordinates()->dz; + + rmp_n * ((BoutReal)jz) * mesh->getCoordinates()->dz(jx,jy); rmp_Psi0(jx, jy, jz) = (((BoutReal)(jx - 4)) / ((BoutReal)(mesh->LocalNx - 5))) * rmp_factor * cos(angle); diff --git a/examples/lapd-drift/lapd_drift.cxx b/examples/lapd-drift/lapd_drift.cxx index 0514904e8e..a9ae191a47 100644 --- a/examples/lapd-drift/lapd_drift.cxx +++ b/examples/lapd-drift/lapd_drift.cxx @@ -769,20 +769,20 @@ class LAPDdrift : public PhysicsModel { (f(jx+1,jy) - f(jx-1,jy)) - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* (f(jx,jy) - f(jx,jy)) ) - / (coord->dx(jx,jy, jz) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); // J+x BoutReal Jpx = 0.25*( f(jx+1,jy)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - f(jx-1,jy)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - f(jx,jy)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + f(jx,jy)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); // Jx+ BoutReal Jxp = 0.25*( f(jx+1,jy)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - f(jx-1,jy)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - f(jx-1,jy)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + f(jx+1,jy)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } @@ -830,20 +830,20 @@ class LAPDdrift : public PhysicsModel { (f(jx+1,jy,jz) - f(jx-1,jy,jz)) - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* (f(jx,jy,jzp) - f(jx,jy,jzm)) ) - / (coord->dx(jx,jy, jz) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); // J+x BoutReal Jpx = 0.25*( f(jx+1,jy,jz)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - f(jx-1,jy,jz)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - f(jx,jy,jzp)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + f(jx,jy,jzm)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); // Jx+ BoutReal Jxp = 0.25*( f(jx+1,jy,jzp)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - f(jx-1,jy,jzm)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - f(jx-1,jy,jzp)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + f(jx+1,jy,jzm)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } From 02b72e01d99749e53247fe4795787201c71526a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 28 Feb 2020 23:45:30 +0000 Subject: [PATCH 093/293] Update boutcore for non-const dz --- tools/pylib/_boutcore_build/boutcore.pyx.in | 9 ++------- tools/pylib/_boutcore_build/boutcpp.pxd.in | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/tools/pylib/_boutcore_build/boutcore.pyx.in b/tools/pylib/_boutcore_build/boutcore.pyx.in index 72673cee53..aa88b07935 100755 --- a/tools/pylib/_boutcore_build/boutcore.pyx.in +++ b/tools/pylib/_boutcore_build/boutcore.pyx.in @@ -822,8 +822,7 @@ cdef class Coordinates: """ cdef c.Coordinates * cobj cdef c.bool isSelfOwned - cdef public $metric_field dx, dy - cdef public double dz + cdef public $metric_field dx, dy, dz cdef public $metric_field J cdef public $metric_field Bxy cdef public $metric_field g11, g22, g33, g12, g13, g23 @@ -841,14 +840,10 @@ cdef class Coordinates: def _setmembers(self): EOF -for f in "dx" "dy" "J" "Bxy" "g11" "g22" "g33" "g12" "g13" "g23" "g_11" "g_22" "g_33" "g_12" "g_13" "g_23" "G1_11" "G1_22" "G1_33" "G1_12" "G1_13" "G1_23" "G2_11" "G2_22" "G2_33" "G2_12" "G2_13" "G2_23" "G3_11" "G3_22" "G3_33" "G3_12" "G3_13" "G3_23" "G1" "G2" "G3" "ShiftTorsion" "IntShiftTorsion" +for f in "dx" "dy" "dz" "J" "Bxy" "g11" "g22" "g33" "g12" "g13" "g23" "g_11" "g_22" "g_33" "g_12" "g_13" "g_23" "G1_11" "G1_22" "G1_33" "G1_12" "G1_13" "G1_23" "G2_11" "G2_22" "G2_33" "G2_12" "G2_13" "G2_23" "G3_11" "G3_22" "G3_33" "G3_12" "G3_13" "G3_23" "G1" "G2" "G3" "ShiftTorsion" "IntShiftTorsion" do echo " self.${f} = ${metric_fdd}FromPtr(&self.cobj.${f})" done -for f in "dz" -do - echo " self.${f} = self.cobj.${f}" -done cat <<"EOF" def __dealloc__(self): diff --git a/tools/pylib/_boutcore_build/boutcpp.pxd.in b/tools/pylib/_boutcore_build/boutcpp.pxd.in index 8090fffa0d..8600c004b9 100755 --- a/tools/pylib/_boutcore_build/boutcpp.pxd.in +++ b/tools/pylib/_boutcore_build/boutcpp.pxd.in @@ -82,8 +82,7 @@ cdef extern from "bout/mesh.hxx": cdef extern from "bout/coordinates.hxx": cppclass Coordinates: Coordinates() - $metric_field dx, dy - double dz + $metric_field dx, dy, dz $metric_field J $metric_field Bxy $metric_field g11, g22, g33, g12, g13, g23 From b78177fc19125ba785c31a7e0e936d9d751ea839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 29 Feb 2020 15:33:01 +0000 Subject: [PATCH 094/293] fix examples --- examples/elm-pb/elm_pb.cxx | 2 +- examples/lapd-drift/lapd_drift.cxx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index 2b2ce8de75..ac019cbbea 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -642,7 +642,7 @@ class ELMpb : public PhysicsModel { for (int jz = 0; jz < mesh->LocalNz; jz++) { BoutReal angle = rmp_m * pol_angle(jx, jy) - + rmp_n * ((BoutReal)jz) * mesh->getCoordinates()->dz(jx,jy); + + rmp_n * ((BoutReal)jz) * mesh->getCoordinates()->dz(jx,jy,jz); rmp_Psi0(jx, jy, jz) = (((BoutReal)(jx - 4)) / ((BoutReal)(mesh->LocalNx - 5))) * rmp_factor * cos(angle); diff --git a/examples/lapd-drift/lapd_drift.cxx b/examples/lapd-drift/lapd_drift.cxx index a9ae191a47..90532a2b04 100644 --- a/examples/lapd-drift/lapd_drift.cxx +++ b/examples/lapd-drift/lapd_drift.cxx @@ -769,20 +769,20 @@ class LAPDdrift : public PhysicsModel { (f(jx+1,jy) - f(jx-1,jy)) - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* (f(jx,jy) - f(jx,jy)) ) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); // J+x BoutReal Jpx = 0.25*( f(jx+1,jy)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - f(jx-1,jy)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - f(jx,jy)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + f(jx,jy)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); // Jx+ BoutReal Jxp = 0.25*( f(jx+1,jy)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - f(jx-1,jy)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - f(jx-1,jy)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + f(jx+1,jy)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } @@ -830,20 +830,20 @@ class LAPDdrift : public PhysicsModel { (f(jx+1,jy,jz) - f(jx-1,jy,jz)) - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* (f(jx,jy,jzp) - f(jx,jy,jzm)) ) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); // J+x BoutReal Jpx = 0.25*( f(jx+1,jy,jz)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - f(jx-1,jy,jz)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - f(jx,jy,jzp)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + f(jx,jy,jzm)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); // Jx+ BoutReal Jxp = 0.25*( f(jx+1,jy,jzp)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - f(jx-1,jy,jzm)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - f(jx-1,jy,jzp)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + f(jx+1,jy,jzm)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy)); + / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } From 7f524f843caebce515593e5abebf8aeeede1b3ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 29 Feb 2020 15:33:41 +0000 Subject: [PATCH 095/293] fix bracket for 3D --- src/mesh/difops.cxx | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 674db5f2f4..34393d7e7e 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -700,8 +700,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, BOUT_FOR(j2D, result.getRegion2D("RGN_NOBNDRY")) { // Get constants for this iteration - const BoutReal fac = 1.0 / (12 * metric->dz[j2D]); - const BoutReal spacingFactor = fac / metric->dx[j2D]; + const BoutReal spacingFactor = 1.0 / (12 * metric->dz[j2D] * metric->dx[j2D]); const int jy = j2D.y(), jx = j2D.x(); const int xm = jx - 1, xp = jx + 1; @@ -982,7 +981,6 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, } case BRACKET_ARAKAWA: { // Arakawa scheme for perpendicular flow -#ifndef COORDINATES_USE_3D const int ncz = mesh->LocalNz; // We need to discard const qualifier in order to manipulate @@ -991,8 +989,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, Field3D g_temp = g; BOUT_FOR(j2D, result.getRegion2D("RGN_NOBNDRY")) { - const BoutReal partialFactor = 1.0/(12 * metric->dz[j2D]); - const BoutReal spacingFactor = partialFactor / metric->dx[j2D]; +#ifndef COORDINATES_USE_3D + const BoutReal spacingFactor = 1.0/(12 * metric->dz[j2D] * metric->dx[j2D]); +#endif const int jy = j2D.y(), jx = j2D.x(); const int xm = jx - 1, xp = jx + 1; @@ -1007,6 +1006,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const int jz = 0; const int jzp = 1; const int jzm = ncz - 1; +#ifdef COORDINATES_USE_3D + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); +#endif // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) const BoutReal Jpp = ((Fx[jzp] - Fx[jzm]) * (Gxp[jz] - Gxm[jz]) - @@ -1026,6 +1028,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, } for (int jz = 1; jz < mesh->LocalNz - 1; jz++) { +#ifdef COORDINATES_USE_3D + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); +#endif const int jzp = jz + 1; const int jzm = jz - 1; @@ -1050,6 +1055,9 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const int jz = ncz - 1; const int jzp = 0; const int jzm = ncz - 2; +#ifdef COORDINATES_USE_3D + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); +#endif // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) const BoutReal Jpp = ((Fx[jzp] - Fx[jzm]) * (Gxp[jz] - Gxm[jz]) - @@ -1068,15 +1076,10 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, result(jx, jy, jz) = (Jpp + Jpx + Jxp) * spacingFactor; } } -#else - throw BoutException("BRACKET_ARAKAWA not valid with 3D metrics yet."); -#endif - break; } case BRACKET_ARAKAWA_OLD: { // Arakawa scheme for perpendicular flow -#ifndef COORDINATES_USE_3D const int ncz = mesh->LocalNz; @@ -1088,8 +1091,10 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, BOUT_OMP(parallel for) for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ +#ifndef COORDINATES_USE_3D const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx,jy) * metric->dx(jx, jy)); +#endif const BoutReal *Fxm = f_temp(jx-1, jy); const BoutReal *Fx = f_temp(jx, jy); const BoutReal *Fxp = f_temp(jx+1, jy); @@ -1097,6 +1102,10 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const BoutReal *Gx = g_temp(jx, jy); const BoutReal *Gxp = g_temp(jx+1, jy); for (int jz = 0; jz < mesh->LocalNz; jz++) { +#ifdef COORDINATES_USE_3D + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) + * metric->dx(jx, jy, jz)); +#endif const int jzp = jz+1 < ncz ? jz + 1 : 0; //Above is alternative to const int jzp = (jz + 1) % ncz; const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; @@ -1122,9 +1131,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, } } } -#else - throw BoutException("BRACKET_ARAKAWA_OLD not valid with 3D metrics yet."); -#endif + break; } case BRACKET_SIMPLE: { From 766c6b0929df26e04e4bdf4c691a6e3434872697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 29 Feb 2020 15:35:34 +0000 Subject: [PATCH 096/293] Fix tests for 3d metrics --- tests/MMS/bracket/runtest | 1 - tests/MMS/diffusion2/diffusion.cxx | 2 +- tests/MMS/hw/runtest | 1 + tests/MMS/spatial/diffusion/diffusion.cxx | 2 +- tests/integrated/test-twistshift-staggered/runtest | 3 +++ 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/MMS/bracket/runtest b/tests/MMS/bracket/runtest index e9ff74457d..ac316316db 100755 --- a/tests/MMS/bracket/runtest +++ b/tests/MMS/bracket/runtest @@ -13,7 +13,6 @@ import numpy as np #Requires: boutcore #requires: not make -#requires: not metric_3d import boutcore as bc diff --git a/tests/MMS/diffusion2/diffusion.cxx b/tests/MMS/diffusion2/diffusion.cxx index 80b08748ba..356fe3ac7e 100644 --- a/tests/MMS/diffusion2/diffusion.cxx +++ b/tests/MMS/diffusion2/diffusion.cxx @@ -23,7 +23,7 @@ int physics_init(bool UNUSED(restarting)) { coords->dy = Ly/(mesh->GlobalNy - 2*mesh->ystart); - output.write("SIZES: %d, %d, %e\n", mesh->GlobalNy, (mesh->GlobalNy - 2*mesh->ystart), coords->dy(0,0)); + output.write("SIZES: %d, %d, %e\n", mesh->GlobalNy, (mesh->GlobalNy - 2*mesh->ystart), coords->dy(0,0,0)); SAVE_ONCE2(Lx,Ly); diff --git a/tests/MMS/hw/runtest b/tests/MMS/hw/runtest index 9569532be2..ca043284df 100755 --- a/tests/MMS/hw/runtest +++ b/tests/MMS/hw/runtest @@ -3,6 +3,7 @@ # Python script to run and analyse MMS test #requires: all_tests +#requires: not metric_3d from __future__ import division from __future__ import print_function diff --git a/tests/MMS/spatial/diffusion/diffusion.cxx b/tests/MMS/spatial/diffusion/diffusion.cxx index 72dfa25bde..e62b2b1c5b 100644 --- a/tests/MMS/spatial/diffusion/diffusion.cxx +++ b/tests/MMS/spatial/diffusion/diffusion.cxx @@ -24,7 +24,7 @@ int physics_init(bool UNUSED(restarting)) { coords->dy = Ly/(mesh->GlobalNy - 2*mesh->ystart); - output.write("SIZES: %d, %d, %e\n", mesh->GlobalNy, (mesh->GlobalNy - 2*mesh->ystart), coords->dy(0,0)); + output.write("SIZES: %d, %d, %e\n", mesh->GlobalNy, (mesh->GlobalNy - 2*mesh->ystart), coords->dy(0,0,0)); SAVE_ONCE2(Lx,Ly); diff --git a/tests/integrated/test-twistshift-staggered/runtest b/tests/integrated/test-twistshift-staggered/runtest index 0c0d05d8f9..3c5cc11751 100755 --- a/tests/integrated/test-twistshift-staggered/runtest +++ b/tests/integrated/test-twistshift-staggered/runtest @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +# Currently broken +#requires: False + from boutdata import collect from boututils.run_wrapper import launch_safe, shell_safe import numpy From 2cf2f25c611d01a4bd014a06cf22138a55fc4c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 29 Feb 2020 15:37:02 +0000 Subject: [PATCH 097/293] Add more -all targets for checks Allows to compile and run all tests by running: make -j 4 build-check-all && make check-all --- makefile | 5 +++++ tests/integrated/makefile | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/makefile b/makefile index b51413e743..e84eb38d30 100644 --- a/makefile +++ b/makefile @@ -69,12 +69,17 @@ build-check-unit-tests: libfast build-check-mms-tests: libfast $(MAKE) --no-print-directory -C tests/MMS +build-check-mms-tests-all: libfast + $(MAKE) --no-print-directory -C tests/MMS allall build-check-integrated-tests: libfast $(MAKE) --no-print-directory -C tests/integrated +build-check-integrated-tests-all: libfast + $(MAKE) --no-print-directory -C tests/integrated allall build-check: build-check-integrated-tests build-check-mms-tests build-check-unit-tests +build-check-all: build-check-integrated-tests-all build-check-mms-tests-all build-check-unit-tests # Build the .mo files needed for Natural Language Support (gettext) .PHONY: locale diff --git a/tests/integrated/makefile b/tests/integrated/makefile index 36a2c4ed21..316db21cdf 100644 --- a/tests/integrated/makefile +++ b/tests/integrated/makefile @@ -6,6 +6,7 @@ BOUT_TOP = ../.. LIST = test_suite_list BUILD = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite_make --get-list) +BUILDALL = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite_make --get-list --all) CHECKING = $(shell PYTHONPATH=../../tools/pylib:$$PYTHONPATH ./test_suite --get-list) @@ -14,17 +15,18 @@ include $(BOUT_TOP)/make.config CHECKING_ = $(CHECKING:%=%_checking) -.PHONY: $(BUILD) $(CHECKING_) check +.PHONY: $(BUILDALL) $(CHECKING_) check all: $(BUILD) +allall: $(BUILDALL) + buildncheck: all check -$(BUILD): +$(BUILDALL): @$(MAKE) --no-print-directory -C $@ check: $(CHECKING_) - @echo $(CHECKING_) $(CHECKING_): @$(MAKE) --no-print-directory -C $(@:%_checking=%) runtest From b979b737806fdfeb613d692b20a4fd5dd638fbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 1 Mar 2020 18:00:56 +0000 Subject: [PATCH 098/293] Fix shift-transform The shift-transform in staggered location requieres dz. To calculate the staggered dz in y direction, the parallel transform is requiered. Thus we special handel the case if dz is constant, and we can do a trivial staggering, without a parallel transform. For non-const dz, staggered dz needs to be given in an input file, so we don't have to interpolate. Also make isConst a free function, similar to min and max. --- include/field.hxx | 18 ++++++++++++ include/field2d.hxx | 2 -- src/field/field2d.cxx | 10 ------- src/field/field3d.cxx | 9 ------ src/field/fieldgenerators.cxx | 2 +- .../laplace/impls/cyclic/cyclic_laplace.cxx | 2 +- src/invert/laplace/impls/pdd/pdd.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 | 2 +- .../impls/cyclic/laplacexz-cyclic.cxx | 2 +- src/invert/parderiv/impls/cyclic/cyclic.cxx | 2 +- src/mesh/coordinates.cxx | 29 +++++++++++++++---- src/mesh/data/gridfromfile.cxx | 4 +-- 15 files changed, 53 insertions(+), 37 deletions(-) diff --git a/include/field.hxx b/include/field.hxx index 84b7013ec8..eb7497f645 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -359,6 +359,24 @@ inline BoutReal min(const T& f, bool allpe, REGION rgn) { return min(f, allpe, toString(rgn)); } + +template> +inline bool isConst(const T& f, bool allpe = false, const std::string& region = "RGN_ALL") { + bool result = true; + auto element = f[*f.getRegion(region).begin()]; + BOUT_FOR_SERIAL(i, f.getRegion(region)){ + if (f[i] != element){ + result=false; + break; + } + } + if(allpe) { + bool localresult = result; + MPI_Allreduce(&localresult, &result, 1, MPI_C_BOOL, MPI_LOR, BoutComm::get()); + } + return result; +} + template> inline BoutReal max(const T& f, bool allpe = false, const std::string& rgn = "RGN_NOBNDRY") { AUTO_TRACE(); diff --git a/include/field2d.hxx b/include/field2d.hxx index e9941de2b0..cb5c150a96 100644 --- a/include/field2d.hxx +++ b/include/field2d.hxx @@ -260,8 +260,6 @@ class Field2D : public Field, public FieldData { int byteSize() const override { return sizeof(BoutReal); } // Just one BoutReal int BoutRealSize() const override { return 1; } - bool isConst(const std::string& region) const; - #if CHECK > 0 void doneComms() override { bndry_xin = bndry_xout = bndry_yup = bndry_ydown = true; } #else diff --git a/src/field/field2d.cxx b/src/field/field2d.cxx index b1b1a188ad..9e2ba75492 100644 --- a/src/field/field2d.cxx +++ b/src/field/field2d.cxx @@ -94,16 +94,6 @@ Field2D::Field2D(Array data_in, Mesh* localmesh, CELL_LOC datalocation setLocation(datalocation); } -bool Field2D::isConst(const std::string & region) const { - auto element = (*this)[this->getRegion(region).begin()[0]]; - BOUT_FOR_SERIAL(i, this->getRegion(region)){ - if ((*this)[i] != element){ - return false; - } - } - return true; -} - Field2D::~Field2D() { delete deriv; } Field2D& Field2D::allocate() { diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 90ed4b0ea3..c18fe27330 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -849,12 +849,3 @@ std::ostream& operator<<(std::ostream &out, const Field3D &value) { return out; } -bool Field3D::isConst(const std::string & region) const { - auto element = (*this)[this->getRegion(region).begin()[0]]; - BOUT_FOR_SERIAL(i, this->getRegion(region)){ - if ((*this)[i] != element){ - return false; - } - } - return true; -} diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 02197d0e2a..6ee80e7be9 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -188,7 +188,7 @@ BoutReal FieldBallooning::generate(double x, double y, double z, double t) { (mesh->xend - mesh->xstart); int jx = ROUND((x - mesh->GlobalX(0)) / dx); - ASSERT1(coords->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coords->zlength())); if(mesh->periodicY(jx, ts)) { // Start with the value at this point diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index 2e9eacc5ad..5c4b0f259e 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -118,7 +118,7 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { outbndry = 1; if(dst) { - ASSERT1(coords->dz.isConst("RGN_ALL")); + ASSERT1(isConst(coords->dz)); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = diff --git a/src/invert/laplace/impls/pdd/pdd.cxx b/src/invert/laplace/impls/pdd/pdd.cxx index 3e0c935310..3796fde6e1 100644 --- a/src/invert/laplace/impls/pdd/pdd.cxx +++ b/src/invert/laplace/impls/pdd/pdd.cxx @@ -165,7 +165,7 @@ void LaplacePDD::start(const FieldPerp &b, PDD_data &data) { /// Create the matrices to be inverted (one for each z point) - ASSERT1(coords->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coords->zlength())); BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); /// Set matrix elements diff --git a/src/invert/laplace/impls/serial_tri/serial_tri.cxx b/src/invert/laplace/impls/serial_tri/serial_tri.cxx index 5010c6bcb6..e0ee4d8ac0 100644 --- a/src/invert/laplace/impls/serial_tri/serial_tri.cxx +++ b/src/invert/laplace/impls/serial_tri/serial_tri.cxx @@ -83,7 +83,7 @@ FieldPerp LaplaceSerialTri::solve(const FieldPerp& b, const FieldPerp& x0) { int ncz = localmesh->LocalNz; // No of z pnts int ncx = localmesh->LocalNx; // No of x pnts - ASSERT1(coords->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coords->zlength())); BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); // Setting the width of the boundary. diff --git a/src/invert/laplace/impls/shoot/shoot_laplace.cxx b/src/invert/laplace/impls/shoot/shoot_laplace.cxx index 06141e857e..c985c47a3e 100644 --- a/src/invert/laplace/impls/shoot/shoot_laplace.cxx +++ b/src/invert/laplace/impls/shoot/shoot_laplace.cxx @@ -129,7 +129,7 @@ FieldPerp LaplaceShoot::solve(const FieldPerp& rhs) { // kc and kp now set to result at x and x+1 respectively // Use b at x to get km at x-1 // Loop inwards from edge - ASSERT1(coords->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coords->zlength())); for(int ix=xe; ix >= xs; ix--) { rfft(rhs[ix], localmesh->LocalNz, std::begin(rhsk)); diff --git a/src/invert/laplace/impls/spt/spt.cxx b/src/invert/laplace/impls/spt/spt.cxx index 8c9361b08b..ea237961c3 100644 --- a/src/invert/laplace/impls/spt/spt.cxx +++ b/src/invert/laplace/impls/spt/spt.cxx @@ -291,7 +291,7 @@ int LaplaceSPT::start(const FieldPerp &b, SPT_data &data) { data.bk(kz, ix) = dc1d[kz]; } - ASSERT1(coords->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coords->zlength())); BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); /// Set matrix elements diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index 3c6cfdae6d..6629197cb6 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -364,7 +364,7 @@ void Laplacian::tridagMatrix(dcomplex **avec, dcomplex **bvec, dcomplex **cvec, const Field2D *a, const Field2D *ccoef, const Field2D *d) { - ASSERT3(coords->zlength().isConst("RGN_ALL")); + ASSERT3(isConst(coords->zlength())); BOUT_OMP(parallel for) for(int kz = 0; kz <= maxmode; kz++) { BoutReal kwave=kz*2.0*PI/coords->zlength()(0,jy); // wave number is 1/[rad] diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 777af53101..c3bd8153f5 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -76,7 +76,7 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { ASSERT2(max(abs(coord->g13)) < 1e-5); int ind = 0; - ASSERT1(coord->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coord->zlength())); for(int y=localmesh->ystart; y <= localmesh->yend; y++) { for(int kz = 0; kz < nmode; kz++) { BoutReal kwave=kz*2.0*PI/(coord->zlength()(0,0)); diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 1eeb4bcbc3..2abe7a79fc 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -96,7 +96,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { auto b = Matrix(nsys, size); auto c = Matrix(nsys, size); - ASSERT1(coord->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(coord->zlength())); // Loop over flux-surfaces for (surf.first(); !surf.isDone(); surf.next()) { int x = surf.xpos; diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 0209b8f61a..08fb65c2c2 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -642,8 +642,6 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, bool extrapolate_x = true; bool extrapolate_y = true; - setParallelTransform(options); - if (!force_interpolate_from_centre && mesh->sourceHasVar("dx"+suffix)) { extrapolate_x = not mesh->sourceHasXBoundaryGuards(); @@ -659,7 +657,20 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, "cells\n")); } - getAtLoc(mesh, dz, "dz", suffix, location, 1.0); + { + auto& options = Options::root(); + const bool has_zperiod = options.isSet("zperiod"); + const auto zmin = has_zperiod ? 0.0 : options["ZMIN"].withDefault(0.0); + const auto zmax = has_zperiod ? 1.0 / options["zperiod"].withDefault(1.0) + : options["ZMAX"].withDefault(1.0); + + const auto default_dz = (zmax - zmin) * TWOPI / nz; + printf("getting dz staggered\n"); + getAtLoc(mesh, dz, "dz", suffix, location, default_dz); + printf("dz staggered is %e\n",dz(0,0,0)); + } + setParallelTransform(options); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false); getAtLoc(mesh, dx, "dx", suffix, location, 1.0); @@ -762,8 +773,16 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } else { // Interpolate fields from coords_in + if (isConst(coords_in->dz)){ + dz = coords_in->dz; + dz.setLocation(location); + } else { + throw BoutException("We are asked to transform dz to get dz before we have a transform, which might require dz!\nPlease provide a dz for the staggered quantity!"); + } + setParallelTransform(options); dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false); dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false); + // not really needed - we have used dz already ... dz = interpolateAndExtrapolate(coords_in->dz, location, true, true, false); // Diagonal components of metric tensor g^{ij} @@ -876,7 +895,7 @@ void Coordinates::outputVars(Datafile& file) { int Coordinates::geometry(bool recalculate_staggered, bool force_interpolate_from_centre) { TRACE("Coordinates::geometry"); - communicate(dx, dy, g11, g22, g33, g12, g13, g23, + communicate(dx, dy, dz, g11, g22, g33, g12, g13, g23, g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); output_progress.write("Calculating differential geometry terms\n"); @@ -1382,7 +1401,7 @@ void Coordinates::setParallelTransform(Options* options) { fixZShiftGuards(zShift); - ASSERT1(zlength().isConst("RGN_ALL")); + ASSERT1(isConst(zlength())); transform = bout::utils::make_unique(*localmesh, location, zShift, zlength()(0,0)); diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index 0fb07cb334..057c3ad364 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -566,7 +566,7 @@ bool GridFile::readgrid_3dvar_fft(Mesh *m, const std::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() - ASSERT1(m->getCoordinates(var.getLocation())->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(m->getCoordinates(var.getLocation())->zlength())); BoutReal zlength = m->getCoordinates(var.getLocation())->zlength()(0,0); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi @@ -698,7 +698,7 @@ bool GridFile::readgrid_perpvar_fft(Mesh *m, const std::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() - ASSERT1(m->getCoordinates(var.getLocation())->zlength().isConst("RGN_ALL")); + ASSERT1(isConst(m->getCoordinates(var.getLocation())->zlength())); BoutReal zlength = m->getCoordinates(var.getLocation())->zlength()(0,0); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi From 151e8e2da056ad9ef446ee96b606ce52088ea5e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 1 Mar 2020 18:01:47 +0000 Subject: [PATCH 099/293] Ensure ffts are OpenMP thread safe If we are deeper nested, omp_get_thread_num isn't unique anymore --- src/invert/fft_fftw.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/invert/fft_fftw.cxx b/src/invert/fft_fftw.cxx index e5c4b5f532..5fb2058a1a 100644 --- a/src/invert/fft_fftw.cxx +++ b/src/invert/fft_fftw.cxx @@ -206,6 +206,8 @@ void rfft(MAYBE_UNUSED(const BoutReal *in), MAYBE_UNUSED(int length), MAYBE_UNUS #ifndef BOUT_HAS_FFTW throw BoutException("This instance of BOUT++ has been compiled without fftw support."); #else + // ensure we are not nested + ASSERT1(omp_get_active_level() < 2); static double *finall; static fftw_complex *foutall; static fftw_plan *p; From 07b48ee29d6aaddddbec5eadb909f8a61bc09db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 1 Mar 2020 18:02:31 +0000 Subject: [PATCH 100/293] Re-enable fixed test --- tests/integrated/test-twistshift-staggered/runtest | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/integrated/test-twistshift-staggered/runtest b/tests/integrated/test-twistshift-staggered/runtest index 3c5cc11751..0c0d05d8f9 100755 --- a/tests/integrated/test-twistshift-staggered/runtest +++ b/tests/integrated/test-twistshift-staggered/runtest @@ -1,8 +1,5 @@ #!/usr/bin/env python3 -# Currently broken -#requires: False - from boutdata import collect from boututils.run_wrapper import launch_safe, shell_safe import numpy From 4d1b5a7dd52b7ea4ca14544189e2a61ae3bb2a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 1 Mar 2020 18:53:43 +0000 Subject: [PATCH 101/293] Add bout_config to cmake * Add metric3D to cmake * cmake with -DENABLE_METRIC_3D=ON to get 3D metrics * Due to the out-of-source build we need to python dirs, one for noarch files, and one for arched ones --- .travis.yml | 2 +- CMakeLists.txt | 15 ++ bout++Config.cmake.in | 1 + tools/pylib/boututils/bout_config.py.cin | 294 +++++++++++++++++++++++ 4 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 tools/pylib/boututils/bout_config.py.cin diff --git a/.travis.yml b/.travis.yml index 6a65fb46bd..c24bdc6926 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,7 +89,7 @@ matrix: - env: - *default_env - OMP_NUM_THREADS=2 - - PYTHONPATH="${TRAVIS_BUILD_DIR}/tools/pylib:$PYTHONPATH" + - PYTHONPATH="${TRAVIS_BUILD_DIR}/tools/pylib:${TRAVIS_BUILD_DIR}/build/tools/pylib:$PYTHONPATH" script: - ./.build_sundials_for_travis.sh - mkdir build && cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index b909ab6482..a680423198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -628,6 +628,16 @@ if(PACKAGE_TESTS) add_subdirectory(tests/integrated) endif() +option(ENABLE_METRIC_3D "Enable 3D metric support" OFF) +if(ENABLE_METRIC_3D) + set(BOUT_METRIC_TYPE "3D") + target_compile_definitions(bout++ + PUBLIC "COORDINATES_USE_3D") + target_link_libraries(bout++ PUBLIC ${CMAKE_DL_LIBS}) +else() + set(BOUT_METRIC_TYPE "2D") +endif() +set(BOUT_USE_METRIC_3D ${ENABLE_METRIC_3D}) ################################################## # Installation @@ -657,6 +667,10 @@ install(EXPORT bout++Targets configure_package_config_file(bout++Config.cmake.in bout++Config.cmake INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake" ) + +configure_package_config_file(tools/pylib/boututils/bout_config.py.cin tools/pylib/boututils/bout_config.py + INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib/boututils/bout_config.py" + ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake" @@ -706,6 +720,7 @@ message(" Field name tracking : ${BOUT_USE_TRACK} Floating point exceptions: ${BOUT_USE_SIGFPE} Backtrace enabled : ${BOUT_USE_BACKTRACE} + 3D Metric enabled : ${BOUT_USE_METRIC_3D} === Python === diff --git a/bout++Config.cmake.in b/bout++Config.cmake.in index a50a356179..46050afc4a 100644 --- a/bout++Config.cmake.in +++ b/bout++Config.cmake.in @@ -10,6 +10,7 @@ set(BOUT_USE_BACKTRACE @BOUT_USE_BACKTRACE@) set(BOUT_USE_OPENMP @BOUT_USE_OPENMP@) set(BOUT_HAS_OUTPUT_DEBUG @BOUT_HAS_OUTPUT_DEBUG@) set(BOUT_CHECK_LEVEL @BOUT_CHECK_LEVEL@) +set(BOUT_USE_METRIC_3D @BOUT_USE_METRIC_3D@) set(BOUT_HAS_PVODE @BOUT_HAS_PVODE@) set(BOUT_HAS_NETCDF @BOUT_HAS_NETCDF@) diff --git a/tools/pylib/boututils/bout_config.py.cin b/tools/pylib/boututils/bout_config.py.cin new file mode 100644 index 0000000000..98888c19ac --- /dev/null +++ b/tools/pylib/boututils/bout_config.py.cin @@ -0,0 +1,294 @@ +"""Functions for getting the config used for compiling BOUT++ + +""" +// Created by cmake +_yesno = {"TRUE": True, "ON"': True, "FALSE": False "no": False} +_iyesno = {True:"yes", False: "no"} + +_cc='@MPICXX@' +_cxx='@MPICXX@' +_ld='@MPICXX@' +_checks="@BOUT_CHECK_LEVEL@" +_cflags='@CONFIG_CFLAGS@' +_libs='@CONFIG_LDFLAGS@' + +_version="@BOUT_VERSION@" +_git="@GIT_REVISION@" +_idlpath="@IDLCONFIGPATH@" +_pythonpath="@PYTHONCONFIGPATH@" + +_has_netcdf="@BOUT_HAS_NETCDF@" +_has_pnetcdf="OFF" +_has_hdf5="@BOUT_HAS_HDF5@" +_has_pvode="@BOUT_HAS_PVODE@" +_has_cvode="OFF" +_has_ida="OFF" +_has_lapack="@BOUT_HAS_LAPACK@" +_has_petsc="@BOUT_HAS_PETSC@" +_has_slepc="@BOUT_HAS_SLEPC@" +_has_mumps="OFF" +_has_arkode="OFF" +_has_openmp="@BOUT_USE_OPENMP@" +_has_nls="@BOUT_HAS_GETTEXT@" +_has_fftw="@BOUT_HAS_FFTW@" + +_petsc_has_sundials="@PETSC_HAS_SUNDIALS@" + +_metric_type="@BOUT_METRIC_TYPE@" +def has_netcdf(): + """Return 'yes' / 'no' whether has_netcdf is available + + """ + return _iyesno[_yesno[_has_netcdf]] + +def hasNetcdf(): + """Return True / False whether has_netcdf is available + + """ + return _yesno[_has_netcdf] + +def has_pnetcdf(): + """Return 'yes' / 'no' whether has_pnetcdf is available + + """ + return _iyesno[_yesno[_has_pnetcdf]] + +def hasPnetcdf(): + """Return True / False whether has_pnetcdf is available + + """ + return _yesno[_has_pnetcdf] + +def has_hdf5(): + """Return 'yes' / 'no' whether has_hdf5 is available + + """ + return _iyesno[_yesno[_has_hdf5]] + +def hasHdf5(): + """Return True / False whether has_hdf5 is available + + """ + return _yesno[_has_hdf5] + +def has_pvode(): + """Return 'yes' / 'no' whether has_pvode is available + + """ + return _iyesno[_yesno[_has_pvode]] + +def hasPvode(): + """Return True / False whether has_pvode is available + + """ + return _yesno[_has_pvode] + +def has_cvode(): + """Return 'yes' / 'no' whether has_cvode is available + + """ + return _iyesno[_yesno[_has_cvode]] + +def hasCvode(): + """Return True / False whether has_cvode is available + + """ + return _yesno[_has_cvode] + +def has_ida(): + """Return 'yes' / 'no' whether has_ida is available + + """ + return _iyesno[_yesno[_has_ida]] + +def hasIda(): + """Return True / False whether has_ida is available + + """ + return _yesno[_has_ida] + +def has_lapack(): + """Return 'yes' / 'no' whether has_lapack is available + + """ + return _iyesno[_yesno[_has_lapack]] + +def hasLapack(): + """Return True / False whether has_lapack is available + + """ + return _yesno[_has_lapack] + +def has_petsc(): + """Return 'yes' / 'no' whether has_petsc is available + + """ + return _iyesno[_yesno[_has_petsc]] + +def hasPetsc(): + """Return True / False whether has_petsc is available + + """ + return _yesno[_has_petsc] + +def has_slepc(): + """Return 'yes' / 'no' whether has_slepc is available + + """ + return _iyesno[_yesno[_has_slepc]] + +def hasSlepc(): + """Return True / False whether has_slepc is available + + """ + return _yesno[_has_slepc] + +def has_mumps(): + """Return 'yes' / 'no' whether has_mumps is available + + """ + return _iyesno[_yesno[_has_mumps]] + +def hasMumps(): + """Return True / False whether has_mumps is available + + """ + return _yesno[_has_mumps] + +def has_arkode(): + """Return 'yes' / 'no' whether has_arkode is available + + """ + return _iyesno[_yesno[_has_arkode]] + +def hasArkode(): + """Return True / False whether has_arkode is available + + """ + return _yesno[_has_arkode] + +def has_openmp(): + """Return 'yes' / 'no' whether has_openmp is available + + """ + return _iyesno[_yesno[_has_openmp]] + +def hasOpenmp(): + """Return True / False whether has_openmp is available + + """ + return _yesno[_has_openmp] + +def has_nls(): + """Return 'yes' / 'no' whether has_nls is available + + """ + return _iyesno[_yesno[_has_nls]] + +def hasNls(): + """Return True / False whether has_nls is available + + """ + return _yesno[_has_nls] + +def has_fftw(): + """Return 'yes' / 'no' whether has_fftw is available + + """ + return _iyesno[_yesno[_has_fftw]] + +def hasFftw(): + """Return True / False whether has_fftw is available + + """ + return _yesno[_has_fftw] + +def petsc_has_sundials(): + """Return 'yes' / 'no' whether petsc_has_sundials is available + + """ + return _iyesno[_yesno[_petsc_has_sundials]] + +def petscHasSundials(): + """Return True / False whether petsc_has_sundials is available + + """ + return _yesno[_petsc_has_sundials] + +def cc(): + """Option for cc + + """ + return _cc + +def cxx(): + """Option for cxx + + """ + return _cxx + +def ld(): + """Option for ld + + """ + return _ld + +def checks(): + """Option for checks + + """ + return _checks + +def cflags(): + """Option for cflags + + """ + return _cflags + +def libs(): + """Option for libs + + """ + return _libs + +def metric_type(): + """Option for metric_type + + """ + return _metric_type + +def version(): + """Option for version + + """ + return _version + +def git(): + """Option for git + + """ + return _git + +def idlpath(): + """Option for idlpath + + """ + return _idlpath + +def pythonpath(): + """Option for pythonpath + + """ + return _pythonpath + +def isMetric2D(): + """Is the metric 2D? + + """ + return _metric_type == "2D" + +def isMetric3D(): + """Is the metric 3D? + + """ + return _metric_type == "3D" From 109b90663eb7bb852af54c58d50d63af19bbdce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 1 Mar 2020 20:02:02 +0000 Subject: [PATCH 102/293] Move boutconfig to own folder. otherwise python finds boututils in one pythonpath, and does not look in other locations for the other file. --- CMakeLists.txt | 4 ++-- configure.ac | 2 +- tests/MMS/spatial/fci/runtest | 2 +- tests/integrated/test-io/runtest | 2 +- .../bout_config.py.cin => boutconfig/__init__.py.cin} | 4 ++-- .../bout_config.py.in => boutconfig/__init__.py.in} | 0 6 files changed, 7 insertions(+), 7 deletions(-) rename tools/pylib/{boututils/bout_config.py.cin => boutconfig/__init__.py.cin} (98%) rename tools/pylib/{boututils/bout_config.py.in => boutconfig/__init__.py.in} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a680423198..66eac98895 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -668,8 +668,8 @@ configure_package_config_file(bout++Config.cmake.in bout++Config.cmake INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/bout++Config.cmake" ) -configure_package_config_file(tools/pylib/boututils/bout_config.py.cin tools/pylib/boututils/bout_config.py - INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib/boututils/bout_config.py" +configure_package_config_file(tools/pylib/boutconfig/__init__.py.cin tools/pylib/boutconfig/__init__.py + INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/tools/pylib/boutconfig/__init__.py" ) install( FILES diff --git a/configure.ac b/configure.ac index d3e1fde93d..30ac9e7ec4 100644 --- a/configure.ac +++ b/configure.ac @@ -1315,7 +1315,7 @@ AC_SUBST(METRIC_TYPE) AC_SUBST(HAS_FFTW) AC_CONFIG_FILES([bin/bout-config]) -AC_CONFIG_FILES([tools/pylib/boututils/bout_config.py]) +AC_CONFIG_FILES([tools/pylib/boutconfig/__init__.py]) AC_OUTPUT chmod a+x bin/bout-config diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index cbf3581c30..342c4603b6 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -5,7 +5,7 @@ from boututils.run_wrapper import shell_safe, launch_safe from boutdata.collect import collect -import boututils.bout_config as conf +import boutconfig as conf from numpy import array, log, polyfit, linspace, arange diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index cd4887f306..082d49f14f 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -14,7 +14,7 @@ except: from boututils.run_wrapper import shell, shell_safe, launch_safe from boutdata.collect import collect -import boututils.bout_config as conf +import boutconfig as conf import numpy as np from sys import stdout, exit diff --git a/tools/pylib/boututils/bout_config.py.cin b/tools/pylib/boutconfig/__init__.py.cin similarity index 98% rename from tools/pylib/boututils/bout_config.py.cin rename to tools/pylib/boutconfig/__init__.py.cin index 98888c19ac..141203897c 100644 --- a/tools/pylib/boututils/bout_config.py.cin +++ b/tools/pylib/boutconfig/__init__.py.cin @@ -1,8 +1,8 @@ """Functions for getting the config used for compiling BOUT++ """ -// Created by cmake -_yesno = {"TRUE": True, "ON"': True, "FALSE": False "no": False} +# Created by cmake +_yesno = {"TRUE": True, "ON": True, "FALSE": False, "OFF": False} _iyesno = {True:"yes", False: "no"} _cc='@MPICXX@' diff --git a/tools/pylib/boututils/bout_config.py.in b/tools/pylib/boutconfig/__init__.py.in similarity index 100% rename from tools/pylib/boututils/bout_config.py.in rename to tools/pylib/boutconfig/__init__.py.in From f73939063d0a4439e00d42064d8347e9531500c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 1 Mar 2020 20:31:58 +0000 Subject: [PATCH 103/293] update configure --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 2a1d4a6f5c..20e0a419ca 100755 --- a/configure +++ b/configure @@ -15788,7 +15788,7 @@ MPARK_VARIANT_INCLUDE_PATH=$PWD/externalpackages/mpark.variant/include ac_config_files="$ac_config_files bin/bout-config" -ac_config_files="$ac_config_files tools/pylib/boututils/bout_config.py" +ac_config_files="$ac_config_files tools/pylib/boutconfig/__init__.py" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -16520,7 +16520,7 @@ do "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; "make.config") CONFIG_FILES="$CONFIG_FILES make.config" ;; "bin/bout-config") CONFIG_FILES="$CONFIG_FILES bin/bout-config" ;; - "tools/pylib/boututils/bout_config.py") CONFIG_FILES="$CONFIG_FILES tools/pylib/boututils/bout_config.py" ;; + "tools/pylib/boutconfig/__init__.py") CONFIG_FILES="$CONFIG_FILES tools/pylib/boutconfig/__init__.py" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac From 451037f2ef5ee681c8495936d102f6f560ea5615 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Mon, 16 Mar 2020 16:31:00 +0100 Subject: [PATCH 104/293] Update operators for FCI compatability --- src/field/vecops.cxx | 13 ++++++-- src/mesh/fv_ops.cxx | 76 ++++++++++++++++++++------------------------ 2 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 5a7374d028..105cd27fef 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -165,8 +165,17 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) Vector3D vcn = v; vcn.toContravariant(); - Field3D result = DDX(vcn.x.getCoordinates()->J * vcn.x, outloc, method); - result += DDY(vcn.y.getCoordinates()->J * vcn.y, outloc, method); + Field3D result = 0.0; + + if(!vcn.y.hasParallelSlices()){ + Field3D vcnJy = vcn.y.getCoordinates()->J * vcn.y; + localmesh->communicate(vcnJy); + result = DDY(vcnJy, outloc, method); + }else{ + result = DDY(vcn.y.getCoordinates()->J * vcn.y, outloc, method); + } + + result += DDX(vcn.x.getCoordinates()->J * vcn.x, outloc, method); result += DDZ(vcn.z.getCoordinates()->J * vcn.z, outloc, method); result /= metric->J; diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 1dfa951f28..b70c9ad81a 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -10,7 +10,6 @@ namespace FV { // Div ( a Laplace_perp(f) ) -- Vorticity const Field3D Div_a_Laplace_perp(const Field3D &a, const Field3D &f) { -#ifndef COORDINATES_USE_3D ASSERT2(a.getLocation() == f.getLocation()); Mesh *mesh = a.getMesh(); @@ -38,11 +37,11 @@ namespace FV { for(int k=0;kLocalNz;k++) { // Calculate flux from i to i+1 - BoutReal fout = 0.5*(a(i,j,k) + a(i+1,j,k)) * (coord->J(i,j)*coord->g11(i,j) + coord->J(i+1,j)*coord->g11(i+1,j)) * - (f(i+1,j,k) - f(i,j,k))/(coord->dx(i,j) + coord->dx(i+1,j)); + BoutReal fout = 0.5*(a(i,j,k) + a(i+1,j,k)) * (coord->J(i,j,k)*coord->g11(i,j,k) + coord->J(i+1,j,k)*coord->g11(i+1,j,k)) * + (f(i+1,j,k) - f(i,j,k))/(coord->dx(i,j,k) + coord->dx(i+1,j,k)); - result(i,j,k) += fout / (coord->dx(i,j)*coord->J(i,j)); - result(i+1,j,k) -= fout / (coord->dx(i+1,j)*coord->J(i+1,j)); + result(i,j,k) += fout / (coord->dx(i,j,k)*coord->J(i,j,k)); + result(i+1,j,k) -= fout / (coord->dx(i+1,j,k)*coord->J(i+1,j,k)); } } @@ -83,46 +82,46 @@ namespace FV { for (int i = mesh->xstart; i <= mesh->xend; i++) { for (int j = mesh->ystart; j <= mesh->yend; j++) { - - BoutReal coef = - 0.5 * (coord->g_23(i, j) / SQ(coord->J(i, j) * coord->Bxy(i, j)) + - coord->g_23(i, j + 1) / SQ(coord->J(i, j + 1) * coord->Bxy(i, j + 1))); - for (int k = 0; k < mesh->LocalNz; k++) { // Calculate flux between j and j+1 int kp = (k + 1) % mesh->LocalNz; int km = (k - 1 + mesh->LocalNz) % mesh->LocalNz; + BoutReal coef = + 0.5 * (coord->g_23(i, j, k) / SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)) + + coord->g_23(i, j + 1, k) / SQ(coord->J(i, j + 1, k) * coord->Bxy(i, j + 1, k))); + + // Calculate Z derivative at y boundary BoutReal dfdz = 0.25 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) / - coord->dz(i, j);// is this at right location? + coord->dz(i, j, k);// is this at right location? // Y derivative BoutReal dfdy = 2. * (fup(i, j + 1, k) - fc(i, j, k)) / - (coord->dy(i, j + 1) + coord->dy(i, j)); + (coord->dy(i, j + 1, k) + coord->dy(i, j, k)); BoutReal fout = 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) * - (coord->J(i, j) * coord->g23(i, j) + - coord->J(i, j + 1) * coord->g23(i, j + 1)) * - (dfdz - coef * dfdy); + (coord->J(i, j, k) * coord->g23(i, j, k) + + coord->J(i, j + 1, k) * coord->g23(i, j + 1, k)) * + (dfdz - coef * dfdy); - yzresult(i, j, k) = fout / (coord->dy(i, j) * coord->J(i, j)); + yzresult(i, j, k) = fout / (coord->dy(i, j, k) * coord->J(i, j, k)); // Calculate flux between j and j-1 dfdz = 0.25 * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) / - coord->dz(i,j);// is this at right location? + coord->dz(i,j,k);// is this at right location? dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) / - (coord->dy(i, j) + coord->dy(i, j - 1)); + (coord->dy(i, j, k) + coord->dy(i, j - 1, k)); fout = 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) * - (coord->J(i, j) * coord->g23(i, j) + - coord->J(i, j - 1) * coord->g23(i, j - 1)) * - (dfdz - coef * dfdy); + (coord->J(i, j, k) * coord->g23(i, j, k) + + coord->J(i, j - 1, k) * coord->g23(i, j - 1, k)) * + (dfdz - coef * dfdy); - yzresult(i, j, k) -= fout / (coord->dy(i, j) * coord->J(i, j)); + yzresult(i, j, k) -= fout / (coord->dy(i, j, k) * coord->J(i, j, k)); } } } @@ -132,27 +131,25 @@ namespace FV { for (int i = mesh->xstart; i <= mesh->xend; i++) { for (int j = mesh->ystart; j <= mesh->yend; j++) { - // Coefficient in front of df/dy term - BoutReal coef = coord->g_23(i, j) / (coord->dy(i, j + 1) + 2. * coord->dy(i, j) + - coord->dy(i, j - 1)) / - SQ(coord->J(i, j) * coord->Bxy(i, j)); - for (int k = 0; k < mesh->LocalNz; k++) { // Calculate flux between k and k+1 int kp = (k + 1) % mesh->LocalNz; - BoutReal fout = 0.5 * (ac(i, j, k) + ac(i, j, kp)) * coord->g33(i, j) * - ( - // df/dz - (fc(i, j, kp) - fc(i, j, k)) / coord->dz(i, j, k) - - // - g_yz * df/dy / SQ(J*B) - - - coef * (fup(i, j + 1, k) + fup(i, j + 1, kp) - - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); - + // Coefficient in front of df/dy term + BoutReal coef = coord->g_23(i, j, k) / (coord->dy(i, j + 1, k) + 2. * coord->dy(i, j, k) + + coord->dy(i, j - 1, k)) / + SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)); + + BoutReal fout = 0.5 * (ac(i, j, k) + ac(i, j, kp)) * coord->g33(i, j, k) * + ( // df/dz + (fc(i, j, kp) - fc(i, j, k)) / coord->dz(i, j, k) + // - g_yz * df/dy / SQ(J*B) + - + coef * (fup(i, j + 1, k) + fup(i, j + 1, kp) - + fdown(i, j - 1, k) - fdown(i, j - 1, kp))); + yzresult(i, j, k) += fout / coord->dz(i,j,k); - yzresult(i, j, kp) -= fout / coord->dz(i,j,k); + yzresult(i, j, kp) -= fout / coord->dz(i,j,kp); } } } @@ -164,9 +161,6 @@ namespace FV { } return result; -#else - throw BoutException("Not all FV:: ops currently support 3D metrics."); -#endif } const Field3D Div_par_K_Grad_par(const Field3D &Kin, const Field3D &fin, bool bndry_flux) { From 5d40a889e7570259f6e918ad0f2484d89e826daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 18 Mar 2020 19:19:24 +0000 Subject: [PATCH 105/293] Run 3D metric test with openmp enabled --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c24bdc6926..6d5e38a1be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,9 +81,10 @@ matrix: - *default_env - CONFIGURE_OPTIONS="--enable-openmp --with-petsc --with-slepc --with-sundials=$HOME/local" - OMP_NUM_THREADS=2 - - env: + - name: "3D Metric" + env: - *default_env - - CONFIGURE_OPTIONS="--enable-metric-3d --enable-shared" + - CONFIGURE_OPTIONS="--enable-metric-3d --enable-shared --enable-openmp" - SCRIPT_FLAGS="-uim -t python -t shared" #CMAKE - env: From 4ca152f2c59e7387dd68ad0ad9a2aff8e203791b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 19 Mar 2020 14:00:02 +0000 Subject: [PATCH 106/293] Fixes for dz being a Field --- include/bout/fv_ops.hxx | 8 ++++---- src/mesh/boundary_standard.cxx | 13 +++++++++---- src/mesh/coordinates.cxx | 2 -- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 73f5f0b9aa..fdac4f95b6 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -467,13 +467,13 @@ namespace FV { if (vU > 0.0) { BoutReal flux = vU * s.R; - result[i] += flux / (coord->J[i] * coord->dz); - result[i.zp()] -= flux / (coord->J[i.zp()] * coord->dz); + result[i] += flux / (coord->J[i] * coord->dz[i]); + result[i.zp()] -= flux / (coord->J[i.zp()] * coord->dz[i.zp()]); } if (vD < 0.0) { BoutReal flux = vD * s.L; - result[i] -= flux / (coord->J[i] * coord->dz); - result[i.zm()] += flux / (coord->J[i.zm()] * coord->dz); + result[i] -= flux / (coord->J[i] * coord->dz[i]); + result[i.zm()] += flux / (coord->J[i.zm()] * coord->dz[i.zm()]); } } diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 59e1395295..1ff8aea67b 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1639,7 +1639,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { + g13shift * dfdz(bndry->x - bndry->bx, bndry->y, z); if (bndry->bx != 0 && bndry->by == 0) { // x boundaries only - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y); + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, z); f(bndry->x, bndry->y, z) = f(bndry->x - bndry->bx, bndry->y, z) + delta / g11shift * (val - xshift); if (bndry->width == 2) { @@ -1942,7 +1942,7 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { for (; !bndry->isDone(); bndry->next1d()) { for (int zk = 0; zk < mesh->LocalNz; zk++) { if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dx(bndry->x - bndry->bx, bndry->y); + val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dx(bndry->x - bndry->bx, bndry->y, zk); } f(bndry->x - bndry->bx, bndry->y, zk) = @@ -1967,10 +1967,15 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { } if (bndry->by != 0) { for (; !bndry->isDone(); bndry->next1d()) { +#ifndef COORDINATES_USE_3D BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) + bndry->by * metric->dy(bndry->x, bndry->y); - +#endif for (int zk = 0; zk < mesh->LocalNz; zk++) { +#ifdef COORDINATES_USE_3D + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); +#endif if (fg) { val = fg->generate(Context(bndry, zk, loc, t, mesh)); } @@ -2019,7 +2024,7 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { for (; !bndry->isDone(); bndry->next1d()) { for (int zk = 0; zk < mesh->LocalNz; zk++) { if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dy(bndry->x, bndry->y - bndry->by); + val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dy(bndry->x, bndry->y - bndry->by, zk); } f(bndry->x, bndry->y - bndry->by, zk) = diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 4d188c6164..984a3b3a76 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -713,9 +713,7 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, : options["ZMAX"].withDefault(1.0); const auto default_dz = (zmax - zmin) * TWOPI / nz; - printf("getting dz staggered\n"); getAtLoc(mesh, dz, "dz", suffix, location, default_dz); - printf("dz staggered is %e\n",dz(0,0,0)); } setParallelTransform(options); From 9d38bf08e5928649946d096db79c72498f34fb8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 19 Mar 2020 14:01:02 +0000 Subject: [PATCH 107/293] Adjust field compat messages for fmt --- include/field.hxx | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/include/field.hxx b/include/field.hxx index 6dfdbbf5c6..4933def420 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -194,29 +194,29 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { #if CHECKLEVEL >= 1 #define ASSERT1_FIELDS_COMPATIBLE(field1, field2) \ if ((field1).getLocation() != (field2).getLocation()){ \ - throw BoutException("Error in %s:%d\nFields at different position:" \ - "`%s` at %s, `%s` at %s",__FILE__,__LINE__, \ - #field1, toString((field1).getLocation()).c_str(), \ - #field2, toString((field2).getLocation()).c_str()); \ + throw BoutException("Error in {:s}:{:d}\nFields at different position:" \ + "`{:s}` at {:s}, `{:s}` at {:s}",__FILE__,__LINE__, \ + #field1, toString((field1).getLocation()), \ + #field2, toString((field2).getLocation())); \ } \ if ((field1).getCoordinates() != (field2).getCoordinates()){ \ - throw BoutException("Error in %s:%d\nFields have different coordinates:" \ - "`%s` at %p, `%s` at %p",__FILE__,__LINE__, \ - #field1, (field1).getCoordinates(), \ - #field2, (field2).getCoordinates()); \ - } \ + throw BoutException("Error in {:s}:{:d}\nFields have different coordinates:" \ + "`{:s}` at {:p}, `{:s}` at {:p}",__FILE__,__LINE__, \ + #field1, (void*) (field1).getCoordinates(), \ + #field2, (void*) (field2).getCoordinates()); \ + } \ if ((field1).getMesh() != (field2).getMesh()){ \ - throw BoutException("Error in %s:%d\nFields are on different Meshes:" \ - "`%s` at %p, `%s` at %p",__FILE__,__LINE__, \ - #field1, (field1).getMesh(), \ - #field2, (field2).getMesh()); \ + throw BoutException("Error in {:s}:{:d}\nFields are on different Meshes:" \ + "`{:s}` at {:p}, `{:s}` at {:p}",__FILE__,__LINE__, \ + #field1, (void*) (field1).getMesh(), \ + #field2, (void*) (field2).getMesh()); \ } \ if (!areDirectionsCompatible((field1).getDirections(), \ (field2).getDirections())){ \ - throw BoutException("Error in %s:%d\nFields at different directions:" \ - "`%s` at %s, `%s` at %s",__FILE__,__LINE__, \ - #field1, toString((field1).getDirections()).c_str(), \ - #field2, toString((field2).getDirections()).c_str()); \ + throw BoutException("Error in {:s}:{:d}\nFields at different directions:" \ + "`{:s}` at {:s}, `{:s}` at {:s}",__FILE__,__LINE__, \ + #field1, toString((field1).getDirections()), \ + #field2, toString((field2).getDirections())); \ } #else From 1a4cd36f950d63acb582cffa69b001928f41bb87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 19 Mar 2020 14:07:20 +0000 Subject: [PATCH 108/293] Evolve something in test-communications Some solver throw errors otherwise --- tests/integrated/test-communications/test-communications.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integrated/test-communications/test-communications.cxx b/tests/integrated/test-communications/test-communications.cxx index a939f5143b..865aebe102 100644 --- a/tests/integrated/test-communications/test-communications.cxx +++ b/tests/integrated/test-communications/test-communications.cxx @@ -3,7 +3,7 @@ class TestCommunications : public PhysicsModel { public: int init(bool) { - SAVE_REPEAT(f); + SOLVE_FOR(f); f = -1.; // fill non-guard cells: @@ -86,7 +86,7 @@ class TestCommunications : public PhysicsModel { int rhs(BoutReal) { // communicate f to fill guard cells mesh->communicate(f); - + ddt(f)=0; return 0; } private: From d19ba267924c78b22dc6a00f5c94fad65a6945f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 19 Mar 2020 19:24:18 +0000 Subject: [PATCH 109/293] Conditionally show backtrace Read the environment variable BOUT_SHOW_BACKTRACE. If the variable is set, show the backtrace, otherwise just show the message. The allows to get the backtrace without having to attache gdb, or catch the exception. The default behaviour is not changed. --- include/boutexception.hxx | 5 ++++ manual/sphinx/user_docs/advanced_install.rst | 4 +++ tests/integrated/test-backtrace/.gitignore | 1 + .../integrated/test-backtrace/CMakeLists.txt | 4 +++ .../integrated/test-backtrace/boutexcept.cxx | 20 +++++++++++++ tests/integrated/test-backtrace/makefile | 6 ++++ tests/integrated/test-backtrace/runtest | 28 +++++++++++++++++++ 7 files changed, 68 insertions(+) create mode 100644 tests/integrated/test-backtrace/.gitignore create mode 100644 tests/integrated/test-backtrace/CMakeLists.txt create mode 100644 tests/integrated/test-backtrace/boutexcept.cxx create mode 100644 tests/integrated/test-backtrace/makefile create mode 100755 tests/integrated/test-backtrace/runtest diff --git a/include/boutexception.hxx b/include/boutexception.hxx index 99bd12f179..646a7c5f41 100644 --- a/include/boutexception.hxx +++ b/include/boutexception.hxx @@ -28,6 +28,11 @@ public: ~BoutException() override; const char* what() const noexcept override { + if (getenv("BOUT_SHOW_BACKTRACE") != nullptr) { + getBacktrace(); + return (backtrace_message + "\n" + message).c_str(); + } + return message.c_str(); } void DEPRECATED(Backtrace()) {}; diff --git a/manual/sphinx/user_docs/advanced_install.rst b/manual/sphinx/user_docs/advanced_install.rst index a3620cc9fa..6a588a651d 100644 --- a/manual/sphinx/user_docs/advanced_install.rst +++ b/manual/sphinx/user_docs/advanced_install.rst @@ -29,6 +29,10 @@ For (sometimes) more useful error messages, there is the ``--enable-track`` option. This keeps track of the names of variables and includes these in error messages. +To get a backtrace, you can set the environment variable +`BOUT_SHOW_BACKTRACE` in order for the exception to include the +backtrace. + To enable optimization, configure with ``--enable-optimize=3``. This will try to set appropriate flags, but may not set the best ones. This should work well for gcc. Similar to checks, different levels can diff --git a/tests/integrated/test-backtrace/.gitignore b/tests/integrated/test-backtrace/.gitignore new file mode 100644 index 0000000000..76a6c0b54f --- /dev/null +++ b/tests/integrated/test-backtrace/.gitignore @@ -0,0 +1 @@ +boutexcept diff --git a/tests/integrated/test-backtrace/CMakeLists.txt b/tests/integrated/test-backtrace/CMakeLists.txt new file mode 100644 index 0000000000..e9ed2edf16 --- /dev/null +++ b/tests/integrated/test-backtrace/CMakeLists.txt @@ -0,0 +1,4 @@ +bout_add_integrated_test(test-backtrace + SOURCES boutexcept.cxx + USE_RUNTEST + ) diff --git a/tests/integrated/test-backtrace/boutexcept.cxx b/tests/integrated/test-backtrace/boutexcept.cxx new file mode 100644 index 0000000000..23e6339117 --- /dev/null +++ b/tests/integrated/test-backtrace/boutexcept.cxx @@ -0,0 +1,20 @@ +#include "boutexception.hxx" +#include "msg_stack.hxx" + +void troublemaker() { + AUTO_TRACE(); + throw BoutException("test"); +} +void f() { + AUTO_TRACE(); + troublemaker(); +} +void e() { + AUTO_TRACE(); + f(); +} + +int main() { + e(); + return 0; +} diff --git a/tests/integrated/test-backtrace/makefile b/tests/integrated/test-backtrace/makefile new file mode 100644 index 0000000000..58ab427bc3 --- /dev/null +++ b/tests/integrated/test-backtrace/makefile @@ -0,0 +1,6 @@ + +BOUT_TOP = ../../.. + +SOURCEC = boutexcept.cxx + +include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-backtrace/runtest b/tests/integrated/test-backtrace/runtest new file mode 100755 index 0000000000..16447b989c --- /dev/null +++ b/tests/integrated/test-backtrace/runtest @@ -0,0 +1,28 @@ +#!/bin/bash +set -ex + +#requires all_tests + +e=1 +make || e=$? +test $e = 1 + +unset BOUT_SHOW_BACKTRACE + +if ./boutexcept 2>&1 | grep troublemaker +then + echo "Did not expect the offending function name in output" + exit 2 +fi + +export BOUT_SHOW_BACKTRACE=yes + +if ./boutexcept 2>&1 | grep troublemaker +then + : +else + echo "Did expect the offending function name in output" + exit 2 +fi + +exit 0 From 0a5a6d697379598642bc0a68ce4d4f90cc388eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 20 Mar 2020 04:56:14 +0000 Subject: [PATCH 110/293] Don't use old-style-cast --- include/field.hxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/field.hxx b/include/field.hxx index 4933def420..6aebc004d1 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -202,14 +202,14 @@ inline bool areFieldsCompatible(const Field& field1, const Field& field2) { if ((field1).getCoordinates() != (field2).getCoordinates()){ \ throw BoutException("Error in {:s}:{:d}\nFields have different coordinates:" \ "`{:s}` at {:p}, `{:s}` at {:p}",__FILE__,__LINE__, \ - #field1, (void*) (field1).getCoordinates(), \ - #field2, (void*) (field2).getCoordinates()); \ + #field1, static_cast((field1).getCoordinates()), \ + #field2, static_cast((field2).getCoordinates())); \ } \ if ((field1).getMesh() != (field2).getMesh()){ \ throw BoutException("Error in {:s}:{:d}\nFields are on different Meshes:" \ "`{:s}` at {:p}, `{:s}` at {:p}",__FILE__,__LINE__, \ - #field1, (void*) (field1).getMesh(), \ - #field2, (void*) (field2).getMesh()); \ + #field1, static_cast((field1).getMesh()), \ + #field2, static_cast((field2).getMesh())); \ } \ if (!areDirectionsCompatible((field1).getDirections(), \ (field2).getDirections())){ \ From 42c525d96fd58a45886196ba865634b545f4ee94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 20 Mar 2020 04:57:48 +0000 Subject: [PATCH 111/293] Don't use old-style-cast in boutexception --- src/sys/boutexception.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sys/boutexception.cxx b/src/sys/boutexception.cxx index 84dbb7d813..bcd71d4172 100644 --- a/src/sys/boutexception.cxx +++ b/src/sys/boutexception.cxx @@ -51,8 +51,8 @@ std::string BoutException::getBacktrace() const { void * ptr=trace[i]; if (dladdr(trace[i],&info)){ // Additionally, check whether this is the default offset for an executable - if (info.dli_fbase != (void*)0x400000) - ptr=(void*) ((size_t)trace[i]-(size_t)info.dli_fbase); + if (info.dli_fbase != reinterpret_cast(0x400000)) + ptr=reinterpret_cast(reinterpret_cast(trace[i])-reinterpret_cast(info.dli_fbase)); } // Pipe stderr to /dev/null to avoid cluttering output From a7705fed2ffedb866991bbe0c50f358fb94962c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 22 Mar 2020 21:11:46 +0000 Subject: [PATCH 112/293] Better error if field is not positive --- include/field.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/field.hxx b/include/field.hxx index 6aebc004d1..d0a545d4e5 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -297,7 +297,7 @@ inline void checkPositive(const T& f, const std::string& name="field", const std BOUT_FOR_SERIAL(i, f.getRegion(rgn)) { if (f[i] <= 0.) { - throw BoutException("{:s} is not positive at {:s}", name, toString(i)); + throw BoutException("{:s} ({:s} {:s}) is {:e} (not positive) at {:s}", name, toString(f.getLocation()), toString(f.getDirections()), f[i], toString(i)); } } } From 9060707d1e33310281755ff4e2c9e261091f73b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 22 Mar 2020 21:13:03 +0000 Subject: [PATCH 113/293] reduce code duplications in test-communications --- tests/integrated/test-communications/runtest | 59 ++++++++------------ 1 file changed, 22 insertions(+), 37 deletions(-) diff --git a/tests/integrated/test-communications/runtest b/tests/integrated/test-communications/runtest index 439fb5f9a7..47ba218352 100755 --- a/tests/integrated/test-communications/runtest +++ b/tests/integrated/test-communications/runtest @@ -33,12 +33,17 @@ s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) with open('run.log.'+str(nxpe), 'w') as f: f.write(out) +def realtest(faillist,actual, expected, procnum, region, boundary): + if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): + msg=('failed in '+boundary+' boundary of region '+str(procnum) + +' ('+region+'). Expected: '+str(expected)+' Actual: ' + +str(actual)) + faillist.append(msg) + print(msg) + failures18 = [] def test(actual, expected, procnum, region, boundary): - if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - failures18.append('failed in '+boundary+' boundary of region '+str(procnum) - +' ('+region+'). Expected: '+str(expected)+' Actual: ' - +str(actual)) + realtest(failures18, actual, expected, procnum, region, boundary) region = 'lower, inner PF' f = DataFile("data/BOUT.dmp.0.nc")['f'][0, :, :, 0] @@ -184,10 +189,8 @@ with open('run.log.'+str(nxpe), 'w') as f: failures12 = [] def test(actual, expected, procnum, region, boundary): - if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - failures12.append('failed in '+boundary+' boundary of region '+str(procnum) - +' ('+region+'). Expected: '+str(expected)+' Actual: ' - +str(actual)) + realtest(failures12, actual, expected, procnum, region, boundary) + region = 'lower, inner leg, interior' f = DataFile("data/BOUT.dmp.0.nc")['f'][0, :, :, 0] @@ -290,10 +293,7 @@ with open('run.log.'+str(nxpe), 'w') as f: failures6 = [] def test(actual, expected, procnum, region, boundary): - if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - failures6.append('failed in '+boundary+' boundary of region '+str(procnum) - +' ('+region+'). Expected: '+str(expected)+' Actual: ' - +str(actual)) + realtest(failures6, actual, expected, procnum, region, boundary) region = 'lower, inner leg' f = DataFile("data/BOUT.dmp.0.nc")['f'][0, :, :, 0] @@ -361,10 +361,7 @@ with open('run_limiter.log.'+str(nxpe), 'w') as f: failures3 = [] def test(actual, expected, procnum, region, boundary): - if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - failures3.append('failed in '+boundary+' boundary of region '+str(procnum) - +' ('+region+'). Expected: '+str(expected)+' Actual: ' - +str(actual)) + realtest(failures3, actual, expected, procnum, region, boundary) region = 'core' f = DataFile("data_limiter/BOUT.dmp.0.nc")['f'][0, :, :, 0] @@ -404,10 +401,7 @@ with open('run_limiter.log.'+str(nxpe), 'w') as f: failures2 = [] def test(actual, expected, procnum, region, boundary): - if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - failures2.append('failed in '+boundary+' boundary of region '+str(procnum) - +' ('+region+'). Expected: '+str(expected)+' Actual: ' - +str(actual)) + realtest(failures2, actual, expected, procnum, region, boundary) region = 'interior' f = DataFile("data_limiter/BOUT.dmp.0.nc")['f'][0, :, :, 0] @@ -440,10 +434,7 @@ with open('run_limiter.log.'+str(nxpe), 'w') as f: failures1 = [] def test(actual, expected, procnum, region, boundary): - if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - failures1.append('failed in '+boundary+' boundary of region '+str(procnum) - +' ('+region+'). Expected: '+str(expected)+' Actual: ' - +str(actual)) + realtest(failures1, actual, expected, procnum, region, boundary) region = 'all' f = DataFile("data_limiter/BOUT.dmp.0.nc")['f'][0, :, :, 0] @@ -453,20 +444,14 @@ test(f[:, 0], [13, 1, 3, 19, 20, 21, 22, 23], 0, region, 'lower y') test(f[:, -1], [12, 0, 2, 27, 28, 29, 30, 31], 0, region, 'upper y') -if failures18 == [] and failures12 == [] and failures6 == [] and failures3 == [] and failures2 == [] and failures1 == []: +allfail=[failures18, failures12, failures6, failures3, failures2, failures1] +success=True +for fail in allfail: + for f in fail: + print(f) + success=False +if success: print('Pass') exit(0) else: - for f in failures18: - print(f) - for f in failures12: - print(f) - for f in failures6: - print(f) - for f in failures3: - print(f) - for f in failures2: - print(f) - for f in failures1: - print(f) exit(1) From 4b7611c84cffeaaed5310f9ebf9fcecb6cbe22fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 31 Mar 2020 13:36:29 +0100 Subject: [PATCH 114/293] Ensure we communicate in both directions --- src/mesh/coordinates.cxx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index e60ad22d29..9fea10cc49 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -41,7 +41,10 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); - localmesh->communicateXZ(result); + auto h = localmesh->sendY(result); + localmesh->wait(h); + h = localmesh->sendX(result); + localmesh->wait(h); // Extrapolate into boundaries (if requested) so that differential geometry // terms can be interpolated if necessary @@ -189,7 +192,10 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); - localmesh->communicateXZ(result); + auto h = localmesh->sendY(result); + localmesh->wait(h); + h = localmesh->sendX(result); + localmesh->wait(h); // Extrapolate into boundaries (if requested) so that differential geometry // terms can be interpolated if necessary @@ -349,7 +355,11 @@ std::string getLocationSuffix(CELL_LOC location) { template void communicate(T & t, Ts&... ts) { FieldGroup g(t,ts...); - t.getMesh()->communicateXZ(g); + // emulate full communicate + auto h = t.getMesh()->sendY(g); + t.getMesh()->wait(h); + h = t.getMesh()->sendX(g); + t.getMesh()->wait(h); } From 2d5247766116945f695e36c5f450ed24323e4b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 31 Mar 2020 13:36:42 +0100 Subject: [PATCH 115/293] Fix test-griddata for 3d metrics --- tests/integrated/test-griddata/screw/BOUT.inp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integrated/test-griddata/screw/BOUT.inp b/tests/integrated/test-griddata/screw/BOUT.inp index 2c098d943b..b4a1a04b72 100644 --- a/tests/integrated/test-griddata/screw/BOUT.inp +++ b/tests/integrated/test-griddata/screw/BOUT.inp @@ -28,3 +28,7 @@ zShift = Btxy * y * L / (2*pi*Rxy * Bpxy) # Define a twist-shift angle, for periodic in y runs ShiftAngle = Btxy * L / (Rxy * Bpxy) # Should be just a function of x + +# With 3D metrics, we can only calcParallelSlice after the coordinates is created. +# Because we use a custom main, we musn't do this. +calcParallelSlices_on_communicate = false From ba651d81aeccc0d44401646505ae5b88d272f085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 16:09:25 +0100 Subject: [PATCH 116/293] Fix boundary_standard for 2d metrics --- src/mesh/boundary_standard.cxx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 1ff8aea67b..0825f832f8 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1618,6 +1618,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { for (bndry->first(); !bndry->isDone(); bndry->next1d()) { #ifdef COORDINATES_USE_3D for (int z = 0; z < mesh->LocalNz; z++) { +#else + int z=0; #endif // Interpolate (linearly) metrics to halfway between last cell and boundary cell BoutReal g11shift = @@ -1634,6 +1636,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { // NOTE: should be fixed to interpolate to boundary line #ifndef COORDINATES_USE_3D for (int z = 0; z < mesh->LocalNz; z++) { +#else + int z=0; #endif BoutReal xshift = g12shift * dfdy(bndry->x - bndry->bx, bndry->y, z) + g13shift * dfdz(bndry->x - bndry->bx, bndry->y, z); @@ -2051,6 +2055,7 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { // x boundaries. for (; !bndry->isDone(); bndry->next1d()) { #ifndef COORDINATES_USE_3D + int zk=0; BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + bndry->by * metric->dy(bndry->x, bndry->y, zk); #endif @@ -2348,7 +2353,8 @@ BoundaryOp* BoundaryNeumannPar::clone(BoundaryRegion* region, } void BoundaryNeumannPar::apply(Field2D& f) { -#ifndef COORDINATES_USE_3D Coordinates* metric = f.getCoordinates(); +#ifndef COORDINATES_USE_3D + Coordinates* metric = f.getCoordinates(); // Loop over all elements and set equal to the next point in for (bndry->first(); !bndry->isDone(); bndry->next()) f(bndry->x, bndry->y) = @@ -2763,7 +2769,8 @@ void BoundaryConstLaplace::apply(Field3D& f) { BoutReal coef = -1.0 * sqrt(metric->g33(x - bx, y) / metric->g11(x - bx, y)) * metric->dx(x - bx, y); for (int jz = 1; jz <= ncz / 2; jz++) { - BoutReal kwave = jz * 2.0 * PI / metric->zlength(); // wavenumber in [rad^-1] +#warning TODO: fix + BoutReal kwave = jz * 2.0 * PI / metric->zlength()(0,0); // wavenumber in [rad^-1] c0[jz] *= exp(coef * kwave); // The decaying solution only // Add the particular solution c2[jz] = c0[jz] - c1[jz] / (metric->g33(x - bx, y) * kwave * kwave); @@ -2838,7 +2845,7 @@ void BoundaryDivCurl::apply(Vector3D& var) { // dB_z / dx = dB_x / dz - tmp = (var.x(jx - 1, jy, jzp) - var.x(jx - 1, jy, jzm)) / (2. * metric->dz); + tmp = (var.x(jx - 1, jy, jzp) - var.x(jx - 1, jy, jzm)) / (2. * metric->dz(jx - 1, jy)); var.z(jx, jy, jz) = var.z(jx - 2, jy, jz) + (metric->dx(jx - 2, jy) + metric->dx(jx - 1, jy)) * tmp; @@ -2873,7 +2880,7 @@ void BoundaryDivCurl::apply(Vector3D& var) { * (var.y(jx - 1, jy, jzp) - var.y(jx - 1, jy, jzm)) + metric->J(jx - 1, jy) * metric->g33(jx - 1, jy) * (var.z(jx - 1, jy, jzp) - var.z(jx - 1, jy, jzm))) - / (2. * metric->dz); + / (2. * metric->dz(jx - 1, jy)); var.x(jx, jy, jz) = (metric->J(jx - 2, jy) * metric->g11(jx - 2, jy) * var.x(jx - 2, jy, jz) From 7cef1c549541c0bbc81f1d19d247d856cbdb0c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 16:09:52 +0100 Subject: [PATCH 117/293] Drop pre python2.4 stuff --- tools/pylib/boututils/run_wrapper.py | 43 +++++++++------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/tools/pylib/boututils/run_wrapper.py b/tools/pylib/boututils/run_wrapper.py index fc59a01aaa..cf128f8adb 100644 --- a/tools/pylib/boututils/run_wrapper.py +++ b/tools/pylib/boututils/run_wrapper.py @@ -5,16 +5,8 @@ import pathlib import re import subprocess +from subprocess import call, Popen, STDOUT, PIPE -try: - # Python 2.4 onwards - from subprocess import call, Popen, STDOUT, PIPE - lib = "call" -except ImportError: - # FIXME: drop support for python < 2.4! - # Use os.system (depreciated) - from os import popen4, system - lib = "system" if os.name == "nt": # Default on Windows @@ -60,27 +52,20 @@ def shell(command, pipe=False): """ output = None status = 0 - if lib == "system": - if pipe: - handle = popen4(command) - output = handle[1].read() - else: - status = system(command) + if pipe: + child = Popen(command, stderr=STDOUT, stdout=PIPE, shell=True) + # This returns a b'string' which is casted to string in + # python 2. However, as we want to use f.write() in our + # runtest, we cast this to utf-8 here + output = child.stdout.read().decode("utf-8", "ignore") + # Wait for the process to finish. Note that child.wait() + # would have deadlocked the system as stdout is PIPEd, we + # therefore use communicate, which in the end also waits for + # the process to finish + child.communicate() + status = child.returncode else: - if pipe: - child = Popen(command, stderr=STDOUT, stdout=PIPE, shell=True) - # This returns a b'string' which is casted to string in - # python 2. However, as we want to use f.write() in our - # runtest, we cast this to utf-8 here - output = child.stdout.read().decode("utf-8", "ignore") - # Wait for the process to finish. Note that child.wait() - # would have deadlocked the system as stdout is PIPEd, we - # therefore use communicate, which in the end also waits for - # the process to finish - child.communicate() - status = child.returncode - else: - status = call(command, shell=True) + status = call(command, shell=True) return status, output From f672148f574553c4aa609917887b85efd159cae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 16:10:20 +0100 Subject: [PATCH 118/293] Improve CPU detection in run_wrapper We only want to know about the ones we can use --- tools/pylib/boututils/run_wrapper.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/pylib/boututils/run_wrapper.py b/tools/pylib/boututils/run_wrapper.py index cf128f8adb..9a91d2c0a7 100644 --- a/tools/pylib/boututils/run_wrapper.py +++ b/tools/pylib/boututils/run_wrapper.py @@ -77,7 +77,7 @@ def determineNumberOfCPUs(): scaling userspace-only program Taken from a post on stackoverflow: - http://stackoverflow.com/questions/1006289/how-to-find-out-the-number-of-cpus-in-python + https://stackoverflow.com/questions/1006289/how-to-find-out-the-number-of-cpus-in-python Returns ------- @@ -85,6 +85,18 @@ def determineNumberOfCPUs(): The number of CPUs """ + # cpuset + # cpuset may restrict the number of *available* processors + try: + m = re.search(r'(?m)^Cpus_allowed:\s*(.*)$', + open('/proc/self/status').read()) + if m: + res = bin(int(m.group(1).replace(',', ''), 16)).count('1') + if res > 0: + return res + except IOError: + pass + # Python 2.6+ try: import multiprocessing From cce01c60a65e4924dd3e84f24fd9c228ba8a9010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 22:08:58 +0100 Subject: [PATCH 119/293] Update petsc3damg for 3d metrics --- src/invert/laplace/impls/petsc3damg/petsc3damg.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx b/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx index 3b767b063b..6b94d5ff83 100644 --- a/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx +++ b/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx @@ -271,7 +271,7 @@ void LaplacePetsc3dAmg::updateMatrix3D() { const Field3D dc_dx = issetC ? DDX(C2) : Field3D(); const Field3D dc_dy = issetC ? DDY(C2) : Field3D(); const Field3D dc_dz = issetC ? DDZ(C2) : Field3D(); - const Field2D dJ_dy = DDY(coords->J/coords->g_22); + const auto dJ_dy = DDY(coords->J/coords->g_22); // Set up the matrix for the internal points on the grid. // Boundary conditions were set in the constructor. @@ -315,13 +315,13 @@ void LaplacePetsc3dAmg::updateMatrix3D() { C_df_dx += C_d2f_dx2 * coords->d1_dx[l]; } C_df_dx /= 2 * coords->dx[l]; - C_df_dz /= 2 * coords->dz; + C_df_dz /= 2 * coords->dz[l]; C_d2f_dx2 /= SQ(coords->dx[l]); C_d2f_dy2 /= SQ(coords->dy[l]); - C_d2f_dz2 /= SQ(coords->dz); + C_d2f_dz2 /= SQ(coords->dz[l]); - C_d2f_dxdz /= 4 * coords->dx[l] * coords->dz; + C_d2f_dxdz /= 4 * coords->dx[l] * coords->dz[l]; operator3D(l, l) = -2 * (C_d2f_dx2 + C_d2f_dy2 + C_d2f_dz2) + A[l]; operator3D(l, l.xp()) = C_df_dx + C_d2f_dx2; @@ -383,7 +383,7 @@ void LaplacePetsc3dAmg::updateMatrix3D() { C_d2f_dxdy /= 4*coords->dx[l]; // NOTE: This value is not completed here. It needs to // be divide by dx(i +/- 1, j, k) when using to set a // matrix element - C_d2f_dydz /= 4*coords->dy[l]*coords->dz; + C_d2f_dydz /= 4*coords->dy[l]*coords->dz[l]; // The values stored in the y-boundary are already interpolated // up/down, so we don't want the matrix to do any such From 051765677d0697faac831c5b0585c3b601710702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 22:09:31 +0100 Subject: [PATCH 120/293] fix boundary standard for 3d metrics --- src/mesh/boundary_standard.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 0825f832f8..e5b7da9eb5 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1636,8 +1636,6 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { // NOTE: should be fixed to interpolate to boundary line #ifndef COORDINATES_USE_3D for (int z = 0; z < mesh->LocalNz; z++) { -#else - int z=0; #endif BoutReal xshift = g12shift * dfdy(bndry->x - bndry->bx, bndry->y, z) + g13shift * dfdz(bndry->x - bndry->bx, bndry->y, z); From dd70e8d2d96719ca65eed221182b9e521c9383dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 22:10:25 +0100 Subject: [PATCH 121/293] never communicate in coordinates constructor via get this requires the coorinate already to exist --- src/mesh/coordinates.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 9fea10cc49..94626a8e31 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -544,7 +544,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // Attempt to read J from the grid file auto Jcalc = J; - if (mesh->get(J, "J")) { + if (mesh->get(J, "J", 0.0, false)) { output_warn.write( "\tWARNING: Jacobian 'J' not found. Calculating from metric tensor\n"); J = Jcalc; @@ -569,7 +569,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // Attempt to read Bxy from the grid file auto Bcalc = Bxy; - if (mesh->get(Bxy, "Bxy")) { + if (mesh->get(Bxy, "Bxy", 0.0, false)) { output_warn.write("\tWARNING: Magnitude of B field 'Bxy' not found. Calculating from " "metric tensor\n"); Bxy = Bcalc; From 38ec67a7229fb90fe8de62569820585bb63ec7e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 2 Apr 2020 22:47:03 +0100 Subject: [PATCH 122/293] fix test-laplacexz --- tests/integrated/test-laplacexz/runtest | 1 + tests/integrated/test-laplacexz/test-laplacexz.cxx | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index 4657ef4800..600374f3c0 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +#requires: not metric_3d #requires: petsc # travis doesn't have superlu_dist #requires: not travis diff --git a/tests/integrated/test-laplacexz/test-laplacexz.cxx b/tests/integrated/test-laplacexz/test-laplacexz.cxx index ce32fa5f6f..42c126d339 100644 --- a/tests/integrated/test-laplacexz/test-laplacexz.cxx +++ b/tests/integrated/test-laplacexz/test-laplacexz.cxx @@ -19,6 +19,7 @@ int main(int argc, char** argv) { auto inv = LaplaceXZ::create(mesh); + auto coord = bout::globals::mesh->getCoordinates(); coord->g13 = 1.8; //test off-diagonal components with nonzero value // create some input field From e5d3e600f5255fde9e47329fe1784ea13c1a4341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 3 Apr 2020 22:44:07 +0100 Subject: [PATCH 123/293] Don't use laplacexy with 3d metrics --- src/invert/laplacexy/laplacexy.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index d862688c63..e021e695fb 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -1,5 +1,5 @@ -#ifdef BOUT_HAS_PETSC +#if defined(BOUT_HAS_PETSC) and not defined(COORDINATES_USE_3D) #include From f39ff36e7031529546883bbd0d1d06a3110b987c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 3 Apr 2020 22:46:10 +0100 Subject: [PATCH 124/293] Potential fix for laplacexz --- include/bout/invert/laplacexz.hxx | 1 + 1 file changed, 1 insertion(+) diff --git a/include/bout/invert/laplacexz.hxx b/include/bout/invert/laplacexz.hxx index 5550a6339b..cf8745c385 100644 --- a/include/bout/invert/laplacexz.hxx +++ b/include/bout/invert/laplacexz.hxx @@ -51,6 +51,7 @@ public: ReturnType create(Mesh* mesh = nullptr, Options* options = nullptr, CELL_LOC loc = CELL_CENTRE) { + options = options == nullptr ? Options::getRoot()->getSection(section_name) : options; return Factory::create(getType(options), mesh, options, loc); } From b69c06f43381f1d3b8d1201cbcae1fc74e3cad3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 4 Apr 2020 00:13:55 +0100 Subject: [PATCH 125/293] prefer getConst() rather then ASSERT(isConst()) --- include/field.hxx | 22 +++++++++++++++++++ include/field3d.hxx | 2 -- src/field/fieldgenerators.cxx | 6 ++--- .../laplace/impls/cyclic/cyclic_laplace.cxx | 11 +++++----- src/invert/laplace/impls/pdd/pdd.cxx | 3 +-- .../laplace/impls/serial_tri/serial_tri.cxx | 3 +-- .../laplace/impls/shoot/shoot_laplace.cxx | 4 ++-- src/invert/laplace/impls/spt/spt.cxx | 3 +-- .../impls/cyclic/laplacexz-cyclic.cxx | 4 ++-- src/invert/parderiv/impls/cyclic/cyclic.cxx | 8 +++---- src/mesh/coordinates.cxx | 3 +-- src/mesh/data/gridfromfile.cxx | 6 ++--- 12 files changed, 45 insertions(+), 30 deletions(-) diff --git a/include/field.hxx b/include/field.hxx index d0a545d4e5..a88961b275 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -377,6 +377,28 @@ inline bool isConst(const T& f, bool allpe = false, const std::string& region = return result; } +template> +inline BoutReal getConst(const T& f, bool allpe = false, const std::string& region = "RGN_ALL") { + bool is_const = true; + auto element = f[*f.getRegion(region).begin()]; +#if CHECK > 1 + BOUT_FOR_SERIAL(i, f.getRegion(region)){ + if (f[i] != element){ + is_const = false; + break; + } + } + if(allpe) { + bool local_is_const = is_const; + MPI_Allreduce(&local_is_const, &is_const, 1, MPI_C_BOOL, MPI_LOR, BoutComm::get()); + } + if (! is_const) { + throw BoutException("Requested getConst but Field is not const"); + } +#endif + return element; +} + template> inline BoutReal max(const T& f, bool allpe = false, const std::string& rgn = "RGN_NOBNDRY") { AUTO_TRACE(); diff --git a/include/field3d.hxx b/include/field3d.hxx index 5d3c370b02..7bc218bef1 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -462,8 +462,6 @@ class Field3D : public Field, public FieldData { int byteSize() const override { return sizeof(BoutReal); } // Just one BoutReal int BoutRealSize() const override { return 1; } - bool isConst(const std::string& region) const; - /// Visitor pattern support void accept(FieldVisitor &v) override { v.accept(*this); } diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 2ab9dff51b..79e8fd3eb9 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -81,7 +81,7 @@ BoutReal FieldBallooning::generate(const Context& ctx) { / (localmesh->xend - localmesh->xstart); int jx = ROUND((ctx.x() - localmesh->GlobalX(0)) / dx); - ASSERT1(isConst(coords->zlength())); + const BoutReal zlength = getConst(coords->zlength()); if (localmesh->periodicY(jx, ts)) { // Start with the value at this point @@ -91,11 +91,11 @@ BoutReal FieldBallooning::generate(const Context& ctx) { // y - i * 2pi value += arg->generate(Context(ctx).set( "y", ctx.y() - i * TWOPI, - "z", ctx.z() + i * ts * TWOPI / coords->zlength()(0,0))); + "z", ctx.z() + i * ts * TWOPI / zlength; value += arg->generate(Context(ctx).set( "y", ctx.y() + i * TWOPI, - "z", ctx.z() - i * ts * TWOPI / coords->zlength()(0,0))); + "z", ctx.z() - i * ts * TWOPI / zlength; } return value; } diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index 5c4b0f259e..20714346f7 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -118,7 +118,6 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { outbndry = 1; if(dst) { - ASSERT1(isConst(coords->dz)); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = @@ -146,9 +145,9 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { // Get elements of the tridiagonal matrix // including boundary conditions + BoutReal zlen = getConst(coords->dz) * (localmesh->LocalNz - 3); BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { - BoutReal zlen = coords->dz(0,0,0) * (localmesh->LocalNz - 3); BoutReal kwave = kz * 2.0 * PI / (2. * zlen); // wave number is 1/[rad]; DST has extra 2. @@ -214,9 +213,10 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { // Get elements of the tridiagonal matrix // including boundary conditions + const BoutReal zlength = getConst(coords->zlength()); BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { - BoutReal kwave = kz * 2.0 * PI / (coords->zlength()(0,0)); // wave number is 1/[rad] + BoutReal kwave = kz * 2.0 * PI / zlength; // wave number is 1/[rad] tridagMatrix(&a(kz, 0), &b(kz, 0), &c(kz, 0), &bcmplx(kz, 0), jy, kz, // True for the component constant (DC) in Z kwave, // Z wave number @@ -344,13 +344,13 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { // Get elements of the tridiagonal matrix // including boundary conditions + const BoutReal zlen = getConst(coords->dz) * (localmesh->LocalNz - 3); BOUT_OMP(for nowait) for (int ind = 0; ind < nsys; ind++) { // ind = (iy - ys) * nmode + kz int iy = ys + ind / nmode; int kz = ind % nmode; - BoutReal zlen = coords->dz(0,0,0) * (localmesh->LocalNz - 3); BoutReal kwave = kz * 2.0 * PI / (2. * zlen); // wave number is 1/[rad]; DST has extra 2. @@ -425,13 +425,14 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { // Get elements of the tridiagonal matrix // including boundary conditions + const BoutReal zlength = getConst(coords->zlength()); BOUT_OMP(for nowait) for (int ind = 0; ind < nsys; ind++) { // ind = (iy - ys) * nmode + kz int iy = ys + ind / nmode; int kz = ind % nmode; - BoutReal kwave = kz * 2.0 * PI / (coords->zlength()(0,0)); // wave number is 1/[rad] + BoutReal kwave = kz * 2.0 * PI / zlength; // wave number is 1/[rad] tridagMatrix(&a3D(ind, 0), &b3D(ind, 0), &c3D(ind, 0), &bcmplx3D(ind, 0), iy, kz, // True for the component constant (DC) in Z kwave, // Z wave number diff --git a/src/invert/laplace/impls/pdd/pdd.cxx b/src/invert/laplace/impls/pdd/pdd.cxx index 3796fde6e1..2bf1986c04 100644 --- a/src/invert/laplace/impls/pdd/pdd.cxx +++ b/src/invert/laplace/impls/pdd/pdd.cxx @@ -165,8 +165,7 @@ void LaplacePDD::start(const FieldPerp &b, PDD_data &data) { /// Create the matrices to be inverted (one for each z point) - ASSERT1(isConst(coords->zlength())); - BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); + BoutReal kwaveFactor = 2.0 * PI / getConst(coords->zlength()); /// Set matrix elements for (int kz = 0; kz <= maxmode; kz++) { diff --git a/src/invert/laplace/impls/serial_tri/serial_tri.cxx b/src/invert/laplace/impls/serial_tri/serial_tri.cxx index 91ea480d4b..0f77154290 100644 --- a/src/invert/laplace/impls/serial_tri/serial_tri.cxx +++ b/src/invert/laplace/impls/serial_tri/serial_tri.cxx @@ -83,8 +83,7 @@ FieldPerp LaplaceSerialTri::solve(const FieldPerp& b, const FieldPerp& x0) { int ncz = localmesh->LocalNz; // No of z pnts int ncx = localmesh->LocalNx; // No of x pnts - ASSERT1(isConst(coords->zlength())); - BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); + BoutReal kwaveFactor = 2.0 * PI / getConst(coords->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 c985c47a3e..f59429f105 100644 --- a/src/invert/laplace/impls/shoot/shoot_laplace.cxx +++ b/src/invert/laplace/impls/shoot/shoot_laplace.cxx @@ -129,12 +129,12 @@ FieldPerp LaplaceShoot::solve(const FieldPerp& rhs) { // kc and kp now set to result at x and x+1 respectively // Use b at x to get km at x-1 // Loop inwards from edge - ASSERT1(isConst(coords->zlength())); + const BoutReal zlength = getConst(coords->zlength()); for(int ix=xe; ix >= xs; ix--) { rfft(rhs[ix], localmesh->LocalNz, std::begin(rhsk)); for(int kz=0; kzzlength()(0,0)); // wave number is 1/[rad] + BoutReal kwave=kz*2.0*PI/zlength; // wave number is 1/[rad] // Get the coefficients dcomplex a,b,c; diff --git a/src/invert/laplace/impls/spt/spt.cxx b/src/invert/laplace/impls/spt/spt.cxx index ea237961c3..193ab1c525 100644 --- a/src/invert/laplace/impls/spt/spt.cxx +++ b/src/invert/laplace/impls/spt/spt.cxx @@ -291,8 +291,7 @@ int LaplaceSPT::start(const FieldPerp &b, SPT_data &data) { data.bk(kz, ix) = dc1d[kz]; } - ASSERT1(isConst(coords->zlength())); - BoutReal kwaveFactor = 2.0 * PI / coords->zlength()(0,0); + BoutReal kwaveFactor = 2.0 * PI / getConst(coords->zlength()); /// Set matrix elements for (int kz = 0; kz <= maxmode; kz++) { diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index c3bd8153f5..01497bc41b 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -76,10 +76,10 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { ASSERT2(max(abs(coord->g13)) < 1e-5); int ind = 0; - ASSERT1(isConst(coord->zlength())); + const BoutReal zlength = getConst(coord->zlength()); for(int y=localmesh->ystart; y <= localmesh->yend; y++) { for(int kz = 0; kz < nmode; kz++) { - BoutReal kwave=kz*2.0*PI/(coord->zlength()(0,0)); + BoutReal kwave = kz * 2.0 * PI / zlength; if(localmesh->firstX()) { // Inner X boundary diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 32690414ff..6d90d5ed84 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -96,7 +96,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { auto b = Matrix(nsys, size); auto c = Matrix(nsys, size); - ASSERT1(isConst(coord->zlength())); + auto zlength = getConst(coord->zlength()); // Loop over flux-surfaces for (surf.first(); !surf.isDone(); surf.next()) { int x = surf.xpos; @@ -127,7 +127,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { // Set up tridiagonal system for(int k=0; kzlength()(0,0); // wave number is 1/[rad] + BoutReal kwave=k*2.0*PI/zlength; // wave number is 1/[rad] for (int y = 0; y < localmesh->LocalNy - 2 * localmesh->ystart; y++) { BoutReal acoef = A(x, y + localmesh->ystart); // Constant @@ -159,14 +159,14 @@ const Field3D InvertParCR::solve(const Field3D &f) { bout::globals::mpi->MPI_Comm_size(surf.communicator(), &np); if(rank == 0) { for(int k=0; kzlength()(0,0); // wave number is 1/[rad] + BoutReal kwave=k*2.0*PI/zlength; // wave number is 1/[rad] dcomplex phase(cos(kwave*ts) , -sin(kwave*ts)); a(k, 0) *= phase; } } if(rank == np-1) { for(int k=0; kzlength()(0,0); // wave number is 1/[rad] + BoutReal kwave=k*2.0*PI/zlength; // wave number is 1/[rad] dcomplex phase(cos(kwave*ts) , sin(kwave*ts)); c(k, localmesh->LocalNy - 2 * localmesh->ystart - 1) *= phase; } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 94626a8e31..12a17b0642 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1522,9 +1522,8 @@ void Coordinates::setParallelTransform(Options* options) { fixZShiftGuards(zShift); if (ptstr == "shifted") { - ASSERT1(isConst(zlength())); transform = bout::utils::make_unique(*localmesh, location, zShift, - zlength()(0,0)); + getConst(zlength())); } else if (ptstr == "shiftedinterp") { transform = bout::utils::make_unique(*localmesh, location, zShift); diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index 5e87336fe2..a8668c9ab1 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -571,8 +571,7 @@ bool GridFile::readgrid_3dvar_fft(Mesh *m, const std::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() - ASSERT1(isConst(m->getCoordinates(var.getLocation())->zlength())); - BoutReal zlength = m->getCoordinates(var.getLocation())->zlength()(0,0); + BoutReal zlength = getConst(m->getCoordinates(var.getLocation())->zlength()); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi @@ -703,8 +702,7 @@ bool GridFile::readgrid_perpvar_fft(Mesh *m, const std::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() - ASSERT1(isConst(m->getCoordinates(var.getLocation())->zlength())); - BoutReal zlength = m->getCoordinates(var.getLocation())->zlength()(0,0); + BoutReal zlength =getConst(m->getCoordinates(var.getLocation())->zlength()); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi From 814baf7eef766ef42d3f33372a1d422da15b2be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sat, 4 Apr 2020 01:54:57 +0100 Subject: [PATCH 126/293] Fix bad merge --- src/field/fieldgenerators.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 79e8fd3eb9..c30e4273f8 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -91,11 +91,11 @@ BoutReal FieldBallooning::generate(const Context& ctx) { // y - i * 2pi value += arg->generate(Context(ctx).set( "y", ctx.y() - i * TWOPI, - "z", ctx.z() + i * ts * TWOPI / zlength; + "z", ctx.z() + i * ts * TWOPI / zlength)); value += arg->generate(Context(ctx).set( "y", ctx.y() + i * TWOPI, - "z", ctx.z() - i * ts * TWOPI / zlength; + "z", ctx.z() - i * ts * TWOPI / zlength)); } return value; } From ddc0563c4b3f0722107faf0830c30997cf8211fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 21 Apr 2020 20:33:22 +0100 Subject: [PATCH 127/293] Do not run test-petsc-laplace-mast-grid on travis --- tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt b/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt index 625365d846..b698702344 100644 --- a/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt +++ b/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt @@ -1,6 +1,7 @@ bout_add_integrated_test(test-petsc-laplace-MAST-grid SOURCES test_petsc_laplace_MAST_grid.cxx REQUIRES BOUT_HAS_PETSC + REQUIRES NOT DEFINED ENV{TRAVIS} USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES From 189e0eb06359be5f5d0c9af6d81cf703675568c1 Mon Sep 17 00:00:00 2001 From: Brendan Date: Fri, 8 May 2020 16:20:40 +0200 Subject: [PATCH 128/293] Add RotatingEllipse magnetic field in Zoidberg --- tools/pylib/zoidberg/field.py | 97 ++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index aa976b5b3b..0c55d99546 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -399,7 +399,93 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") + class RotatingEllipse(MagneticField): + """A "rotating ellipse" stellarator + Parameters + ---------- + xcentre : float, optional + Middle of the domain in x [m] + zcentre : float, optional + Middle of the domain in z [m] + radius : float, optional + Radius of coils [meters] + yperiod : float, optional + The period over which the coils return to their original position + I_coil : float, optional + Current in each coil + Btor : float, optional + Toroidal magnetic field strength + """ + + def coil(self, xcentre, zcentre, radius, angle, iota, I): + """Defines a single coil + Parameters + ---------- + radius : float + Radius to coil + angle : float + Initial angle of coil + iota : float + Rotational transform of coil + I : float + Current through coil + Returns + ------- + (x, z) - x, z coordinates of coils along phi + """ + + return (xcentre + radius * cos(angle + iota * self.phi), + zcentre + radius * sin(angle + iota * self.phi), I) + + def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, + I_coil=0.05, Btor=1.0, smooth=False, smooth_args={}): + xcentre = float(xcentre) + zcentre = float(zcentre) + radius = float(radius) + yperiod = float(yperiod) + Btor = float(Btor) + + iota = 2.*np.pi / yperiod + + self.x = Symbol('x') + self.z = Symbol('z') + self.y = Symbol('y') + self.r = Symbol('r') + self.r = (self.x**2 + self.z**2)**(0.5) + self.phi = Symbol('phi') + + self.xcentre = xcentre + self.zcentre = zcentre + self.radius = radius + + # Four coils equally spaced, alternating direction for current + self.coil_list = [self.coil(xcentre, zcentre, radius, n*pi, iota, ((-1)**np.mod(i,2))*I_coil) + for i, n in enumerate(np.arange(4)/2.)] + + A = 0.0 + Bx = 0.0 + Bz = 0.0 + + for c in self.coil_list: + xc, zc, Ic = c + rc = (xc**2 + zc**2)**(0.5) + r2 = (self.x - xc)**2 + (self.z - zc)**2 + theta = atan2(self.z - zc, self.x - xc) # Angle relative to coil + A -= Ic * 0.1 * log(r2) + + B = Ic * 0.2/sqrt(r2) + + Bx += B * sin(theta) + Bz -= B * cos(theta) + + By = Btor/self.x + self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") + + self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") + self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") + self.Byfunc = lambdify((self.x, self.z, self.phi), By, "numpy") + except ImportError: class StraightStellarator(MagneticField): """ @@ -412,7 +498,16 @@ class StraightStellarator(MagneticField): def __init__(self, *args, **kwargs): raise ImportError("No Sympy module: Can't generate StraightStellarator fields") - + class RotatingEllipse(MagneticField): + """ + Invalid RotatingEllipse, since no Sympy module. + Rather than printing an error on startup, which may + be missed or ignored, this raises + an exception if StraightStellarator is ever used. + """ + def __init__(self, *args, **kwargs): + raise ImportError("No Sympy module: Can't generate RotatingEllipse fields") + class VMEC(MagneticField): """A numerical magnetic field from a VMEC equilibrium file From 4345fa88d2b8e67bad779be832430c1a286dfa0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 10:02:18 +0100 Subject: [PATCH 129/293] Minor printing improvements --- examples/orszag-tang/mhd.cxx | 4 ++-- src/mesh/parallel/fci.cxx | 7 ++++--- .../test_petsc_laplace_MAST_grid.cxx | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/examples/orszag-tang/mhd.cxx b/examples/orszag-tang/mhd.cxx index b7274c1135..0c185c781a 100644 --- a/examples/orszag-tang/mhd.cxx +++ b/examples/orszag-tang/mhd.cxx @@ -47,8 +47,8 @@ class MHD : public PhysicsModel { bout_solve(B, "B"); Coordinates *coord = mesh->getCoordinates(); - output.write("dx[0,0] = {:e}, dy[0,0] = {:e}, dz = {:e}\n", coord->dx(0, 0, 0), - coord->dy(0, 0, 0), coord->dz(0,0,0)); + output.write("dx(0,0,0) = {:e}, dy(0,0,0) = {:e}, dz(0,0,0) = {:e}\n", + coord->dx(0, 0, 0), coord->dy(0, 0, 0), coord->dz(0, 0, 0)); SAVE_REPEAT(divB); diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 2c6266a41d..fdd379e1e9 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -205,10 +205,10 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* bou // Check that t_x and t_z are in range if ((t_x < 0.0) || (t_x > 1.0)) - throw BoutException("t_x=%e out of range at (%d,%d,%d)", t_x, x, y, z); + throw BoutException("t_x={:e} out of range at ({:d},{:d},{:d})", t_x, x, y, z); if ((t_z < 0.0) || (t_z > 1.0)) - throw BoutException("t_z=%e out of range at (%d,%d,%d)", t_z, x, y, z); + throw BoutException("t_z={:e} out of range at ({:d},{:d},{:d})", t_z, x, y, z); //---------------------------------------- @@ -221,7 +221,8 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* bou if (xt_prime(x, y, z) < 0.0) { // Hit a boundary - boundary_mask(x, y, z) = false; // true; + // Set to false to not skip this point + boundary_mask(x, y, z) = false; // Need to specify the index of the boundary intersection, but // this may not be defined in general. diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx b/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx index 293da6e0b7..5730bc63c3 100644 --- a/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx +++ b/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx @@ -663,7 +663,7 @@ int main(int argc, char** argv) { dump.write(); dump.close(); - output << "\nFinished running test. Triggering error to quit\n\n"; + output << "\nFinished running test.\n"; MPI_Barrier(BoutComm::get()); // Wait for all processors to write data } From fa4d519b742aa6f4aba56a98388f1a583a4e13ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 10:04:37 +0100 Subject: [PATCH 130/293] Make more values const --- include/bout/coordinates.hxx | 2 +- .../laplace/impls/serial_band/serial_band.cxx | 3 +- src/mesh/coordinates.cxx | 2 +- src/mesh/fv_ops.cxx | 58 +++++++++---------- tests/unit/solver/test_solver.cxx | 8 +-- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index ca02a12206..5631651c3c 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -140,7 +140,7 @@ public: int jacobian(); ///< Calculate J and Bxy /// Return if the metrics are 3D - bool is3D(); + constexpr bool is3D() const; /////////////////////////////////////////////////////////// // Parallel transforms diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index ee93ff0d0e..19b92dffba 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -126,11 +126,10 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { BoutReal coef1=0.0, coef2=0.0, coef3=0.0, coef4=0.0, coef5=0.0, coef6=0.0; - Field2D kwave_; ///////// PERFORM INVERSION ///////// // shift freqs according to FFT convention - kwave_=iz*2.0*PI/coords->zlength(); // wave number is 1/[rad] + const Field2D kwave_ = iz * TWOPI / coords->zlength(); // wave number is 1/[rad] // set bk1d for(int ix=0;ixLocalNx;ix++) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 12a17b0642..147293eb75 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -2000,7 +2000,7 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, return bout::derivatives::index::DDY(f, outloc, method, region); } -bool Coordinates::is3D() { +constexpr bool Coordinates::is3D() const { #ifdef COORDINATES_USE_3D return true; #else diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index b70c9ad81a..4c56040b24 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -314,24 +314,24 @@ namespace FV { for (int k = 0; k < mesh->LocalNz; k++) { // Right boundary common factors - BoutReal common_factor = 0.25 + const BoutReal common_factor = 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) * (coord->J(i, j, j) + coord->J(i, j + 1, k)); - BoutReal factor_rc = + const BoutReal factor_rc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); - BoutReal factor_rp = + const BoutReal factor_rp = common_factor / (coord->J(i, j + 1, k) * coord->dy(i, j + 1, k)); // Not on domain boundary // 3rd derivative at right cell boundary - BoutReal d3fdx3 = ( - f(i,j+2,k) - - 3.*f(i,j+1,k) - + 3.*f(i,j, k) - - f(i,j-1,k) - ); + const BoutReal d3fdx3 = ( + f(i,j+2,k) + - 3.*f(i,j+1,k) + + 3.*f(i,j, k) + - f(i,j-1,k) + ); result(i,j, k) += d3fdx3 * factor_rc; result(i,j+1,k) -= d3fdx3 * factor_rp; @@ -342,21 +342,21 @@ namespace FV { for(int k=0;kLocalNz;k++) { // Right boundary common factors - BoutReal common_factor = 0.25 + const BoutReal common_factor = 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) * (coord->J(i, j, j) + coord->J(i, j + 1, k)); - BoutReal factor_rc = + const BoutReal factor_rc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); - BoutReal factor_rp = + const BoutReal factor_rp = common_factor / (coord->J(i, j + 1, k) * coord->dy(i, j + 1, k)); - BoutReal d3fdx3 = -((16. / 5) * 0.5 * - (f(i, j + 1, k) + f(i, j, k)) // Boundary value f_b - - 6. * f(i, j, k) // f_0 - + 4. * f(i, j - 1, k) // f_1 - - (6. / 5) * f(i, j - 2, k) // f_2 - ); + const BoutReal d3fdx3 = -((16. / 5) * 0.5 * + (f(i, j + 1, k) + f(i, j, k)) // Boundary value f_b + - 6. * f(i, j, k) // f_0 + + 4. * f(i, j - 1, k) // f_1 + - (6. / 5) * f(i, j - 2, k) // f_2 + ); result(i,j, k) += d3fdx3 * factor_rc; result(i,j+1,k) -= d3fdx3 * factor_rp; @@ -372,20 +372,20 @@ namespace FV { if ( j != mesh->ystart || !has_lower_boundary ) { for(int k=0;kLocalNz;k++) { - BoutReal common_factor = 0.25 + const BoutReal common_factor = 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) * (coord->J(i, j, k) + coord->J(i, j - 1, k)); - BoutReal factor_lc = + const BoutReal factor_lc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); - BoutReal factor_lm = + const BoutReal factor_lm = common_factor / (coord->J(i, j - 1, k) * coord->dy(i, j - 1, k)); // Not on a domain boundary - BoutReal d3fdx3 = (f(i, j + 1, k) - - 3. * f(i, j, k) - + 3. * f(i, j - 1, k) - - f(i, j - 2, k)); + const BoutReal d3fdx3 = (f(i, j + 1, k) + - 3. * f(i, j, k) + + 3. * f(i, j - 1, k) + - f(i, j - 2, k)); result(i, j , k) -= d3fdx3 * factor_lc; result(i, j - 1, k) += d3fdx3 * factor_lm; @@ -393,15 +393,15 @@ namespace FV { } else { // On a domain (Y) boundary for(int k=0;kLocalNz;k++) { - BoutReal common_factor = 0.25 + const BoutReal common_factor = 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) * (coord->J(i, j, k) + coord->J(i, j - 1, k)); - BoutReal factor_lc = + const BoutReal factor_lc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); - BoutReal factor_lm = + const BoutReal factor_lm = common_factor / (coord->J(i, j - 1, k) * coord->dy(i, j - 1, k)); - BoutReal d3fdx3 = + const BoutReal d3fdx3 = -(-(16. / 5) * 0.5 * (f(i, j - 1, k) + f(i, j, k)) // Boundary value f_b + 6. * f(i, j, k) // f_0 - 4. * f(i, j + 1, k) // f_1 diff --git a/tests/unit/solver/test_solver.cxx b/tests/unit/solver/test_solver.cxx index 8d8e6f8de0..df133d528f 100644 --- a/tests/unit/solver/test_solver.cxx +++ b/tests/unit/solver/test_solver.cxx @@ -256,9 +256,9 @@ TEST_F(SolverTest, AddVector2D) { Vector2D vector1{}, vector2{}; EXPECT_NO_THROW(solver.add(vector1, "vector")); #ifndef COORDINATES_USE_3D - int n2d=3, n3d=0; + constexpr int n2d=3, n3d=0; #else - int n2d=0, n3d=3; + constexpr int n2d=0, n3d=3; #endif EXPECT_EQ(solver.n2Dvars(), n2d); EXPECT_EQ(solver.n3Dvars(), n3d); @@ -387,9 +387,9 @@ TEST_F(SolverTest, ConstraintVector2D) { Vector2D vector1{}, vector2{}; EXPECT_NO_THROW(solver.constraint(vector1, vector1, "vector")); #ifndef COORDINATES_USE_3D - int n2d=3, n3d=0; + constexpr int n2d=3, n3d=0; #else - int n2d=0, n3d=3; + constexpr int n2d=0, n3d=3; #endif EXPECT_EQ(solver.n2Dvars(), n2d); EXPECT_EQ(solver.n3Dvars(), n3d); From 60925e0a871676b58a57d09a7bad5e4b17a0632f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 11:09:51 +0100 Subject: [PATCH 131/293] Do not return const --- include/difops.hxx | 260 +++++++++++++++++++-------------------- src/mesh/difops.cxx | 294 ++++++++++++++++++++++---------------------- 2 files changed, 277 insertions(+), 277 deletions(-) diff --git a/include/difops.hxx b/include/difops.hxx index f00154129a..3633db1d96 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -53,32 +53,32 @@ * enabled) * @param[in] method The method to use. The default is set in the options. */ -const Coordinates::metric_field_type Grad_par(const Field2D& var, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Coordinates::metric_field_type Grad_par(const Field2D& var, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, - DIFF_METHOD method) { +Coordinates::metric_field_type Grad_par(const Field2D& var, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Coordinates::metric_field_type Grad_par(const Field2D& var, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, + DIFF_METHOD method) { return Grad_par(var, outloc, toString(method)); } -DEPRECATED(inline const Coordinates::metric_field_type Grad_par(const Field2D& var, - DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline Coordinates::metric_field_type Grad_par(const Field2D& var, + DIFF_METHOD method, + CELL_LOC outloc)) { return Grad_par(var, outloc, toString(method)); } -const Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field3D Grad_par(const Field3D& var, const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const DEPRECATED(Field3D Grad_par(const Field3D& var, CELL_LOC outloc, - DIFF_METHOD method)) { +Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Field3D Grad_par(const Field3D& var, const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline DEPRECATED(Field3D Grad_par(const Field3D& var, CELL_LOC outloc, + DIFF_METHOD method)) { return Grad_par(var, outloc, toString(method)); }; -DEPRECATED(inline const - Field3D Grad_par(const Field3D& var, DIFF_METHOD method, CELL_LOC outloc)) { +DEPRECATED(inline Field3D Grad_par(const Field3D& var, DIFF_METHOD method, + CELL_LOC outloc)) { return Grad_par(var, outloc, toString(method)); } @@ -92,7 +92,7 @@ DEPRECATED(inline const * Combines the parallel and perpendicular calculation to include * grid-points at the corners. */ -const Field3D Grad_parP(const Field3D& apar, const Field3D& f); +Field3D Grad_parP(const Field3D& apar, const Field3D& f); /*! * vpar times parallel derivative along unperturbed B-field (upwinding) @@ -108,35 +108,35 @@ const Field3D Grad_parP(const Field3D& apar, const Field3D& f); * @param[in] method The numerical method to use. The default is set in the options * */ -const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Coordinates::metric_field_type Vpar_Grad_par( +Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Coordinates::metric_field_type Vpar_Grad_par( const Field2D& v, const Field2D& f, const std::string& method, CELL_LOC outloc = CELL_DEFAULT)); -inline const Coordinates::metric_field_type +inline Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -DEPRECATED(inline const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, - const Field2D& f, - DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, + const Field2D& f, + DIFF_METHOD method, + CELL_LOC outloc)) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -const Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, +Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -DEPRECATED(inline const Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, - DIFF_METHOD method, CELL_LOC outloc)) { +DEPRECATED(inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, + DIFF_METHOD method, CELL_LOC outloc)) { return Vpar_Grad_par(v, f, outloc, toString(method)); } @@ -152,31 +152,31 @@ DEPRECATED(inline const Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f * @param[in] method The numerical method to use * */ -const Coordinates::metric_field_type Div_par(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Coordinates::metric_field_type Div_par(const Field2D& f, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { +Coordinates::metric_field_type Div_par(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Coordinates::metric_field_type Div_par(const Field2D& f, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Div_par(f, outloc, toString(method)); } -DEPRECATED(inline const Coordinates::metric_field_type Div_par(const Field2D& f, - DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline Coordinates::metric_field_type Div_par(const Field2D& f, + DIFF_METHOD method, + CELL_LOC outloc)) { return Div_par(f, outloc, toString(method)); } -const Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field3D Div_par(const Field3D& f, const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Field3D Div_par(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { +Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Field3D Div_par(const Field3D& f, const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline Field3D Div_par(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { return Div_par(f, outloc, toString(method)); } -DEPRECATED(inline const Field3D Div_par(const Field3D& f, DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline Field3D Div_par(const Field3D& f, DIFF_METHOD method, + CELL_LOC outloc)) { return Div_par(f, outloc, toString(method)); } @@ -184,23 +184,23 @@ DEPRECATED(inline const Field3D Div_par(const Field3D& f, DIFF_METHOD method, // Both f and v are interpolated onto cell boundaries // using 2nd order central difference, then multiplied together // to get the flux at the boundary. -const Field3D Div_par(const Field3D& f, const Field3D& v); +Field3D Div_par(const Field3D& f, const Field3D& v); // Flux methods. Model divergence of flux: df/dt = Div(v * f) // TODO : Should we add Field2D versions? -const Field3D Div_par_flux(const Field3D& v, const Field3D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(const Field3D Div_par_flux(const Field3D& v, const Field3D& f, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline const Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc, - DIFF_METHOD method) { +Field3D Div_par_flux(const Field3D& v, const Field3D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Field3D Div_par_flux(const Field3D& v, const Field3D& f, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Div_par_flux(v, f, outloc, toString(method)); } -DEPRECATED(inline const Field3D Div_par_flux(const Field3D& v, const Field3D& f, - DIFF_METHOD method, - CELL_LOC outloc = CELL_DEFAULT)) { +DEPRECATED(inline Field3D Div_par_flux(const Field3D& v, const Field3D& f, + DIFF_METHOD method, + CELL_LOC outloc = CELL_DEFAULT)) { return Div_par_flux(v, f, outloc, toString(method)); } @@ -215,17 +215,17 @@ DEPRECATED(inline const Field3D Div_par_flux(const Field3D& v, const Field3D& f, * @param[in] f The field to be differentiated * @param[in] outloc The cell location of the result */ -const Coordinates::metric_field_type Grad2_par2(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -inline const Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { +Coordinates::metric_field_type Grad2_par2(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +inline Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, + DIFF_METHOD method) { return Grad2_par2(f, outloc, toString(method)); } -const Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -inline const Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { +Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +inline Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { return Grad2_par2(f, outloc, toString(method)); } @@ -235,19 +235,19 @@ inline const Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD m */ [[deprecated( "Grad_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline const Field3D Grad_par_CtoL(const Field3D &var) { +inline Field3D Grad_par_CtoL(const Field3D &var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Grad_par(var, CELL_YLOW); } [[deprecated( "Grad_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline const Coordinates::metric_field_type Grad_par_CtoL(const Field2D &var) { +inline Coordinates::metric_field_type Grad_par_CtoL(const Field2D &var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Grad_par(var, CELL_YLOW); } [[deprecated( "Vpar_Grad_par_LCtoC is deprecated. Staggering is now supported in Vpar_Grad_par.")]] -inline const Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, +inline Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, const std::string& region="RGN_NOBNDRY") { ASSERT2(v.getLocation() == CELL_YLOW); ASSERT2(f.getLocation() == CELL_CENTRE); @@ -255,7 +255,7 @@ inline const Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, } [[deprecated( "Vpar_Grad_par_LCtoC is deprecated. Staggering is now supported in Vpar_Grad_par.")]] -inline const Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, +inline Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, REGION region=RGN_NOBNDRY) { ASSERT2(v.getLocation() == CELL_YLOW); ASSERT2(f.getLocation() == CELL_CENTRE); @@ -263,37 +263,37 @@ inline const Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, } [[deprecated( "Grad_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline const Field3D Grad_par_LtoC(const Field3D &var) { +inline Field3D Grad_par_LtoC(const Field3D &var) { ASSERT2(var.getLocation() == CELL_YLOW); return Grad_par(var, CELL_CENTRE); } [[deprecated( "Grad_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline const Coordinates::metric_field_type Grad_par_LtoC(const Field2D &var) { +inline Coordinates::metric_field_type Grad_par_LtoC(const Field2D &var) { ASSERT2(var.getLocation() == CELL_YLOW); return Grad_par(var, CELL_CENTRE); } [[deprecated( "Div_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline const Field3D Div_par_LtoC(const Field3D &var) { +inline Field3D Div_par_LtoC(const Field3D &var) { ASSERT2(var.getLocation() == CELL_YLOW); return Div_par(var, CELL_CENTRE); } [[deprecated( "Div_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline const Coordinates::metric_field_type Div_par_LtoC(const Field2D &var) { +inline Coordinates::metric_field_type Div_par_LtoC(const Field2D &var) { ASSERT2(var.getLocation() == CELL_YLOW); return Div_par(var, CELL_CENTRE); } [[deprecated( "Div_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline const Field3D Div_par_CtoL(const Field3D &var) { +inline Field3D Div_par_CtoL(const Field3D &var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Div_par(var, CELL_YLOW); } [[deprecated( "Div_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline const Coordinates::metric_field_type Div_par_CtoL(const Field2D &var) { +inline Coordinates::metric_field_type Div_par_CtoL(const Field2D &var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Div_par(var, CELL_YLOW); } @@ -308,14 +308,14 @@ inline const Coordinates::metric_field_type Div_par_CtoL(const Field2D &var) { * @param[in] kY The diffusion coefficient * @param[in] f The field whose gradient drives a flux */ -const Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, +Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); -const Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); -const Coordinates::metric_field_type +Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); +Coordinates::metric_field_type Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); -const Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); -const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); -const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); /*! * Perpendicular Laplacian operator @@ -326,51 +326,51 @@ const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC o * * For the full perpendicular Laplacian, use Laplace_perp */ -const Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); -const Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); -const FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, - bool useFFT = true); +Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); +Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); +FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, + bool useFFT = true); /*! * Perpendicular Laplacian, keeping y derivatives * * */ -const Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); -const Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); +Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); /*! * Parallel Laplacian operator * */ -const Coordinates::metric_field_type Laplace_par(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); -const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); +Coordinates::metric_field_type Laplace_par(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); +Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); /*! * Full Laplacian operator (par + perp) */ -const Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); -const Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); +Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); /*! * Inverse of Laplacian operator in LaplaceXY solver */ -const Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); +Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); /*! * Terms of form b0 x Grad(phi) dot Grad(A) * */ -const Coordinates::metric_field_type +Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc = CELL_DEFAULT); /*! @@ -384,15 +384,15 @@ b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc = CELL_DE * @param[in] A The field being advected * @param[in] outloc The cell location where the result is defined. By default the same as A. */ -const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field2D &A, CELL_LOC outloc=CELL_DEFAULT); -const Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); -const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); +Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field2D &A, CELL_LOC outloc=CELL_DEFAULT); +Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); +Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); /*! * X-Z Finite Volume diffusion operator */ -const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); /*! @@ -427,18 +427,18 @@ constexpr BRACKET_METHOD BRACKET_ARAKAWA_OLD = BRACKET_METHOD::arakawa_old; * @param[in] solver Pointer to the time integration solver * */ -const Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, - BRACKET_METHOD method = BRACKET_STD, - CELL_LOC outloc = CELL_DEFAULT, - Solver* solver = nullptr); -const Field3D bracket(const Field2D &f, const Field3D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); -const Field3D bracket(const Field3D &f, const Field2D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); -const Field3D bracket(const Field3D &f, const Field3D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); +Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, + BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, + Solver* solver = nullptr); +Field3D bracket(const Field2D &f, const Field3D &g, + BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, + Solver *solver = nullptr); +Field3D bracket(const Field3D &f, const Field2D &g, + BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, + Solver *solver = nullptr); +Field3D bracket(const Field3D &f, const Field3D &g, + BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, + Solver *solver = nullptr); #endif /* __DIFOPS_H__ */ diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index b04bfc6d50..eb849e1735 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -5,7 +5,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 @@ -20,7 +20,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with BOUT++. If not, see . -* +* **************************************************************************/ #include @@ -45,21 +45,21 @@ * The parallel derivative along unperturbed B-field *******************************************************************************/ -const Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, +Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, const std::string& method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -const Coordinates::metric_field_type +Coordinates::metric_field_type Grad_par(const Field2D& var, const std::string& method, CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -const Field3D Grad_par(const Field3D &var, CELL_LOC outloc, const std::string &method) { +Field3D Grad_par(const Field3D &var, CELL_LOC outloc, const std::string &method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -const Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC outloc) { +Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } @@ -74,14 +74,14 @@ const Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC o * grid-points at the corners. *******************************************************************************/ -const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { +Field3D Grad_parP(const Field3D &apar, const Field3D &f) { ASSERT1_FIELDS_COMPATIBLE(apar, f); ASSERT1(f.hasParallelSlices()); Mesh *mesh = apar.getMesh(); Field3D result{emptyFrom(f)}; - + int ncz = mesh->LocalNz; Coordinates *metric = apar.getCoordinates(); @@ -94,46 +94,46 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { for(int z=0;zdy(x, y+1, z) + metric->dy(x, y, z) + 0.5*metric->dy(x, y-1, z)); } - + for(int x=1;x<=mesh->LocalNx-2;x++) { for(int y=mesh->ystart;y<=mesh->yend;y++) { for(int z=0;zg_22(x, y, z)); + BoutReal by = 1./sqrt(metric->g_22(x, y, z)); // Z indices zm and zp int zm = (z - 1 + ncz) % ncz; int zp = (z + 1) % ncz; - + // bx = -DDZ(apar) BoutReal bx = (apar(x, y, zm) - apar(x, y, zp))/(0.5*metric->dz(x, y, zm) + metric->dz(x, y, z) + 0.5*metric->dz(x, y, zp)); // bz = DDX(f) BoutReal bz = (apar(x+1, y, z) - apar(x-1, y, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)); - - // Now calculate (bx*d/dx + by*d/dy + bz*d/dz) f - + + // Now calculate (bx*d/dx + by*d/dy + bz*d/dz) f + // Length dl for predictor BoutReal dl = fabs(metric->dx(x, y, z)) / (fabs(bx) + 1e-16); dl = BOUTMIN(dl, fabs(metric->dy(x, y, z)) / (fabs(by) + 1e-16)); dl = BOUTMIN(dl, fabs(metric->dz(x, y, z)) / (fabs(bz) + 1e-16)); - - BoutReal fp, fm; - + + BoutReal fp, fm; + // X differencing fp = f(x+1, y, z) + (0.25*dl/metric->dz(x, y, z)) * bz * (f(x+1, y, zm) - f(x+1, y, zp)) - 0.5*dl * by * gys(x+1, y, z); - + fm = f(x-1, y, z) + (0.25*dl/metric->dz(x, y, z)) * bz * (f(x-1, y, zm) - f(x-1, y, zp)) - 0.5*dl * by * gys(x-1, y, z); - + result(x, y, z) = bx * (fp - fm) / (0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)); - // Z differencing - + // Z differencing + fp = f(x, y, zp) + (0.25*dl/metric->dx(x, y, z)) * bx * (f(x-1, y, zp) - f(x+1, y, zp)) - 0.5*dl * by * gys(x, y, zp); - + fm = f(x, y, zm) + (0.25*dl/metric->dx(x, y, z)) * bx * (f(x-1,y,zm) - f(x+1, y, zm)) - 0.5*dl * by * gys(x, y, zm); @@ -141,12 +141,12 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { result(x, y, z) += bz * (fp - fm) / (0.5*metric->dz(x, y, zm) + metric->dz(x, y, z) + 0.5*metric->dz(x, y, zp)); // Y differencing - + fp = f.yup()(x,y+1,z) - 0.5*dl * bx * (f.yup()(x+1, y+1, z) - f.yup()(x-1, y+1, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)) - + + (0.25*dl/metric->dz(x,y,z)) * bz * (f.yup()(x,y+1,zm) - f.yup()(x,y+1,zp)); - + fm = f.ydown()(x,y-1,z) - 0.5*dl * bx * (f.ydown()(x+1, y-1, z) - f.ydown()(x-1, y-1, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)) + (0.25*dl/metric->dz(x,y,z)) * bz * (f.ydown()(x,y-1,zm) - f.ydown()(x,y-1,zp)); @@ -155,7 +155,7 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { } } } - + ASSERT2(result.getLocation() == f.getLocation()); return result; @@ -166,23 +166,23 @@ const Field3D Grad_parP(const Field3D &apar, const Field3D &f) { * vparallel times the parallel derivative along unperturbed B-field *******************************************************************************/ -const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, +Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -const Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, +Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, const std::string& method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -const Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -const Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, const std::string &method, CELL_LOC outloc) { +Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, const std::string &method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } @@ -190,25 +190,25 @@ const Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, const std::strin * Div_par * parallel divergence operator B \partial_{||} (F/B) *******************************************************************************/ -const Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, +Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -const Coordinates::metric_field_type Div_par(const Field2D& f, const std::string& method, - CELL_LOC outloc) { +Coordinates::metric_field_type Div_par(const Field2D& f, const std::string& method, + CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -const Field3D Div_par(const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Div_par(const Field3D &f, CELL_LOC outloc, const std::string &method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -const Field3D Div_par(const Field3D &f, const std::string &method, CELL_LOC outloc) { +Field3D Div_par(const Field3D &f, const std::string &method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -const Field3D Div_par(const Field3D& f, const Field3D& v) { +Field3D Div_par(const Field3D& f, const Field3D& v) { ASSERT1_FIELDS_COMPATIBLE(f, v); ASSERT1(f.hasParallelSlices()); ASSERT1(v.hasParallelSlices()); @@ -251,7 +251,7 @@ const Field3D Div_par(const Field3D& f, const Field3D& v) { //////// Flux methods -const Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { Coordinates *metric = f.getCoordinates(outloc); auto Bxy_floc = f.getCoordinates()->Bxy; @@ -269,7 +269,7 @@ const Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, return metric->Bxy*FDDY(v, f_B, outloc, method)/sqrt(metric->g_22); } -const Field3D Div_par_flux(const Field3D &v, const Field3D &f, const std::string &method, CELL_LOC outloc) { +Field3D Div_par_flux(const Field3D &v, const Field3D &f, const std::string &method, CELL_LOC outloc) { return Div_par_flux(v,f, outloc, method); } @@ -282,12 +282,12 @@ const Field3D Div_par_flux(const Field3D &v, const Field3D &f, const std::string * Note: For parallel Laplacian use LaplacePar *******************************************************************************/ -const Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, +Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } -const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, const std::string &method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } @@ -296,29 +296,29 @@ const Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, const std::string &m * Parallel divergence of diffusive flux, K*Grad_par *******************************************************************************/ -const Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, +Coordinates::metric_field_type 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } -const Coordinates::metric_field_type +Coordinates::metric_field_type 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, CELL_LOC outloc) { +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, CELL_LOC outloc) { +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, CELL_LOC outloc) { +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); } @@ -327,15 +327,15 @@ const Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC o * perpendicular Laplacian operator *******************************************************************************/ -const Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc, bool useFFT) { +Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc, bool useFFT) { return f.getCoordinates(outloc)->Delp2(f, outloc, useFFT); } -const Field3D Delp2(const Field3D& f, CELL_LOC outloc, bool useFFT) { +Field3D Delp2(const Field3D& f, CELL_LOC outloc, bool useFFT) { return f.getCoordinates(outloc)->Delp2(f, outloc, useFFT); } -const FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { +FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { return f.getCoordinates(outloc)->Delp2(f, outloc, useFFT); } @@ -346,14 +346,14 @@ const FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { * Laplace_perp = Laplace - Laplace_par *******************************************************************************/ -const Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc, +Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc, const std::string& dfdy_boundary_condition, const std::string& dfdy_region) { return Laplace(f, outloc, dfdy_boundary_condition, dfdy_region) - Laplace_par(f, outloc); } -const Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc, +Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc, const std::string& dfdy_boundary_condition, const std::string& dfdy_region) { return Laplace(f, outloc, dfdy_boundary_condition, dfdy_region) @@ -364,15 +364,15 @@ const Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc, * LaplacePar * Full parallel Laplacian operator on scalar field * -* LaplacePar(f) = Div( b (b dot Grad(f)) ) +* LaplacePar(f) = Div( b (b dot Grad(f)) ) * *******************************************************************************/ -const Coordinates::metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc) { +Coordinates::metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } -const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { +Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } @@ -381,14 +381,14 @@ const Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { * Full Laplacian operator on scalar field *******************************************************************************/ -const Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc, +Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc, const std::string& dfdy_boundary_condition, const std::string& dfdy_region) { return f.getCoordinates(outloc)->Laplace(f, outloc, dfdy_boundary_condition, dfdy_region); } -const Field3D Laplace(const Field3D& f, CELL_LOC outloc, +Field3D Laplace(const Field3D& f, CELL_LOC outloc, const std::string& dfdy_boundary_condition, const std::string& dfdy_region) { return f.getCoordinates(outloc)->Laplace(f, outloc, dfdy_boundary_condition, @@ -400,7 +400,7 @@ const Field3D Laplace(const Field3D& f, CELL_LOC outloc, * Inverse of Laplacian operator in LaplaceXY solver *******************************************************************************/ -const Field2D Laplace_perpXY(const Field2D& A, const Field2D& f) { +Field2D Laplace_perpXY(const Field2D& A, const Field2D& f) { return f.getCoordinates()->Laplace_perpXY(A, f); } @@ -410,11 +410,11 @@ const Field2D Laplace_perpXY(const Field2D& A, const Field2D& f) { * Used for ExB terms and perturbed B field using A_|| *******************************************************************************/ -const Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, +Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field2D , Field2D )"); - + if (outloc == CELL_DEFAULT) outloc = A.getLocation(); ASSERT1(phi.getMesh() == A.getMesh()); @@ -441,7 +441,7 @@ const Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, return result; } -const Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc) { +Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field2D , Field3D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -477,11 +477,11 @@ const Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC ou #endif ASSERT2(result.getLocation() == outloc); - + return result; } -const Field3D b0xGrad_dot_Grad(const Field3D &p, const Field2D &A, CELL_LOC outloc) { +Field3D b0xGrad_dot_Grad(const Field3D &p, const Field2D &A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field3D , Field2D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -504,17 +504,17 @@ const Field3D b0xGrad_dot_Grad(const Field3D &p, const Field2D &A, CELL_LOC outl Field3D result = VDDX(vx, A, outloc) + VDDY(vy, A, outloc); result /= (metric->J*sqrt(metric->g_22)); - + #ifdef TRACK result.name = "b0xGrad_dot_Grad("+p.name+","+A.name+")"; #endif - + ASSERT2(result.getLocation() == outloc); return result; } -const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc) { +Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field3D , Field3D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -554,16 +554,16 @@ const Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC ou } -const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { - +Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { + Field3D result = 0.0; ////////////////////////////////////////// // X-Z diffusion - // + // // Z // | - // + // // o --- gU --- o // | nU | // | | @@ -582,39 +582,39 @@ const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outlo for(int j=mesh->ystart;j<=mesh->yend;j++) for(int k=0;kLocalNz;k++) { - // wrap k-index around as Z is (currently) periodic. - int kp = (k+1) % (mesh->LocalNz); - int km = (k-1+mesh->LocalNz) % (mesh->LocalNz); - + // wrap k-index around as Z is (currently) periodic. + int kp = (k+1) % (mesh->LocalNz); + int km = (k-1+mesh->LocalNz) % (mesh->LocalNz); + // Calculate gradients on cell faces -- assumes constant grid spacing - + BoutReal gR = (coords->g11(i,j,k) + coords->g11(i+1,j,k)) * (fs(i+1,j,k) - fs(i,j,k))/(coords->dx(i+1,j,k) + coords->dx(i,j,k)) + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(fs(i+1,j,kp) - fs(i+1,j,km) + fs(i,j,kp) - fs(i,j,km))/(4.*coords->dz(i,j,k)); - - BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(fs(i,j,k) - fs(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(fs(i-1,j,kp) - fs(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4*coords->dz(i,j,k)); - - BoutReal gD = coords->g13(i,j,k)*(fs(i+1,j,km) - fs(i-1,j,km) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(fs(i,j,k) - fs(i,j,km))/coords->dz(i,j,k); - + + BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(fs(i,j,k) - fs(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) + + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(fs(i-1,j,kp) - fs(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4*coords->dz(i,j,k)); + + BoutReal gD = coords->g13(i,j,k)*(fs(i+1,j,km) - fs(i-1,j,km) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) + + coords->g33(i,j,k)*(fs(i,j,k) - fs(i,j,km))/coords->dz(i,j,k); + BoutReal gU = coords->g13(i,j,k)*(fs(i+1,j,kp) - fs(i-1,j,kp) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) + coords->g33(i,j,k)*(fs(i,j,kp) - fs(i,j,k))/coords->dz(i,j,k); - - + + // Flow right BoutReal flux = gR * 0.25*(coords->J(i+1,j,k) + coords->J(i,j,k)) *(as(i+1,j,k) + as(i,j,k)); result(i,j,k) += flux / (coords->dx(i,j,k)*coords->J(i,j,k)); - + // Flow left flux = gL * 0.25*(coords->J(i-1,j,k) + coords->J(i,j,k)) *(as(i-1,j,k) + as(i,j,k)); result(i,j,k) -= flux / (coords->dx(i,j,k)*coords->J(i,j,k)); - - + + // Flow up flux = gU * 0.25*(coords->J(i,j,k) + coords->J(i,j,kp)) *(as(i,j,k) + as(i,j,kp)); result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); - // Flow down + // Flow down flux = gD * 0.25*(coords->J(i,j,km) + coords->J(i,j,k)) *(as(i,j,km) + as(i,j,k)); result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); } @@ -628,7 +628,7 @@ const Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outlo * Terms of form b0 x Grad(f) dot Grad(g) / B = [f, g] *******************************************************************************/ -const Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, +Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, BRACKET_METHOD method, CELL_LOC outloc, Solver* UNUSED(solver)) { TRACE("bracket(Field2D, Field2D)"); @@ -652,7 +652,7 @@ const Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, return result; } -const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, +Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *solver) { TRACE("bracket(Field3D, Field2D)"); @@ -672,7 +672,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, case BRACKET_CTU: { // First order Corner Transport Upwind method // P.Collela JCP 87, 171-200 (1990) - + if(!solver) throw BoutException("CTU method requires access to the solver"); @@ -683,25 +683,25 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, for(int y=mesh->ystart;y<=mesh->yend;y++) { for (int z = 0; z < ncz; z++) { int zm = (z - 1 + ncz) % ncz; - int zp = (z + 1) % ncz; - - BoutReal gp, gm; - + int zp = (z + 1) % ncz; + + BoutReal gp, gm; + // Vx = DDZ(f) BoutReal vx = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz(x,y,z)); - + // Set stability condition solver->setMaxTimestep(metric->dx(x, y, z) / (fabs(vx) + 1e-16)); // X differencing if(vx > 0.0) { gp = g(x,y); - + gm = g(x-1,y); - + }else { gp = g(x+1,y); - + gm = g(x,y); } @@ -792,35 +792,35 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, BOUT_OMP(parallel for) for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ - const BoutReal partialFactor = 1.0/(12 * metric->dz(jx,jy)); - const BoutReal spacingFactor = partialFactor / metric->dx(jx,jy); + const BoutReal partialFactor = 1.0/(12 * metric->dz(jx,jy)); + const BoutReal spacingFactor = partialFactor / metric->dx(jx,jy); for (int jz = 0; jz < mesh->LocalNz; jz++) { const int jzp = jz+1 < ncz ? jz + 1 : 0; - //Above is alternative to const int jzp = (jz + 1) % ncz; - const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; - //Above is alternative to const int jzmTmp = (jz - 1 + ncz) % ncz; + //Above is alternative to const int jzp = (jz + 1) % ncz; + const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; + //Above is alternative to const int jzmTmp = (jz - 1 + ncz) % ncz; // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) BoutReal Jpp = ( (f(jx,jy,jzp) - f(jx,jy,jzm))* - (g(jx+1,jy) - g(jx-1,jy)) - - (f(jx+1,jy,jz) - f(jx-1,jy,jz))* - (g(jx,jy) - g(jx,jy)) ); - + (g(jx+1,jy) - g(jx-1,jy)) - + (f(jx+1,jy,jz) - f(jx-1,jy,jz))* + (g(jx,jy) - g(jx,jy)) ); + // J+x BoutReal Jpx = ( g(jx+1,jy)*(f(jx+1,jy,jzp)-f(jx+1,jy,jzm)) - - g(jx-1,jy)*(f(jx-1,jy,jzp)-f(jx-1,jy,jzm)) - - g(jx,jy)*(f(jx+1,jy,jzp)-f(jx-1,jy,jzp)) + - g(jx,jy)*(f(jx+1,jy,jzm)-f(jx-1,jy,jzm))); + g(jx-1,jy)*(f(jx-1,jy,jzp)-f(jx-1,jy,jzm)) - + g(jx,jy)*(f(jx+1,jy,jzp)-f(jx-1,jy,jzp)) + + g(jx,jy)*(f(jx+1,jy,jzm)-f(jx-1,jy,jzm))); // Jx+ BoutReal Jxp = ( g(jx+1,jy)*(f(jx,jy,jzp)-f(jx+1,jy,jz)) - - g(jx-1,jy)*(f(jx-1,jy,jz)-f(jx,jy,jzm)) - - g(jx-1,jy)*(f(jx,jy,jzp)-f(jx-1,jy,jz)) + - g(jx+1,jy)*(f(jx+1,jy,jz)-f(jx,jy,jzm))); - + g(jx-1,jy)*(f(jx-1,jy,jz)-f(jx,jy,jzm)) - + g(jx-1,jy)*(f(jx,jy,jzp)-f(jx-1,jy,jz)) + + g(jx+1,jy)*(f(jx+1,jy,jz)-f(jx,jy,jzm))); + result(jx,jy,jz) = (Jpp + Jpx + Jxp) * spacingFactor; - } - } + } + } } #else throw BoutException("BRACKET_ARAKAWA_OLD not valid with 3D metrics yet."); @@ -840,7 +840,7 @@ const Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, return result; } -const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, +Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *solver) { TRACE("bracket(Field2D, Field3D)"); @@ -858,7 +858,7 @@ const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, case BRACKET_CTU: throw BoutException("Bracket method CTU is not yet implemented for [2d,3d] fields."); break; - case BRACKET_ARAKAWA: + case BRACKET_ARAKAWA: // It is symmetric, therefore we can return -[3d,2d] return -bracket(g,f,method,outloc,solver); break; @@ -873,11 +873,11 @@ const Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, result = b0xGrad_dot_Grad(f, g, outloc) / metric->Bxy; } } - + return result; } -const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, +Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, CELL_LOC outloc, Solver *solver) { TRACE("Field3D, Field3D"); @@ -898,7 +898,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, result.setLocation(outloc); return result; } - + switch(method) { case BRACKET_CTU: { // First order Corner Transport Upwind method @@ -909,33 +909,33 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, // Get current timestep BoutReal dt = solver->getCurrentTimestep(); - + FieldPerp vx(mesh), vz(mesh); vx.allocate(); vx.setLocation(outloc); vz.allocate(); vz.setLocation(outloc); - + int ncz = mesh->LocalNz; for(int y=mesh->ystart;y<=mesh->yend;y++) { for(int x=1;x<=mesh->LocalNx-2;x++) { for (int z = 0; z < mesh->LocalNz; z++) { int zm = (z - 1 + ncz) % ncz; int zp = (z + 1) % ncz; - + // Vx = DDZ(f) vx(x,z) = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz(x,y,z)); // Vz = -DDX(f) vz(x,z) = (f(x-1,y,z) - f(x+1,y,z))/(0.5*metric->dx(x-1,y) + metric->dx(x,y) + 0.5*metric->dx(x+1,y)); - + // Set stability condition solver->setMaxTimestep(fabs(metric->dx(x,y)) / (fabs(vx(x,z)) + 1e-16)); solver->setMaxTimestep(metric->dz(x,y) / (fabs(vz(x,z)) + 1e-16)); } } - + // Simplest form: use cell-centered velocities (no divergence included so not flux conservative) - + for(int x=mesh->xstart;x<=mesh->xend;x++) for (int z = 0; z < ncz; z++) { int zm = (z - 1 + ncz) % ncz; @@ -1028,7 +1028,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const int jzp = 1; const int jzm = ncz - 1; #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) @@ -1050,7 +1050,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, for (int jz = 1; jz < mesh->LocalNz - 1; jz++) { #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif const int jzp = jz + 1; const int jzm = jz - 1; @@ -1077,7 +1077,7 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const int jzp = 0; const int jzm = ncz - 2; #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) @@ -1113,8 +1113,8 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ #ifndef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx,jy) - * metric->dx(jx, jy)); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx,jy) + * metric->dx(jx, jy)); #endif const BoutReal *Fxm = f_temp(jx-1, jy); const BoutReal *Fx = f_temp(jx, jy); @@ -1124,30 +1124,30 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const BoutReal *Gxp = g_temp(jx+1, jy); for (int jz = 0; jz < mesh->LocalNz; jz++) { #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) - * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) + * metric->dx(jx, jy, jz)); #endif const int jzp = jz+1 < ncz ? jz + 1 : 0; - //Above is alternative to const int jzp = (jz + 1) % ncz; - const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; - //Above is alternative to const int jzm = (jz - 1 + ncz) % ncz; + //Above is alternative to const int jzp = (jz + 1) % ncz; + const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; + //Above is alternative to const int jzm = (jz - 1 + ncz) % ncz; // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) - BoutReal Jpp = ((Fx[jzp] - Fx[jzm])*(Gxp[jz] - Gxm[jz]) - - (Fxp[jz] - Fxm[jz])*(Gx[jzp] - Gx[jzm])); + BoutReal Jpp = ((Fx[jzp] - Fx[jzm])*(Gxp[jz] - Gxm[jz]) - + (Fxp[jz] - Fxm[jz])*(Gx[jzp] - Gx[jzm])); // J+x BoutReal Jpx = ( Gxp[jz]*(Fxp[jzp]-Fxp[jzm]) - - Gxm[jz]*(Fxm[jzp]-Fxm[jzm]) - - Gx[jzp]*(Fxp[jzp]-Fxm[jzp]) + - Gx[jzm]*(Fxp[jzm]-Fxm[jzm])) ; + Gxm[jz]*(Fxm[jzp]-Fxm[jzm]) - + Gx[jzp]*(Fxp[jzp]-Fxm[jzp]) + + Gx[jzm]*(Fxp[jzm]-Fxm[jzm])) ; // Jx+ BoutReal Jxp = ( Gxp[jzp]*(Fx[jzp]-Fxp[jz]) - - Gxm[jzm]*(Fxm[jz]-Fx[jzm]) - - Gxm[jzp]*(Fx[jzp]-Fxm[jz]) + - Gxp[jzm]*(Fxp[jz]-Fx[jzm])); - + Gxm[jzm]*(Fxm[jz]-Fx[jzm]) - + Gxm[jzp]*(Fx[jzp]-Fxm[jz]) + + Gxp[jzm]*(Fxp[jz]-Fx[jzm])); + result(jx, jy, jz) = (Jpp + Jpx + Jxp) * spacingFactor; } } @@ -1165,6 +1165,6 @@ const Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, result = b0xGrad_dot_Grad(f, g, outloc) / metric->Bxy; } } - + return result; } From 37861c4011b8c110d46a37105ce6a506766420fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 11:11:00 +0100 Subject: [PATCH 132/293] Cleanup --- include/bout/coordinates.hxx | 14 +++++++------- include/bout/invert/laplacexz.hxx | 2 +- tests/integrated/test-laplacexz/runtest | 4 +--- tests/requirements/metric_3d | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 5631651c3c..e80b8f9084 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -165,18 +165,18 @@ public: #ifdef DERIV_FUNC_REGION_ENUM_TO_STRING #error This utility macro should not clash with another one #else -#define DERIV_FUNC_REGION_ENUM_TO_STRING(func, Tr, T) \ - [[deprecated("Please use Coordinates::#func(const #T& f, " \ +#define DERIV_FUNC_REGION_ENUM_TO_STRING(func, ResultType, T) \ + [[deprecated("Please use Coordinates::#func(const #T& f, " \ "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\", " \ "const std::string& region = \"RGN_ALL\") instead")]] \ - inline Tr func(const T& f, CELL_LOC outloc, const std::string& method, \ + inline ResultType func(const T& f, CELL_LOC outloc, const std::string& method, \ REGION region) { \ return func(f, outloc, method, toString(region)); \ } \ [[deprecated("Please use Coordinates::#func(const #T& f, " \ "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\", " \ "const std::string& region = \"RGN_ALL\") instead")]] \ - inline Tr func(const T& f, CELL_LOC outloc, DIFF_METHOD method, \ + inline ResultType func(const T& f, CELL_LOC outloc, DIFF_METHOD method, \ REGION region = RGN_NOBNDRY) { \ return func(f, outloc, toString(method), toString(region)); \ } @@ -185,11 +185,11 @@ public: #ifdef GRAD_FUNC_REGION_ENUM_TO_STRING #error This utility macro should not clash with another one #else -#define GRAD_FUNC_REGION_ENUM_TO_STRING(func, Tr, T) \ - [[deprecated("Please use Coordinates::#func(const #T& f, " \ +#define GRAD_FUNC_REGION_ENUM_TO_STRING(func, ResultType, T) \ + [[deprecated("Please use Coordinates::#func(const #T& f, " \ "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\") " \ "instead")]] \ - inline Tr func(const T& f, CELL_LOC outloc, DIFF_METHOD method) { \ + inline ResultType func(const T& f, CELL_LOC outloc, DIFF_METHOD method) { \ return func(f, outloc, toString(method)); \ } #endif diff --git a/include/bout/invert/laplacexz.hxx b/include/bout/invert/laplacexz.hxx index cf8745c385..a8bc611fb6 100644 --- a/include/bout/invert/laplacexz.hxx +++ b/include/bout/invert/laplacexz.hxx @@ -51,7 +51,7 @@ public: ReturnType create(Mesh* mesh = nullptr, Options* options = nullptr, CELL_LOC loc = CELL_CENTRE) { - options = options == nullptr ? Options::getRoot()->getSection(section_name) : options; + options = optionsOrDefaultSection(options); return Factory::create(getType(options), mesh, options, loc); } diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index 600374f3c0..ee21d1149a 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -24,9 +24,7 @@ from sys import stdout, exit MPIRUN = getmpirun() -print("Making LaplaceXZ test") -shell("rm test-laplacexz") -shell_safe("make > make.log") +build_and_log("LaplaceXZ test") print("Running LaplaceXZ test") success = True diff --git a/tests/requirements/metric_3d b/tests/requirements/metric_3d index 38c2146d3b..052813fc84 100755 --- a/tests/requirements/metric_3d +++ b/tests/requirements/metric_3d @@ -7,7 +7,7 @@ from sys import exit from boututils.run_wrapper import shell selflocation = os.path.realpath(__file__) -selflocation = selflocation.rsplit("/", 1)[0] +selflocation = os.path.dirname(selflocation) status, out = shell(selflocation+"/../../bin/bout-config --metric-type", pipe=True) if "3D" in out: From a89fef04c428150e4f4771e4704ae1ca30ff2776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 11:12:03 +0100 Subject: [PATCH 133/293] Whitespace fixes Use spaces not tabs --- .../laplace/impls/petsc/petsc_laplace.cxx | 52 +-- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 414 +++++++++--------- 2 files changed, 233 insertions(+), 233 deletions(-) diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index ffbc06f097..8d2d62799f 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -400,25 +400,25 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { if(inner_boundary_flags & INVERT_AC_GRAD) { // Set values corresponding to nodes adjacent in x if( fourth_order ) { - // Fourth Order Accuracy on Boundary - Element(i,x,z, 0, 0, -25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 1, 0, 4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 2, 0, -3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 3, 0, 4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 4, 0, -1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + // Fourth Order Accuracy on Boundary + Element(i,x,z, 0, 0, -25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 1, 0, 4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 2, 0, -3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 3, 0, 4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 4, 0, -1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); } else { - // Second Order Accuracy on Boundary - // Element(i,x,z, 0, 0, -3.0 / (2.0*coords->dx(x,y)), MatA ); - // Element(i,x,z, 1, 0, 2.0 / coords->dx(x,y), MatA ); - // Element(i,x,z, 2, 0, -1.0 / (2.0*coords->dx(x,y)), MatA ); - // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now - // Element(i,x,z, 4, 0, 0.0, MatA ); - // Second Order Accuracy on Boundary, set half-way between grid points - Element(i,x,z, 0, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 1, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 2, 0, 0.0, MatA ); - // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now - // Element(i,x,z, 4, 0, 0.0, MatA ); + // Second Order Accuracy on Boundary + // Element(i,x,z, 0, 0, -3.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, 1, 0, 2.0 / coords->dx(x,y), MatA ); + // Element(i,x,z, 2, 0, -1.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, 4, 0, 0.0, MatA ); + // Second Order Accuracy on Boundary, set half-way between grid points + Element(i,x,z, 0, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 1, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 2, 0, 0.0, MatA ); + // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, 4, 0, 0.0, MatA ); } } else { if (fourth_order) { @@ -650,11 +650,11 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { // Set values corresponding to nodes adjacent in x if( fourth_order ) { // Fourth Order Accuracy on Boundary - Element(i,x,z, 0, 0, 25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -1, 0, -4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -2, 0, 3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -3, 0, -4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -4, 0, 1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, 0, 0, 25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -1, 0, -4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -2, 0, 3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -3, 0, -4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -4, 0, 1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); } else { // // Second Order Accuracy on Boundary @@ -664,9 +664,9 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { // // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now // // Element(i,x,z, -4, 0, 0.0, MatA ); // Second Order Accuracy on Boundary, set half-way between grid points - Element(i,x,z, 0, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -1, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -2, 0, 0.0, MatA ); + Element(i,x,z, 0, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -1, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i,x,z, -2, 0, 0.0, MatA ); // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now // Element(i,x,z, -4, 0, 0.0, MatA ); } diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index 762434eda7..c6f9426ff9 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -141,7 +141,7 @@ LaplaceXZpetsc::LaplaceXZpetsc(Mesh *m, Options *opt, const CELL_LOC loc) // Get KSP Solver Type const std::string ksptype = (*opt)["ksptype"].doc("KSP solver type").withDefault("gmres"); - + // Get PC type const std::string pctype = (*opt)["pctype"].doc("Preconditioner type").withDefault("none"); @@ -186,7 +186,7 @@ LaplaceXZpetsc::LaplaceXZpetsc(Mesh *m, Options *opt, const CELL_LOC loc) for (int i=0;igetCoordinates(location); - + for(int x=localmesh->xstart; x <= localmesh->xend; x++) { for(int z=0; z < localmesh->LocalNz; z++) { - // stencil entries - PetscScalar c, xm, xp, zm, zp, xpzp, xpzm, xmzp, xmzm; - PetscScalar zpxp, zpxm, zmxp, zmxm; - - // XX component - - // Metrics on x+1/2 boundary - BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); - BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); - xp = val; - c = -val; - - // Metrics on x-1/2 boundary - J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); - g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); - dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - - val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); - xm = val; - c -= val; - - // ZZ component - // Wrap around z-1 and z+1 indices - int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); - int zplus = (z + 1) % (localmesh->LocalNz); - - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); - BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); - const BoutReal dz = coords->dz(x,y,z); - // Metrics on z+1/2 boundary - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); - zp = val; - c -= val; - - // Metrics on z-1/2 boundary - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); - g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); - zm = val; - c -= val; - - // XZ components - - // x+1/2, z+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); - const BoutReal fourdz= 4.*dz; - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xpzp = val; - c -= val; - - // x+1/2, z-1/2 - // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xpzm = val; - c -= val; - - // x-1/2, z+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); - g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xmzp = val; - c -= val; - - // x-1/2, z-1/2 - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xmzm = val; - c -= val; - - - // ZX components - // z+1/2, x+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); - g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zpxp = val; - c -= val; - - //z+1/2, x-1/2 - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zpxm = val; - c -= val; - - // z-1/2, x+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); - g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zmxp = val; - c -= val; - - // z-1/2, x-1/2 - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zmxm = val; - c -= val; - - - ///////////// OLDER CODE ///////////////// - // Note that because metrics are constant in Z many terms cancel - - // // Wrap around z-1 and z+1 indices - // // int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); - // // int zplus = (z + 1) % (localmesh->LocalNz); - - // // Metrics on z+1/2 boundary - // Acoef = 0.5*(A(x,y,z) + A(x,y,z+1)); - - // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); - // zp = val; - // c -= val; - - // // Metrics on z-1/2 boundary - // Acoef = 0.5*(A(x,y,z) + A(x,y,z-1)); - - // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); - // zm = val; - // c -= val; - ////////////////////////////////////////// - - - // B term - c += B(x,y,z); - - ///////////////////////////////////////////////// - // Now have a 5-point stencil for the Laplacian - - // Set the centre (diagonal) - MatSetValues(it.MatA,1,&row,1,&row,&c,INSERT_VALUES); - - // X + 1 - int col = row + (localmesh->LocalNz); - MatSetValues(it.MatA,1,&row,1,&col,&xp,INSERT_VALUES); - - // X - 1 - col = row - (localmesh->LocalNz); - MatSetValues(it.MatA,1,&row,1,&col,&xm,INSERT_VALUES); - - // Z + 1 - col = row + 1; - if(z == localmesh->LocalNz-1) { - col -= localmesh->LocalNz; // Wrap around - } - MatSetValues(it.MatA,1,&row,1,&col,&zp,INSERT_VALUES); - - int xzcol = col + (localmesh->LocalNz); // X+1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzp,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxp,INSERT_VALUES); - - xzcol = col - (localmesh->LocalNz); // X-1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzp,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxm,INSERT_VALUES); - - // Z - 1 - col = row - 1; - if(z == 0) { - col += localmesh->LocalNz; // Wrap around - } - MatSetValues(it.MatA,1,&row,1,&col,&zm,INSERT_VALUES); - - xzcol = col + (localmesh->LocalNz); // X+1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzm,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxp,INSERT_VALUES); - - xzcol = col - (localmesh->LocalNz); // X-1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzm,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxm,INSERT_VALUES); - - row++; + // stencil entries + PetscScalar c, xm, xp, zm, zp, xpzp, xpzm, xmzp, xmzm; + PetscScalar zpxp, zpxm, zmxp, zmxm; + + // XX component + + // Metrics on x+1/2 boundary + BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); + BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xp = val; + c = -val; + + // Metrics on x-1/2 boundary + J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); + dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xm = val; + c -= val; + + // ZZ component + // Wrap around z-1 and z+1 indices + int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); + int zplus = (z + 1) % (localmesh->LocalNz); + + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); + BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); + const BoutReal dz = coords->dz(x,y,z); + // Metrics on z+1/2 boundary + Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + zp = val; + c -= val; + + // Metrics on z-1/2 boundary + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); + g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); + Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + zm = val; + c -= val; + + // XZ components + + // x+1/2, z+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); + const BoutReal fourdz= 4.*dz; + Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xpzp = val; + c -= val; + + // x+1/2, z-1/2 + // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xpzm = val; + c -= val; + + // x-1/2, z+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xmzp = val; + c -= val; + + // x-1/2, z-1/2 + Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xmzm = val; + c -= val; + + + // ZX components + // z+1/2, x+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); + g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zpxp = val; + c -= val; + + //z+1/2, x-1/2 + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zpxm = val; + c -= val; + + // z-1/2, x+1/2 + J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); + g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zmxp = val; + c -= val; + + // z-1/2, x-1/2 + dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zmxm = val; + c -= val; + + + ///////////// OLDER CODE ///////////////// + // Note that because metrics are constant in Z many terms cancel + + // // Wrap around z-1 and z+1 indices + // // int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); + // // int zplus = (z + 1) % (localmesh->LocalNz); + + // // Metrics on z+1/2 boundary + // Acoef = 0.5*(A(x,y,z) + A(x,y,z+1)); + + // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); + // zp = val; + // c -= val; + + // // Metrics on z-1/2 boundary + // Acoef = 0.5*(A(x,y,z) + A(x,y,z-1)); + + // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); + // zm = val; + // c -= val; + ////////////////////////////////////////// + + + // B term + c += B(x,y,z); + + ///////////////////////////////////////////////// + // Now have a 5-point stencil for the Laplacian + + // Set the centre (diagonal) + MatSetValues(it.MatA,1,&row,1,&row,&c,INSERT_VALUES); + + // X + 1 + int col = row + (localmesh->LocalNz); + MatSetValues(it.MatA,1,&row,1,&col,&xp,INSERT_VALUES); + + // X - 1 + col = row - (localmesh->LocalNz); + MatSetValues(it.MatA,1,&row,1,&col,&xm,INSERT_VALUES); + + // Z + 1 + col = row + 1; + if(z == localmesh->LocalNz-1) { + col -= localmesh->LocalNz; // Wrap around + } + MatSetValues(it.MatA,1,&row,1,&col,&zp,INSERT_VALUES); + + int xzcol = col + (localmesh->LocalNz); // X+1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzp,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxp,INSERT_VALUES); + + xzcol = col - (localmesh->LocalNz); // X-1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzp,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxm,INSERT_VALUES); + + // Z - 1 + col = row - 1; + if(z == 0) { + col += localmesh->LocalNz; // Wrap around + } + MatSetValues(it.MatA,1,&row,1,&col,&zm,INSERT_VALUES); + + xzcol = col + (localmesh->LocalNz); // X+1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzm,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxp,INSERT_VALUES); + + xzcol = col - (localmesh->LocalNz); // X-1 + MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzm,INSERT_VALUES); + MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxm,INSERT_VALUES); + + row++; } } - + //////////////////////////////////////////////// // Outer X boundary (see note about BC in LaplaceXZ constructor) if(localmesh->lastX()) { @@ -797,12 +797,12 @@ Field3D LaplaceXZpetsc::solve(const Field3D &bin, const Field3D &x0in) { // Set the inner points for(int x=localmesh->xstart;x<= localmesh->xend;x++) { for(int z=0; z < localmesh->LocalNz; z++) { - PetscScalar val = x0(x,y,z); - VecSetValues( xs, 1, &ind, &val, INSERT_VALUES ); - - val = b(x,y,z); - VecSetValues( bs, 1, &ind, &val, INSERT_VALUES ); - ind++; + PetscScalar val = x0(x,y,z); + VecSetValues( xs, 1, &ind, &val, INSERT_VALUES ); + + val = b(x,y,z); + VecSetValues( bs, 1, &ind, &val, INSERT_VALUES ); + ind++; } } From 891c40dc45e90d82fdbc94a0b2142adf4eabb0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 14:12:32 +0100 Subject: [PATCH 134/293] move definition of is3D to header constexpr need to be known at compile time --- include/bout/coordinates.hxx | 8 +++++++- src/mesh/coordinates.cxx | 7 ------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index e80b8f9084..cf7db3b44c 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -140,7 +140,13 @@ public: int jacobian(); ///< Calculate J and Bxy /// Return if the metrics are 3D - constexpr bool is3D() const; + constexpr bool is3D() const { +#ifdef COORDINATES_USE_3D + return true; +#else + return false; +#endif + } /////////////////////////////////////////////////////////// // Parallel transforms diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 147293eb75..5d3a59843b 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -2000,10 +2000,3 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, return bout::derivatives::index::DDY(f, outloc, method, region); } -constexpr bool Coordinates::is3D() const { -#ifdef COORDINATES_USE_3D - return true; -#else - return false; -#endif -} From b7e02f14363bbf689a672f7b77d0d74a4d7c3c3a Mon Sep 17 00:00:00 2001 From: Brendan Date: Thu, 14 May 2020 15:49:37 +0200 Subject: [PATCH 135/293] Add R_maj function to RotatingEllipse in Zoidberg --- tools/pylib/zoidberg/field.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 0c55d99546..0e6174e003 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -485,6 +485,9 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") self.Byfunc = lambdify((self.x, self.z, self.phi), By, "numpy") + + def Rfunc(self, x, z, phi): + return np.full(x.shape, x) except ImportError: class StraightStellarator(MagneticField): From 88605d0b3574a1e8cb88c7079ba62ffd03fb24ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 15:16:23 +0100 Subject: [PATCH 136/293] Workaround for old gcc --- include/bout/coordinates.hxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index cf7db3b44c..99a824005d 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -140,7 +140,8 @@ public: int jacobian(); ///< Calculate J and Bxy /// Return if the metrics are 3D - constexpr bool is3D() const { + // needs to be static for old gcc + static constexpr bool is3D() { #ifdef COORDINATES_USE_3D return true; #else From 0ff2f79771627e373a09dc9f98528053cba5c779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 14 May 2020 16:39:13 +0100 Subject: [PATCH 137/293] More const vars --- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 245 ++++++++++-------- 1 file changed, 134 insertions(+), 111 deletions(-) diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index c6f9426ff9..e837e618f1 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -390,125 +390,148 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { PetscScalar zpxp, zpxm, zmxp, zmxm; // XX component + { + // Metrics on x+1/2 boundary + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + const BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); + const BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + const BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xp = val; + c = -val; + } - // Metrics on x+1/2 boundary - BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); - BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); - xp = val; - c = -val; - - // Metrics on x-1/2 boundary - J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); - g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); - dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + { + // Metrics on x-1/2 boundary + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + const BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); + const BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); - xm = val; - c -= val; + const BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + xm = val; + c -= val; + } // ZZ component // Wrap around z-1 and z+1 indices - int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); - int zplus = (z + 1) % (localmesh->LocalNz); - - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); - BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); - const BoutReal dz = coords->dz(x,y,z); - // Metrics on z+1/2 boundary - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); - zp = val; - c -= val; - - // Metrics on z-1/2 boundary - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); - g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); - zm = val; - c -= val; + const int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); + const int zplus = (z + 1) % (localmesh->LocalNz); + + { + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); + const BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); + const BoutReal dz = coords->dz(x,y,z); + // Metrics on z+1/2 boundary + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + const BoutReal val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + zp = val; + c -= val; + } + { + // Metrics on z-1/2 boundary + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); + const BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + const BoutReal val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + zm = val; + c -= val; + } // XZ components - // x+1/2, z+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); - const BoutReal fourdz= 4.*dz; - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xpzp = val; - c -= val; - - // x+1/2, z-1/2 - // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xpzm = val; - c -= val; - - // x-1/2, z+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); - g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xmzp = val; - c -= val; - - // x-1/2, z-1/2 - Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); - xmzm = val; - c -= val; - - - // ZX components - // z+1/2, x+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); - g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zpxp = val; - c -= val; - - //z+1/2, x-1/2 - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zpxm = val; - c -= val; - - // z-1/2, x+1/2 - J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); - g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); - - val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zmxp = val; - c -= val; - - // z-1/2, x-1/2 - dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); - - val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); - zmxm = val; - c -= val; + { + // x+1/2, z+1/2 + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); + const BoutReal fourdz= 4.*dz; + { + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xpzp = val; + c -= val; + } + { + // x+1/2, z-1/2 + // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); + // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xpzm = val; + c -= val; + } + + { + // x-1/2, z+1/2 + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); + const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); + { + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + + const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xmzp = val; + c -= val; + } + { + // x-1/2, z-1/2 + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + + const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + xmzm = val; + c -= val; + } + } + + { + // ZX components + // z+1/2, x+1/2 + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); + const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); + { + const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zpxp = val; + c -= val; + } + { + //z+1/2, x-1/2 + const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zpxm = val; + c -= val; + } + } + { + // z-1/2, x+1/2 + const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); + const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); + { + const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + + const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zmxp = val; + c -= val; + } + { + // z-1/2, x-1/2 + const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); + const BoutReal Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + + const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + zmxm = val; + c -= val; + } + } ///////////// OLDER CODE ///////////////// From 115b52214e851ba5c670cb2992c7d771c7e68cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 12:52:36 +0100 Subject: [PATCH 138/293] Take dz at the same location as the other metric quantities --- src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index e837e618f1..bfe67f7dc7 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -422,7 +422,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { { const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); const BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); - const BoutReal dz = coords->dz(x,y,z); + const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zplus)); // Metrics on z+1/2 boundary const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); @@ -435,6 +435,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); const BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zminus)); const BoutReal val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); zm = val; @@ -445,9 +446,10 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { { // x+1/2, z+1/2 + // TODOL Should they have a z dependency? const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); - const BoutReal fourdz= 4.*dz; + const BoutReal fourdz = 2 * (coords->dz(x,y,z)+ coords->dz(x+1,y,zplus)); { const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); @@ -465,11 +467,12 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { xpzm = val; c -= val; } - + } { // x-1/2, z+1/2 const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); + const BoutReal fourdz = 2 * (coords->dz(x,y,z)+ coords->dz(x-1,y,z)); { const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); @@ -492,6 +495,8 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // z+1/2, x+1/2 const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); + const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zplus)); + { const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); @@ -514,6 +519,7 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // z-1/2, x+1/2 const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); + const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zminus)); { const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); From 21e916c72070a41c4de2a33dcb1b4847039f4c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 14:03:29 +0100 Subject: [PATCH 139/293] Fix whitespace in coordinates.cxx --- src/mesh/coordinates.cxx | 105 +++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 5d3a59843b..22c091b4ef 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -28,8 +28,8 @@ namespace { /// 'free_o3' boundary conditions /// Corner guard cells are set to BoutNaN Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, - bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* UNUSED(pt) = nullptr) { + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* UNUSED(pt) = nullptr) { Mesh* localmesh = f.getMesh(); Field2D result = interp_to(f, location, "RGN_NOBNDRY"); @@ -151,8 +151,8 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, #define interpolateAndExtrapolate(a,b,c,d,e) _interpolateAndExtrapolate(a, b, c, d, e, transform.get()) Field3D _interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, - bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* pt_) { + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* pt_) { Mesh* localmesh = f_.getMesh(); Field3D result; @@ -166,9 +166,9 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, // Cannot use normal ifs, so that f is const if (f.getDirectionY() != YDirectionType::Standard) { if (pt_f->canToFromFieldAligned()) { - f = pt_f->fromFieldAligned(f); + f = pt_f->fromFieldAligned(f); } else { - f.setDirectionY(YDirectionType::Standard); + f.setDirectionY(YDirectionType::Standard); } } if (location == CELL_YLOW){ @@ -176,9 +176,9 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, result = interp_to(f_aligned, location, "RGN_NOBNDRY"); ParallelTransform * pt_result; if (result.getCoordinates() == nullptr){ - pt_result = pt_; + pt_result = pt_; } else { - pt_result = & result.getCoordinates()->getParallelTransform(); + pt_result = & result.getCoordinates()->getParallelTransform(); } result = pt_result->fromFieldAligned(result, "RGN_NOBNDRY"); } else { @@ -228,15 +228,15 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, ASSERT1(bndry->bx == 0 or localmesh->xstart > 1); ASSERT1(bndry->by == 0 or localmesh->ystart > 1); // note that either bx or by is >0 here - for (int zi=0; zi < localmesh->LocalNz; ++zi){ - result(bndry->x, bndry->y, zi) = + for (int zi=0; zi < localmesh->LocalNz; ++zi){ + result(bndry->x, bndry->y, zi) = (9. * (f(bndry->x - bndry->bx, bndry->y - bndry->by, zi) + f(bndry->x, bndry->y, zi)) - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, zi) - f(bndry->x + bndry->bx, bndry->y + bndry->by, zi)) / 16.; - } + } - } + } // set boundary guard cells if ((bndry->bx != 0 && localmesh->GlobalNx - 2 * bndry->width >= 3) || (bndry->by != 0 @@ -261,19 +261,19 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, for (int i = extrap_start; i < bndry->width; i++) { int xi = bndry->x + i * bndry->bx; int yi = bndry->y + i * bndry->by; - for (int zi=0; zi < localmesh->LocalNz; ++zi){ - result(xi, yi, zi) = 3.0 * result(xi - bndry->bx, yi - bndry->by, zi) - - 3.0 * result(xi - 2 * bndry->bx, yi - 2 * bndry->by, zi) - + result(xi - 3 * bndry->bx, yi - 3 * bndry->by, zi); - } + for (int zi=0; zi < localmesh->LocalNz; ++zi){ + result(xi, yi, zi) = 3.0 * result(xi - bndry->bx, yi - bndry->by, zi) + - 3.0 * result(xi - 2 * bndry->bx, yi - 2 * bndry->by, zi) + + result(xi - 3 * bndry->bx, yi - 3 * bndry->by, zi); + } } } else { // not enough grid points to extrapolate, set equal to last grid point for (int i = extrap_start; i < bndry->width; i++) { - for (int zi = 0; zi < localmesh->LocalNz; ++zi){ - result(bndry->x + i * bndry->bx, bndry->y + i * bndry->by, zi) = - result(bndry->x - bndry->bx, bndry->y - bndry->by, zi); - } + for (int zi = 0; zi < localmesh->LocalNz; ++zi){ + result(bndry->x + i * bndry->bx, bndry->y + i * bndry->by, zi) = + result(bndry->x - bndry->bx, bndry->y - bndry->by, zi); + } } } } @@ -293,12 +293,12 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, // Invalidate corner guard cells for (int i = 0; i < localmesh->xstart; i++) { for (int j = 0; j < localmesh->ystart; j++) { - for (int k = 0; k < localmesh->LocalNz; ++k) { - result(i, j, k) = BoutNaN; - result(i, localmesh->LocalNy - 1 - j, k) = BoutNaN; - result(localmesh->LocalNx - 1 - i, j, k) = BoutNaN; - result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, k) = BoutNaN; - } + for (int k = 0; k < localmesh->LocalNz; ++k) { + result(i, j, k) = BoutNaN; + result(i, localmesh->LocalNy - 1 - j, k) = BoutNaN; + result(localmesh->LocalNx - 1 - i, j, k) = BoutNaN; + result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, k) = BoutNaN; + } } } } @@ -459,7 +459,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) GET(g12, 0.0); GET(g13, 0.0); GET(g23, 0.0); - + communicate(g11, g22, g33, g12, g13, g23); // Check input metrics @@ -652,24 +652,24 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->xstart; i++){ - COORDS_ITER_Z - { - result(bndry->x + i * bndry->bx, bndry->y, z) = + COORDS_ITER_Z + { + result(bndry->x + i * bndry->bx, bndry->y, z) = result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); - } - } + } + } } } if (bndry->by != 0) { // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->ystart; i++) { - COORDS_ITER_Z + COORDS_ITER_Z { - result(bndry->x, bndry->y + i * bndry->by, z) = - result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); - } - } + result(bndry->x, bndry->y + i * bndry->by, z) = + result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); + } + } } } } @@ -679,10 +679,10 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY for (int j = 0; j < localmesh->ystart; j++) { COORDS_ITER_Z { - result(i, j, z) = BoutNaN; - result(i, localmesh->LocalNy - 1 - j, z) = BoutNaN; - result(localmesh->LocalNx - 1 - i, j, z) = BoutNaN; - result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, z) = BoutNaN; + result(i, j, z) = BoutNaN; + result(i, localmesh->LocalNy - 1 - j, z) = BoutNaN; + result(localmesh->LocalNx - 1 - i, j, z) = BoutNaN; + result(localmesh->LocalNx - 1 - i, localmesh->LocalNy - 1 - j, z) = BoutNaN; } } } @@ -1025,7 +1025,7 @@ int Coordinates::geometry(bool recalculate_staggered, bool force_interpolate_from_centre) { TRACE("Coordinates::geometry"); communicate(dx, dy, dz, g11, g22, g33, g12, g13, g23, - g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); + g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); output_progress.write("Calculating differential geometry terms\n"); @@ -1142,9 +1142,9 @@ int Coordinates::geometry(bool recalculate_staggered, output_progress.write("\tCommunicating connection terms\n"); communicate(G1_11, G1_22, G1_33, G1_12, G1_13, G1_23, - G2_11, G2_22, G2_33, G2_12, G2_13, G2_23, - G3_11, G3_22, G3_33, G3_12, G3_13, G3_23, - G1, G2, G3); + G2_11, G2_22, G2_33, G2_12, G2_13, G2_23, + G3_11, G3_22, G3_33, G3_12, G3_13, G3_23, + G1, G2, G3); // Set boundary guard cells of Christoffel symbol terms // Ideally, when location is staggered, we would set the upper/outer boundary point @@ -1448,7 +1448,7 @@ namespace { zShift = _interpolateAndExtrapolate(zShift, zShift.getLocation(), not localmesh->sourceHasXBoundaryGuards(), not localmesh->sourceHasYBoundaryGuards(), - false); + false); // make sure zShift has been communicated communicate(zShift); @@ -1458,13 +1458,13 @@ namespace { const auto lower = localmesh->hasBranchCutLower(x); if (lower.first) { for (int y = 0; y < localmesh->ystart; y++) { - zShift(x, y) -= lower.second; + zShift(x, y) -= lower.second; } } const auto upper = localmesh->hasBranchCutUpper(x); if (upper.first) { for (int y = localmesh->yend + 1; y < localmesh->LocalNy; y++) { - zShift(x, y) += upper.second; + zShift(x, y) += upper.second; } } } @@ -1594,7 +1594,7 @@ Coordinates::metric_field_type Coordinates::DDZ(const Field2D& f, CELL_LOC loc, return zeroFrom(f).setLocation(loc); } Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::DDZ(f, outloc, method, region) / dz; }; @@ -1968,7 +1968,7 @@ Field2D Coordinates::Laplace_perpXY(const Field2D& A, const Field2D& f) { } Coordinates::metric_field_type Coordinates::indexDDY(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region){ + const std::string& method, const std::string& region){ #ifdef COORDINATES_USE_3D if (!f.hasParallelSlices()){ const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); @@ -1981,7 +1981,7 @@ Coordinates::metric_field_type Coordinates::indexDDY(const Field2D& f, CELL_LOC } Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region){ + const std::string& method, const std::string& region){ #ifdef COORDINATES_USE_3D if (!f.hasParallelSlices()){ const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); @@ -1999,4 +1999,3 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, #endif return bout::derivatives::index::DDY(f, outloc, method, region); } - From 4b3dd1fe6c1c9822415294501fb0596b4cddddbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 14:29:02 +0100 Subject: [PATCH 140/293] Don't use macro to add argument to interpolateAndExtrapolate --- src/mesh/coordinates.cxx | 198 +++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 100 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 22c091b4ef..638a333624 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -27,9 +27,9 @@ namespace { /// Boundary guard cells are set by extrapolating from the grid, like /// 'free_o3' boundary conditions /// Corner guard cells are set to BoutNaN -Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, - bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* UNUSED(pt) = nullptr) { +Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* UNUSED(pt) = nullptr) { Mesh* localmesh = f.getMesh(); Field2D result = interp_to(f, location, "RGN_NOBNDRY"); @@ -148,11 +148,9 @@ Field2D _interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, return result; } -#define interpolateAndExtrapolate(a,b,c,d,e) _interpolateAndExtrapolate(a, b, c, d, e, transform.get()) - - Field3D _interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, - bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* pt_) { + Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* pt_) { Mesh* localmesh = f_.getMesh(); Field3D result; @@ -437,14 +435,14 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // required early for differentiation. setParallelTransform(options); - dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, transform.get()); + dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, transform.get()); if (mesh->periodicX) { communicate(dx); } - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false); + dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, transform.get()); #define GET(a,b) \ mesh->get(a, #a, b, false); \ @@ -517,12 +515,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) } // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false); - g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false); - g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false); - g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false); - g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false); - g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false); + g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false, transform.get()); // Check covariant metrics // Diagonal metric components should be finite @@ -549,7 +547,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) "\tWARNING: Jacobian 'J' not found. Calculating from metric tensor\n"); J = Jcalc; } else { - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, transform.get()); // Compare calculated and loaded values output_warn.write("\tMaximum difference in J is {:e}\n", max(abs(J - Jcalc))); @@ -575,7 +573,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) Bxy = Bcalc; } else { - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, transform.get()); output_warn.write("\tMaximum difference in Bxy is {:e}\n", max(abs(Bxy - Bcalc))); } @@ -594,7 +592,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) "\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); ShiftTorsion = 0.0; } - ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false); + ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); ////////////////////////////////////////////////////// @@ -602,7 +600,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) if (mesh->get(IntShiftTorsion, "IntShiftTorsion", 0.0, false)) { output_warn.write("\tWARNING: No Integrated torsion specified\n"); } - IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false); + IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; @@ -618,7 +616,7 @@ namespace { /// 2nd order accurate Neumann boundary condition). /// Corner guard cells are set to BoutNaN Coordinates::metric_field_type -interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAYBE_UNUSED(CELL_LOC location), ParallelTransform * pt) { +interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAYBE_UNUSED(CELL_LOC location), MAYBE_UNUSED(ParallelTransform * pt)) { #ifndef COORDINATES_USE_3D #define COORDS_ITER_Z int z=0; #else @@ -738,32 +736,32 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } setParallelTransform(options); - dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, transform.get()); getAtLoc(mesh, dx, "dx", suffix, location, 1.0); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false); + dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, transform.get()); if (mesh->periodicX) { communicate(dx); } getAtLoc(mesh, dy, "dy", suffix, location, 1.0); - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false); + dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, transform.get()); // grid data source has staggered fields, so read instead of interpolating // Diagonal components of metric tensor g^{ij} (default to 1) getAtLoc(mesh, g11, "g11", suffix, location, 1.0); - g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false); + g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, transform.get()); getAtLoc(mesh, g22, "g22", suffix, location, 1.0); - g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false); + g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, transform.get()); getAtLoc(mesh, g33, "g33", suffix, location, 1.0); - g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false); + g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, transform.get()); getAtLoc(mesh, g12, "g12", suffix, location, 0.0); - g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false); + g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, transform.get()); getAtLoc(mesh, g13, "g13", suffix, location, 0.0); - g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false); + g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, transform.get()); getAtLoc(mesh, g23, "g23", suffix, location, 0.0); - g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false); + g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, transform.get()); // Check input metrics // Diagonal metric components should be finite @@ -817,12 +815,12 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false); - g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false); - g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false); - g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false); - g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false); - g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false); + g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false, transform.get()); // Check covariant metrics // Diagonal metric components should be finite @@ -852,7 +850,7 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, suffix.c_str()); J = Jcalc; } else { - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, transform.get()); // Compare calculated and loaded values output_warn.write("\tMaximum difference in J is %e\n", max(abs(J - Jcalc))); @@ -875,7 +873,7 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, " from metric tensor\n", suffix.c_str()); Bxy = Bcalc; } else { - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, transform.get()); output_warn.write("\tMaximum difference in Bxy is %e\n", max(abs(Bxy - Bcalc))); } @@ -890,7 +888,7 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, ShiftTorsion = 0.0; } ShiftTorsion.setLocation(location); - ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false); + ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); ////////////////////////////////////////////////////// @@ -901,7 +899,7 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, IntShiftTorsion = 0.0; } IntShiftTorsion.setLocation(location); - IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false); + IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; @@ -916,31 +914,31 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, throw BoutException("We are asked to transform dz to get dz before we have a transform, which might require dz!\nPlease provide a dz for the staggered quantity!"); } setParallelTransform(options); - dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false); - dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false); + dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false, transform.get()); + dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false, transform.get()); // not really needed - we have used dz already ... - dz = interpolateAndExtrapolate(coords_in->dz, location, true, true, false); + dz = interpolateAndExtrapolate(coords_in->dz, location, true, true, false, transform.get()); // Diagonal components of metric tensor g^{ij} - g11 = interpolateAndExtrapolate(coords_in->g11, location, true, true, false); - g22 = interpolateAndExtrapolate(coords_in->g22, location, true, true, false); - g33 = interpolateAndExtrapolate(coords_in->g33, location, true, true, false); + g11 = interpolateAndExtrapolate(coords_in->g11, location, true, true, false, transform.get()); + g22 = interpolateAndExtrapolate(coords_in->g22, location, true, true, false, transform.get()); + g33 = interpolateAndExtrapolate(coords_in->g33, location, true, true, false, transform.get()); // Off-diagonal elements. - g12 = interpolateAndExtrapolate(coords_in->g12, location, true, true, false); - g13 = interpolateAndExtrapolate(coords_in->g13, location, true, true, false); - g23 = interpolateAndExtrapolate(coords_in->g23, location, true, true, false); + g12 = interpolateAndExtrapolate(coords_in->g12, location, true, true, false, transform.get()); + g13 = interpolateAndExtrapolate(coords_in->g13, location, true, true, false, transform.get()); + g23 = interpolateAndExtrapolate(coords_in->g23, location, true, true, false, transform.get()); // 3x3 matrix inversion can exaggerate small interpolation errors, so it is // more robust to interpolate and extrapolate derived quantities directly, // rather than deriving from interpolated/extrapolated covariant metric // components - g_11 = interpolateAndExtrapolate(coords_in->g_11, location, true, true, false); - g_22 = interpolateAndExtrapolate(coords_in->g_22, location, true, true, false); - g_33 = interpolateAndExtrapolate(coords_in->g_33, location, true, true, false); - g_12 = interpolateAndExtrapolate(coords_in->g_12, location, true, true, false); - g_13 = interpolateAndExtrapolate(coords_in->g_13, location, true, true, false); - g_23 = interpolateAndExtrapolate(coords_in->g_23, location, true, true, false); + g_11 = interpolateAndExtrapolate(coords_in->g_11, location, true, true, false, transform.get()); + g_22 = interpolateAndExtrapolate(coords_in->g_22, location, true, true, false, transform.get()); + g_33 = interpolateAndExtrapolate(coords_in->g_33, location, true, true, false, transform.get()); + g_12 = interpolateAndExtrapolate(coords_in->g_12, location, true, true, false, transform.get()); + g_13 = interpolateAndExtrapolate(coords_in->g_13, location, true, true, false, transform.get()); + g_23 = interpolateAndExtrapolate(coords_in->g_23, location, true, true, false, transform.get()); // Check input metrics // Diagonal metric components should be finite @@ -965,18 +963,18 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); - J = interpolateAndExtrapolate(coords_in->J, location, true, true, false); - Bxy = interpolateAndExtrapolate(coords_in->Bxy, location, true, true, false); + J = interpolateAndExtrapolate(coords_in->J, location, true, true, false, transform.get()); + Bxy = interpolateAndExtrapolate(coords_in->Bxy, location, true, true, false, transform.get()); bout::checkFinite(J, "The Jacobian", "RGN_NOCORNERS"); bout::checkPositive(J, "The Jacobian", "RGN_NOCORNERS"); bout::checkFinite(Bxy, "Bxy", "RGN_NOCORNERS"); bout::checkPositive(Bxy, "Bxy", "RGN_NOCORNERS"); - ShiftTorsion = interpolateAndExtrapolate(coords_in->ShiftTorsion, location, true, true, false); + ShiftTorsion = interpolateAndExtrapolate(coords_in->ShiftTorsion, location, true, true, false, transform.get()); if (mesh->IncIntShear) { - IntShiftTorsion = interpolateAndExtrapolate(coords_in->IntShiftTorsion, location, true, true, false); + IntShiftTorsion = interpolateAndExtrapolate(coords_in->IntShiftTorsion, location, true, true, false, transform.get()); } } @@ -1156,30 +1154,30 @@ int Coordinates::geometry(bool recalculate_staggered, // CELL_YLOW grid is at a 'guard cell' location (yend+1). // However, the above would require lots of special handling, so just extrapolate for // now. - G1_11 = interpolateAndExtrapolate(G1_11, location, true, true, true); - G1_22 = interpolateAndExtrapolate(G1_22, location, true, true, true); - G1_33 = interpolateAndExtrapolate(G1_33, location, true, true, true); - G1_12 = interpolateAndExtrapolate(G1_12, location, true, true, true); - G1_13 = interpolateAndExtrapolate(G1_13, location, true, true, true); - G1_23 = interpolateAndExtrapolate(G1_23, location, true, true, true); - - G2_11 = interpolateAndExtrapolate(G2_11, location, true, true, true); - G2_22 = interpolateAndExtrapolate(G2_22, location, true, true, true); - G2_33 = interpolateAndExtrapolate(G2_33, location, true, true, true); - G2_12 = interpolateAndExtrapolate(G2_12, location, true, true, true); - G2_13 = interpolateAndExtrapolate(G2_13, location, true, true, true); - G2_23 = interpolateAndExtrapolate(G2_23, location, true, true, true); - - G3_11 = interpolateAndExtrapolate(G3_11, location, true, true, true); - G3_22 = interpolateAndExtrapolate(G3_22, location, true, true, true); - G3_33 = interpolateAndExtrapolate(G3_33, location, true, true, true); - G3_12 = interpolateAndExtrapolate(G3_12, location, true, true, true); - G3_13 = interpolateAndExtrapolate(G3_13, location, true, true, true); - G3_23 = interpolateAndExtrapolate(G3_23, location, true, true, true); - - G1 = interpolateAndExtrapolate(G1, location, true, true, true); - G2 = interpolateAndExtrapolate(G2, location, true, true, true); - G3 = interpolateAndExtrapolate(G3, location, true, true, true); + G1_11 = interpolateAndExtrapolate(G1_11, location, true, true, true, transform.get()); + G1_22 = interpolateAndExtrapolate(G1_22, location, true, true, true, transform.get()); + G1_33 = interpolateAndExtrapolate(G1_33, location, true, true, true, transform.get()); + G1_12 = interpolateAndExtrapolate(G1_12, location, true, true, true, transform.get()); + G1_13 = interpolateAndExtrapolate(G1_13, location, true, true, true, transform.get()); + G1_23 = interpolateAndExtrapolate(G1_23, location, true, true, true, transform.get()); + + G2_11 = interpolateAndExtrapolate(G2_11, location, true, true, true, transform.get()); + G2_22 = interpolateAndExtrapolate(G2_22, location, true, true, true, transform.get()); + G2_33 = interpolateAndExtrapolate(G2_33, location, true, true, true, transform.get()); + G2_12 = interpolateAndExtrapolate(G2_12, location, true, true, true, transform.get()); + G2_13 = interpolateAndExtrapolate(G2_13, location, true, true, true, transform.get()); + G2_23 = interpolateAndExtrapolate(G2_23, location, true, true, true, transform.get()); + + G3_11 = interpolateAndExtrapolate(G3_11, location, true, true, true, transform.get()); + G3_22 = interpolateAndExtrapolate(G3_22, location, true, true, true, transform.get()); + G3_33 = interpolateAndExtrapolate(G3_33, location, true, true, true, transform.get()); + G3_12 = interpolateAndExtrapolate(G3_12, location, true, true, true, transform.get()); + G3_13 = interpolateAndExtrapolate(G3_13, location, true, true, true, transform.get()); + G3_23 = interpolateAndExtrapolate(G3_23, location, true, true, true, transform.get()); + + G1 = interpolateAndExtrapolate(G1, location, true, true, true, transform.get()); + G2 = interpolateAndExtrapolate(G2, location, true, true, true, transform.get()); + G3 = interpolateAndExtrapolate(G3, location, true, true, true, transform.get()); ////////////////////////////////////////////////////// /// Non-uniform meshes. Need to use DDX, DDY @@ -1201,11 +1199,11 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) communicate(d1_dx); - d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true); + d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true, transform.get()); } else { d2x.setLocation(location); // set boundary cells if necessary - d2x = interpolateAndExtrapolate(d2x, location, extrapolate_x, extrapolate_y, false); + d2x = interpolateAndExtrapolate(d2x, location, extrapolate_x, extrapolate_y, false, transform.get()); d1_dx = -d2x / (dx * dx); } @@ -1216,11 +1214,11 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = indexDDY(1. / dy); // d/di(1/dy) communicate(d1_dy); - d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true); + d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true, transform.get()); } else { d2y.setLocation(location); // set boundary cells if necessary - d2y = interpolateAndExtrapolate(d2y, location, extrapolate_x, extrapolate_y, false); + d2y = interpolateAndExtrapolate(d2y, location, extrapolate_x, extrapolate_y, false, transform.get()); d1_dy = -d2y / (dy * dy); } @@ -1231,11 +1229,11 @@ int Coordinates::geometry(bool recalculate_staggered, "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) communicate(d1_dz); - d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true); + d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); } else { d2z.setLocation(location); // set boundary cells if necessary - d2z = interpolateAndExtrapolate(d2z, location, extrapolate_x, extrapolate_y, false); + d2z = interpolateAndExtrapolate(d2z, location, extrapolate_x, extrapolate_y, false, transform.get()); d1_dz = -d2z / (dz * dz); } @@ -1249,10 +1247,10 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) communicate(d1_dx); - d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true); + d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true, transform.get()); } else { // Shift d2x to our location - d2x = interpolateAndExtrapolate(d2x, location, true, true, false); + d2x = interpolateAndExtrapolate(d2x, location, true, true, false, transform.get()); d1_dx = -d2x / (dx * dx); } @@ -1263,10 +1261,10 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = indexDDY(1. / dy); // d/di(1/dy) communicate(d1_dy); - d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true); + d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true, transform.get()); } else { // Shift d2y to our location - d2y = interpolateAndExtrapolate(d2y, location, true, true, false); + d2y = interpolateAndExtrapolate(d2y, location, true, true, false, transform.get()); d1_dy = -d2y / (dy * dy); } @@ -1278,10 +1276,10 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) communicate(d1_dz); - d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true); + d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); } else { // Shift d2z to our location - d2z = interpolateAndExtrapolate(d2z, location, true, true, false); + d2z = interpolateAndExtrapolate(d2z, location, true, true, false, transform.get()); d1_dz = -d2z / (dz * dz); } @@ -1431,10 +1429,10 @@ int Coordinates::jacobian() { J = 1. / sqrt(g); // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, transform.get()); Bxy = sqrt(g_22) / J; - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, transform.get()); return 0; } @@ -1445,7 +1443,7 @@ namespace { auto localmesh = zShift.getMesh(); // extrapolate into boundary guard cells if necessary - zShift = _interpolateAndExtrapolate(zShift, zShift.getLocation(), + zShift = interpolateAndExtrapolate(zShift, zShift.getLocation(), not localmesh->sourceHasXBoundaryGuards(), not localmesh->sourceHasYBoundaryGuards(), false); @@ -1516,7 +1514,7 @@ void Coordinates::setParallelTransform(Options* options) { fixZShiftGuards(zShift_centre); - zShift = interpolateAndExtrapolate(zShift_centre, location, true, true, false); + zShift = interpolateAndExtrapolate(zShift_centre, location, true, true, false, transform.get()); } fixZShiftGuards(zShift); From 39a597c9d5c6bc74b76956e83a62b7ac0aae50d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 14:29:38 +0100 Subject: [PATCH 141/293] Remove stale comment --- src/mesh/coordinates.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 638a333624..b28790d0d8 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -161,7 +161,6 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, } else { pt_f = & f.getCoordinates()->getParallelTransform(); } - // Cannot use normal ifs, so that f is const if (f.getDirectionY() != YDirectionType::Standard) { if (pt_f->canToFromFieldAligned()) { f = pt_f->fromFieldAligned(f); From faa2d628620a2371e8279aa4a41f8554561d8b72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 14:34:47 +0100 Subject: [PATCH 142/293] use 1. if physical value is meant --- src/mesh/coordinates.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index b28790d0d8..88869ca1a9 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -383,10 +383,10 @@ Coordinates::Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2 } Coordinates::Coordinates(Mesh* mesh, Options* options) - : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1, mesh), Bxy(1, mesh), + : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1., mesh), Bxy(1., mesh), // Identity metric tensor - g11(1, mesh), g22(1, mesh), g33(1, mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), - g_11(1, mesh), g_22(1, mesh), g_33(1, mesh), g_12(0, mesh), g_13(0, mesh), + g11(1., mesh), g22(1., mesh), g33(1., mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), + g_11(1., mesh), g_22(1., mesh), g_33(1., mesh), g_12(0, mesh), g_13(0, mesh), g_23(0, mesh), G1_11(mesh), G1_22(mesh), G1_33(mesh), G1_12(mesh), G1_13(mesh), G1_23(mesh), G2_11(mesh), G2_22(mesh), G2_33(mesh), G2_12(mesh), G2_13(mesh), G2_23(mesh), G3_11(mesh), G3_22(mesh), G3_33(mesh), G3_12(mesh), G3_13(mesh), @@ -690,10 +690,10 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, const Coordinates* coords_in, bool force_interpolate_from_centre) - : dx(1, mesh), dy(1, mesh), dz(1, mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1, mesh), Bxy(1, mesh), + : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1., mesh), Bxy(1., mesh), // Identity metric tensor - g11(1, mesh), g22(1, mesh), g33(1, mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), - g_11(1, mesh), g_22(1, mesh), g_33(1, mesh), g_12(0, mesh), g_13(0, mesh), + g11(1., mesh), g22(1., mesh), g33(1., mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), + g_11(1., mesh), g_22(1., mesh), g_33(1., mesh), g_12(0, mesh), g_13(0, mesh), g_23(0, mesh), G1_11(mesh), G1_22(mesh), G1_33(mesh), G1_12(mesh), G1_13(mesh), G1_23(mesh), G2_11(mesh), G2_22(mesh), G2_33(mesh), G2_12(mesh), G2_13(mesh), G2_23(mesh), G3_11(mesh), G3_22(mesh), G3_33(mesh), G3_12(mesh), G3_13(mesh), From 8319e7d84666eeb96b1788a20cf59ee8d3bb4ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 15:02:12 +0100 Subject: [PATCH 143/293] interpolate all components --- src/mesh/coordinates.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 88869ca1a9..2c9d21e6be 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -457,7 +457,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) GET(g13, 0.0); GET(g23, 0.0); - communicate(g11, g22, g33, g12, g13, g23); + g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, transform.get()); + g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, transform.get()); + g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, transform.get()); + g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, transform.get()); + g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, transform.get()); + g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, transform.get()); // Check input metrics // Diagonal metric components should be finite @@ -493,8 +498,6 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) #undef GET - communicate(g_11, g_22, g_33, g_12, g_13, g_23); - output_warn.write("\tWARNING! Covariant components of metric tensor set manually. " "Contravariant components NOT recalculated\n"); From 4c4cecf3760a0d3bf38e3b1b9dad24c3bad6bf0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 15:02:29 +0100 Subject: [PATCH 144/293] Always use for loop in z --- src/mesh/coordinates.cxx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 2c9d21e6be..decbb99457 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -619,13 +619,6 @@ namespace { /// Corner guard cells are set to BoutNaN Coordinates::metric_field_type interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAYBE_UNUSED(CELL_LOC location), MAYBE_UNUSED(ParallelTransform * pt)) { -#ifndef COORDINATES_USE_3D -#define COORDS_ITER_Z int z=0; -#else -#define COORDS_ITER_Z for (int z=0;zLocalNz;++z) - //throw BoutException( - // "Staggered coordinates locations not currently supported with 3D metrics."); -#endif Mesh* localmesh = f.getMesh(); Coordinates::metric_field_type result; #ifdef COORDINATES_USE_3D @@ -652,8 +645,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->xstart; i++){ - COORDS_ITER_Z - { + for (int z=0;zx + i * bndry->bx, bndry->y, z) = result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); } @@ -664,8 +656,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->ystart; i++) { - COORDS_ITER_Z - { + for (int z=0;zx, bndry->y + i * bndry->by, z) = result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); } @@ -677,8 +668,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // Set corner guard cells for (int i = 0; i < localmesh->xstart; i++) { for (int j = 0; j < localmesh->ystart; j++) { - COORDS_ITER_Z - { + for (int z=0;zLocalNy - 1 - j, z) = BoutNaN; result(localmesh->LocalNx - 1 - i, j, z) = BoutNaN; From cf47f476820830675fb781f36ee32d40474df1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 15:02:38 +0100 Subject: [PATCH 145/293] Add comment for test --- tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt b/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt index b698702344..9ccd3b1947 100644 --- a/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt +++ b/tests/integrated/test-petsc_laplace_MAST-grid/CMakeLists.txt @@ -1,3 +1,4 @@ +# Extremly slow on travis - thus skip bout_add_integrated_test(test-petsc-laplace-MAST-grid SOURCES test_petsc_laplace_MAST_grid.cxx REQUIRES BOUT_HAS_PETSC From a5e8bbca7e2349ff374165f76601290726da775b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 15 May 2020 15:13:56 +0100 Subject: [PATCH 146/293] Update CMake files for skipping 3D metric tests Fixed with: grep not\ metric_3d tests -r --include=runtest|cut -d: -f1 |sed 's/runtest/CMakeLists.txt/' | xargs -n 1 sed -e '3 i \ REQUIRES NOT BOUT_USE_METRIC_3D' --- tests/integrated/test-drift-instability-staggered/CMakeLists.txt | 1 + tests/integrated/test-drift-instability/CMakeLists.txt | 1 + tests/integrated/test-fieldgroupComm/CMakeLists.txt | 1 + tests/integrated/test-gyro/CMakeLists.txt | 1 + tests/integrated/test-interchange-instability/CMakeLists.txt | 1 + tests/integrated/test-invertable-operator/CMakeLists.txt | 1 + tests/integrated/test-invpar/CMakeLists.txt | 1 + tests/integrated/test-io_hdf5/CMakeLists.txt | 1 + tests/integrated/test-laplace/CMakeLists.txt | 1 + tests/integrated/test-multigrid_laplace/CMakeLists.txt | 1 + tests/integrated/test-naulin-laplace/CMakeLists.txt | 1 + tests/integrated/test-snb/CMakeLists.txt | 1 + 12 files changed, 12 insertions(+) diff --git a/tests/integrated/test-drift-instability-staggered/CMakeLists.txt b/tests/integrated/test-drift-instability-staggered/CMakeLists.txt index 340a5429e2..e87f88c6d8 100644 --- a/tests/integrated/test-drift-instability-staggered/CMakeLists.txt +++ b/tests/integrated/test-drift-instability-staggered/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-drift-instability-staggered SOURCES 2fluid.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES runtest.py uedge.grd_std.cdl diff --git a/tests/integrated/test-drift-instability/CMakeLists.txt b/tests/integrated/test-drift-instability/CMakeLists.txt index 31037226a6..d533a79446 100644 --- a/tests/integrated/test-drift-instability/CMakeLists.txt +++ b/tests/integrated/test-drift-instability/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-drift-instability SOURCES 2fluid.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES runtest.py uedge.grd_std.cdl diff --git a/tests/integrated/test-fieldgroupComm/CMakeLists.txt b/tests/integrated/test-fieldgroupComm/CMakeLists.txt index 24b0924d30..6266c560a4 100644 --- a/tests/integrated/test-fieldgroupComm/CMakeLists.txt +++ b/tests/integrated/test-fieldgroupComm/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-fieldgroupComm SOURCES test_fieldgroupcomm.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES cyclone_68x32.nc diff --git a/tests/integrated/test-gyro/CMakeLists.txt b/tests/integrated/test-gyro/CMakeLists.txt index 94f74c5776..28b65c010f 100644 --- a/tests/integrated/test-gyro/CMakeLists.txt +++ b/tests/integrated/test-gyro/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-gyro SOURCES test_gyro.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES cyclone_68x32.nc data/benchmark.0.nc diff --git a/tests/integrated/test-interchange-instability/CMakeLists.txt b/tests/integrated/test-interchange-instability/CMakeLists.txt index 971a70805a..ef6b403fac 100644 --- a/tests/integrated/test-interchange-instability/CMakeLists.txt +++ b/tests/integrated/test-interchange-instability/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-interchange-instability SOURCES 2fluid.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST EXTRA_FILES slab.6b5.r1.cdl slab.6b5.r10.cdl data_1/BOUT.inp data_10/BOUT.inp ) diff --git a/tests/integrated/test-invertable-operator/CMakeLists.txt b/tests/integrated/test-invertable-operator/CMakeLists.txt index 9931b2a9b5..10b4f0ec76 100644 --- a/tests/integrated/test-invertable-operator/CMakeLists.txt +++ b/tests/integrated/test-invertable-operator/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-invertable-operator SOURCES invertable_operator.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP REQUIRES BOUT_HAS_PETSC diff --git a/tests/integrated/test-invpar/CMakeLists.txt b/tests/integrated/test-invpar/CMakeLists.txt index 418709e7df..848aa26879 100644 --- a/tests/integrated/test-invpar/CMakeLists.txt +++ b/tests/integrated/test-invpar/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-invpar SOURCES test_invpar.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES test_io.grd.nc diff --git a/tests/integrated/test-io_hdf5/CMakeLists.txt b/tests/integrated/test-io_hdf5/CMakeLists.txt index 25eb3a4e6f..0b9dd50102 100644 --- a/tests/integrated/test-io_hdf5/CMakeLists.txt +++ b/tests/integrated/test-io_hdf5/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-io-hdf5 SOURCES test_io_hdf5.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES test_io.grd.hdf5 data/benchmark.out.0.hdf5 diff --git a/tests/integrated/test-laplace/CMakeLists.txt b/tests/integrated/test-laplace/CMakeLists.txt index 488b0b7314..7cebde10f2 100644 --- a/tests/integrated/test-laplace/CMakeLists.txt +++ b/tests/integrated/test-laplace/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-laplace SOURCES test_laplace.cxx + REQUIRES NOT BOUT_USE_METRIC_3D EXTRA_FILES test_laplace.grd.nc data/benchmark.0.nc USE_RUNTEST USE_DATA_BOUT_INP diff --git a/tests/integrated/test-multigrid_laplace/CMakeLists.txt b/tests/integrated/test-multigrid_laplace/CMakeLists.txt index 482d91f38f..13bf202554 100644 --- a/tests/integrated/test-multigrid_laplace/CMakeLists.txt +++ b/tests/integrated/test-multigrid_laplace/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-multigrid-laplace SOURCES test_multigrid_laplace.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP ) diff --git a/tests/integrated/test-naulin-laplace/CMakeLists.txt b/tests/integrated/test-naulin-laplace/CMakeLists.txt index 62e723e727..3055d8395c 100644 --- a/tests/integrated/test-naulin-laplace/CMakeLists.txt +++ b/tests/integrated/test-naulin-laplace/CMakeLists.txt @@ -1,5 +1,6 @@ bout_add_integrated_test(test-naulin-laplace SOURCES test_naulin_laplace.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP ) diff --git a/tests/integrated/test-snb/CMakeLists.txt b/tests/integrated/test-snb/CMakeLists.txt index e426b7f3fb..80a6ea761a 100644 --- a/tests/integrated/test-snb/CMakeLists.txt +++ b/tests/integrated/test-snb/CMakeLists.txt @@ -1,4 +1,5 @@ bout_add_integrated_test(test-snb SOURCES test_snb.cxx + REQUIRES NOT BOUT_USE_METRIC_3D USE_DATA_BOUT_INP ) From b0729f0ec58c2ec4279d0d25324dec112b172686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 18 May 2020 11:22:22 +0100 Subject: [PATCH 147/293] Avoid copy of fields --- src/mesh/difops.cxx | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index eb849e1735..a895322a33 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -575,9 +575,6 @@ Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { Coordinates *coords = a.getCoordinates(outloc); Mesh *mesh = f.getMesh(); - Field3D fs = f; - Field3D as = a; - for(int i=mesh->xstart;i<=mesh->xend;i++) for(int j=mesh->ystart;j<=mesh->yend;j++) for(int k=0;kLocalNz;k++) { @@ -588,34 +585,34 @@ Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { // Calculate gradients on cell faces -- assumes constant grid spacing - BoutReal gR = (coords->g11(i,j,k) + coords->g11(i+1,j,k)) * (fs(i+1,j,k) - fs(i,j,k))/(coords->dx(i+1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(fs(i+1,j,kp) - fs(i+1,j,km) + fs(i,j,kp) - fs(i,j,km))/(4.*coords->dz(i,j,k)); + BoutReal gR = (coords->g11(i,j,k) + coords->g11(i+1,j,k)) * (f(i+1,j,k) - f(i,j,k))/(coords->dx(i+1,j,k) + coords->dx(i,j,k)) + + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(f(i+1,j,kp) - f(i+1,j,km) + f(i,j,kp) - f(i,j,km))/(4.*coords->dz(i,j,k)); - BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(fs(i,j,k) - fs(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(fs(i-1,j,kp) - fs(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4*coords->dz(i,j,k)); + BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(f(i,j,k) - f(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) + + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(f(i-1,j,kp) - f(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4*coords->dz(i,j,k)); - BoutReal gD = coords->g13(i,j,k)*(fs(i+1,j,km) - fs(i-1,j,km) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(fs(i,j,k) - fs(i,j,km))/coords->dz(i,j,k); + BoutReal gD = coords->g13(i,j,k)*(f(i+1,j,km) - f(i-1,j,km) + f(i+1,j,k) - f(i-1,j,k))/(4.*coords->dx(i,j,k)) + + coords->g33(i,j,k)*(f(i,j,k) - f(i,j,km))/coords->dz(i,j,k); - BoutReal gU = coords->g13(i,j,k)*(fs(i+1,j,kp) - fs(i-1,j,kp) + fs(i+1,j,k) - fs(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(fs(i,j,kp) - fs(i,j,k))/coords->dz(i,j,k); + BoutReal gU = coords->g13(i,j,k)*(f(i+1,j,kp) - f(i-1,j,kp) + f(i+1,j,k) - f(i-1,j,k))/(4.*coords->dx(i,j,k)) + + coords->g33(i,j,k)*(f(i,j,kp) - f(i,j,k))/coords->dz(i,j,k); // Flow right - BoutReal flux = gR * 0.25*(coords->J(i+1,j,k) + coords->J(i,j,k)) *(as(i+1,j,k) + as(i,j,k)); + BoutReal flux = gR * 0.25*(coords->J(i+1,j,k) + coords->J(i,j,k)) *(a(i+1,j,k) + a(i,j,k)); result(i,j,k) += flux / (coords->dx(i,j,k)*coords->J(i,j,k)); // Flow left - flux = gL * 0.25*(coords->J(i-1,j,k) + coords->J(i,j,k)) *(as(i-1,j,k) + as(i,j,k)); + flux = gL * 0.25*(coords->J(i-1,j,k) + coords->J(i,j,k)) *(a(i-1,j,k) + a(i,j,k)); result(i,j,k) -= flux / (coords->dx(i,j,k)*coords->J(i,j,k)); // Flow up - flux = gU * 0.25*(coords->J(i,j,k) + coords->J(i,j,kp)) *(as(i,j,k) + as(i,j,kp)); + flux = gU * 0.25*(coords->J(i,j,k) + coords->J(i,j,kp)) *(a(i,j,k) + a(i,j,kp)); result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); // Flow down - flux = gD * 0.25*(coords->J(i,j,km) + coords->J(i,j,k)) *(as(i,j,km) + as(i,j,k)); + flux = gD * 0.25*(coords->J(i,j,km) + coords->J(i,j,k)) *(a(i,j,km) + a(i,j,k)); result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); } From 351e81fd248325b64dfa89822f8786f0477aa989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 18 May 2020 11:22:45 +0100 Subject: [PATCH 148/293] Remove outdated comments --- src/sys/derivs.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index 75a8a667de..f17f1d853f 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -379,7 +379,7 @@ Field3D D2DYDZ(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string ////////////// X DERIVATIVE ///////////////// -/// Special case where both arguments are 2D. Output location ignored for now +/// Special case where both arguments are 2D. Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { @@ -425,7 +425,6 @@ Coordinates::metric_field_type VDDZ(const Field2D &v, const Field2D &f, Coordinates::metric_field_type VDDZ(const Field3D &v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { - // Should we take location from v or f? #ifdef COORDINATES_USE_3D Field3D tmp{f}; return bout::derivatives::index::VDDZ(v, tmp, outloc, method, region) @@ -481,7 +480,6 @@ Field3D FDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str Coordinates::metric_field_type FDDZ(const Field2D &v, const Field2D &f, CELL_LOC outloc, const std::string &method, const std::string& region) { - // Should we take location from v or f? return bout::derivatives::index::FDDZ(v, f, outloc, method, region) / f.getCoordinates(outloc)->dz; } From 4f38c35c449cbf520c27f16d2ae071debbce22a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 18 May 2020 11:26:16 +0100 Subject: [PATCH 149/293] use getConst --- src/mesh/boundary_standard.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index e5b7da9eb5..ad96c68a82 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -2767,8 +2767,7 @@ void BoundaryConstLaplace::apply(Field3D& f) { BoutReal coef = -1.0 * sqrt(metric->g33(x - bx, y) / metric->g11(x - bx, y)) * metric->dx(x - bx, y); for (int jz = 1; jz <= ncz / 2; jz++) { -#warning TODO: fix - BoutReal kwave = jz * 2.0 * PI / metric->zlength()(0,0); // wavenumber in [rad^-1] + BoutReal kwave = jz * 2.0 * PI / getConst(metric->zlength()); // wavenumber in [rad^-1] c0[jz] *= exp(coef * kwave); // The decaying solution only // Add the particular solution c2[jz] = c0[jz] - c1[jz] / (metric->g33(x - bx, y) * kwave * kwave); From bba9241ae5fe480e424da9b9a125a8d6da5399b4 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Mon, 18 May 2020 13:49:24 +0200 Subject: [PATCH 150/293] Add DC operations to LaplaceXY * This generalizes for 3D metrics --- src/invert/laplacexy/laplacexy.cxx | 93 ++++++++++++++++++------------ 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index e021e695fb..9139032675 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -1,5 +1,4 @@ - -#if defined(BOUT_HAS_PETSC) and not defined(COORDINATES_USE_3D) +#ifdef BOUT_HAS_PETSC #include @@ -894,7 +893,14 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B // (1/J) d/dx ( J * g11 d/dx ) + (1/J) d/dy ( J * g22 d/dy ) auto coords = localmesh->getCoordinates(location); - + Field2D J_DC = DC(coords->J); + Field2D g11_DC = DC(coords->g11); + Field2D dx_DC = DC(coords->dx); + Field2D dy_DC = DC(coords->dy); + Field2D g_22_DC = DC(coords->g_22); + Field2D g_23_DC = DC(coords->g_23); + Field2D g23_DC = DC(coords->g23); + for(int x=localmesh->xstart; x <= localmesh->xend; x++) { for(int y=localmesh->ystart;y<=localmesh->yend;y++) { // stencil entries @@ -903,22 +909,22 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B // XX component // Metrics on x+1/2 boundary - BoutReal J = 0.5*(coords->J(x,y) + coords->J(x+1,y)); - BoutReal g11 = 0.5*(coords->g11(x,y) + coords->g11(x+1,y)); - BoutReal dx = 0.5*(coords->dx(x,y) + coords->dx(x+1,y)); + BoutReal J = 0.5*(J_DC(x,y) + J_DC(x+1,y)); + BoutReal g11 = 0.5*(g11_DC(x,y) + g11_DC(x+1,y)); + BoutReal dx = 0.5*(dx_DC(x,y) + dx_DC(x+1,y)); BoutReal Acoef = 0.5*(A(x,y) + A(x+1,y)); - BoutReal val = Acoef * J * g11 / (coords->J(x,y) * dx * coords->dx(x,y)); + BoutReal val = Acoef * J * g11 / (J_DC(x,y) * dx * dx_DC(x,y)); xp = val; c = -val; // Metrics on x-1/2 boundary - J = 0.5*(coords->J(x,y) + coords->J(x-1,y)); - g11 = 0.5*(coords->g11(x,y) + coords->g11(x-1,y)); - dx = 0.5*(coords->dx(x,y) + coords->dx(x-1,y)); + J = 0.5*(J_DC(x,y) + J_DC(x-1,y)); + g11 = 0.5*(g11_DC(x,y) + g11_DC(x-1,y)); + dx = 0.5*(dx_DC(x,y) + dx_DC(x-1,y)); Acoef = 0.5*(A(x,y) + A(x-1,y)); - val = Acoef * J * g11 / (coords->J(x,y) * dx * coords->dx(x,y)); + val = Acoef * J * g11 / (J_DC(x,y) * dx * dx_DC(x,y)); xm = val; c -= val; @@ -932,26 +938,26 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B if( include_y_derivs ) { // YY component // Metrics at y+1/2 - J = 0.5*(coords->J(x,y) + coords->J(x,y+1)); - BoutReal g_22 = 0.5*(coords->g_22(x,y) + coords->g_22(x,y+1)); - BoutReal g23 = 0.5*(coords->g23(x,y) + coords->g23(x,y+1)); - BoutReal g_23 = 0.5*(coords->g_23(x,y) + coords->g_23(x,y+1)); - BoutReal dy = 0.5*(coords->dy(x,y) + coords->dy(x,y+1)); + J = 0.5*(J_DC(x,y) + J_DC(x,y+1)); + BoutReal g_22 = 0.5*(g_22_DC(x,y) + g_22_DC(x,y+1)); + BoutReal g23 = 0.5*(g23_DC(x,y) + g23_DC(x,y+1)); + BoutReal g_23 = 0.5*(g_23_DC(x,y) + g_23_DC(x,y+1)); + BoutReal dy = 0.5*(dy_DC(x,y) + dy_DC(x,y+1)); Acoef = 0.5*(A(x,y+1) + A(x,y)); - val = -Acoef * J * g23 * g_23 / (g_22 * coords->J(x,y) * dy * coords->dy(x,y)); + val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x,y) * dy * dy_DC(x,y)); yp = val; c -= val; // Metrics at y-1/2 - J = 0.5*(coords->J(x,y) + coords->J(x,y-1)); - g_22 = 0.5*(coords->g_22(x,y) + coords->g_22(x,y-1)); - g23 = 0.5*(coords->g23(x,y) + coords->g23(x,y-1)); - g_23 = 0.5*(coords->g_23(x,y) + coords->g_23(x,y-1)); - dy = 0.5*(coords->dy(x,y) + coords->dy(x,y-1)); + J = 0.5*(J_DC(x,y) + J_DC(x,y-1)); + g_22 = 0.5*(g_22_DC(x,y) + g_22_DC(x,y-1)); + g23 = 0.5*(g23_DC(x,y) + g23_DC(x,y-1)); + g_23 = 0.5*(g_23_DC(x,y) + g_23_DC(x,y-1)); + dy = 0.5*(dy_DC(x,y) + dy_DC(x,y-1)); Acoef = 0.5*(A(x,y-1) + A(x,y)); - val = -Acoef * J * g23 * g_23 / (g_22 * coords->J(x,y) * dy * coords->dy(x,y)); + val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x,y) * dy * dy_DC(x,y)); ym = val; c -= val; } @@ -997,33 +1003,44 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 // + B*f auto coords = localmesh->getCoordinates(location); - - Field2D coef_dfdy = coords->G2 - DDY(coords->J/coords->g_22)/coords->J; + Field2D G1_2D = DC(coords->G1); + Field2D G2_2D = DC(coords->G2); + Field2D J_2D = DC(coords->J); + Field2D g11_2D = DC(coords->g11); + Field2D g_22_2D = DC(coords->g_22); + Field2D g22_2D = DC(coords->g22); + Field2D g12_2D = DC(coords->g12); + Field2D d1_dx_2D = DC(coords->d1_dx); + Field2D d1_dy_2D = DC(coords->d1_dy); + Field2D dx_2D = DC(coords->dx); + Field2D dy_2D = DC(coords->dy); + + Field2D coef_dfdy = G2_2D - DC(DDY(J_2D/g_22_2D)/J_2D); for(int x = localmesh->xstart; x <= localmesh->xend; x++) { for(int y = localmesh->ystart; y <= localmesh->yend; y++) { // stencil entries PetscScalar c, xm, xp, ym, yp, xpyp, xpym, xmyp, xmym; - BoutReal dx = coords->dx(x,y); + BoutReal dx = dx_2D(x,y); // A*G1*dfdx - BoutReal val = A(x, y)*coords->G1(x, y)/(2.*dx); + BoutReal val = A(x, y)*G1_2D(x, y)/(2.*dx); xp = val; xm = -val; // A*g11*d2fdx2 - val = A(x, y)*coords->g11(x, y)/SQ(dx); + val = A(x, y)*g11_2D(x, y)/SQ(dx); xp += val; c = -2.*val; xm += val; // Non-uniform grid correction - val = A(x, y)*coords->g11(x, y)*coords->d1_dx(x, y)/(2.*dx); + val = A(x, y)*g11_2D(x, y)*d1_dx_2D(x, y)/(2.*dx); xp += val; xm -= val; // g11*dAdx*dfdx - val = coords->g11(x, y)*(A(x+1, y) - A(x-1, y))/(4.*SQ(dx)); + val = g11_2D(x, y)*(A(x+1, y) - A(x-1, y))/(4.*SQ(dx)); xp += val; xm -= val; @@ -1036,7 +1053,7 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 ccoef(y - localmesh->ystart, x - xstart) = xp; if(include_y_derivs) { - BoutReal dy = coords->dy(x,y); + BoutReal dy = dy_2D(x,y); BoutReal dAdx = (A(x+1, y) - A(x-1, y))/(2.*dx); BoutReal dAdy = (A(x, y+1) - A(x, y-1))/(2.*dy); @@ -1046,33 +1063,33 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 ym = -val; // A*(g22-1/g_22)*d2fdy2 - val = A(x, y)*(coords->g22(x, y) - 1./coords->g_22(x,y))/SQ(dy); + val = A(x, y)*(g22_2D(x, y) - 1./g_22_2D(x,y))/SQ(dy); yp += val; c -= 2.*val; ym += val; // Non-uniform mesh correction - val = A(x, y)*(coords->g22(x, y) - 1./coords->g_22(x,y)) - *coords->d1_dy(x, y)/(2.*dy); + val = A(x, y)*(g22_2D(x, y) - 1./g_22_2D(x,y)) + *d1_dy_2D(x, y)/(2.*dy); yp += val; ym -= val; // 2*A*g12*d2dfdxdy - val = A(x, y)*coords->g12(x, y)/(2.*dx*dy); + val = A(x, y)*g12_2D(x, y)/(2.*dx*dy); xpyp = val; xpym = -val; xmyp = -val; xmym = val; // g22*dAdy*dfdy - val = (coords->g22(x, y) - 1./coords->g_22(x,y))*dAdy/(2.*dy); + val = (g22_2D(x, y) - 1./g_22_2D(x,y))*dAdy/(2.*dy); yp += val; ym -= val; // g12*(dAdx*dfdy + dAdy*dfdx) - val = coords->g12(x, y)*dAdx/(2.*dy); + val = g12_2D(x, y)*dAdx/(2.*dy); yp += val; ym -= val; - val = coords->g12(x, y)*dAdy/(2.*dx); + val = g12_2D(x, y)*dAdy/(2.*dx); xp += val; xm -= val; } From f47f39f7ea71372b2397245e2b092f18b88f346e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 18 May 2020 15:18:32 +0100 Subject: [PATCH 151/293] Avoid uninitallised Field in vecops --- src/field/vecops.cxx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 0b49bdd20f..5a9ef01165 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -186,15 +186,11 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) Vector3D vcn = v; vcn.toContravariant(); - Field3D result = 0.0; - + Field3D vcnJy = vcn.y.getCoordinates()->J * vcn.y; if(!vcn.y.hasParallelSlices()){ - Field3D vcnJy = vcn.y.getCoordinates()->J * vcn.y; localmesh->communicate(vcnJy); - result = DDY(vcnJy, outloc, method); - }else{ - result = DDY(vcn.y.getCoordinates()->J * vcn.y, outloc, method); } + Field3D result = DDY(vcnJy, outloc, method); result += DDX(vcn.x.getCoordinates()->J * vcn.x, outloc, method); result += DDZ(vcn.z.getCoordinates()->J * vcn.z, outloc, method); From 0c61fc7cd34a94a38d29e23d21125c81739720e8 Mon Sep 17 00:00:00 2001 From: Brendan Shanahan Date: Wed, 20 May 2020 10:59:26 +0200 Subject: [PATCH 152/293] Add const to laplacexy DC functions. --- src/invert/laplacexy/laplacexy.cxx | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index 9139032675..a52da73b19 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -893,13 +893,13 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B // (1/J) d/dx ( J * g11 d/dx ) + (1/J) d/dy ( J * g22 d/dy ) auto coords = localmesh->getCoordinates(location); - Field2D J_DC = DC(coords->J); - Field2D g11_DC = DC(coords->g11); - Field2D dx_DC = DC(coords->dx); - Field2D dy_DC = DC(coords->dy); - Field2D g_22_DC = DC(coords->g_22); - Field2D g_23_DC = DC(coords->g_23); - Field2D g23_DC = DC(coords->g23); + const Field2D J_DC = DC(coords->J); + const Field2D g11_DC = DC(coords->g11); + const Field2D dx_DC = DC(coords->dx); + const Field2D dy_DC = DC(coords->dy); + const Field2D g_22_DC = DC(coords->g_22); + const Field2D g_23_DC = DC(coords->g_23); + const Field2D g23_DC = DC(coords->g23); for(int x=localmesh->xstart; x <= localmesh->xend; x++) { for(int y=localmesh->ystart;y<=localmesh->yend;y++) { @@ -1003,19 +1003,19 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 // + B*f auto coords = localmesh->getCoordinates(location); - Field2D G1_2D = DC(coords->G1); - Field2D G2_2D = DC(coords->G2); - Field2D J_2D = DC(coords->J); - Field2D g11_2D = DC(coords->g11); - Field2D g_22_2D = DC(coords->g_22); - Field2D g22_2D = DC(coords->g22); - Field2D g12_2D = DC(coords->g12); - Field2D d1_dx_2D = DC(coords->d1_dx); - Field2D d1_dy_2D = DC(coords->d1_dy); - Field2D dx_2D = DC(coords->dx); - Field2D dy_2D = DC(coords->dy); + const Field2D G1_2D = DC(coords->G1); + const Field2D G2_2D = DC(coords->G2); + const Field2D J_2D = DC(coords->J); + const Field2D g11_2D = DC(coords->g11); + const Field2D g_22_2D = DC(coords->g_22); + const Field2D g22_2D = DC(coords->g22); + const Field2D g12_2D = DC(coords->g12); + const Field2D d1_dx_2D = DC(coords->d1_dx); + const Field2D d1_dy_2D = DC(coords->d1_dy); + const Field2D dx_2D = DC(coords->dx); + const Field2D dy_2D = DC(coords->dy); - Field2D coef_dfdy = G2_2D - DC(DDY(J_2D/g_22_2D)/J_2D); + const Field2D coef_dfdy = G2_2D - DC(DDY(J_2D/g_22_2D)/J_2D); for(int x = localmesh->xstart; x <= localmesh->xend; x++) { for(int y = localmesh->ystart; y <= localmesh->yend; y++) { From f95d0060a8ba5da4ef725775898c3b3c1f08dd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 20 May 2020 12:33:07 +0100 Subject: [PATCH 153/293] Fix bad iteration over z --- 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 decbb99457..8ea5734a16 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -668,7 +668,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // Set corner guard cells for (int i = 0; i < localmesh->xstart; i++) { for (int j = 0; j < localmesh->ystart; j++) { - for (int z=0;zLocalNy - 1 - j, z) = BoutNaN; result(localmesh->LocalNx - 1 - i, j, z) = BoutNaN; From a43cd455c349109e6d92f5836ebd381faf40aa99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 20 May 2020 12:36:29 +0100 Subject: [PATCH 154/293] Apply DC to test-laplacexy-short --- tests/integrated/test-laplacexy-short/test-laplacexy.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx index 4e85b48fef..3bd6471ead 100644 --- a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx @@ -62,9 +62,9 @@ int main(int argc, char** argv) { Field2D rhs, rhs_check; if (include_y_derivs) { - rhs = a*Laplace_perp(f) + Grad_perp(a)*Grad_perp(f) + b*f; + rhs = a*DC(Laplace_perp(f)) + DC(Grad_perp(a)*Grad_perp(f)) + b*f; } else { - rhs = a*Delp2(f, CELL_DEFAULT, false) + coords->g11*DDX(a)*DDX(f) + b*f; + rhs = a*DC(Delp2(f, CELL_DEFAULT, false)) + DC(coords->g11*DDX(a)*DDX(f)) + b*f; } laplacexy.setCoefs(a, b); @@ -78,9 +78,9 @@ int main(int argc, char** argv) { mesh->communicate(sol); if (include_y_derivs) { - rhs_check = a*Laplace_perp(sol) + Grad_perp(a)*Grad_perp(sol) + b*sol; + rhs_check = a*DC(Laplace_perp(sol)) + DC(Grad_perp(a)*Grad_perp(sol)) + b*sol; } else { - rhs_check = a*Delp2(sol, CELL_DEFAULT, false) + coords->g11*DDX(a)*DDX(sol) + b*sol; + rhs_check = a*DC(Delp2(sol, CELL_DEFAULT, false)) + DC(coords->g11*DDX(a)*DDX(sol)) + b*sol; } dump.add(a, "a"); From 136625c4cbd4cd4d5104cc9d3e0e8959c1585e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 20 May 2020 13:57:08 +0100 Subject: [PATCH 155/293] Fix bad iteration over z --- src/mesh/coordinates.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 8ea5734a16..3402338ba6 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -645,7 +645,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->xstart; i++){ - for (int z=0;zx + i * bndry->bx, bndry->y, z) = result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); } @@ -656,7 +656,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->ystart; i++) { - for (int z=0;zx, bndry->y + i * bndry->by, z) = result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); } From 0c5b881e12cdd6b0d499364859cf4d729c425ee6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 22 May 2020 12:38:06 +0000 Subject: [PATCH 156/293] [clang-format-command] fixes --- examples/blob2d-laplacexz/blob2d.cxx | 13 +- examples/elm-pb/elm_pb.cxx | 9 +- examples/lapd-drift/lapd_drift.cxx | 80 +- examples/orszag-tang/mhd.cxx | 2 +- include/bout/coordinates.hxx | 123 +- include/bout/fv_ops.hxx | 29 +- include/bout/mesh.hxx | 6 +- include/derivs.hxx | 151 +- include/difops.hxx | 163 +- include/field.hxx | 31 +- include/field2d.hxx | 4 +- include/field3d.hxx | 1 - include/vecops.hxx | 18 +- include/vector2d.hxx | 14 +- src/field/field.cxx | 8 +- src/field/field3d.cxx | 3 +- src/field/field_factory.cxx | 14 +- src/field/fieldgenerators.cxx | 10 +- src/field/vecops.cxx | 18 +- src/field/vector2d.cxx | 13 +- src/fileio/datafile.cxx | 36 +- .../impls/multigrid/multigrid_laplace.cxx | 35 +- .../laplace/impls/petsc/petsc_laplace.cxx | 115 +- .../laplace/impls/petsc3damg/petsc3damg.cxx | 6 +- .../laplace/impls/serial_band/serial_band.cxx | 11 +- .../laplace/impls/shoot/shoot_laplace.cxx | 4 +- src/invert/laplace/invert_laplace.cxx | 2 +- src/invert/laplacexy/laplacexy.cxx | 71 +- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 148 +- src/invert/parderiv/impls/cyclic/cyclic.cxx | 11 +- src/mesh/boundary_standard.cxx | 3119 +++++++++-------- src/mesh/coordinates.cxx | 541 +-- src/mesh/data/gridfromfile.cxx | 4 +- src/mesh/difops.cxx | 426 ++- src/mesh/fv_ops.cxx | 154 +- src/mesh/mesh.cxx | 25 +- src/mesh/parallel/fci.cxx | 14 +- src/sys/boutexception.cxx | 3 +- src/sys/derivs.cxx | 74 +- tests/MMS/diffusion/diffusion.cxx | 5 +- tests/MMS/diffusion2/diffusion.cxx | 5 +- tests/MMS/spatial/diffusion/diffusion.cxx | 5 +- tests/MMS/wave-1d/wave.cxx | 16 +- .../test-laplacexy-short/test-laplacexy.cxx | 10 +- .../test-laplacexz/test-laplacexz.cxx | 20 +- .../test_petsc_laplace_MAST_grid.cxx | 4 +- tests/unit/mesh/data/test_gridfromoptions.cxx | 15 +- .../unit/mesh/parallel/test_shiftedmetric.cxx | 5 +- tests/unit/solver/test_solver.cxx | 16 +- 49 files changed, 2945 insertions(+), 2665 deletions(-) diff --git a/examples/blob2d-laplacexz/blob2d.cxx b/examples/blob2d-laplacexz/blob2d.cxx index 9622f48933..72f673f582 100644 --- a/examples/blob2d-laplacexz/blob2d.cxx +++ b/examples/blob2d-laplacexz/blob2d.cxx @@ -110,7 +110,7 @@ class Blob2D : public PhysicsModel { } int rhs(BoutReal UNUSED(t)) { - //Coordinates *coord = mesh->getCoordinates(); + // Coordinates *coord = mesh->getCoordinates(); // Run communications //////////////////////////////////////////////////////////////////////////// @@ -140,15 +140,15 @@ class Blob2D : public PhysicsModel { ///////////////////////////////////////////////////////////////////////////// ddt(n) = -bracket(phi, n, BRACKET_SIMPLE) // ExB term - + 2 * DDZ(n) * (rho_s / R_c); // Curvature term - ddt(n) += D_n*Delp2(n, CELL_DEFAULT, false); + + 2 * DDZ(n) * (rho_s / R_c); // Curvature term + ddt(n) += D_n * Delp2(n, CELL_DEFAULT, false); // if(coord->is3D()){ // ddt(n) += Div_Perp_Lap_FV(D_n, n); // Diffusion term // }else{ // ddt(n) += D_n*Delp2(n); // } - + if (compressible) { ddt(n) -= 2 * n * DDZ(phi) * (rho_s / R_c); // ExB Compression term } @@ -162,8 +162,9 @@ class Blob2D : public PhysicsModel { ///////////////////////////////////////////////////////////////////////////// ddt(omega) = -bracket(phi, omega, BRACKET_SIMPLE) // ExB term - + 2 * DDZ(n) * (rho_s / R_c) / n; // Curvature term - ddt(omega) += D_vort * Delp2(omega, CELL_DEFAULT, false)/n; // Viscous diffusion term + + 2 * DDZ(n) * (rho_s / R_c) / n; // Curvature term + ddt(omega) += + D_vort * Delp2(omega, CELL_DEFAULT, false) / n; // Viscous diffusion term // if(coord->is3D()){ // ddt(omega) += Div_Perp_Lap_FV(D_vort ,omega) / n ; // Viscous diffusion term diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index f8148d6a85..5549e881eb 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -26,10 +26,10 @@ class ELMpb : public PhysicsModel { // 2D inital profiles Field2D J0, P0; // Current and pressure Vector2D b0xcv; // Curvature term - Field2D beta; // Used for Vpar terms + Field2D beta; // Used for Vpar terms Coordinates::metric_field_type gradparB; Field2D phi0; // When diamagnetic terms used - Field2D Psixy, x; // 0th vorticity of equilibrium flow, + Field2D Psixy, x; // 0th vorticity of equilibrium flow, Coordinates::metric_field_type U0; // radial flux coordinate, normalized radial flux coordinate @@ -657,8 +657,9 @@ class ELMpb : public PhysicsModel { for (int jy = 0; jy < mesh->LocalNy; jy++) for (int jz = 0; jz < mesh->LocalNz; jz++) { - BoutReal angle = rmp_m * pol_angle(jx, jy) - + rmp_n * ((BoutReal)jz) * mesh->getCoordinates()->dz(jx,jy,jz); + BoutReal angle = + rmp_m * pol_angle(jx, jy) + + rmp_n * ((BoutReal)jz) * mesh->getCoordinates()->dz(jx, jy, jz); rmp_Psi0(jx, jy, jz) = (((BoutReal)(jx - 4)) / ((BoutReal)(mesh->LocalNx - 5))) * rmp_factor * cos(angle); diff --git a/examples/lapd-drift/lapd_drift.cxx b/examples/lapd-drift/lapd_drift.cxx index 3b7aa7950b..356ffefa6b 100644 --- a/examples/lapd-drift/lapd_drift.cxx +++ b/examples/lapd-drift/lapd_drift.cxx @@ -728,8 +728,8 @@ class LAPDdrift : public PhysicsModel { /****************SPECIAL DIFFERENTIAL OPERATORS******************/ - Coordinates::metric_field_type Perp_Grad_dot_Grad(const Field2D &p, const Field2D &f) { - + Coordinates::metric_field_type Perp_Grad_dot_Grad(const Field2D& p, const Field2D& f) { + return DDX(p)*DDX(f)*mesh->getCoordinates()->g11; } @@ -738,7 +738,7 @@ class LAPDdrift : public PhysicsModel { // ExB terms. These routines allow comparisons with BOUT-06 // if bout_exb=true is set in BOUT.inp ///////////////////////////////////////////////////////////////// - Coordinates::metric_field_type vE_Grad(const Field2D &f, const Field2D &p) { + Coordinates::metric_field_type vE_Grad(const Field2D& f, const Field2D& p) { Coordinates::metric_field_type result; if (bout_exb) { // Use a subset of terms for comparison to BOUT-06 @@ -767,25 +767,27 @@ class LAPDdrift : public PhysicsModel { int jzm = (jz - 1 + ncz) % ncz; // J++ = DDZ(p)*DDX(f) - DDX(p)*DDZ(f) - BoutReal Jpp = 0.25*( (p(jx,jy,jzp) - p(jx,jy,jzm))* - (f(jx+1,jy) - f(jx-1,jy)) - - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* - (f(jx,jy) - f(jx,jy)) ) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); - + BoutReal Jpp = + 0.25 + * ((p(jx, jy, jzp) - p(jx, jy, jzm)) * (f(jx + 1, jy) - f(jx - 1, jy)) + - (p(jx + 1, jy, jz) - p(jx - 1, jy, jz)) * (f(jx, jy) - f(jx, jy))) + / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); + // J+x - BoutReal Jpx = 0.25*( f(jx+1,jy)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - - f(jx-1,jy)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - - f(jx,jy)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + - f(jx,jy)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); + BoutReal Jpx = 0.25 + * (f(jx + 1, jy) * (p(jx + 1, jy, jzp) - p(jx + 1, jy, jzm)) + - f(jx - 1, jy) * (p(jx - 1, jy, jzp) - p(jx - 1, jy, jzm)) + - f(jx, jy) * (p(jx + 1, jy, jzp) - p(jx - 1, jy, jzp)) + + f(jx, jy) * (p(jx + 1, jy, jzm) - p(jx - 1, jy, jzm))) + / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); // Jx+ - BoutReal Jxp = 0.25*( f(jx+1,jy)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - - f(jx-1,jy)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - - f(jx-1,jy)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + - f(jx+1,jy)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); - + BoutReal Jxp = 0.25 + * (f(jx + 1, jy) * (p(jx, jy, jzp) - p(jx + 1, jy, jz)) + - f(jx - 1, jy) * (p(jx - 1, jy, jz) - p(jx, jy, jzm)) + - f(jx - 1, jy) * (p(jx, jy, jzp) - p(jx - 1, jy, jz)) + + f(jx + 1, jy) * (p(jx + 1, jy, jz) - p(jx, jy, jzm))) + / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); + result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } @@ -828,25 +830,29 @@ class LAPDdrift : public PhysicsModel { int jzm = (jz - 1 + ncz) % ncz; // J++ = DDZ(p)*DDX(f) - DDX(p)*DDZ(f) - BoutReal Jpp = 0.25*( (p(jx,jy,jzp) - p(jx,jy,jzm))* - (f(jx+1,jy,jz) - f(jx-1,jy,jz)) - - (p(jx+1,jy,jz) - p(jx-1,jy,jz))* - (f(jx,jy,jzp) - f(jx,jy,jzm)) ) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); - + BoutReal Jpp = 0.25 + * ((p(jx, jy, jzp) - p(jx, jy, jzm)) + * (f(jx + 1, jy, jz) - f(jx - 1, jy, jz)) + - (p(jx + 1, jy, jz) - p(jx - 1, jy, jz)) + * (f(jx, jy, jzp) - f(jx, jy, jzm))) + / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); + // J+x - BoutReal Jpx = 0.25*( f(jx+1,jy,jz)*(p(jx+1,jy,jzp)-p(jx+1,jy,jzm)) - - f(jx-1,jy,jz)*(p(jx-1,jy,jzp)-p(jx-1,jy,jzm)) - - f(jx,jy,jzp)*(p(jx+1,jy,jzp)-p(jx-1,jy,jzp)) + - f(jx,jy,jzm)*(p(jx+1,jy,jzm)-p(jx-1,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); + BoutReal Jpx = + 0.25 + * (f(jx + 1, jy, jz) * (p(jx + 1, jy, jzp) - p(jx + 1, jy, jzm)) + - f(jx - 1, jy, jz) * (p(jx - 1, jy, jzp) - p(jx - 1, jy, jzm)) + - f(jx, jy, jzp) * (p(jx + 1, jy, jzp) - p(jx - 1, jy, jzp)) + + f(jx, jy, jzm) * (p(jx + 1, jy, jzm) - p(jx - 1, jy, jzm))) + / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); // Jx+ - BoutReal Jxp = 0.25*( f(jx+1,jy,jzp)*(p(jx,jy,jzp)-p(jx+1,jy,jz)) - - f(jx-1,jy,jzm)*(p(jx-1,jy,jz)-p(jx,jy,jzm)) - - f(jx-1,jy,jzp)*(p(jx,jy,jzp)-p(jx-1,jy,jz)) + - f(jx+1,jy,jzm)*(p(jx+1,jy,jz)-p(jx,jy,jzm))) - / (coord->dx(jx,jy, jz) * coord->dz(jx,jy,jz)); - + BoutReal Jxp = 0.25 + * (f(jx + 1, jy, jzp) * (p(jx, jy, jzp) - p(jx + 1, jy, jz)) + - f(jx - 1, jy, jzm) * (p(jx - 1, jy, jz) - p(jx, jy, jzm)) + - f(jx - 1, jy, jzp) * (p(jx, jy, jzp) - p(jx - 1, jy, jz)) + + f(jx + 1, jy, jzm) * (p(jx + 1, jy, jz) - p(jx, jy, jzm))) + / (coord->dx(jx, jy, jz) * coord->dz(jx, jy, jz)); + result(jx,jy,jz) = (Jpp + Jpx + Jxp) / 3.; } diff --git a/examples/orszag-tang/mhd.cxx b/examples/orszag-tang/mhd.cxx index 0c185c781a..0687f3663d 100644 --- a/examples/orszag-tang/mhd.cxx +++ b/examples/orszag-tang/mhd.cxx @@ -48,7 +48,7 @@ class MHD : public PhysicsModel { Coordinates *coord = mesh->getCoordinates(); output.write("dx(0,0,0) = {:e}, dy(0,0,0) = {:e}, dz(0,0,0) = {:e}\n", - coord->dx(0, 0, 0), coord->dy(0, 0, 0), coord->dz(0, 0, 0)); + coord->dx(0, 0, 0), coord->dy(0, 0, 0), coord->dz(0, 0, 0)); SAVE_REPEAT(divB); diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 99a824005d..13547e00cc 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -93,10 +93,8 @@ public: Field2D zlength() const { #ifdef COORDINATES_USE_3D - Field2D result(0.,localmesh); - BOUT_FOR_SERIAL(i, dz.getRegion("RGN_ALL")) { - result[i] += dz[i]; - } + Field2D result(0., localmesh); + BOUT_FOR_SERIAL(i, dz.getRegion("RGN_ALL")) { result[i] += dz[i]; } return result; #else return dz * nz; @@ -105,8 +103,8 @@ public: /// True if corrections for non-uniform mesh spacing should be included in operators bool non_uniform; - metric_field_type d1_dx, - d1_dy, d1_dz; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) + metric_field_type d1_dx, d1_dy, + d1_dz; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) metric_field_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz @@ -172,59 +170,66 @@ public: #ifdef DERIV_FUNC_REGION_ENUM_TO_STRING #error This utility macro should not clash with another one #else -#define DERIV_FUNC_REGION_ENUM_TO_STRING(func, ResultType, T) \ - [[deprecated("Please use Coordinates::#func(const #T& f, " \ - "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\", " \ - "const std::string& region = \"RGN_ALL\") instead")]] \ - inline ResultType func(const T& f, CELL_LOC outloc, const std::string& method, \ - REGION region) { \ - return func(f, outloc, method, toString(region)); \ - } \ - [[deprecated("Please use Coordinates::#func(const #T& f, " \ - "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\", " \ - "const std::string& region = \"RGN_ALL\") instead")]] \ - inline ResultType func(const T& f, CELL_LOC outloc, DIFF_METHOD method, \ - REGION region = RGN_NOBNDRY) { \ - return func(f, outloc, toString(method), toString(region)); \ +#define DERIV_FUNC_REGION_ENUM_TO_STRING(func, ResultType, T) \ + [[deprecated( \ + "Please use Coordinates::#func(const #T& f, " \ + "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\", " \ + "const std::string& region = \"RGN_ALL\") instead")]] inline ResultType \ + func(const T& f, CELL_LOC outloc, const std::string& method, REGION region) { \ + return func(f, outloc, method, toString(region)); \ + } \ + [[deprecated( \ + "Please use Coordinates::#func(const #T& f, " \ + "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\", " \ + "const std::string& region = \"RGN_ALL\") instead")]] inline ResultType \ + func(const T& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY) { \ + return func(f, outloc, toString(method), toString(region)); \ } #endif #ifdef GRAD_FUNC_REGION_ENUM_TO_STRING #error This utility macro should not clash with another one #else -#define GRAD_FUNC_REGION_ENUM_TO_STRING(func, ResultType, T) \ - [[deprecated("Please use Coordinates::#func(const #T& f, " \ +#define GRAD_FUNC_REGION_ENUM_TO_STRING(func, ResultType, T) \ + [[deprecated( \ + "Please use Coordinates::#func(const #T& f, " \ "CELL_LOC outloc = CELL_DEFAULT, const std::string& method = \"DEFAULT\") " \ - "instead")]] \ - inline ResultType func(const T& f, CELL_LOC outloc, DIFF_METHOD method) { \ - return func(f, outloc, toString(method)); \ + "instead")]] inline ResultType \ + func(const T& f, CELL_LOC outloc, DIFF_METHOD method) { \ + return func(f, outloc, toString(method)); \ } #endif metric_field_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, metric_field_type, Field2D); metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, metric_field_type, Field2D); metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, metric_field_type, Field2D); Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); Field3D DDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); Field3D DDZ(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); /// Gradient along magnetic field b.Grad(f) metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); + const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Grad_par, metric_field_type, Field2D); Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, @@ -233,12 +238,13 @@ public: /// Advection along magnetic field V*b.Grad(f) metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - [[deprecated("Please use Coordinates::Vpar_Grad_par(const Field2D& v, " + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + [[deprecated( + "Please use Coordinates::Vpar_Grad_par(const Field2D& v, " "const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " - "const std::string& method = \"DEFAULT\") instead")]] - inline metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { + "const std::string& method = \"DEFAULT\") instead")]] inline metric_field_type + Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } @@ -254,7 +260,7 @@ public: /// Divergence along magnetic field Div(b*f) = B.Grad(f/B) metric_field_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); + const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Div_par, metric_field_type, Field2D); Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, @@ -263,7 +269,7 @@ public: // Second derivative along magnetic field metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); + const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Grad2_par2, metric_field_type, Field2D); Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, @@ -276,19 +282,20 @@ public: // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code // since it makes use of the same coefficients and FFT routines - metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); + metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); // Full parallel Laplacian operator on scalar field - // Laplace_par(f) = Div( b (b dot Grad(f)) ) - metric_field_type Laplace_par(const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); + // Laplace_par(f) = Div( b (b dot Grad(f)) ) + metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); // Full Laplacian operator on scalar field metric_field_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_conditions = "free_o3", - const std::string& dfdy_dy_region = ""); + const std::string& dfdy_boundary_conditions = "free_o3", + const std::string& dfdy_dy_region = ""); Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_conditions = "free_o3", const std::string& dfdy_dy_region = ""); @@ -309,32 +316,36 @@ private: /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); - inline Field3D maybeFromFieldAligned(const Field3D& f, const std::string& region = "RGN_ALL") { + inline Field3D maybeFromFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") { ASSERT1(location == f.getLocation()); ASSERT1(localmesh == f.getMesh()); - if (f.getDirectionY() != YDirectionType::Standard){ - if (this->getParallelTransform().canToFromFieldAligned()){ - return this->getParallelTransform().fromFieldAligned(f, region); + if (f.getDirectionY() != YDirectionType::Standard) { + if (this->getParallelTransform().canToFromFieldAligned()) { + return this->getParallelTransform().fromFieldAligned(f, region); } else { - Field3D f_ = f; - f_.setDirectionY(YDirectionType::Standard); - return f_; + Field3D f_ = f; + f_.setDirectionY(YDirectionType::Standard); + return f_; } } return f; } - inline Field2D maybeFromFieldAligned(const Field2D& f, const std::string& UNUSED(region) = "RGN_ALL") { + inline Field2D maybeFromFieldAligned(const Field2D& f, + const std::string& UNUSED(region) = "RGN_ALL") { return f; } /// A wrapper for index:DDY derivative that is able to tranform /// fields before the constructor is finished. - Coordinates::metric_field_type indexDDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); + Coordinates::metric_field_type indexDDY(const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); Field3D indexDDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); - + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); }; /* diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index fdac4f95b6..5f54274226 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -249,18 +249,23 @@ namespace FV { for (int k = 0; k < mesh->LocalNz; k++) { #ifdef COORDINATES_USE_3D // For right cell boundaries - BoutReal common_factor = (coord->J(i, j, k) + coord->J(i, j + 1, k)) / - (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j + 1, k))); - - BoutReal flux_factor_rc = common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); - BoutReal flux_factor_rp = common_factor / (coord->dy(i, j + 1, k) * coord->J(i, j + 1, k)); - - // For left cell boundaries - common_factor = (coord->J(i, j, k) + coord->J(i, j - 1, k)) / - (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j - 1, k))); - - BoutReal flux_factor_lc = common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); - BoutReal flux_factor_lm = common_factor / (coord->dy(i, j - 1, k) * coord->J(i, j - 1, k)); + BoutReal common_factor = + (coord->J(i, j, k) + coord->J(i, j + 1, k)) + / (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j + 1, k))); + + BoutReal flux_factor_rc = + common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); + BoutReal flux_factor_rp = + common_factor / (coord->dy(i, j + 1, k) * coord->J(i, j + 1, k)); + + // For left cell boundaries + common_factor = (coord->J(i, j, k) + coord->J(i, j - 1, k)) + / (sqrt(coord->g_22(i, j, k)) + sqrt(coord->g_22(i, j - 1, k))); + + BoutReal flux_factor_lc = + common_factor / (coord->dy(i, j, k) * coord->J(i, j, k)); + BoutReal flux_factor_lm = + common_factor / (coord->dy(i, j - 1, k) * coord->J(i, j - 1, k)); #endif //////////////////////////////////////////// diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index 25964db431..5caa984377 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -224,7 +224,8 @@ class Mesh { /// By default all fields revert to zero /// /// @param[in] var This will be set to the value read - /// @param[in] name The name of the vector. Individual fields are read based on this name by appending. See above + /// @param[in] name The name of the vector. Individual fields are read based on this + /// name by appending. See above /// @param[in] def The default value if not found (used for all the components) /// @param[in] communicate Should the field be communicated to fill guard cells? /// @@ -240,7 +241,8 @@ class Mesh { /// By default all fields revert to zero /// /// @param[in] var This will be set to the value read - /// @param[in] name The name of the vector. Individual fields are read based on this name by appending. See above + /// @param[in] name The name of the vector. Individual fields are read based on this + /// name by appending. See above /// @param[in] def The default value if not found (used for all the components) /// @param[in] communicate Should the field be communicated to fill guard cells? /// diff --git a/include/derivs.hxx b/include/derivs.hxx index 83a27798cb..b49d9353e7 100644 --- a/include/derivs.hxx +++ b/include/derivs.hxx @@ -39,21 +39,21 @@ #ifdef DERIV_FUNC_REGION_ENUM_TO_STRING #error This utility macro should not clash with another one #else -#define DERIV_FUNC_REGION_ENUM_TO_STRING(func, T, Tr) \ -[[deprecated("Please use #func(const #T& f, CELL_LOC outloc = CELL_DEFAULT, " \ - "const std::string& method = \"DEFAULT\", const std::string& region = \"RGN_ALL\") " \ - "instead")]] \ -inline Tr func(const T& f, CELL_LOC outloc, const std::string& method, \ - REGION region) { \ - return func(f, outloc, method, toString(region)); \ -} \ -[[deprecated("Please use #func(const #T& f, CELL_LOC outloc = CELL_DEFAULT, " \ - "const std::string& method = \"DEFAULT\", const std::string& region = \"RGN_ALL\") " \ - "instead")]] \ -inline Tr func(const T& f, CELL_LOC outloc, DIFF_METHOD method, \ - REGION region = RGN_NOBNDRY) { \ - return func(f, outloc, toString(method), toString(region)); \ -} +#define DERIV_FUNC_REGION_ENUM_TO_STRING(func, T, Tr) \ + [[deprecated("Please use #func(const #T& f, CELL_LOC outloc = CELL_DEFAULT, " \ + "const std::string& method = \"DEFAULT\", const std::string& region = " \ + "\"RGN_ALL\") " \ + "instead")]] inline Tr \ + func(const T& f, CELL_LOC outloc, const std::string& method, REGION region) { \ + return func(f, outloc, method, toString(region)); \ + } \ + [[deprecated("Please use #func(const #T& f, CELL_LOC outloc = CELL_DEFAULT, " \ + "const std::string& method = \"DEFAULT\", const std::string& region = " \ + "\"RGN_ALL\") " \ + "instead")]] inline Tr \ + func(const T& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY) { \ + return func(f, outloc, toString(method), toString(region)); \ + } #endif #ifdef VDERIV_FUNC_REGION_ENUM_TO_STRING @@ -139,8 +139,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field2D, Coordinates::metric_field_type) /// Calculate first partial derivative in Z @@ -171,8 +172,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field2D, Coordinates::metric_field_type) /// Calculate first partial derivative in Z @@ -237,8 +239,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field2D, Coordinates::metric_field_type) /// Calculate second partial derivative in Y @@ -269,8 +272,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field2D, Coordinates::metric_field_type) /// Calculate second partial derivative in Z @@ -301,8 +305,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field2D, Coordinates::metric_field_type) ////////// FOURTH DERIVATIVES ////////// @@ -335,8 +340,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field2D, Coordinates::metric_field_type) /// Calculate forth partial derivative in Y @@ -367,8 +373,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field2D, Coordinates::metric_field_type) /// Calculate forth partial derivative in Z @@ -399,8 +406,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field2D, Coordinates::metric_field_type) /// For terms of form v * grad(f) @@ -433,8 +441,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Coordinates::metric_field_type, Field2D, Field2D) /// For terms of form v * grad(f) @@ -467,8 +477,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Coordinates::metric_field_type, Field2D, Field2D) /// For terms of form v * grad(f) @@ -501,8 +513,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::metric_field_type, Field2D, Field2D) /// For terms of form v * grad(f) @@ -518,8 +532,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::metric_field_type, Field2D, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::metric_field_type, Field3D, Field2D) /// for terms of form div(v * f) @@ -552,8 +568,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Coordinates::metric_field_type, Field2D, Field2D) /// for terms of form div(v * f) @@ -586,8 +604,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Coordinates::metric_field_type, Field2D, Field2D) /// for terms of form div(v * f) @@ -620,8 +640,10 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Coordinates::metric_field_type, Field2D, Field2D) /// Calculate mixed partial derivative in x and y @@ -685,28 +707,31 @@ D2DXDY(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RG /// (default) then the same as the region for the calculation as a /// whole. If dfdy_region < region in size then this will cause /// errors. -Coordinates::metric_field_type D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY", - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +Coordinates::metric_field_type +D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY", + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); [[deprecated( "Please use D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " "const std::string& method = \"DEFAULT\", const std::string& region = \"RGN_ALL\", " - "const std::string& dfdy_boundary_condition) instead")]] inline Coordinates::metric_field_type -D2DXDY(const Field2D& f, CELL_LOC outloc, const std::string& method, REGION region, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = "") { + "const std::string& dfdy_boundary_condition) instead")]] inline Coordinates:: + metric_field_type + D2DXDY(const Field2D& f, CELL_LOC outloc, const std::string& method, REGION region, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = "") { return D2DXDY(f, outloc, method, toString(region), dfdy_boundary_condition, dfdy_region); } [[deprecated( "Please use D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " "const std::string& method = \"DEFAULT\", const std::string& region = \"RGN_ALL\", " - "const std::string& dfdy_boundary_condition) instead")]] inline Coordinates::metric_field_type -D2DXDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = "") { + "const std::string& dfdy_boundary_condition) instead")]] inline Coordinates:: + metric_field_type + D2DXDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, + REGION region = RGN_NOBNDRY, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = "") { return D2DXDY(f, outloc, toString(method), toString(region), dfdy_boundary_condition, dfdy_region); }; @@ -739,8 +764,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field2D, Coordinates::metric_field_type) /// Calculate mixed partial derivative in y and z @@ -771,8 +797,9 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& - method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); +Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field2D, Coordinates::metric_field_type) #undef DERIV_FUNC_REGION_ENUM_TO_STRING diff --git a/include/difops.hxx b/include/difops.hxx index 3633db1d96..41daa122a2 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -111,28 +111,26 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f); Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -DEPRECATED(Coordinates::metric_field_type Vpar_Grad_par( - const Field2D& v, const Field2D& f, const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); -inline Coordinates::metric_field_type -Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { +DEPRECATED(Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, + const Field2D& f, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); +inline Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -DEPRECATED(inline Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, - const Field2D& f, - DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline Coordinates::metric_field_type Vpar_Grad_par( + const Field2D& v, const Field2D& f, DIFF_METHOD method, CELL_LOC outloc)) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, - CELL_LOC outloc = CELL_DEFAULT, +Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); DEPRECATED(Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, const std::string& method, CELL_LOC outloc = CELL_DEFAULT)); inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, - DIFF_METHOD method) { + DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } DEPRECATED(inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, @@ -152,8 +150,7 @@ DEPRECATED(inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, * @param[in] method The numerical method to use * */ -Coordinates::metric_field_type Div_par(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, +Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); DEPRECATED(Coordinates::metric_field_type Div_par(const Field2D& f, const std::string& method, @@ -188,8 +185,7 @@ Field3D Div_par(const Field3D& f, const Field3D& v); // Flux methods. Model divergence of flux: df/dt = Div(v * f) // TODO : Should we add Field2D versions? -Field3D Div_par_flux(const Field3D& v, const Field3D& f, - CELL_LOC outloc = CELL_DEFAULT, +Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); DEPRECATED(Field3D Div_par_flux(const Field3D& v, const Field3D& f, const std::string& method, @@ -233,67 +229,66 @@ inline Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) * Parallel derivatives, converting between cell-centred and lower cell boundary * These are a simple way to do staggered differencing */ -[[deprecated( - "Grad_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline Field3D Grad_par_CtoL(const Field3D &var) { +[[deprecated("Grad_par_CtoL is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Field3D +Grad_par_CtoL(const Field3D& var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Grad_par(var, CELL_YLOW); } -[[deprecated( - "Grad_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline Coordinates::metric_field_type Grad_par_CtoL(const Field2D &var) { +[[deprecated("Grad_par_CtoL is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Coordinates::metric_field_type +Grad_par_CtoL(const Field2D& var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Grad_par(var, CELL_YLOW); } -[[deprecated( - "Vpar_Grad_par_LCtoC is deprecated. Staggering is now supported in Vpar_Grad_par.")]] -inline Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, - const std::string& region="RGN_NOBNDRY") { +[[deprecated("Vpar_Grad_par_LCtoC is deprecated. Staggering is now supported in " + "Vpar_Grad_par.")]] inline Field3D +Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, + const std::string& region = "RGN_NOBNDRY") { ASSERT2(v.getLocation() == CELL_YLOW); ASSERT2(f.getLocation() == CELL_CENTRE); return Vpar_Grad_par(v, f, CELL_CENTRE, region); } -[[deprecated( - "Vpar_Grad_par_LCtoC is deprecated. Staggering is now supported in Vpar_Grad_par.")]] -inline Field3D Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, - REGION region=RGN_NOBNDRY) { +[[deprecated("Vpar_Grad_par_LCtoC is deprecated. Staggering is now supported in " + "Vpar_Grad_par.")]] inline Field3D +Vpar_Grad_par_LCtoC(const Field3D& v, const Field3D& f, REGION region = RGN_NOBNDRY) { ASSERT2(v.getLocation() == CELL_YLOW); ASSERT2(f.getLocation() == CELL_CENTRE); return Vpar_Grad_par(v, f, CELL_CENTRE, toString(region)); } -[[deprecated( - "Grad_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline Field3D Grad_par_LtoC(const Field3D &var) { +[[deprecated("Grad_par_LtoC is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Field3D +Grad_par_LtoC(const Field3D& var) { ASSERT2(var.getLocation() == CELL_YLOW); return Grad_par(var, CELL_CENTRE); } -[[deprecated( - "Grad_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline Coordinates::metric_field_type Grad_par_LtoC(const Field2D &var) { +[[deprecated("Grad_par_LtoC is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Coordinates::metric_field_type +Grad_par_LtoC(const Field2D& var) { ASSERT2(var.getLocation() == CELL_YLOW); return Grad_par(var, CELL_CENTRE); } -[[deprecated( - "Div_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline Field3D Div_par_LtoC(const Field3D &var) { +[[deprecated("Div_par_LtoC is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Field3D +Div_par_LtoC(const Field3D& var) { ASSERT2(var.getLocation() == CELL_YLOW); return Div_par(var, CELL_CENTRE); } -[[deprecated( - "Div_par_LtoC is deprecated. Staggering is now supported in Grad_par.")]] -inline Coordinates::metric_field_type Div_par_LtoC(const Field2D &var) { +[[deprecated("Div_par_LtoC is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Coordinates::metric_field_type +Div_par_LtoC(const Field2D& var) { ASSERT2(var.getLocation() == CELL_YLOW); return Div_par(var, CELL_CENTRE); } -[[deprecated( - "Div_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline Field3D Div_par_CtoL(const Field3D &var) { +[[deprecated("Div_par_CtoL is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Field3D +Div_par_CtoL(const Field3D& var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Div_par(var, CELL_YLOW); } -[[deprecated( - "Div_par_CtoL is deprecated. Staggering is now supported in Grad_par.")]] -inline Coordinates::metric_field_type Div_par_CtoL(const Field2D &var) { +[[deprecated("Div_par_CtoL is deprecated. Staggering is now supported in " + "Grad_par.")]] inline Coordinates::metric_field_type +Div_par_CtoL(const Field2D& var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Div_par(var, CELL_YLOW); } @@ -309,13 +304,16 @@ inline Coordinates::metric_field_type Div_par_CtoL(const Field2D &var) { * @param[in] f The field whose gradient drives a flux */ Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); -Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); -Coordinates::metric_field_type -Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); -Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); -Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc=CELL_DEFAULT); -Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); + CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); +Coordinates::metric_field_type Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field2D& kY, const Field3D& f, + CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field3D& kY, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT); +Field3D Div_par_K_Grad_par(const Field3D& kY, const Field3D& f, + CELL_LOC outloc = CELL_DEFAULT); /*! * Perpendicular Laplacian operator @@ -326,19 +324,20 @@ Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc= * * For the full perpendicular Laplacian, use Laplace_perp */ -Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); +Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); -FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, - bool useFFT = true); +FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); /*! * Perpendicular Laplacian, keeping y derivatives * * */ -Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +Coordinates::metric_field_type +Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -349,14 +348,15 @@ Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, */ Coordinates::metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); -Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); +Field3D Laplace_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); /*! * Full Laplacian operator (par + perp) */ -Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +Coordinates::metric_field_type +Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -370,8 +370,8 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); * Terms of form b0 x Grad(phi) dot Grad(A) * */ -Coordinates::metric_field_type -b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc = CELL_DEFAULT); +Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, + CELL_LOC outloc = CELL_DEFAULT); /*! * Terms of form @@ -384,16 +384,18 @@ b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc = CELL_DE * @param[in] A The field being advected * @param[in] outloc The cell location where the result is defined. By default the same as A. */ -Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field2D &A, CELL_LOC outloc=CELL_DEFAULT); -Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); -Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc=CELL_DEFAULT); - +Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field2D& A, + CELL_LOC outloc = CELL_DEFAULT); +Field3D b0xGrad_dot_Grad(const Field2D& phi, const Field3D& A, + CELL_LOC outloc = CELL_DEFAULT); +Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, + CELL_LOC outloc = CELL_DEFAULT); /*! * X-Z Finite Volume diffusion operator */ -Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc = CELL_DEFAULT); - +Field3D Div_Perp_Lap_FV(const Field3D& a, const Field3D& f, + CELL_LOC outloc = CELL_DEFAULT); /*! * Poisson bracket methods @@ -431,14 +433,11 @@ Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); -Field3D bracket(const Field2D &f, const Field3D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); -Field3D bracket(const Field3D &f, const Field2D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); -Field3D bracket(const Field3D &f, const Field3D &g, - BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, - Solver *solver = nullptr); +Field3D bracket(const Field2D& f, const Field3D& g, BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); +Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); +Field3D bracket(const Field3D& f, const Field3D& g, BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); #endif /* __DIFOPS_H__ */ diff --git a/include/field.hxx b/include/field.hxx index a88961b275..d5e929d258 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -297,7 +297,9 @@ inline void checkPositive(const T& f, const std::string& name="field", const std BOUT_FOR_SERIAL(i, f.getRegion(rgn)) { if (f[i] <= 0.) { - throw BoutException("{:s} ({:s} {:s}) is {:e} (not positive) at {:s}", name, toString(f.getLocation()), toString(f.getDirections()), f[i], toString(i)); + throw BoutException("{:s} ({:s} {:s}) is {:e} (not positive) at {:s}", name, + toString(f.getLocation()), toString(f.getDirections()), f[i], + toString(i)); } } } @@ -359,40 +361,41 @@ inline BoutReal min(const T& f, bool allpe, REGION rgn) { return min(f, allpe, toString(rgn)); } - -template> -inline bool isConst(const T& f, bool allpe = false, const std::string& region = "RGN_ALL") { +template > +inline bool isConst(const T& f, bool allpe = false, + const std::string& region = "RGN_ALL") { bool result = true; auto element = f[*f.getRegion(region).begin()]; - BOUT_FOR_SERIAL(i, f.getRegion(region)){ - if (f[i] != element){ - result=false; + BOUT_FOR_SERIAL(i, f.getRegion(region)) { + if (f[i] != element) { + result = false; break; } } - if(allpe) { + if (allpe) { bool localresult = result; MPI_Allreduce(&localresult, &result, 1, MPI_C_BOOL, MPI_LOR, BoutComm::get()); } return result; } -template> -inline BoutReal getConst(const T& f, bool allpe = false, const std::string& region = "RGN_ALL") { +template > +inline BoutReal getConst(const T& f, bool allpe = false, + const std::string& region = "RGN_ALL") { bool is_const = true; auto element = f[*f.getRegion(region).begin()]; #if CHECK > 1 - BOUT_FOR_SERIAL(i, f.getRegion(region)){ - if (f[i] != element){ + BOUT_FOR_SERIAL(i, f.getRegion(region)) { + if (f[i] != element) { is_const = false; break; } } - if(allpe) { + if (allpe) { bool local_is_const = is_const; MPI_Allreduce(&local_is_const, &is_const, 1, MPI_C_BOOL, MPI_LOR, BoutComm::get()); } - if (! is_const) { + if (!is_const) { throw BoutException("Requested getConst but Field is not const"); } #endif diff --git a/include/field2d.hxx b/include/field2d.hxx index 6e5702117b..29d330b971 100644 --- a/include/field2d.hxx +++ b/include/field2d.hxx @@ -380,9 +380,7 @@ inline void invalidateGuards(Field2D &UNUSED(var)) {} /// Average in the Z direction /// Field2D has no Z direction -- return input /// @param[in] f Variable to average -inline Field2D DC(const Field2D &f) { - return f; -} +inline Field2D DC(const Field2D& f) { return f; } /// Returns a reference to the time-derivative of a field \p f /// diff --git a/include/field3d.hxx b/include/field3d.hxx index 7bc218bef1..03177569ac 100644 --- a/include/field3d.hxx +++ b/include/field3d.hxx @@ -473,7 +473,6 @@ class Field3D : public Field, public FieldData { friend class Vector3D; friend class Vector2D; - Field3D& calcParallelSlices(); diff --git a/include/vecops.hxx b/include/vecops.hxx index 451175a0c8..deae65ed03 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -34,9 +34,9 @@ class Field3D; class Vector2D; class Vector3D; -#include "bout/deprecated.hxx" #include "bout_types.hxx" #include "bout/coordinates.hxx" +#include "bout/deprecated.hxx" // Those are needed because we implement functions here. // They can be dropped if we remove the deprecated wrappers. #include "field2d.hxx" @@ -87,13 +87,15 @@ const Vector2D Grad_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, /// @param[in] outloc The cell location where the result is desired /// @param[in] method The method to use. The default is set in the options. /// -const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -const Field3D Div(const Vector3D &v, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +const Coordinates::metric_field_type Div(const Vector2D& v, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +const Field3D Div(const Vector3D& v, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); -const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, - CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); +const Coordinates::metric_field_type Div(const Vector2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); @@ -132,7 +134,7 @@ const Vector3D Curl(const Vector3D &v); /// /// The vector and the field must be at the same location, which /// cannot be CELL_VSHIFT -const Coordinates::metric_field_type V_dot_Grad(const Vector2D &v, const Field2D &f); +const Coordinates::metric_field_type 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); diff --git a/include/vector2d.hxx b/include/vector2d.hxx index e15254132d..f886f2121d 100644 --- a/include/vector2d.hxx +++ b/include/vector2d.hxx @@ -128,7 +128,8 @@ public: const Vector2D operator/(const Field2D &rhs) const; ///< Divides all components by \p rhs const Vector3D operator/(const Field3D &rhs) const; ///< Divides all components by \p rhs - const Coordinates::metric_field_type operator*(const Vector2D &rhs) const; ///< Dot product + const Coordinates::metric_field_type + operator*(const Vector2D& rhs) const; ///< Dot product const Field3D operator*(const Vector3D &rhs) const; ///< Dot product /*! @@ -180,10 +181,13 @@ const Vector3D cross(const Vector2D & lhs, const Vector3D &rhs); * * |v| = sqrt( v dot v ) */ -const Coordinates::metric_field_type abs(const Vector2D& v, const std::string& region = "RGN_ALL"); -[[deprecated("Please use Vector2D abs(const Vector2D& f, " - "const std::string& region = \"RGN_ALL\") instead")]] -inline const Coordinates::metric_field_type abs(const Vector2D &v, REGION region) { +const Coordinates::metric_field_type abs(const Vector2D& v, + const std::string& region = "RGN_ALL"); +[[deprecated( + "Please use Vector2D abs(const Vector2D& f, " + "const std::string& region = \"RGN_ALL\") instead")]] inline const Coordinates:: + metric_field_type + abs(const Vector2D& v, REGION region) { return abs(v, toString(region)); } diff --git a/src/field/field.cxx b/src/field/field.cxx index bae415532b..8eb499d702 100644 --- a/src/field/field.cxx +++ b/src/field/field.cxx @@ -25,13 +25,13 @@ //#include +#include +#include +#include #include -#include #include -#include +#include #include -#include -#include Field::Field(Mesh *localmesh, CELL_LOC location_in, DirectionTypes directions_in) diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index 98005e4b82..a9af3ed37e 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -209,7 +209,7 @@ bool Field3D::requiresTwistShift(bool twist_shift_enabled) { // We need to communicate in the coordinates constructure in that // case a Field3D, but coordinates isn't valid yet. As such we // disable twist-shift in that case. - if (getCoordinates() == nullptr){ + if (getCoordinates() == nullptr) { return false; } return getCoordinates()->getParallelTransform().requiresTwistShift(twist_shift_enabled, @@ -868,4 +868,3 @@ std::ostream& operator<<(std::ostream &out, const Field3D &value) { out << toString(value); return out; } - diff --git a/src/field/field_factory.cxx b/src/field/field_factory.cxx index d62cbcae23..77a2cb119a 100644 --- a/src/field/field_factory.cxx +++ b/src/field/field_factory.cxx @@ -222,11 +222,11 @@ Field3D FieldFactory::create3D(FieldGeneratorPtr gen, Mesh* localmesh, CELL_LOC output_warn.write("Skipping parallel transformation - coordinates not set!\n"); } else { if (coords->getParallelTransform().canToFromFieldAligned()) { - // Transform from field aligned coordinates, to be compatible with - // older BOUT++ inputs. This is not a particularly "nice" solution. - result = fromFieldAligned(result, "RGN_ALL"); + // Transform from field aligned coordinates, to be compatible with + // older BOUT++ inputs. This is not a particularly "nice" solution. + result = fromFieldAligned(result, "RGN_ALL"); } else { - result.setDirectionY(YDirectionType::Standard); + result.setDirectionY(YDirectionType::Standard); } } } @@ -273,9 +273,9 @@ FieldPerp FieldFactory::createPerp(FieldGeneratorPtr gen, Mesh* localmesh, CELL_ output_warn.write("Skipping parallel transformation - coordinates not set!\n"); } else { if (coords->getParallelTransform().canToFromFieldAligned()) { - // Transform from field aligned coordinates, to be compatible with - // older BOUT++ inputs. This is not a particularly "nice" solution. - result = fromFieldAligned(result, "RGN_ALL"); + // Transform from field aligned coordinates, to be compatible with + // older BOUT++ inputs. This is not a particularly "nice" solution. + result = fromFieldAligned(result, "RGN_ALL"); } } } diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index c30e4273f8..7a884bb053 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -89,13 +89,11 @@ BoutReal FieldBallooning::generate(const Context& ctx) { for (int i = 1; i <= ball_n; i++) { // y - i * 2pi - value += arg->generate(Context(ctx).set( - "y", ctx.y() - i * TWOPI, - "z", ctx.z() + i * ts * TWOPI / zlength)); + value += arg->generate(Context(ctx).set("y", ctx.y() - i * TWOPI, "z", + ctx.z() + i * ts * TWOPI / zlength)); - value += arg->generate(Context(ctx).set( - "y", ctx.y() + i * TWOPI, - "z", ctx.z() - i * ts * TWOPI / zlength)); + value += arg->generate(Context(ctx).set("y", ctx.y() + i * TWOPI, "z", + ctx.z() - i * ts * TWOPI / zlength)); } return value; } diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 5a9ef01165..27856eb840 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -143,7 +143,8 @@ const Vector2D Grad_perp(const Field2D &f, CELL_LOC outloc, const std::string& m * Divergence operators **************************************************************************/ -const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc, const std::string& method) { +const Coordinates::metric_field_type Div(const Vector2D& v, CELL_LOC outloc, + const std::string& method) { TRACE("Div( Vector2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -159,8 +160,8 @@ const Coordinates::metric_field_type Div(const Vector2D &v, CELL_LOC outloc, con // get contravariant components of v Vector2D vcn = v; vcn.toContravariant(); - - Coordinates::metric_field_type result = DDX(metric->J*vcn.x, outloc, method); + + Coordinates::metric_field_type result = DDX(metric->J * vcn.x, outloc, method); result += DDY(metric->J*vcn.y, outloc, method); result += DDZ(metric->J*vcn.z, outloc, method); result /= metric->J; @@ -187,7 +188,7 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) vcn.toContravariant(); Field3D vcnJy = vcn.y.getCoordinates()->J * vcn.y; - if(!vcn.y.hasParallelSlices()){ + if (!vcn.y.hasParallelSlices()) { localmesh->communicate(vcnJy); } Field3D result = DDY(vcnJy, outloc, method); @@ -203,8 +204,8 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) * Divergence operators for flux methods **************************************************************************/ -const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, CELL_LOC outloc, - const std::string& method) { +const Coordinates::metric_field_type Div(const Vector2D& v, const Field2D& f, + CELL_LOC outloc, const std::string& method) { TRACE("Div( Vector2D, Field2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -221,7 +222,8 @@ const Coordinates::metric_field_type Div(const Vector2D &v, const Field2D &f, CE Vector2D vcn = v; vcn.toContravariant(); - Coordinates::metric_field_type result = FDDX(vcn.x.getCoordinates()->J * vcn.x, f, outloc, method); + Coordinates::metric_field_type 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; @@ -317,7 +319,7 @@ const Vector3D Curl(const Vector3D &v) { /************************************************************************** * Upwinding operators **************************************************************************/ -const Coordinates::metric_field_type V_dot_Grad(const Vector2D &v, const Field2D &f) { +const Coordinates::metric_field_type V_dot_Grad(const Vector2D& v, const Field2D& f) { TRACE("V_dot_Grad( Vector2D , Field2D )"); SCOREP0(); diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index 8dd5e0f5d2..96568e75f3 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -85,7 +85,7 @@ void Vector2D::toCovariant() { const auto y_at_z = interp_to(y, z.getLocation()); // multiply by g_{ij} - BOUT_FOR(i, x.getRegion("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")) { x[i] = metric_x->g_11[i]*x[i] + metric_x->g_12[i]*y_at_x[i] + metric_x->g_13[i]*z_at_x[i]; y[i] = metric_y->g_22[i]*y[i] + metric_y->g_12[i]*x_at_y[i] + metric_y->g_23[i]*z_at_y[i]; z[i] = metric_z->g_33[i]*z[i] + metric_z->g_13[i]*x_at_z[i] + metric_z->g_23[i]*y_at_z[i]; @@ -96,7 +96,7 @@ void Vector2D::toCovariant() { // Need to use temporary arrays to store result Coordinates::metric_field_type gx{emptyFrom(x)}, gy{emptyFrom(y)}, gz{emptyFrom(z)}; - BOUT_FOR(i, x.getRegion("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")) { gx[i] = metric->g_11[i]*x[i] + metric->g_12[i]*y[i] + metric->g_13[i]*z[i]; gy[i] = metric->g_22[i]*y[i] + metric->g_12[i]*x[i] + metric->g_23[i]*z[i]; gz[i] = metric->g_33[i]*z[i] + metric->g_13[i]*x[i] + metric->g_23[i]*y[i]; @@ -136,7 +136,7 @@ void Vector2D::toContravariant() { const auto y_at_z = interp_to(y, z.getLocation()); // multiply by g_{ij} - BOUT_FOR(i, x.getRegion("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")) { x[i] = metric_x->g11[i]*x[i] + metric_x->g12[i]*y_at_x[i] + metric_x->g13[i]*z_at_x[i]; y[i] = metric_y->g22[i]*y[i] + metric_y->g12[i]*x_at_y[i] + metric_y->g23[i]*z_at_y[i]; z[i] = metric_z->g33[i]*z[i] + metric_z->g13[i]*x_at_z[i] + metric_z->g23[i]*y_at_z[i]; @@ -148,7 +148,7 @@ void Vector2D::toContravariant() { // Need to use temporary arrays to store result Coordinates::metric_field_type gx{emptyFrom(x)}, gy{emptyFrom(y)}, gz{emptyFrom(z)}; - BOUT_FOR(i, x.getRegion("RGN_ALL")){ + BOUT_FOR(i, x.getRegion("RGN_ALL")) { gx[i] = metric->g11[i]*x[i] + metric->g12[i]*y[i] + metric->g13[i]*z[i]; gy[i] = metric->g22[i]*y[i] + metric->g12[i]*x[i] + metric->g23[i]*z[i]; gz[i] = metric->g33[i]*z[i] + metric->g13[i]*x[i] + metric->g23[i]*y[i]; @@ -371,7 +371,7 @@ const Vector3D Vector2D::operator/(const Field3D &rhs) const { ////////////////// DOT PRODUCT /////////////////// -const Coordinates::metric_field_type Vector2D::operator*(const Vector2D &rhs) const { +const Coordinates::metric_field_type Vector2D::operator*(const Vector2D& rhs) const { ASSERT2(location == rhs.getLocation()); Mesh *localmesh = x.getMesh(); @@ -474,8 +474,7 @@ const Vector3D operator*(const Field3D &lhs, const Vector2D &rhs) { ***************************************************************/ // Return the magnitude of a vector -const Coordinates::metric_field_type -abs(const Vector2D &v, const std::string& region) { +const Coordinates::metric_field_type abs(const Vector2D& v, const std::string& region) { return sqrt(v*v, region); } diff --git a/src/fileio/datafile.cxx b/src/fileio/datafile.cxx index d79de67626..27127cbcd8 100644 --- a/src/fileio/datafile.cxx +++ b/src/fileio/datafile.cxx @@ -1030,9 +1030,9 @@ bool Datafile::read() { } // 2D vectors -#ifdef COORDINATES_USE_3D - for(const auto& var : v2d_arr) { - if(var.covar) { +#ifdef COORDINATES_USE_3D + for (const auto& var : v2d_arr) { + if (var.covar) { // Reading covariant vector read_f3d(var.name + "_x", &(var.ptr->x), var.save_repeat); read_f3d(var.name + "_y", &(var.ptr->y), var.save_repeat); @@ -1054,7 +1054,7 @@ bool Datafile::read() { read_f2d(var.name + "y", &(var.ptr->y), var.save_repeat); read_f2d(var.name + "z", &(var.ptr->z), var.save_repeat); } -#endif +#endif var.ptr->covariant = var.covar; } @@ -1188,24 +1188,24 @@ bool Datafile::write() { } // 2D vectors -#ifdef COORDINATES_USE_3D - for(const auto& var : v2d_arr) { - if(var.covar) { +#ifdef COORDINATES_USE_3D + for (const auto& var : v2d_arr) { + if (var.covar) { // Writing covariant vector - Vector2D v = *(var.ptr); + Vector2D v = *(var.ptr); v.toCovariant(); - - write_f3d(var.name+"_x", &(v.x), var.save_repeat); - write_f3d(var.name+"_y", &(v.y), var.save_repeat); - write_f3d(var.name+"_z", &(v.z), var.save_repeat); + + write_f3d(var.name + "_x", &(v.x), var.save_repeat); + write_f3d(var.name + "_y", &(v.y), var.save_repeat); + write_f3d(var.name + "_z", &(v.z), var.save_repeat); } else { // Writing contravariant vector - Vector2D v = *(var.ptr); + Vector2D v = *(var.ptr); v.toContravariant(); - - write_f3d(var.name+"x", &(v.x), var.save_repeat); - write_f3d(var.name+"y", &(v.y), var.save_repeat); - write_f3d(var.name+"z", &(v.z), var.save_repeat); + + write_f3d(var.name + "x", &(v.x), var.save_repeat); + write_f3d(var.name + "y", &(v.y), var.save_repeat); + write_f3d(var.name + "z", &(v.z), var.save_repeat); } } #else @@ -1227,7 +1227,7 @@ bool Datafile::write() { write_f2d(name+"z", &(v.z), var.save_repeat); } #endif - + // 3D vectors for(const auto& var : v3d_arr) { Vector3D v = *(var.ptr); diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index 255b47e307..7f633dbadc 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -579,17 +579,19 @@ BOUT_OMP(for collapse(2)) BoutReal dz = coords->dz(i2, yindex); BoutReal ddx_C = (C2(i2+1, yindex, k2) - C2(i2-1, yindex, k2))/2./coords->dx(i2, yindex)/C1(i2, yindex, k2); - BoutReal ddz_C = (C2(i2, yindex, k2p) - C2(i2, yindex, k2m)) /2./dz/C1(i2, yindex, k2); - + BoutReal ddz_C = + (C2(i2, yindex, k2p) - C2(i2, yindex, k2m)) / 2. / dz / C1(i2, yindex, k2); + BoutReal ddx = D(i2, yindex, k2)*coords->g11(i2, yindex)/coords->dx(i2, yindex)/coords->dx(i2, yindex); // coefficient of 2nd derivative stencil (x-direction) - - BoutReal ddz = D(i2, yindex, k2)*coords->g33(i2, yindex)/SQ(dz); - // coefficient of 2nd derivative stencil (z-direction) - - BoutReal dxdz = D(i2, yindex, k2)*2.*coords->g13(i2, yindex)/coords->dx(i2, yindex)/dz; - // coefficient of mixed derivative stencil (could assume zero, at least initially, - // if easier; then check this is true in constructor) + + BoutReal ddz = D(i2, yindex, k2) * coords->g33(i2, yindex) / SQ(dz); + // coefficient of 2nd derivative stencil (z-direction) + + BoutReal dxdz = + D(i2, yindex, k2) * 2. * coords->g13(i2, yindex) / coords->dx(i2, yindex) / dz; + // coefficient of mixed derivative stencil (could assume zero, at least initially, + // if easier; then check this is true in constructor) BoutReal dxd = (D(i2, yindex, k2)*coords->G1(i2, yindex) + coords->g11(i2, yindex)*ddx_C @@ -599,12 +601,15 @@ BOUT_OMP(for collapse(2)) // add correction for non-uniform dx dxd += D(i2, yindex, k2)*coords->d1_dx(i2, yindex); } - - BoutReal dzd = (D(i2, yindex, k2)*coords->G3(i2, yindex) - + coords->g33(i2, yindex)*ddz_C - + coords->g13(i2, yindex)*ddx_C // (could assume zero, at least initially, if easier; then check this is true in constructor) - )/dz; // coefficient of 1st derivative stencil (z-direction) - + + BoutReal dzd = + (D(i2, yindex, k2) * coords->G3(i2, yindex) + coords->g33(i2, yindex) * ddz_C + + coords->g13(i2, yindex) + * ddx_C // (could assume zero, at least initially, if easier; then check + // this is true in constructor) + ) + / dz; // coefficient of 1st derivative stencil (z-direction) + int ic = i*(llz+2)+k; mat[ic*9] = dxdz/4.; mat[ic*9+1] = ddx - dxd/2.; diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index 8d2d62799f..6c2b1462a2 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -401,23 +401,43 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { // Set values corresponding to nodes adjacent in x if( fourth_order ) { // Fourth Order Accuracy on Boundary - Element(i,x,z, 0, 0, -25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 1, 0, 4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 2, 0, -3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 3, 0, 4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 4, 0, -1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i, x, z, 0, 0, + -25.0 / (12.0 * coords->dx(x, y, z)) + / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, 1, 0, + 4.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, 2, 0, + -3.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, 3, 0, + 4.0 / (3.0 * coords->dx(x, y, z)) + / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, 4, 0, + -1.0 / (4.0 * coords->dx(x, y, z)) + / sqrt(coords->g_11(x, y, z)), + MatA); } else { // Second Order Accuracy on Boundary // Element(i,x,z, 0, 0, -3.0 / (2.0*coords->dx(x,y)), MatA ); // Element(i,x,z, 1, 0, 2.0 / coords->dx(x,y), MatA ); // Element(i,x,z, 2, 0, -1.0 / (2.0*coords->dx(x,y)), MatA ); - // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 + // in case 4th order flag was used previously: not allowed now // Element(i,x,z, 4, 0, 0.0, MatA ); // Second Order Accuracy on Boundary, set half-way between grid points - Element(i,x,z, 0, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 1, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, 2, 0, 0.0, MatA ); - // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + Element(i, x, z, 0, 0, + -1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, 1, 0, + 1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, 2, 0, 0.0, MatA); + // Element(i,x,z, 3, 0, 0.0, MatA ); // Reset + // these elements to 0 in case 4th order flag was + // used previously: not allowed now // Element(i,x,z, 4, 0, 0.0, MatA ); } } else { @@ -472,12 +492,12 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { // Set the matrix coefficients Coeffs( x, y, z, A1, A2, A3, A4, A5 ); - BoutReal dx = coords->dx(x,y,z); - BoutReal dx2 = SQ(dx); - BoutReal dz = coords->dz(x,y,z); - BoutReal dz2 = SQ(dz); + BoutReal dx = coords->dx(x, y, z); + BoutReal dx2 = SQ(dx); + BoutReal dz = coords->dz(x, y, z); + BoutReal dz2 = SQ(dz); BoutReal dxdz = dx * dz; - + ASSERT3(finite(A1)); ASSERT3(finite(A2)); ASSERT3(finite(A3)); @@ -650,11 +670,24 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { // Set values corresponding to nodes adjacent in x if( fourth_order ) { // Fourth Order Accuracy on Boundary - Element(i,x,z, 0, 0, 25.0 / (12.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -1, 0, -4.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -2, 0, 3.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -3, 0, -4.0 / (3.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -4, 0, 1.0 / (4.0*coords->dx(x,y,z)) / sqrt(coords->g_11(x,y,z)), MatA ); + Element(i, x, z, 0, 0, + 25.0 / (12.0 * coords->dx(x, y, z)) + / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, -1, 0, + -4.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, -2, 0, + 3.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, -3, 0, + -4.0 / (3.0 * coords->dx(x, y, z)) + / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, -4, 0, + 1.0 / (4.0 * coords->dx(x, y, z)) + / sqrt(coords->g_11(x, y, z)), + MatA); } else { // // Second Order Accuracy on Boundary @@ -664,9 +697,9 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { // // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now // // Element(i,x,z, -4, 0, 0.0, MatA ); // Second Order Accuracy on Boundary, set half-way between grid points - Element(i,x,z, 0, 0, 1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -1, 0, -1.0 / coords->dx(x,y,z) / sqrt(coords->g_11(x,y,z)), MatA ); - Element(i,x,z, -2, 0, 0.0, MatA ); +Element(i, x, z, 0, 0, 1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); +Element(i, x, z, -1, 0, -1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); +Element(i, x, z, -2, 0, 0.0, MatA); // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now // Element(i,x,z, -4, 0, 0.0, MatA ); } @@ -938,16 +971,16 @@ 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 ) { - coef1 = coords->g11(x,y,z); // X 2nd derivative coefficient - coef2 = coords->g33(x,y,z); // Z 2nd derivative coefficient - coef3 = 2.*coords->g13(x,y,z); // X-Z mixed derivative coefficient + coef1 = coords->g11(x, y, z); // X 2nd derivative coefficient + coef2 = coords->g33(x, y, z); // Z 2nd derivative coefficient + coef3 = 2. * coords->g13(x, y, z); // X-Z mixed derivative coefficient coef4 = 0.0; coef5 = 0.0; // If global flag all_terms are set (true by default) if (all_terms) { - coef4 = coords->G1(x,y,z); // X 1st derivative - coef5 = coords->G3(x,y,z); // Z 1st derivative + coef4 = coords->G1(x, y, z); // X 1st derivative + coef5 = coords->G3(x, y, z); // Z 1st derivative ASSERT3(finite(coef4)); ASSERT3(finite(coef5)); @@ -956,13 +989,17 @@ void LaplacePetsc::Coeffs( int x, int y, int z, BoutReal &coef1, BoutReal &coef2 if(nonuniform) { // non-uniform mesh correction if((x != 0) && (x != (localmesh->LocalNx-1))) { - coef4 -= 0.5 * ( ( coords->dx(x+1,y,z) - coords->dx(x-1,y,z) ) / SQ(coords->dx(x,y,z)) ) * coef1; // BOUT-06 term + coef4 -= 0.5 + * ((coords->dx(x + 1, y, z) - coords->dx(x - 1, y, z)) + / SQ(coords->dx(x, y, z))) + * coef1; // BOUT-06 term } } if(localmesh->IncIntShear) { // d2dz2 term - coef2 += coords->g11(x,y,z) * coords->IntShiftTorsion(x,y,z) * coords->IntShiftTorsion(x,y,z); + coef2 += coords->g11(x, y, z) * coords->IntShiftTorsion(x, y, z) + * coords->IntShiftTorsion(x, y, z); // Mixed derivative coef3 = 0.0; // This cancels out } @@ -992,19 +1029,25 @@ void LaplacePetsc::Coeffs( int x, int y, int z, BoutReal &coef1, BoutReal &coef2 int zmm = z-2; // z minus 1 minus 1 if (zmm<0) zmm += meshz; // Fourth order discretization of C in x - ddx_C = (-C2(x+2,y,z) + 8.*C2(x+1,y,z) - 8.*C2(x-1,y,z) + C2(x-2,y,z)) / (12.*coords->dx(x,y,z)*(C1(x,y,z))); + ddx_C = (-C2(x + 2, y, z) + 8. * C2(x + 1, y, z) - 8. * C2(x - 1, y, z) + + C2(x - 2, y, z)) + / (12. * coords->dx(x, y, z) * (C1(x, y, z))); // Fourth order discretization of C in z - ddz_C = (-C2(x,y,zpp) + 8.*C2(x,y,zp) - 8.*C2(x,y,zm) + C2(x,y,zmm)) / (12.*coords->dz(x,y,z)*(C1(x,y,z))); + ddz_C = + (-C2(x, y, zpp) + 8. * C2(x, y, zp) - 8. * C2(x, y, zm) + C2(x, y, zmm)) + / (12. * coords->dz(x, y, z) * (C1(x, y, z))); } else { // Second order discretization of C in x - ddx_C = (C2(x+1,y,z) - C2(x-1,y,z)) / (2.*coords->dx(x,y,z)*(C1(x,y,z))); + ddx_C = (C2(x + 1, y, z) - C2(x - 1, y, z)) + / (2. * coords->dx(x, y, z) * (C1(x, y, z))); // Second order discretization of C in z - ddz_C = (C2(x,y,zp) - C2(x,y,zm)) / (2.*coords->dz(x,y,z)*(C1(x,y,z))); + ddz_C = (C2(x, y, zp) - C2(x, y, zm)) + / (2. * coords->dz(x, y, z) * (C1(x, y, z))); } - coef4 += coords->g11(x,y,z) * ddx_C + coords->g13(x,y,z) * ddz_C; - coef5 += coords->g13(x,y,z) * ddx_C + coords->g33(x,y,z) * ddz_C; + coef4 += coords->g11(x, y, z) * ddx_C + coords->g13(x, y, z) * ddz_C; + coef5 += coords->g13(x, y, z) * ddx_C + coords->g33(x, y, z) * ddz_C; } } diff --git a/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx b/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx index 6b94d5ff83..3e7e69ef6e 100644 --- a/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx +++ b/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx @@ -271,8 +271,8 @@ void LaplacePetsc3dAmg::updateMatrix3D() { const Field3D dc_dx = issetC ? DDX(C2) : Field3D(); const Field3D dc_dy = issetC ? DDY(C2) : Field3D(); const Field3D dc_dz = issetC ? DDZ(C2) : Field3D(); - const auto dJ_dy = DDY(coords->J/coords->g_22); - + const auto dJ_dy = DDY(coords->J / coords->g_22); + // Set up the matrix for the internal points on the grid. // Boundary conditions were set in the constructor. BOUT_FOR_SERIAL(l, indexer->getRegionNobndry()) { @@ -383,7 +383,7 @@ void LaplacePetsc3dAmg::updateMatrix3D() { C_d2f_dxdy /= 4*coords->dx[l]; // NOTE: This value is not completed here. It needs to // be divide by dx(i +/- 1, j, k) when using to set a // matrix element - C_d2f_dydz /= 4*coords->dy[l]*coords->dz[l]; + C_d2f_dydz /= 4 * coords->dy[l] * coords->dz[l]; // The values stored in the y-boundary are already interpolated // up/down, so we don't want the matrix to do any such diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index 19b92dffba..daa51c15f2 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -123,9 +123,8 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { for(int iz=0;iz<=maxmode;iz++) { // solve differential equation in x - - BoutReal coef1=0.0, coef2=0.0, coef3=0.0, coef4=0.0, - coef5=0.0, coef6=0.0; + + BoutReal coef1 = 0.0, coef2 = 0.0, coef3 = 0.0, coef4 = 0.0, coef5 = 0.0, coef6 = 0.0; ///////// PERFORM INVERSION ///////// // shift freqs according to FFT convention @@ -200,7 +199,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { int ix = 1; - auto kwave = kwave_(ix,jy); + auto kwave = kwave_(ix, jy); coef1=coords->g11(ix,jy)/(SQ(coords->dx(ix,jy))); coef2=coords->g33(ix,jy); coef3= kwave * coords->g13(ix,jy)/(2. * coords->dx(ix,jy)); @@ -322,7 +321,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { int ix = 1; - auto kwave = kwave_(ix,jy); + auto kwave = kwave_(ix, jy); coef1=coords->g11(ix,jy)/(12.* SQ(coords->dx(ix,jy))); coef2=coords->g33(ix,jy); @@ -369,7 +368,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { coef2=coords->g33(ix,jy); - auto kwave = kwave_(ix,jy); + auto kwave = kwave_(ix, jy); coef3= kwave * coords->g13(ix,jy)/(2. * coords->dx(ix,jy)); coef4 = Acoef(ix,jy); diff --git a/src/invert/laplace/impls/shoot/shoot_laplace.cxx b/src/invert/laplace/impls/shoot/shoot_laplace.cxx index f59429f105..ae61eb7710 100644 --- a/src/invert/laplace/impls/shoot/shoot_laplace.cxx +++ b/src/invert/laplace/impls/shoot/shoot_laplace.cxx @@ -134,8 +134,8 @@ FieldPerp LaplaceShoot::solve(const FieldPerp& rhs) { rfft(rhs[ix], localmesh->LocalNz, std::begin(rhsk)); for(int kz=0; kzgetLocation() == loc); ASSERT1(d == nullptr || d->getLocation() == loc); - BoutReal kwave=jz*2.0*PI/coords->zlength()(jx,jy); // wave number is 1/[rad] + BoutReal kwave = jz * 2.0 * PI / coords->zlength()(jx, jy); // wave number is 1/[rad] tridagCoefs(jx, jy, kwave, a, b, c, diff --git a/src/invert/laplacexy/laplacexy.cxx b/src/invert/laplacexy/laplacexy.cxx index a52da73b19..56b3289ef8 100644 --- a/src/invert/laplacexy/laplacexy.cxx +++ b/src/invert/laplacexy/laplacexy.cxx @@ -900,7 +900,7 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B const Field2D g_22_DC = DC(coords->g_22); const Field2D g_23_DC = DC(coords->g_23); const Field2D g23_DC = DC(coords->g23); - + for(int x=localmesh->xstart; x <= localmesh->xend; x++) { for(int y=localmesh->ystart;y<=localmesh->yend;y++) { // stencil entries @@ -909,22 +909,22 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B // XX component // Metrics on x+1/2 boundary - BoutReal J = 0.5*(J_DC(x,y) + J_DC(x+1,y)); - BoutReal g11 = 0.5*(g11_DC(x,y) + g11_DC(x+1,y)); - BoutReal dx = 0.5*(dx_DC(x,y) + dx_DC(x+1,y)); + BoutReal J = 0.5 * (J_DC(x, y) + J_DC(x + 1, y)); + BoutReal g11 = 0.5 * (g11_DC(x, y) + g11_DC(x + 1, y)); + BoutReal dx = 0.5 * (dx_DC(x, y) + dx_DC(x + 1, y)); BoutReal Acoef = 0.5*(A(x,y) + A(x+1,y)); - BoutReal val = Acoef * J * g11 / (J_DC(x,y) * dx * dx_DC(x,y)); + BoutReal val = Acoef * J * g11 / (J_DC(x, y) * dx * dx_DC(x, y)); xp = val; c = -val; // Metrics on x-1/2 boundary - J = 0.5*(J_DC(x,y) + J_DC(x-1,y)); - g11 = 0.5*(g11_DC(x,y) + g11_DC(x-1,y)); - dx = 0.5*(dx_DC(x,y) + dx_DC(x-1,y)); + J = 0.5 * (J_DC(x, y) + J_DC(x - 1, y)); + g11 = 0.5 * (g11_DC(x, y) + g11_DC(x - 1, y)); + dx = 0.5 * (dx_DC(x, y) + dx_DC(x - 1, y)); Acoef = 0.5*(A(x,y) + A(x-1,y)); - val = Acoef * J * g11 / (J_DC(x,y) * dx * dx_DC(x,y)); + val = Acoef * J * g11 / (J_DC(x, y) * dx * dx_DC(x, y)); xm = val; c -= val; @@ -938,26 +938,26 @@ void LaplaceXY::setMatrixElementsFiniteVolume(const Field2D &A, const Field2D &B if( include_y_derivs ) { // YY component // Metrics at y+1/2 - J = 0.5*(J_DC(x,y) + J_DC(x,y+1)); - BoutReal g_22 = 0.5*(g_22_DC(x,y) + g_22_DC(x,y+1)); - BoutReal g23 = 0.5*(g23_DC(x,y) + g23_DC(x,y+1)); - BoutReal g_23 = 0.5*(g_23_DC(x,y) + g_23_DC(x,y+1)); - BoutReal dy = 0.5*(dy_DC(x,y) + dy_DC(x,y+1)); + J = 0.5 * (J_DC(x, y) + J_DC(x, y + 1)); + BoutReal g_22 = 0.5 * (g_22_DC(x, y) + g_22_DC(x, y + 1)); + BoutReal g23 = 0.5 * (g23_DC(x, y) + g23_DC(x, y + 1)); + BoutReal g_23 = 0.5 * (g_23_DC(x, y) + g_23_DC(x, y + 1)); + BoutReal dy = 0.5 * (dy_DC(x, y) + dy_DC(x, y + 1)); Acoef = 0.5*(A(x,y+1) + A(x,y)); - val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x,y) * dy * dy_DC(x,y)); + val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x, y) * dy * dy_DC(x, y)); yp = val; c -= val; // Metrics at y-1/2 - J = 0.5*(J_DC(x,y) + J_DC(x,y-1)); - g_22 = 0.5*(g_22_DC(x,y) + g_22_DC(x,y-1)); - g23 = 0.5*(g23_DC(x,y) + g23_DC(x,y-1)); - g_23 = 0.5*(g_23_DC(x,y) + g_23_DC(x,y-1)); - dy = 0.5*(dy_DC(x,y) + dy_DC(x,y-1)); + J = 0.5 * (J_DC(x, y) + J_DC(x, y - 1)); + g_22 = 0.5 * (g_22_DC(x, y) + g_22_DC(x, y - 1)); + g23 = 0.5 * (g23_DC(x, y) + g23_DC(x, y - 1)); + g_23 = 0.5 * (g_23_DC(x, y) + g_23_DC(x, y - 1)); + dy = 0.5 * (dy_DC(x, y) + dy_DC(x, y - 1)); Acoef = 0.5*(A(x,y-1) + A(x,y)); - val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x,y) * dy * dy_DC(x,y)); + val = -Acoef * J * g23 * g_23 / (g_22 * J_DC(x, y) * dy * dy_DC(x, y)); ym = val; c -= val; } @@ -1014,33 +1014,33 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 const Field2D d1_dy_2D = DC(coords->d1_dy); const Field2D dx_2D = DC(coords->dx); const Field2D dy_2D = DC(coords->dy); - - const Field2D coef_dfdy = G2_2D - DC(DDY(J_2D/g_22_2D)/J_2D); + + const Field2D coef_dfdy = G2_2D - DC(DDY(J_2D / g_22_2D) / J_2D); for(int x = localmesh->xstart; x <= localmesh->xend; x++) { for(int y = localmesh->ystart; y <= localmesh->yend; y++) { // stencil entries PetscScalar c, xm, xp, ym, yp, xpyp, xpym, xmyp, xmym; - BoutReal dx = dx_2D(x,y); + BoutReal dx = dx_2D(x, y); // A*G1*dfdx - BoutReal val = A(x, y)*G1_2D(x, y)/(2.*dx); + BoutReal val = A(x, y) * G1_2D(x, y) / (2. * dx); xp = val; xm = -val; // A*g11*d2fdx2 - val = A(x, y)*g11_2D(x, y)/SQ(dx); + val = A(x, y) * g11_2D(x, y) / SQ(dx); xp += val; c = -2.*val; xm += val; // Non-uniform grid correction - val = A(x, y)*g11_2D(x, y)*d1_dx_2D(x, y)/(2.*dx); + val = A(x, y) * g11_2D(x, y) * d1_dx_2D(x, y) / (2. * dx); xp += val; xm -= val; // g11*dAdx*dfdx - val = g11_2D(x, y)*(A(x+1, y) - A(x-1, y))/(4.*SQ(dx)); + val = g11_2D(x, y) * (A(x + 1, y) - A(x - 1, y)) / (4. * SQ(dx)); xp += val; xm -= val; @@ -1053,7 +1053,7 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 ccoef(y - localmesh->ystart, x - xstart) = xp; if(include_y_derivs) { - BoutReal dy = dy_2D(x,y); + BoutReal dy = dy_2D(x, y); BoutReal dAdx = (A(x+1, y) - A(x-1, y))/(2.*dx); BoutReal dAdy = (A(x, y+1) - A(x, y-1))/(2.*dy); @@ -1063,33 +1063,32 @@ void LaplaceXY::setMatrixElementsFiniteDifference(const Field2D &A, const Field2 ym = -val; // A*(g22-1/g_22)*d2fdy2 - val = A(x, y)*(g22_2D(x, y) - 1./g_22_2D(x,y))/SQ(dy); + val = A(x, y) * (g22_2D(x, y) - 1. / g_22_2D(x, y)) / SQ(dy); yp += val; c -= 2.*val; ym += val; // Non-uniform mesh correction - val = A(x, y)*(g22_2D(x, y) - 1./g_22_2D(x,y)) - *d1_dy_2D(x, y)/(2.*dy); + val = A(x, y) * (g22_2D(x, y) - 1. / g_22_2D(x, y)) * d1_dy_2D(x, y) / (2. * dy); yp += val; ym -= val; // 2*A*g12*d2dfdxdy - val = A(x, y)*g12_2D(x, y)/(2.*dx*dy); + val = A(x, y) * g12_2D(x, y) / (2. * dx * dy); xpyp = val; xpym = -val; xmyp = -val; xmym = val; // g22*dAdy*dfdy - val = (g22_2D(x, y) - 1./g_22_2D(x,y))*dAdy/(2.*dy); + val = (g22_2D(x, y) - 1. / g_22_2D(x, y)) * dAdy / (2. * dy); yp += val; ym -= val; // g12*(dAdx*dfdy + dAdy*dfdx) - val = g12_2D(x, y)*dAdx/(2.*dy); + val = g12_2D(x, y) * dAdx / (2. * dy); yp += val; ym -= val; - val = g12_2D(x, y)*dAdy/(2.*dx); + val = g12_2D(x, y) * dAdy / (2. * dx); xp += val; xm -= val; } diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index bfe67f7dc7..4e0a166f5e 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -392,26 +392,28 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // XX component { // Metrics on x+1/2 boundary - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - const BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x+1,y,z)); - const BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x + 1, y, z)); + const BoutReal g11 = 0.5 * (coords->g11(x, y, z) + coords->g11(x + 1, y, z)); + const BoutReal dx = 0.5 * (coords->dx(x, y, z) + coords->dx(x + 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x + 1, y, z)); - const BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + const BoutReal val = + Acoef * J * g11 / (coords->J(x, y, z) * dx * coords->dx(x, y, z)); xp = val; - c = -val; + c = -val; } { // Metrics on x-1/2 boundary - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); - const BoutReal g11 = 0.5*(coords->g11(x,y,z) + coords->g11(x-1,y,z)); - const BoutReal dx = 0.5*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x - 1, y, z)); + const BoutReal g11 = 0.5 * (coords->g11(x, y, z) + coords->g11(x - 1, y, z)); + const BoutReal dx = 0.5 * (coords->dx(x, y, z) + coords->dx(x - 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x - 1, y, z)); - const BoutReal val = Acoef * J * g11 / (coords->J(x,y,z) * dx * coords->dx(x,y,z)); + const BoutReal val = + Acoef * J * g11 / (coords->J(x, y, z) * dx * coords->dx(x, y, z)); xm = val; - c -= val; + c -= val; } // ZZ component @@ -420,26 +422,26 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { const int zplus = (z + 1) % (localmesh->LocalNz); { - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); - const BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zplus)); - const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zplus)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x, y, zplus)); + const BoutReal g33 = 0.5 * (coords->g33(x, y, z) + coords->g33(x, y, zplus)); + const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x, y, zplus)); // Metrics on z+1/2 boundary - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zplus)); - const BoutReal val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + const BoutReal val = Acoef * J * g33 / (coords->J(x, y, z) * dz * dz); zp = val; - c -= val; + c -= val; } { // Metrics on z-1/2 boundary - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); - const BoutReal g33 = 0.5*(coords->g33(x,y,z) + coords->g33(x,y,zminus)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); - const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zminus)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x, y, zminus)); + const BoutReal g33 = 0.5 * (coords->g33(x, y, z) + coords->g33(x, y, zminus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); + const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x, y, zminus)); - const BoutReal val = Acoef * J * g33 / (coords->J(x,y,z) * dz * dz); + const BoutReal val = Acoef * J * g33 / (coords->J(x, y, z) * dz * dz); zm = val; - c -= val; + c -= val; } // XZ components @@ -447,13 +449,14 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { { // x+1/2, z+1/2 // TODOL Should they have a z dependency? - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x+1,y,z)); - const BoutReal fourdz = 2 * (coords->dz(x,y,z)+ coords->dz(x+1,y,zplus)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x + 1, y, z)); + const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x + 1, y, z)); + const BoutReal fourdz = 2 * (coords->dz(x, y, z) + coords->dz(x + 1, y, zplus)); { - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zplus)); - const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + const BoutReal val = + Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); xpzp = val; c -= val; } @@ -461,30 +464,33 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // x+1/2, z-1/2 // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); - const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + const BoutReal val = + -Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); xpzm = val; c -= val; } } { // x-1/2, z+1/2 - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x-1,y,z)); - const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x-1,y,z)); - const BoutReal fourdz = 2 * (coords->dz(x,y,z)+ coords->dz(x-1,y,z)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x - 1, y, z)); + const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x - 1, y, z)); + const BoutReal fourdz = 2 * (coords->dz(x, y, z) + coords->dz(x - 1, y, z)); { - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zplus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zplus)); - const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + const BoutReal val = + -Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); xmzp = val; c -= val; } { // x-1/2, z-1/2 - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x,y,zminus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); - const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * fourdz * coords->dx(x,y,z)); + const BoutReal val = + Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); xmzm = val; c -= val; } @@ -493,53 +499,52 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { { // ZX components // z+1/2, x+1/2 - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zplus)); - const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zplus)); - const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zplus)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x, y, zplus)); + const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x, y, zplus)); + const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x, y, zplus)); { - const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x + 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x + 1, y, z)); - const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + const BoutReal val = Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); zpxp = val; c -= val; } { - //z+1/2, x-1/2 - const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + // z+1/2, x-1/2 + const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x - 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x - 1, y, z)); - const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + const BoutReal val = -Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); zpxm = val; c -= val; } } { // z-1/2, x+1/2 - const BoutReal J = 0.5*(coords->J(x,y,z) + coords->J(x,y,zminus)); - const BoutReal g13 = 0.5*(coords->g13(x,y,z) + coords->g13(x,y,zminus)); - const BoutReal dz = 0.5 * (coords->dz(x,y,z)+ coords->dz(x,y,zminus)); + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x, y, zminus)); + const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x, y, zminus)); + const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x, y, zminus)); { - const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x+1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x+1,y,z)); + const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x + 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x + 1, y, z)); - const BoutReal val = - Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + const BoutReal val = -Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); zmxp = val; c -= val; } { // z-1/2, x-1/2 - const BoutReal dx = 2.0*(coords->dx(x,y,z) + coords->dx(x-1,y,z)); - const BoutReal Acoef = 0.5*(A(x,y,z) + A(x-1,y,z)); + const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x - 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x - 1, y, z)); - const BoutReal val = Acoef * J * g13 / (coords->J(x,y,z) * dx * dz); + const BoutReal val = Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); zmxm = val; c -= val; } } - ///////////// OLDER CODE ///////////////// // Note that because metrics are constant in Z many terms cancel @@ -562,7 +567,6 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // c -= val; ////////////////////////////////////////// - // B term c += B(x,y,z); @@ -570,45 +574,45 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { // Now have a 5-point stencil for the Laplacian // Set the centre (diagonal) - MatSetValues(it.MatA,1,&row,1,&row,&c,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &row, &c, INSERT_VALUES); // X + 1 int col = row + (localmesh->LocalNz); - MatSetValues(it.MatA,1,&row,1,&col,&xp,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &col, &xp, INSERT_VALUES); // X - 1 col = row - (localmesh->LocalNz); - MatSetValues(it.MatA,1,&row,1,&col,&xm,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &col, &xm, INSERT_VALUES); // Z + 1 col = row + 1; if(z == localmesh->LocalNz-1) { col -= localmesh->LocalNz; // Wrap around } - MatSetValues(it.MatA,1,&row,1,&col,&zp,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &col, &zp, INSERT_VALUES); int xzcol = col + (localmesh->LocalNz); // X+1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzp,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxp,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xpzp, INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zpxp, INSERT_VALUES); xzcol = col - (localmesh->LocalNz); // X-1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzp,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zpxm,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xmzp, INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zpxm, INSERT_VALUES); // Z - 1 col = row - 1; if(z == 0) { col += localmesh->LocalNz; // Wrap around } - MatSetValues(it.MatA,1,&row,1,&col,&zm,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &col, &zm, INSERT_VALUES); xzcol = col + (localmesh->LocalNz); // X+1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xpzm,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxp,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xpzm, INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zmxp, INSERT_VALUES); xzcol = col - (localmesh->LocalNz); // X-1 - MatSetValues(it.MatA,1,&row,1,&xzcol,&xmzm,INSERT_VALUES); - MatSetValues(it.MatA,1,&row,1,&xzcol,&zmxm,INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xmzm, INSERT_VALUES); + MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zmxm, INSERT_VALUES); row++; } diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 6d90d5ed84..5f14122757 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -127,7 +127,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { // Set up tridiagonal system for(int k=0; kLocalNy - 2 * localmesh->ystart; y++) { BoutReal acoef = A(x, y + localmesh->ystart); // Constant @@ -138,7 +138,8 @@ const Field3D InvertParCR::solve(const Field3D &f) { BoutReal ecoef = E(x, y + localmesh->ystart); // ddy bcoef /= SQ(coord->dy(x, y + localmesh->ystart)); - ccoef /= coord->dy(x, y + localmesh->ystart) * coord->dz(x, y + localmesh->ystart); + ccoef /= + coord->dy(x, y + localmesh->ystart) * coord->dz(x, y + localmesh->ystart); dcoef /= SQ(coord->dz(x, y + localmesh->ystart)); ecoef /= coord->dy(x, y + localmesh->ystart); @@ -159,14 +160,14 @@ const Field3D InvertParCR::solve(const Field3D &f) { bout::globals::mpi->MPI_Comm_size(surf.communicator(), &np); if(rank == 0) { for(int k=0; kLocalNy - 2 * localmesh->ystart - 1) *= phase; } @@ -217,5 +218,3 @@ const Field3D InvertParCR::solve(const Field3D &f) { return Field3D{}; #endif }; - - diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index ad96c68a82..86fd031f6f 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1619,311 +1619,116 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { #ifdef COORDINATES_USE_3D for (int z = 0; z < mesh->LocalNz; z++) { #else - int z=0; + int z = 0; #endif - // Interpolate (linearly) metrics to halfway between last cell and boundary cell - BoutReal g11shift = - 0.5 - * (metric->g11(bndry->x, bndry->y, z) + metric->g11(bndry->x - bndry->bx, bndry->y, z)); - BoutReal g12shift = - 0.5 - * (metric->g12(bndry->x, bndry->y, z) + metric->g12(bndry->x - bndry->bx, bndry->y, z)); - BoutReal g13shift = - 0.5 - * (metric->g13(bndry->x, bndry->y, z) + metric->g13(bndry->x - bndry->bx, bndry->y, z)); - // 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 + // Interpolate (linearly) metrics to halfway between last cell and boundary cell + BoutReal g11shift = 0.5 + * (metric->g11(bndry->x, bndry->y, z) + + metric->g11(bndry->x - bndry->bx, bndry->y, z)); + BoutReal g12shift = 0.5 + * (metric->g12(bndry->x, bndry->y, z) + + metric->g12(bndry->x - bndry->bx, bndry->y, z)); + BoutReal g13shift = 0.5 + * (metric->g13(bndry->x, bndry->y, z) + + metric->g13(bndry->x - bndry->bx, bndry->y, z)); + // 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 #ifndef COORDINATES_USE_3D - for (int z = 0; z < mesh->LocalNz; z++) { + for (int z = 0; z < mesh->LocalNz; z++) { #endif - 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) { - // x boundaries only - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, z); - f(bndry->x, bndry->y, z) = - f(bndry->x - bndry->bx, bndry->y, z) + delta / g11shift * (val - xshift); - if (bndry->width == 2) { - f(bndry->x + bndry->bx, bndry->y, z) = - f(bndry->x - 2 * bndry->bx, bndry->y, z) - + 3.0 * delta / g11shift * (val - xshift); - } - } else if (bndry->by != 0 && bndry->bx == 0) { - // y boundaries only - // no need to shift this b/c we want parallel nuemann not theta - BoutReal delta = bndry->by * metric->dy(bndry->x, bndry->y, z); - f(bndry->x, bndry->y, z) = f(bndry->x, bndry->y - bndry->by, z) + delta * val; - if (bndry->width == 2) { - f(bndry->x, bndry->y + bndry->by, z) = - f(bndry->x, bndry->y - 2 * bndry->by, z) + 3.0 * delta * val; - } - } else { - // set corners to zero - f(bndry->x, bndry->y, z) = 0.0; - if (bndry->width == 2) { - f(bndry->x + bndry->bx, bndry->y + bndry->by, z) = 0.0; - } - } - } - } -} - -/////////////////////////////////////////////////////////////// - -BoundaryOp* BoundaryNeumann::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 1); - std::shared_ptr newgen = nullptr; - if (!args.empty()) { - // First argument should be an expression - newgen = FieldFactory::get()->parse(args.front()); - } - return new BoundaryNeumann(region, newgen); -} - -void BoundaryNeumann::apply(Field2D& f) { BoundaryNeumann::apply(f, 0.); } - -void BoundaryNeumann::apply(Field2D& f, BoutReal t) { - // Set (at 2nd order / 3rd order) the value at the mid-point between - // the guard cell and the grid cell to be val - // N.B. First guard cells (closest to the grid) is 2nd order, while - // 2nd is 3rd order - -#ifndef COORDINATES_USE_3D - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - 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 (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { - // 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) { - val = fg->generate(Context(bndry, loc, t, mesh)) * 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; i < bndry->width; 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) { - val = fg->generate(Context(bndry, loc, t, mesh)) * 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; i < bndry->width; 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) { - val = fg->generate(Context(bndry, loc, t, mesh)); - } - - f(bndry->x, bndry->y) = - f(bndry->x - bndry->bx, bndry->y - bndry->by) + delta * val; + 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) { + // x boundaries only + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, z); + f(bndry->x, bndry->y, z) = + f(bndry->x - bndry->bx, bndry->y, z) + delta / g11shift * (val - xshift); 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) { - val = fg->generate(Context(bndry, loc, t, mesh)) * metric->dy(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; i < bndry->width; 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) { - val = fg->generate(Context(bndry, loc, t, mesh)) * metric->dy(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; i < bndry->width; 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) { - val = fg->generate(Context(bndry, loc, t, mesh)); + f(bndry->x + bndry->bx, bndry->y, z) = + f(bndry->x - 2 * bndry->bx, bndry->y, z) + + 3.0 * delta / g11shift * (val - xshift); + } + } else if (bndry->by != 0 && bndry->bx == 0) { + // y boundaries only + // no need to shift this b/c we want parallel nuemann not theta + BoutReal delta = bndry->by * metric->dy(bndry->x, bndry->y, z); + f(bndry->x, bndry->y, z) = f(bndry->x, bndry->y - bndry->by, z) + delta * val; + if (bndry->width == 2) { + f(bndry->x, bndry->y + bndry->by, z) = + f(bndry->x, bndry->y - 2 * bndry->by, z) + 3.0 * delta * val; } - - f(bndry->x, bndry->y) = - f(bndry->x - bndry->bx, bndry->y - bndry->by) + delta * val; + } else { + // set corners to zero + f(bndry->x, bndry->y, z) = 0.0; 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, z) = 0.0; } } } } - } else { - // Non-staggered, standard case - - 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) { - val = fg->generate(Context(bndry, loc, t, mesh)); - } + /////////////////////////////////////////////////////////////// - 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; - } + BoundaryOp* BoundaryNeumann::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 1); + std::shared_ptr newgen = nullptr; + if (!args.empty()) { + // First argument should be an expression + newgen = FieldFactory::get()->parse(args.front()); } + return new BoundaryNeumann(region, newgen); } -#else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); -#endif -} -void BoundaryNeumann::apply(Field3D& f) { BoundaryNeumann::apply(f, 0.); } + void BoundaryNeumann::apply(Field2D & f) { BoundaryNeumann::apply(f, 0.); } -void BoundaryNeumann::apply(Field3D& f, BoutReal t) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Coordinates* metric = f.getCoordinates(); + void BoundaryNeumann::apply(Field2D & f, BoutReal t) { + // Set (at 2nd order / 3rd order) the value at the mid-point between + // the guard cell and the grid cell to be val + // N.B. First guard cells (closest to the grid) is 2nd order, while + // 2nd is 3rd order - bndry->first(); +#ifndef COORDINATES_USE_3D + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Coordinates* metric = f.getCoordinates(); - // Decide which generator to use - std::shared_ptr fg = gen; - if (!fg) - fg = f.getBndryGenerator(bndry->location); + bndry->first(); - BoutReal val = 0.0; + // Decide which generator to use + std::shared_ptr fg = gen; + if (!fg) + fg = f.getBndryGenerator(bndry->location); - // Check for staggered grids + BoutReal val = 0.0; - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids && loc != CELL_CENTRE) { - // Staggered. Need to apply slightly differently - // Use one-sided differencing. Cell is now on - // the boundary, so use one-sided differencing + // Check for staggered grids - if (loc == CELL_XLOW) { - // Field is shifted in X + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { + // 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 (bndry->bx > 0) { - // Outer x boundary - for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dx(bndry->x, bndry->y, zk); + val = fg->generate(Context(bndry, loc, t, mesh)) + * 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.; - + 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; i < bndry->width; i++) { @@ -1932,24 +1737,24 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { // 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); + 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 - for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for (; !bndry->isDone(); bndry->next1d()) { + if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dx(bndry->x - bndry->bx, bndry->y, zk); + val = fg->generate(Context(bndry, loc, t, mesh)) + * metric->dx(bndry->x, 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) + 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 @@ -1960,51 +1765,46 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { // 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); + 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()) { -#ifndef COORDINATES_USE_3D - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) - + bndry->by * metric->dy(bndry->x, bndry->y); -#endif - for (int zk = 0; zk < mesh->LocalNz; zk++) { -#ifdef COORDINATES_USE_3D - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) - + bndry->by * metric->dy(bndry->x, bndry->y, zk); -#endif + 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) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)); + val = fg->generate(Context(bndry, loc, t, mesh)); } - f(bndry->x, bndry->y, zk) = - f(bndry->x - bndry->bx, bndry->y - bndry->by, zk) + delta * val; + + 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, zk) = - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, zk) + 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) { - // Field is shifted in Y + } 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()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->by > 0) { + // Outer y boundary + + for (; !bndry->isDone(); bndry->next1d()) { if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dy(bndry->x, bndry->y, zk); + val = fg->generate(Context(bndry, loc, t, mesh)) + * 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.; + 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 @@ -2014,24 +1814,23 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { // 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); + 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()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->by < 0) { + // Inner y boundary. Set one point inwards + for (; !bndry->isDone(); bndry->next1d()) { + if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)) * metric->dy(bndry->x, bndry->y - bndry->by, zk); + val = fg->generate(Context(bndry, loc, t, mesh)) + * 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) + 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 @@ -2042,28 +1841,271 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { // 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); + 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) { + val = fg->generate(Context(bndry, loc, t, mesh)); + } + + 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->bx != 0) { - // x boundaries. - for (; !bndry->isDone(); bndry->next1d()) { + } else { + // Non-staggered, standard case + + 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) { + val = fg->generate(Context(bndry, loc, t, mesh)); + } + + 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( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); +#endif + } + + void BoundaryNeumann::apply(Field3D & f) { BoundaryNeumann::apply(f, 0.); } + + void BoundaryNeumann::apply(Field3D & f, BoutReal t) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + 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 (mesh->StaggerGrids && loc != CELL_CENTRE) { + // 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()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)) + * metric->dx(bndry->x, bndry->y, zk); + } + + 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; i < bndry->width; 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()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)) + * metric->dx(bndry->x - bndry->bx, bndry->y, zk); + } + + 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; i < bndry->width; 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()) { #ifndef COORDINATES_USE_3D - int zk=0; - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) - + bndry->by * metric->dy(bndry->x, bndry->y, zk); + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) + + bndry->by * metric->dy(bndry->x, bndry->y); #endif - for (int zk = 0; zk < mesh->LocalNz; zk++) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { #ifdef COORDINATES_USE_3D - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) - + bndry->by * metric->dy(bndry->x, bndry->y, zk); + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); +#endif + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)); + } + 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()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)) + * metric->dy(bndry->x, bndry->y, zk); + } + 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; i < bndry->width; 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()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)) + * metric->dy(bndry->x, bndry->y - bndry->by, zk); + } + + 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; i < bndry->width; 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()) { +#ifndef COORDINATES_USE_3D + int zk = 0; + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); +#endif + for (int zk = 0; zk < mesh->LocalNz; zk++) { +#ifdef COORDINATES_USE_3D + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); #endif + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)); + } + 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_ZLOW) { + // Shifted in Z + 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 ynorm = 0.5 + * (mesh->GlobalY(bndry->y) // In the guard cell + + mesh->GlobalY(bndry->y - bndry->by)); // the grid cell + + for (int zk = 0; zk < mesh->LocalNz; zk++) { + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)); + val = fg->generate(xnorm, TWOPI * ynorm, + TWOPI * (zk - 0.5) / (mesh->LocalNz), t); } f(bndry->x, bndry->y, zk) = f(bndry->x - bndry->bx, bndry->y - bndry->by, zk) + delta * val; @@ -2074,1568 +2116,1571 @@ void BoundaryNeumann::apply(Field3D& f, BoutReal t) { } } } - } - } else if (loc == CELL_ZLOW) { - // Shifted in Z - 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 ynorm = 0.5*( mesh->GlobalY(bndry->y) // In the guard cell - + mesh->GlobalY(bndry->y - bndry->by) ); // the grid cell - - - for(int zk=0;zkLocalNz;zk++) { - BoutReal delta = bndry->bx*metric->dx(bndry->x,bndry->y, zk)+bndry->by*metric->dy(bndry->x,bndry->y, zk); - if(fg){ - val = fg->generate(xnorm,TWOPI*ynorm,TWOPI*(zk - 0.5)/(mesh->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("Unrecognized location"); } } else { - throw BoutException("Unrecognized location"); - } - } else { - for (; !bndry->isDone(); bndry->next1d()) { + for (; !bndry->isDone(); bndry->next1d()) { #ifdef COORDINATES_USE_3D - for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) - + bndry->by * metric->dy(bndry->x, bndry->y, zk); + for (int zk = 0; zk < mesh->LocalNz; zk++) { + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + + bndry->by * metric->dy(bndry->x, bndry->y, zk); #else BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) - + bndry->by * metric->dy(bndry->x, bndry->y); + + bndry->by * metric->dy(bndry->x, bndry->y); for (int zk = 0; zk < mesh->LocalNz; zk++) { #endif - if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)); - } - 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(Context(bndry, zk, loc, t, mesh)); + } + 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; + } } } } } -} -void BoundaryNeumann::apply_ddt(Field2D& f) { - Field2D* dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero -} + void BoundaryNeumann::apply_ddt(Field2D & f) { + Field2D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero + } -void BoundaryNeumann::apply_ddt(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Field3D* dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0; z < mesh->LocalNz; z++) - (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero -} + void BoundaryNeumann::apply_ddt(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Field3D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; z++) + (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero + } -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryNeumann_O4::clone(BoundaryRegion* region, - const std::list& args) { - std::shared_ptr newgen = nullptr; - if (!args.empty()) { - // First argument should be an expression - newgen = FieldFactory::get()->parse(args.front()); + BoundaryOp* BoundaryNeumann_O4::clone(BoundaryRegion * region, + const std::list& args) { + std::shared_ptr newgen = nullptr; + if (!args.empty()) { + // First argument should be an expression + newgen = FieldFactory::get()->parse(args.front()); + } + return new BoundaryNeumann_O4(region, newgen); } - return new BoundaryNeumann_O4(region, newgen); -} -void BoundaryNeumann_O4::apply(Field2D& f) { BoundaryNeumann_O4::apply(f, 0.); } + void BoundaryNeumann_O4::apply(Field2D & f) { BoundaryNeumann_O4::apply(f, 0.); } -void BoundaryNeumann_O4::apply(Field2D& f, BoutReal t) { + void BoundaryNeumann_O4::apply(Field2D & f, BoutReal t) { #ifndef COORDINATES_USE_3D - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); - // 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 - bndry->first(); + // 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 + bndry->first(); - // Decide which generator to use - std::shared_ptr fg = gen; - if (!fg) - fg = f.getBndryGenerator(bndry->location); + // Decide which generator to use + std::shared_ptr fg = gen; + if (!fg) + fg = f.getBndryGenerator(bndry->location); - BoutReal val = 0.0; + BoutReal val = 0.0; - // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids && loc != CELL_CENTRE) { - throw BoutException("neumann_o4 not implemented with staggered grid yet"); - } else { - // Non-staggered, standard case + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids && loc != CELL_CENTRE) { + throw BoutException("neumann_o4 not implemented with staggered grid yet"); + } else { + // Non-staggered, standard case - Coordinates* coords = f.getCoordinates(); + 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); + 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) { - val = fg->generate(Context(bndry, loc, t, mesh)); - } + if (fg) { + val = fg->generate(Context(bndry, loc, t, mesh)); + } - 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.; + 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"); + if (bndry->width == 2) { + throw BoutException( + "neumann_o4 with a boundary width of 2 not implemented yet"); + } } } - } #else throw BoutException( "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif -} + } -void BoundaryNeumann_O4::apply(Field3D& f) { BoundaryNeumann_O4::apply(f, 0.); } + void BoundaryNeumann_O4::apply(Field3D & f) { BoundaryNeumann_O4::apply(f, 0.); } -void BoundaryNeumann_O4::apply(Field3D& f, BoutReal t) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - bndry->first(); + void BoundaryNeumann_O4::apply(Field3D & f, BoutReal t) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + bndry->first(); - // Decide which generator to use - std::shared_ptr fg = gen; - if (!fg) - fg = f.getBndryGenerator(bndry->location); + // Decide which generator to use + std::shared_ptr fg = gen; + if (!fg) + fg = f.getBndryGenerator(bndry->location); - BoutReal val = 0.0; + BoutReal val = 0.0; - // Check for staggered grids - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids && loc != CELL_CENTRE) { - throw BoutException("neumann_o4 not implemented with staggered grid yet"); - } else { - Coordinates* coords = f.getCoordinates(); - for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal delta = bndry->bx * coords->dx(bndry->x, bndry->y, zk) - + bndry->by * coords->dy(bndry->x, bndry->y, zk); - if (fg) { - val = fg->generate(Context(bndry, zk, loc, t, mesh)); - } + // Check for staggered grids + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids && loc != CELL_CENTRE) { + throw BoutException("neumann_o4 not implemented with staggered grid yet"); + } else { + Coordinates* coords = f.getCoordinates(); + for (; !bndry->isDone(); bndry->next1d()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + BoutReal delta = bndry->bx * coords->dx(bndry->x, bndry->y, zk) + + bndry->by * coords->dy(bndry->x, bndry->y, zk); + if (fg) { + val = fg->generate(Context(bndry, zk, loc, t, mesh)); + } - 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.; + 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"); + if (bndry->width == 2) { + throw BoutException( + "neumann_o4 with a boundary width of 2 not implemented yet"); + } } } } } -} -void BoundaryNeumann_O4::apply_ddt(Field2D& f) { - Field2D* dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero -} + void BoundaryNeumann_O4::apply_ddt(Field2D & f) { + Field2D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero + } -void BoundaryNeumann_O4::apply_ddt(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Field3D *dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0; z < mesh->LocalNz; z++) - (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero -} + void BoundaryNeumann_O4::apply_ddt(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Field3D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; z++) + (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero + } -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryNeumann_4thOrder::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 4); - if (!args.empty()) { - // First argument should be a value - val = stringToReal(args.front()); - return new BoundaryNeumann_4thOrder(region, val); + BoundaryOp* BoundaryNeumann_4thOrder::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 4); + if (!args.empty()) { + // First argument should be a value + val = stringToReal(args.front()); + return new BoundaryNeumann_4thOrder(region, val); + } + return new BoundaryNeumann_4thOrder(region); } - return new BoundaryNeumann_4thOrder(region); -} -void BoundaryNeumann_4thOrder::apply(Field2D& f) { + void BoundaryNeumann_4thOrder::apply(Field2D & f) { #ifndef COORDINATES_USE_3D - 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()) { - BoutReal delta = -(bndry->bx * metric->dx(bndry->x, bndry->y) - + bndry->by * metric->dy(bndry->x, bndry->y)); - f(bndry->x, bndry->y) = - 12. * delta / 11. * val - + 17. / 22. * f(bndry->x - bndry->bx, bndry->y - bndry->by) - + 9. / 22. * f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by) - - 5. / 22. * f(bndry->x - 3 * bndry->bx, bndry->y - 3 * bndry->by) - + 1. / 22. * f(bndry->x - 4 * bndry->bx, bndry->y - 4 * bndry->by); - f(bndry->x + bndry->bx, bndry->y + bndry->by) = - -24. * delta * val + 27. * f(bndry->x, bndry->y) - - 27. * f(bndry->x - bndry->bx, bndry->y - bndry->by) - + f(bndry->x - 2 * bndry->bx, - bndry->y - - 2 * bndry->by); // The f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by) 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 - } + 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()) { + BoutReal delta = -(bndry->bx * metric->dx(bndry->x, bndry->y) + + bndry->by * metric->dy(bndry->x, bndry->y)); + f(bndry->x, bndry->y) = + 12. * delta / 11. * val + + 17. / 22. * f(bndry->x - bndry->bx, bndry->y - bndry->by) + + 9. / 22. * f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by) + - 5. / 22. * f(bndry->x - 3 * bndry->bx, bndry->y - 3 * bndry->by) + + 1. / 22. * f(bndry->x - 4 * bndry->bx, bndry->y - 4 * bndry->by); + f(bndry->x + bndry->bx, bndry->y + bndry->by) = + -24. * delta * val + 27. * f(bndry->x, bndry->y) + - 27. * f(bndry->x - bndry->bx, bndry->y - bndry->by) + + f(bndry->x - 2 * bndry->bx, + bndry->y + - 2 * bndry->by); // The f(bndry->x-4*bndry->bx,bndry->y-4*bndry->by) + // 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 + } #else - throw BoutException("void BoundaryNeumann_4thOrder::apply(Field2D& f) not implemented with 3D metrics"); + throw BoutException( + "void BoundaryNeumann_4thOrder::apply(Field2D& f) not implemented with 3D metrics"); #endif -} - -void BoundaryNeumann_4thOrder::apply(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == 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;z < mesh->LocalNz; z++) { - BoutReal delta = -(bndry->bx*metric->dx(bndry->x,bndry->y, z)+bndry->by*metric->dy(bndry->x,bndry->y, z)); - 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 - } -} + } -void BoundaryNeumann_4thOrder::apply_ddt(Field2D& f) { - Field2D* dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero -} + void BoundaryNeumann_4thOrder::apply(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == 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; z < mesh->LocalNz; z++) { + BoutReal delta = -(bndry->bx * metric->dx(bndry->x, bndry->y, z) + + bndry->by * metric->dy(bndry->x, bndry->y, z)); + 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 + } + } + + void BoundaryNeumann_4thOrder::apply_ddt(Field2D & f) { + Field2D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero + } -void BoundaryNeumann_4thOrder::apply_ddt(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Field3D *dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0;z < mesh->LocalNz; z++) - (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero -} + void BoundaryNeumann_4thOrder::apply_ddt(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Field3D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; z++) + (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero + } -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryNeumannPar::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 1); - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryNeumann2\n"; + BoundaryOp* BoundaryNeumannPar::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 1); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryNeumann2\n"; + } + return new BoundaryNeumannPar(region); } - return new BoundaryNeumannPar(region); -} -void BoundaryNeumannPar::apply(Field2D& f) { + void BoundaryNeumannPar::apply(Field2D & f) { #ifndef COORDINATES_USE_3D - Coordinates* metric = f.getCoordinates(); - // Loop over all elements and set equal to the next point in - for (bndry->first(); !bndry->isDone(); bndry->next()) - f(bndry->x, bndry->y) = - f(bndry->x - bndry->bx, bndry->y - bndry->by) - * sqrt(metric->g_22(bndry->x, bndry->y) - / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); + Coordinates* metric = f.getCoordinates(); + // Loop over all elements and set equal to the next point in + for (bndry->first(); !bndry->isDone(); bndry->next()) + f(bndry->x, bndry->y) = + f(bndry->x - bndry->bx, bndry->y - bndry->by) + * sqrt(metric->g_22(bndry->x, bndry->y) + / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); #else throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif -} - -void BoundaryNeumannPar::apply(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Coordinates *metric = f.getCoordinates(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0;z < mesh->LocalNz; 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, z)/metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by,z)); -} + } -/////////////////////////////////////////////////////////////// + void BoundaryNeumannPar::apply(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Coordinates* metric = f.getCoordinates(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; 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, z) + / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by, z)); + } -BoundaryOp* BoundaryRobin::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 1); - BoutReal a = 0.5, b = 1.0, g = 0.; + /////////////////////////////////////////////////////////////// - auto it = args.begin(); + BoundaryOp* BoundaryRobin::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 1); + BoutReal a = 0.5, b = 1.0, g = 0.; - if (it != args.end()) { - // First argument is 'a' - a = stringToReal(*it); - it++; + auto it = args.begin(); if (it != args.end()) { - // Second is 'b' - b = stringToReal(*it); + // First argument is 'a' + a = stringToReal(*it); it++; if (it != args.end()) { - // Third is 'g' - g = stringToReal(*it); + // Second is 'b' + b = stringToReal(*it); it++; + if (it != args.end()) { - output - << "WARNING: BoundaryRobin takes maximum of 3 arguments. Ignoring extras\n"; + // Third is 'g' + g = stringToReal(*it); + it++; + if (it != args.end()) { + output << "WARNING: BoundaryRobin takes maximum of 3 arguments. Ignoring " + "extras\n"; + } } } } + + return new BoundaryRobin(region, a, b, g); } - return new BoundaryRobin(region, a, b, g); -} + void BoundaryRobin::apply(Field2D & f) { + if (fabs(bval) < 1.e-12) { + // No derivative term so just constant value + for (bndry->first(); !bndry->isDone(); bndry->next()) + f(bndry->x, bndry->y) = gval / aval; + } else { + BoutReal sign = 1.; + if ((bndry->bx < 0) || (bndry->by < 0)) + sign = -1.; + for (bndry->first(); !bndry->isDone(); bndry->next()) + f(bndry->x, bndry->y) = + f(bndry->x - bndry->bx, bndry->y - bndry->by) + + sign * (gval - aval * f(bndry->x - bndry->bx, bndry->y - bndry->by)) / bval; + } + } -void BoundaryRobin::apply(Field2D& f) { - if (fabs(bval) < 1.e-12) { - // No derivative term so just constant value - for (bndry->first(); !bndry->isDone(); bndry->next()) - f(bndry->x, bndry->y) = gval / aval; - } else { - BoutReal sign = 1.; - if ((bndry->bx < 0) || (bndry->by < 0)) - sign = -1.; - for (bndry->first(); !bndry->isDone(); bndry->next()) - f(bndry->x, bndry->y) = - f(bndry->x - bndry->bx, bndry->y - bndry->by) - + sign * (gval - aval * f(bndry->x - bndry->bx, bndry->y - bndry->by)) / bval; + void BoundaryRobin::apply(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + if (fabs(bval) < 1.e-12) { + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; 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; z < mesh->LocalNz; 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; + } } -} -void BoundaryRobin::apply(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - if (fabs(bval) < 1.e-12) { + /////////////////////////////////////////////////////////////// + + void BoundaryConstGradient::apply(Field2D & f) { + // Loop over all elements and set equal to the next point in for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0;z < mesh->LocalNz; z++) - f(bndry->x, bndry->y, z) = gval / aval; - } else { - BoutReal sign = 1.; - if ((bndry->bx < 0) || (bndry->by < 0)) - sign = -1.; + f(bndry->x, bndry->y) = 2. * f(bndry->x - bndry->bx, bndry->y - bndry->by) + - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by); + } + + void BoundaryConstGradient::apply(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); for (bndry->first(); !bndry->isDone(); bndry->next()) for (int z = 0; z < mesh->LocalNz; 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; + 2. * f(bndry->x - bndry->bx, bndry->y - bndry->by, z) + - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, z); } -} - -/////////////////////////////////////////////////////////////// - -void BoundaryConstGradient::apply(Field2D& f) { - // Loop over all elements and set equal to the next point in - for (bndry->first(); !bndry->isDone(); bndry->next()) - f(bndry->x, bndry->y) = 2. * f(bndry->x - bndry->bx, bndry->y - bndry->by) - - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by); -} - -void BoundaryConstGradient::apply(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0;z < mesh->LocalNz; 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 std::list& args) { - verifyNumPoints(region, 2); - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryConstGradient\n"; + BoundaryOp* BoundaryConstGradient::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 2); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryConstGradient\n"; + } + return new BoundaryConstGradient(region); } - return new BoundaryConstGradient(region); -} -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryZeroLaplace::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 2); - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryZeroLaplace\n"; + BoundaryOp* BoundaryZeroLaplace::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 2); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryZeroLaplace\n"; + } + return new BoundaryZeroLaplace(region); } - return new BoundaryZeroLaplace(region); -} -void BoundaryZeroLaplace::apply(Field2D& f) { + void BoundaryZeroLaplace::apply(Field2D & f) { #ifndef COORDINATES_USE_3D - Coordinates* metric = f.getCoordinates(); - if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { - // Can't apply this boundary condition to non-X boundaries - throw BoutException( - "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); - } - // Constant X derivative - int bx = bndry->bx; - // Loop over the Y dimension - for (bndry->first(); !bndry->isDone(); bndry->nextY()) { - int x = bndry->x; - int y = bndry->y; - BoutReal g = (f(x - bx, y) - f(x - 2 * bx, y)) / metric->dx(x - bx, y); - // Loop in X towards edge of domain - do { - f(x, y) = f(x - bx, y) + g * metric->dx(x, y); - bndry->nextX(); - x = bndry->x; - y = bndry->y; - } while (!bndry->isDone()); - } + Coordinates* metric = f.getCoordinates(); + if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { + // Can't apply this boundary condition to non-X boundaries + throw BoutException( + "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); + } + // Constant X derivative + int bx = bndry->bx; + // Loop over the Y dimension + for (bndry->first(); !bndry->isDone(); bndry->nextY()) { + int x = bndry->x; + int y = bndry->y; + BoutReal g = (f(x - bx, y) - f(x - 2 * bx, y)) / metric->dx(x - bx, y); + // Loop in X towards edge of domain + do { + f(x, y) = f(x - bx, y) + g * metric->dx(x, y); + bndry->nextX(); + x = bndry->x; + y = bndry->y; + } while (!bndry->isDone()); + } #else throw BoutException( "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif -} - -void BoundaryZeroLaplace::apply(Field3D& f) { -#ifndef COORDINATES_USE_3D - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - int ncz = mesh->LocalNz; - - Coordinates* metric = f.getCoordinates(); - - Array c0(ncz / 2 + 1); - Array c1(ncz / 2 + 1); - - if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { - // Can't apply this boundary condition to non-X boundaries - throw BoutException( - "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); } - int bx = bndry->bx; - // Loop over the Y dimension - for (bndry->first(); !bndry->isDone(); bndry->nextY()) { - // bndry->(x,y) is the first point in the boundary - // bndry->(x-bx,y) is the last "real" point in the domain - - int x = bndry->x; - 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()); - c1[0] = c0[0] - c1[0]; // Only need gradient + void BoundaryZeroLaplace::apply(Field3D & f) { +#ifndef COORDINATES_USE_3D + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + int ncz = mesh->LocalNz; - // Solve metric->g11*d2f/dx2 - metric->g33*kz^2f = 0 - // Assume metric->g11, metric->g33 constant -> exponential growth or decay + Coordinates* metric = f.getCoordinates(); - // Loop in X towards edge of domain - do { - // kz = 0 solution - c0[0] += c1[0]; // Straight line + Array c0(ncz / 2 + 1); + Array c1(ncz / 2 + 1); - // kz != 0 solution - BoutReal coef = - -1.0 * sqrt(metric->g33(x, y) / metric->g11(x, y)) * metric->dx(x, y); - for (int jz = 1; jz <= ncz / 2; jz++) { - BoutReal kwave = jz * 2.0 * PI / metric->zlength()(x,y); // wavenumber in [rad^-1] - c0[jz] *= exp(coef * kwave); // The decaying solution only - } - // Reverse FFT - irfft(c0.begin(), mesh->LocalNz, f(x, y)); + if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { + // Can't apply this boundary condition to non-X boundaries + throw BoutException( + "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); + } - bndry->nextX(); - x = bndry->x; - y = bndry->y; - } while (!bndry->isDone()); - } + int bx = bndry->bx; + // Loop over the Y dimension + for (bndry->first(); !bndry->isDone(); bndry->nextY()) { + // bndry->(x,y) is the first point in the boundary + // bndry->(x-bx,y) is the last "real" point in the domain + + int x = bndry->x; + 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()); + c1[0] = c0[0] - c1[0]; // Only need gradient + + // Solve metric->g11*d2f/dx2 - metric->g33*kz^2f = 0 + // Assume metric->g11, metric->g33 constant -> exponential growth or decay + + // Loop in X towards edge of domain + do { + // kz = 0 solution + c0[0] += c1[0]; // Straight line + + // kz != 0 solution + BoutReal coef = + -1.0 * sqrt(metric->g33(x, y) / metric->g11(x, y)) * metric->dx(x, y); + for (int jz = 1; jz <= ncz / 2; jz++) { + BoutReal kwave = + jz * 2.0 * PI / metric->zlength()(x, y); // wavenumber in [rad^-1] + c0[jz] *= exp(coef * kwave); // The decaying solution only + } + // Reverse FFT + irfft(c0.begin(), mesh->LocalNz, f(x, y)); + + bndry->nextX(); + x = bndry->x; + y = bndry->y; + } while (!bndry->isDone()); + } #else throw BoutException( "Applying boundary to Field3D not compatible with 3D metrics in ZeroLaplace case."); #endif -} + } -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryZeroLaplace2::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 3); - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryZeroLaplace2\n"; + BoundaryOp* BoundaryZeroLaplace2::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 3); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryZeroLaplace2\n"; + } + return new BoundaryZeroLaplace2(region); } - return new BoundaryZeroLaplace2(region); -} -void BoundaryZeroLaplace2::apply(Field2D& f) { + void BoundaryZeroLaplace2::apply(Field2D & f) { #ifndef COORDINATES_USE_3D - if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { - // Can't apply this boundary condition to non-X boundaries - throw BoutException( - "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); - } - - Coordinates* metric = f.getCoordinates(); + if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { + // Can't apply this boundary condition to non-X boundaries + throw BoutException( + "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); + } - // Constant X derivative - int bx = bndry->bx; - // Loop over the Y dimension - for (bndry->first(); !bndry->isDone(); bndry->nextY()) { - int x = bndry->x; - int y = bndry->y; - BoutReal g = (f(x - bx, y) - f(x - 2 * bx, y)) / metric->dx(x - bx, y); - // Loop in X towards edge of domain - do { - f(x, y) = f(x - bx, y) + g * metric->dx(x, y); - bndry->nextX(); - x = bndry->x; - y = bndry->y; - } while (!bndry->isDone()); - } + Coordinates* metric = f.getCoordinates(); + + // Constant X derivative + int bx = bndry->bx; + // Loop over the Y dimension + for (bndry->first(); !bndry->isDone(); bndry->nextY()) { + int x = bndry->x; + int y = bndry->y; + BoutReal g = (f(x - bx, y) - f(x - 2 * bx, y)) / metric->dx(x - bx, y); + // Loop in X towards edge of domain + do { + f(x, y) = f(x - bx, y) + g * metric->dx(x, y); + bndry->nextX(); + x = bndry->x; + y = bndry->y; + } while (!bndry->isDone()); + } #else throw BoutException( "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif -} - -void BoundaryZeroLaplace2::apply(Field3D& f) { -#ifndef COORDINATES_USE_3D - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - int ncz = mesh->LocalNz; - - ASSERT0(ncz % 2 == 0); // Allocation assumes even number - - // allocate memory - Array c0(ncz / 2 + 1), c1(ncz / 2 + 1), c2(ncz / 2 + 1); - - if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { - // Can't apply this boundary condition to non-X boundaries - throw BoutException( - "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); } - int bx = bndry->bx; - // Loop over the Y dimension - for (bndry->first(); !bndry->isDone(); bndry->nextY()) { - // bndry->(x,y) is the first point in the boundary - // bndry->(x-bx,y) is the last "real" point in the domain + void BoundaryZeroLaplace2::apply(Field3D & f) { +#ifndef COORDINATES_USE_3D + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + int ncz = mesh->LocalNz; - int x = bndry->x; - int y = bndry->y; + ASSERT0(ncz % 2 == 0); // Allocation assumes even number - // Take FFT of last 2 points in domain - rfft(f(x - bx, y), ncz, c1.begin()); - rfft(f(x - 2 * bx, y), ncz, c2.begin()); + // allocate memory + Array c0(ncz / 2 + 1), c1(ncz / 2 + 1), c2(ncz / 2 + 1); - // Loop in X towards edge of domain - do { - for (int jz = 0; jz <= ncz / 2; jz++) { - dcomplex la, lb, lc; - laplace_tridag_coefs(x - bx, y, jz, la, lb, lc); - if (bx > 0) { - // Outer boundary - swap(la, lc); - } - c0[jz] = -(lb * c1[jz] + lc * c2[jz]) / la; - } - // Reverse FFT - irfft(c0.begin(), ncz, f(x, y)); - // cycle c0 -> c1 -> c2 -> c0 - swap(c0, c2); - swap(c2, c1); + if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { + // Can't apply this boundary condition to non-X boundaries + throw BoutException( + "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); + } - bndry->nextX(); - x = bndry->x; - y = bndry->y; - } while (!bndry->isDone()); - } + int bx = bndry->bx; + // Loop over the Y dimension + for (bndry->first(); !bndry->isDone(); bndry->nextY()) { + // bndry->(x,y) is the first point in the boundary + // bndry->(x-bx,y) is the last "real" point in the domain + + int x = bndry->x; + int y = bndry->y; + + // Take FFT of last 2 points in domain + rfft(f(x - bx, y), ncz, c1.begin()); + rfft(f(x - 2 * bx, y), ncz, c2.begin()); + + // Loop in X towards edge of domain + do { + for (int jz = 0; jz <= ncz / 2; jz++) { + dcomplex la, lb, lc; + laplace_tridag_coefs(x - bx, y, jz, la, lb, lc); + if (bx > 0) { + // Outer boundary + swap(la, lc); + } + c0[jz] = -(lb * c1[jz] + lc * c2[jz]) / la; + } + // Reverse FFT + irfft(c0.begin(), ncz, f(x, y)); + // cycle c0 -> c1 -> c2 -> c0 + swap(c0, c2); + swap(c2, c1); + + bndry->nextX(); + x = bndry->x; + y = bndry->y; + } while (!bndry->isDone()); + } #else throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " "ZeroLaplace2 case."); #endif -} + } -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryConstLaplace::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 2); - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryConstLaplace\n"; + BoundaryOp* BoundaryConstLaplace::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 2); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryConstLaplace\n"; + } + return new BoundaryConstLaplace(region); } - return new BoundaryConstLaplace(region); -} -void BoundaryConstLaplace::apply(Field2D& f) { - if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { - // Can't apply this boundary condition to non-X boundaries - throw BoutException( - "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); - } - - // Constant X second derivative - int bx = bndry->bx; - // Loop over the Y dimension - for (bndry->first(); !bndry->isDone(); bndry->nextY()) { - int x = bndry->x; - int y = bndry->y; - // Calculate the Laplacian on the last point - dcomplex la, lb, lc; - laplace_tridag_coefs(x - 2 * bx, y, 0, la, lb, lc); - dcomplex val = - la * f(x - bx - 1, y) + lb * f(x - 2 * bx, y) + lc * f(x - 2 * bx + 1, y); - // Loop in X towards edge of domain - do { - laplace_tridag_coefs(x - bx, y, 0, la, lb, lc); - if (bx < 0) { // Lower X - f(x, y) = ((val - lb * f(x - bx, y) + lc * f(x - 2 * bx, y)) / la).real(); - } else // Upper X - f(x, y) = ((val - lb * f(x - bx, y) + la * f(x - 2 * bx, y)) / lc).real(); - - bndry->nextX(); - x = bndry->x; - y = bndry->y; - } while (!bndry->isDone()); + void BoundaryConstLaplace::apply(Field2D & f) { + if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { + // Can't apply this boundary condition to non-X boundaries + throw BoutException( + "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); + } + + // Constant X second derivative + int bx = bndry->bx; + // Loop over the Y dimension + for (bndry->first(); !bndry->isDone(); bndry->nextY()) { + int x = bndry->x; + int y = bndry->y; + // Calculate the Laplacian on the last point + dcomplex la, lb, lc; + laplace_tridag_coefs(x - 2 * bx, y, 0, la, lb, lc); + dcomplex val = + la * f(x - bx - 1, y) + lb * f(x - 2 * bx, y) + lc * f(x - 2 * bx + 1, y); + // Loop in X towards edge of domain + do { + laplace_tridag_coefs(x - bx, y, 0, la, lb, lc); + if (bx < 0) { // Lower X + f(x, y) = ((val - lb * f(x - bx, y) + lc * f(x - 2 * bx, y)) / la).real(); + } else // Upper X + f(x, y) = ((val - lb * f(x - bx, y) + la * f(x - 2 * bx, y)) / lc).real(); + + bndry->nextX(); + x = bndry->x; + y = bndry->y; + } while (!bndry->isDone()); + } } -} -void BoundaryConstLaplace::apply(Field3D& f) { + void BoundaryConstLaplace::apply(Field3D & f) { #ifndef COORDINATES_USE_3D - if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { - // Can't apply this boundary condition to non-X boundaries - throw BoutException( - "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); - } + if ((bndry->location != BNDRY_XIN) && (bndry->location != BNDRY_XOUT)) { + // Can't apply this boundary condition to non-X boundaries + throw BoutException( + "ERROR: Can't apply Zero Laplace condition to non-X boundaries\n"); + } - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Coordinates *metric = f.getCoordinates(); - - int ncz = mesh->LocalNz; - - // Allocate memory - Array c0(ncz / 2 + 1), c1(ncz / 2 + 1), c2(ncz / 2 + 1); - - int bx = bndry->bx; - // Loop over the Y dimension - for (bndry->first(); !bndry->isDone(); bndry->nextY()) { - int x = bndry->x; - int y = bndry->y; - - // Take FFT of last 3 points in domain - rfft(f(x - bx, y), ncz, c0.begin()); - rfft(f(x - 2 * bx, y), ncz, c1.begin()); - rfft(f(x - 3 * bx, y), ncz, c2.begin()); - dcomplex k0lin = (c1[0] - c0[0]) / metric->dx(x - bx, y); // for kz=0 solution - - // Calculate Delp2 on point MXG+1 (and put into c1) - for (int jz = 0; jz <= ncz / 2; jz++) { - dcomplex la, lb, lc; - laplace_tridag_coefs(x - 2 * bx, y, jz, la, lb, lc); - if (bx < 0) { // Inner X - c1[jz] = la * c0[jz] + lb * c1[jz] + lc * c2[jz]; - } else { // Outer X - c1[jz] = la * c2[jz] + lb * c1[jz] + lc * c0[jz]; - } + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Coordinates* metric = f.getCoordinates(); + + int ncz = mesh->LocalNz; + + // Allocate memory + Array c0(ncz / 2 + 1), c1(ncz / 2 + 1), c2(ncz / 2 + 1); + + int bx = bndry->bx; + // Loop over the Y dimension + for (bndry->first(); !bndry->isDone(); bndry->nextY()) { + int x = bndry->x; + int y = bndry->y; + + // Take FFT of last 3 points in domain + rfft(f(x - bx, y), ncz, c0.begin()); + rfft(f(x - 2 * bx, y), ncz, c1.begin()); + rfft(f(x - 3 * bx, y), ncz, c2.begin()); + dcomplex k0lin = (c1[0] - c0[0]) / metric->dx(x - bx, y); // for kz=0 solution + + // Calculate Delp2 on point MXG+1 (and put into c1) + for (int jz = 0; jz <= ncz / 2; jz++) { + dcomplex la, lb, lc; + laplace_tridag_coefs(x - 2 * bx, y, jz, la, lb, lc); + if (bx < 0) { // Inner X + c1[jz] = la * c0[jz] + lb * c1[jz] + lc * c2[jz]; + } else { // Outer X + c1[jz] = la * c2[jz] + lb * c1[jz] + lc * c0[jz]; + } + } + // Solve metric->g11*d2f/dx2 - metric->g33*kz^2f = 0 + // Assume metric->g11, metric->g33 constant -> exponential growth or decay + BoutReal xpos = 0.0; + // Loop in X towards edge of domain + do { + // kz = 0 solution + xpos -= metric->dx(x, y); + c2[0] = c0[0] + k0lin * xpos + 0.5 * c1[0] * xpos * xpos / metric->g11(x - bx, y); + // kz != 0 solution + BoutReal coef = -1.0 * sqrt(metric->g33(x - bx, y) / metric->g11(x - bx, y)) + * metric->dx(x - bx, y); + for (int jz = 1; jz <= ncz / 2; jz++) { + BoutReal kwave = + jz * 2.0 * PI / getConst(metric->zlength()); // wavenumber in [rad^-1] + c0[jz] *= exp(coef * kwave); // The decaying solution only + // Add the particular solution + c2[jz] = c0[jz] - c1[jz] / (metric->g33(x - bx, y) * kwave * kwave); + } + // Reverse FFT + irfft(c2.begin(), ncz, f(x, y)); + + bndry->nextX(); + x = bndry->x; + y = bndry->y; + } while (!bndry->isDone()); } - // Solve metric->g11*d2f/dx2 - metric->g33*kz^2f = 0 - // Assume metric->g11, metric->g33 constant -> exponential growth or decay - BoutReal xpos = 0.0; - // Loop in X towards edge of domain - do { - // kz = 0 solution - xpos -= metric->dx(x, y); - c2[0] = c0[0] + k0lin * xpos + 0.5 * c1[0] * xpos * xpos / metric->g11(x - bx, y); - // kz != 0 solution - BoutReal coef = -1.0 * sqrt(metric->g33(x - bx, y) / metric->g11(x - bx, y)) - * metric->dx(x - bx, y); - for (int jz = 1; jz <= ncz / 2; jz++) { - BoutReal kwave = jz * 2.0 * PI / getConst(metric->zlength()); // wavenumber in [rad^-1] - c0[jz] *= exp(coef * kwave); // The decaying solution only - // Add the particular solution - c2[jz] = c0[jz] - c1[jz] / (metric->g33(x - bx, y) * kwave * kwave); - } - // Reverse FFT - irfft(c2.begin(), ncz, f(x, y)); - - bndry->nextX(); - x = bndry->x; - y = bndry->y; - } while (!bndry->isDone()); - } #else throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " "ConstLaplace case."); #endif -} + } -/////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryDivCurl::clone(BoundaryRegion* region, - const std::list& args) { - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryDivCurl\n"; + BoundaryOp* BoundaryDivCurl::clone(BoundaryRegion * region, + const std::list& args) { + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryDivCurl\n"; + } + return new BoundaryDivCurl(region); } - return new BoundaryDivCurl(region); -} -void BoundaryDivCurl::apply(Vector2D& UNUSED(f)) { - throw BoutException("ERROR: DivCurl boundary not yet implemented for 2D vectors\n"); -} + void BoundaryDivCurl::apply(Vector2D & UNUSED(f)) { + throw BoutException("ERROR: DivCurl boundary not yet implemented for 2D vectors\n"); + } -void BoundaryDivCurl::apply(Vector3D& var) { + void BoundaryDivCurl::apply(Vector3D & var) { #ifndef COORDINATES_USE_3D - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == var.x.getMesh()); + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == var.x.getMesh()); - int jx, jy, jz, jzp, jzm; - BoutReal tmp; + int jx, jy, jz, jzp, jzm; + BoutReal tmp; - Coordinates* metric = mesh->getCoordinates(var.getLocation()); + Coordinates* metric = mesh->getCoordinates(var.getLocation()); - int ncz = mesh->LocalNz; + int ncz = mesh->LocalNz; - if (bndry->location != BNDRY_XOUT) { - throw BoutException("ERROR: DivCurl boundary only works for outer X currently\n"); - } - var.toCovariant(); + if (bndry->location != BNDRY_XOUT) { + throw BoutException("ERROR: DivCurl boundary only works for outer X currently\n"); + } + var.toCovariant(); - if (mesh->xstart > 2) { - throw BoutException( - "Error: Div = Curl = 0 boundary condition doesn't work for MXG > 2. Sorry\n"); - } + if (mesh->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; jy < mesh->LocalNy - 1; jy++) { - for (jz = 0; jz < ncz; jz++) { - jzp = (jz + 1) % ncz; - jzm = (jz - 1 + ncz) % ncz; + jx = mesh->xend + 1; + for (jy = 1; jy < mesh->LocalNy - 1; jy++) { + for (jz = 0; jz < ncz; jz++) { + jzp = (jz + 1) % ncz; + jzm = (jz - 1 + ncz) % ncz; - // dB_y / dx = dB_x / dy + // dB_y / dx = dB_x / dy - // dB_x / dy - tmp = (var.x(jx - 1, jy + 1, jz) - var.x(jx - 1, jy - 1, jz)) - / (metric->dy(jx - 1, jy - 1) + metric->dy(jx - 1, jy)); + // dB_x / dy + tmp = (var.x(jx - 1, jy + 1, jz) - var.x(jx - 1, jy - 1, jz)) + / (metric->dy(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) - // 4th order to get last point - var.y(jx + 1, jy, jz) = var.y(jx - 3, jy, jz) + 4. * metric->dx(jx, jy) * tmp; + 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) + // 4th order to get last point + var.y(jx + 1, jy, jz) = var.y(jx - 3, jy, jz) + 4. * metric->dx(jx, jy) * tmp; - // dB_z / dx = dB_x / dz + // dB_z / dx = dB_x / dz - tmp = (var.x(jx - 1, jy, jzp) - var.x(jx - 1, jy, jzm)) / (2. * metric->dz(jx - 1, jy)); + tmp = (var.x(jx - 1, jy, jzp) - var.x(jx - 1, jy, jzm)) + / (2. * metric->dz(jx - 1, jy)); - 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) - var.z(jx + 1, jy, jz) = var.z(jx - 3, jy, jz) + 4. * metric->dx(jx, jy) * tmp; + 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) + 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) - // - d/dy( JB^y ) - d/dz( JB^z ) + // d/dx( Jmetric->g11 B_x ) = - d/dx( Jmetric->g12 B_y + Jmetric->g13 B_z) + // - d/dy( JB^y ) - d/dz( JB^z ) - tmp = -(metric->J(jx, jy) * metric->g12(jx, jy) * var.y(jx, jy, jz) + tmp = + -(metric->J(jx, jy) * metric->g12(jx, jy) * var.y(jx, jy, jz) + metric->J(jx, jy) * metric->g13(jx, jy) * var.z(jx, jy, jz) - metric->J(jx - 2, jy) * metric->g12(jx - 2, jy) * var.y(jx - 2, jy, jz) + metric->J(jx - 2, jy) * metric->g13(jx - 2, jy) * var.z(jx - 2, jy, jz)) / (metric->dx(jx - 2, jy) + metric->dx(jx - 1, jy)); // First term (d/dx) using vals calculated above - tmp -= (metric->J(jx - 1, jy + 1) * metric->g12(jx - 1, jy + 1) - * var.x(jx - 1, jy + 1, jz) - - metric->J(jx - 1, jy - 1) * metric->g12(jx - 1, jy - 1) - * var.x(jx - 1, jy - 1, jz) - + metric->J(jx - 1, jy + 1) * metric->g22(jx - 1, jy + 1) - * var.y(jx - 1, jy + 1, jz) - - metric->J(jx - 1, jy - 1) * metric->g22(jx - 1, jy - 1) - * var.y(jx - 1, jy - 1, jz) - + metric->J(jx - 1, jy + 1) * metric->g23(jx - 1, jy + 1) - * var.z(jx - 1, jy + 1, jz) - - metric->J(jx - 1, jy - 1) * metric->g23(jx - 1, jy - 1) - * var.z(jx - 1, jy - 1, jz)) - / (metric->dy(jx - 1, jy - 1) + metric->dy(jx - 1, jy)); // second (d/dy) - tmp -= (metric->J(jx - 1, jy) * metric->g13(jx - 1, jy) - * (var.x(jx - 1, jy, jzp) - var.x(jx - 1, jy, jzm)) - + metric->J(jx - 1, jy) * metric->g23(jx - 1, jy) - * (var.y(jx - 1, jy, jzp) - var.y(jx - 1, jy, jzm)) - + metric->J(jx - 1, jy) * metric->g33(jx - 1, jy) - * (var.z(jx - 1, jy, jzp) - var.z(jx - 1, jy, jzm))) - / (2. * metric->dz(jx - 1, jy)); - - 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) - 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); + tmp -= (metric->J(jx - 1, jy + 1) * metric->g12(jx - 1, jy + 1) + * var.x(jx - 1, jy + 1, jz) + - metric->J(jx - 1, jy - 1) * metric->g12(jx - 1, jy - 1) + * var.x(jx - 1, jy - 1, jz) + + metric->J(jx - 1, jy + 1) * metric->g22(jx - 1, jy + 1) + * var.y(jx - 1, jy + 1, jz) + - metric->J(jx - 1, jy - 1) * metric->g22(jx - 1, jy - 1) + * var.y(jx - 1, jy - 1, jz) + + metric->J(jx - 1, jy + 1) * metric->g23(jx - 1, jy + 1) + * var.z(jx - 1, jy + 1, jz) + - metric->J(jx - 1, jy - 1) * metric->g23(jx - 1, jy - 1) + * var.z(jx - 1, jy - 1, jz)) + / (metric->dy(jx - 1, jy - 1) + metric->dy(jx - 1, jy)); // second (d/dy) + tmp -= (metric->J(jx - 1, jy) * metric->g13(jx - 1, jy) + * (var.x(jx - 1, jy, jzp) - var.x(jx - 1, jy, jzm)) + + metric->J(jx - 1, jy) * metric->g23(jx - 1, jy) + * (var.y(jx - 1, jy, jzp) - var.y(jx - 1, jy, jzm)) + + metric->J(jx - 1, jy) * metric->g33(jx - 1, jy) + * (var.z(jx - 1, jy, jzp) - var.z(jx - 1, jy, jzm))) + / (2. * metric->dz(jx - 1, jy)); + + 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) + 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); + } } - } #else throw BoutException( "Applying boundary to Vector3D not compatible with 3D metrics in DivCurl."); #endif -} - -/////////////////////////////////////////////////////////////// - -BoundaryOp* BoundaryFree::clone(BoundaryRegion* region, - const std::list& args) { - if (!args.empty()) { - // First argument should be a value - val = stringToReal(args.front()); - return new BoundaryFree(region, val); } - return new BoundaryFree(region); -} - -void BoundaryFree::apply(Field2D& UNUSED(f)) { - // Do nothing for free boundary -} - -void BoundaryFree::apply(Field3D& UNUSED(f)) { - // Do nothing for free boundary -} - -void BoundaryFree::apply_ddt(Field2D& UNUSED(f)) { - // Do nothing for free boundary -} -void BoundaryFree::apply_ddt(Field3D& UNUSED(f)) { - // Do nothing for free boundary -} -/////////////////////////////////////////////////////////////// -// New free boundary implementation. Uses last grid points to extrapolate into the guard -// cells. Written by L. Easy. -/////////////////////////////////////////////////////////////// - -// 2nd order extrapolation: + /////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryFree_O2::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 2); - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryFree\n"; + BoundaryOp* BoundaryFree::clone(BoundaryRegion * region, + const std::list& args) { + if (!args.empty()) { + // First argument should be a value + val = stringToReal(args.front()); + return new BoundaryFree(region, val); + } + return new BoundaryFree(region); } - return new BoundaryFree_O2(region); -} - -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* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - bndry->first(); - // Check for staggered grids - - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { - // 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; i < bndry->width; 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; i < bndry->width; 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; i < bndry->width; 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 + void BoundaryFree::apply(Field2D & UNUSED(f)) { + // Do nothing for free boundary + } - if (bndry->by > 0) { - // Upper y boundary + void BoundaryFree::apply(Field3D & UNUSED(f)) { + // Do nothing for free boundary + } - for (; !bndry->isDone(); bndry->next1d()) { - for (int i = 0; i < bndry->width; 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; i < bndry->width; 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()) { + void BoundaryFree::apply_ddt(Field2D & UNUSED(f)) { + // Do nothing for free boundary + } - for (int i = 0; i < bndry->width; 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 { - // Non-staggered, standard case + void BoundaryFree::apply_ddt(Field3D & UNUSED(f)) { + // Do nothing for free boundary + } + /////////////////////////////////////////////////////////////// + // New free boundary implementation. Uses last grid points to extrapolate into the + // guard cells. Written by L. Easy. + /////////////////////////////////////////////////////////////// - for (; !bndry->isDone(); bndry->next1d()) { + // 2nd order extrapolation: - for (int i = 0; i < bndry->width; 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); - } + BoundaryOp* BoundaryFree_O2::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 2); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryFree\n"; } + return new BoundaryFree_O2(region); } -} - -void BoundaryFree_O2::apply(Field3D& f) { - // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. - - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - bndry->first(); - // Check for staggered grids + 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 - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { - // Staggered. Need to apply slightly differently + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + bndry->first(); - if (loc == CELL_XLOW) { - // Field is shifted in X + // Check for staggered grids - if (bndry->bx > 0) { - // Outer x boundary + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { + // Staggered. Need to apply slightly differently - for (; !bndry->isDone(); bndry->next1d()) { + if (loc == CELL_XLOW) { + // Field is shifted in X - for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->bx > 0) { + // Outer x boundary + for (; !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < bndry->width; 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); + 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 zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for (; !bndry->isDone(); bndry->next1d()) { for (int i = -1; i < bndry->width; 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); + 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 zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->by != 0) { + // y boundaries + for (; !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < bndry->width; 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); + 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 + } 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; zk < mesh->LocalNz; zk++) { + if (bndry->by > 0) { + // Upper y boundary + + for (; !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < bndry->width; 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); + 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 zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->by < 0) { + // Lower y boundary. Set one point inwards + for (; !bndry->isDone(); bndry->next1d()) { for (int i = -1; i < bndry->width; 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); + 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()) { + if (bndry->bx != 0) { + // x boundaries + for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { for (int i = 0; i < bndry->width; 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); + f(xi, yi) = 2 * f(xi - bndry->bx, yi - bndry->by) + - f(xi - 2 * bndry->bx, yi - 2 * bndry->by); } } } } - } - } else { - // Standard (non-staggered) case - for (; !bndry->isDone(); bndry->next1d()) { + } else { + // Non-staggered, standard case + + for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { for (int i = 0; i < bndry->width; 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); + f(xi, yi) = 2 * f(xi - bndry->bx, yi - bndry->by) + - f(xi - 2 * bndry->bx, yi - 2 * bndry->by); } } } } -} - -void BoundaryFree_O2::apply_ddt(Field2D& f) { - Field2D* dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero -} -void BoundaryFree_O2::apply_ddt(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Field3D *dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0; z < mesh->LocalNz; z++) - (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero -} - -////////////////////////////////// -// Third order extrapolation: -////////////////////////////////// -BoundaryOp* BoundaryFree_O3::clone(BoundaryRegion* region, - const std::list& args) { - verifyNumPoints(region, 3); + void BoundaryFree_O2::apply(Field3D & f) { + // Extrapolate from the last evolved simulation cells into the guard cells at 3rd + // order. - if (!args.empty()) { - output << "WARNING: Ignoring arguments to BoundaryConstLaplace\n"; - } - return new BoundaryFree_O3(region); -} + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + bndry->first(); -void BoundaryFree_O3::apply(Field2D& f) { + // Check for staggered grids - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - bndry->first(); + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { + // Staggered. Need to apply slightly differently - // Check for staggered grids + if (loc == CELL_XLOW) { + // Field is shifted in X - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { - // Staggered. Need to apply slightly differently + if (bndry->bx > 0) { + // Outer x boundary - if (loc == CELL_XLOW) { - // Field is shifted in X + for (; !bndry->isDone(); bndry->next1d()) { - if (bndry->bx > 0) { - // Outer x boundary - for (; !bndry->isDone(); bndry->next1d()) { - for (int i = 0; i < bndry->width; 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); + for (int zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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 i = -1; i < bndry->width; 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 zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = -1; i < bndry->width; 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 i = 0; i < bndry->width; 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 zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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 + } else if (loc == CELL_YLOW) { + // Field is shifted in Y - if (bndry->by > 0) { - // Upper y boundary + if (bndry->by > 0) { + // Upper y boundary + for (; !bndry->isDone(); bndry->next1d()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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 (; !bndry->isDone(); bndry->next1d()) { - for (int i = 0; i < bndry->width; 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); + for (int zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = -1; i < bndry->width; 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 i = -1; i < bndry->width; 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 zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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()) { + } else { + // Standard (non-staggered) case + for (; !bndry->isDone(); bndry->next1d()) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { for (int i = 0; i < bndry->width; 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); + f(xi, yi, zk) = 2 * f(xi - bndry->bx, yi - bndry->by, zk) + - f(xi - 2 * bndry->bx, yi - 2 * bndry->by, zk); } } } } - } else { - // Non-staggered, standard case + } - for (; !bndry->isDone(); bndry->next1d()) { + void BoundaryFree_O2::apply_ddt(Field2D & f) { + Field2D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero + } - for (int i = 0; i < bndry->width; 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 BoundaryFree_O2::apply_ddt(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Field3D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; z++) + (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero } -} -void BoundaryFree_O3::apply(Field3D& f) { - // Extrapolate from the last evolved simulation cells into the guard cells at 3rd order. + ////////////////////////////////// + // Third order extrapolation: + ////////////////////////////////// + BoundaryOp* BoundaryFree_O3::clone(BoundaryRegion * region, + const std::list& args) { + verifyNumPoints(region, 3); - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - bndry->first(); + if (!args.empty()) { + output << "WARNING: Ignoring arguments to BoundaryConstLaplace\n"; + } + return new BoundaryFree_O3(region); + } - // Check for staggered grids + void BoundaryFree_O3::apply(Field2D & f) { - CELL_LOC loc = f.getLocation(); - if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { - // Staggered. Need to apply slightly differently + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + bndry->first(); - if (loc == CELL_XLOW) { - // Field is shifted in X + // Check for staggered grids - if (bndry->bx > 0) { - // Outer x boundary + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { + // Staggered. Need to apply slightly differently - for (; !bndry->isDone(); bndry->next1d()) { + if (loc == CELL_XLOW) { + // Field is shifted in X - for (int zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->bx > 0) { + // Outer x boundary + for (; !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < bndry->width; 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); + 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 zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->bx < 0) { + // Inner x boundary. Set one point inwards + for (; !bndry->isDone(); bndry->next1d()) { for (int i = -1; i < bndry->width; 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); + 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 zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->by != 0) { + // y boundaries + for (; !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < bndry->width; 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); + 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 + } 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; zk < mesh->LocalNz; zk++) { + if (bndry->by > 0) { + // Upper y boundary + + for (; !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < bndry->width; 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); + 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 zk = 0; zk < mesh->LocalNz; zk++) { + if (bndry->by < 0) { + // Lower y boundary. Set one point inwards + for (; !bndry->isDone(); bndry->next1d()) { for (int i = -1; i < bndry->width; 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); + 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 (bndry->bx != 0) { + // x boundaries + for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { for (int i = 0; i < bndry->width; 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); + 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 { - // Standard (non-staggered) case - for (; !bndry->isDone(); bndry->next1d()) { + } else { + // Non-staggered, standard case + + for (; !bndry->isDone(); bndry->next1d()) { - for (int zk = 0; zk < mesh->LocalNz; zk++) { for (int i = 0; i < bndry->width; 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); + 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_ddt(Field2D& f) { - Field2D* dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero -} + void BoundaryFree_O3::apply(Field3D & f) { + // Extrapolate from the last evolved simulation cells into the guard cells at 3rd + // order. -void BoundaryFree_O3::apply_ddt(Field3D& f) { - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); - Field3D *dt = f.timeDeriv(); - for (bndry->first(); !bndry->isDone(); bndry->next()) - for (int z = 0; z < mesh->LocalNz; z++) - (*dt)(bndry->x,bndry->y,z) = 0.; // Set time derivative to zero -} + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + bndry->first(); -/////////////////////////////////////////////////////////////// + // Check for staggered grids -BoundaryOp* BoundaryRelax::cloneMod(BoundaryOp* operation, - const std::list& args) { - auto* result = new BoundaryRelax(operation, r); + CELL_LOC loc = f.getLocation(); + if (mesh->StaggerGrids and (loc == CELL_XLOW or loc == CELL_YLOW)) { + // Staggered. Need to apply slightly differently - if (!args.empty()) { - // First argument should be the rate - BoutReal val = stringToReal(args.front()); - val = fabs(val); // Should always be positive - result->r = val; + 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; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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; zk < mesh->LocalNz; zk++) { + for (int i = -1; i < bndry->width; 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; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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; zk < mesh->LocalNz; zk++) { + for (int i = -1; i < bndry->width; 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; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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 { + // Standard (non-staggered) case + for (; !bndry->isDone(); bndry->next1d()) { + + for (int zk = 0; zk < mesh->LocalNz; zk++) { + for (int i = 0; i < bndry->width; 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); + } + } + } + } } - return result; -} + void BoundaryFree_O3::apply_ddt(Field2D & f) { + Field2D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + (*dt)(bndry->x, bndry->y) = 0.; // Set time derivative to zero + } -void BoundaryRelax::apply(Field2D& f, BoutReal t) { - // Just apply the original boundary condition to f - op->apply(f, t); -} + void BoundaryFree_O3::apply_ddt(Field3D & f) { + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + Field3D* dt = f.timeDeriv(); + for (bndry->first(); !bndry->isDone(); bndry->next()) + for (int z = 0; z < mesh->LocalNz; z++) + (*dt)(bndry->x, bndry->y, z) = 0.; // Set time derivative to zero + } -void BoundaryRelax::apply(Field3D& f, BoutReal UNUSED(t)) { - // Just apply the original boundary condition to f - op->apply(f); -} + /////////////////////////////////////////////////////////////// -void BoundaryRelax::apply_ddt(Field2D& f) { - TRACE("BoundaryRelax::apply_ddt(Field2D)"); + BoundaryOp* BoundaryRelax::cloneMod(BoundaryOp * operation, + const std::list& args) { + auto* result = new BoundaryRelax(operation, r); - // Make a copy of f - Field2D g = f; - // Apply the boundary to g - op->apply(g); + if (!args.empty()) { + // First argument should be the rate + BoutReal val = stringToReal(args.front()); + val = fabs(val); // Should always be positive + result->r = val; + } - bndry->first(); + return result; + } - // Set time-derivatives - for (bndry->first(); !bndry->isDone(); bndry->next()) { - ddt(f)(bndry->x, bndry->y) = r * (g(bndry->x, bndry->y) - f(bndry->x, bndry->y)); + void BoundaryRelax::apply(Field2D & f, BoutReal t) { + // Just apply the original boundary condition to f + op->apply(f, t); } -} -void BoundaryRelax::apply_ddt(Field3D& f) { - TRACE("BoundaryRelax::apply_ddt(Field3D)"); + void BoundaryRelax::apply(Field3D & f, BoutReal UNUSED(t)) { + // Just apply the original boundary condition to f + op->apply(f); + } - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == f.getMesh()); + void BoundaryRelax::apply_ddt(Field2D & f) { + TRACE("BoundaryRelax::apply_ddt(Field2D)"); - // 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; z < mesh->LocalNz; z++) { - ddt(f)(bndry->x, bndry->y, z) = - r * (g(bndry->x, bndry->y, z) - f(bndry->x, bndry->y, z)); + // Make a copy of f + Field2D g = f; + // Apply the boundary to g + op->apply(g); + + bndry->first(); + + // Set time-derivatives + for (bndry->first(); !bndry->isDone(); bndry->next()) { + ddt(f)(bndry->x, bndry->y) = r * (g(bndry->x, bndry->y) - f(bndry->x, bndry->y)); } -} + } -/////////////////////////////////////////////////////////////// + void BoundaryRelax::apply_ddt(Field3D & f) { + TRACE("BoundaryRelax::apply_ddt(Field3D)"); -BoundaryOp* BoundaryWidth::cloneMod(BoundaryOp* operation, - const std::list& args) { - auto* result = new BoundaryWidth(operation, width); + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); - if (args.empty()) { - output << "WARNING: BoundaryWidth expected 1 argument\n"; - } else { - // First argument should be the rate - int val = stringToInt(args.front()); - result->width = val; + // 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; z < mesh->LocalNz; z++) { + ddt(f)(bndry->x, bndry->y, z) = + r * (g(bndry->x, bndry->y, z) - f(bndry->x, bndry->y, z)); + } } - return result; -} + /////////////////////////////////////////////////////////////// -void BoundaryWidth::apply(Field2D& f, BoutReal t) { - // Pointer to boundary region shared between all BoundaryOp, BoundaryModifiers - int oldwid = bndry->width; - bndry->width = width; - op->apply(f, t); - bndry->width = oldwid; -} + BoundaryOp* BoundaryWidth::cloneMod(BoundaryOp * operation, + const std::list& args) { + auto* result = new BoundaryWidth(operation, width); -void BoundaryWidth::apply(Field3D& f, BoutReal t) { - int oldwid = bndry->width; - bndry->width = width; - op->apply(f, t); - bndry->width = oldwid; -} + if (args.empty()) { + output << "WARNING: BoundaryWidth expected 1 argument\n"; + } else { + // First argument should be the rate + int val = stringToInt(args.front()); + result->width = val; + } -void BoundaryWidth::apply_ddt(Field2D& f) { - int oldwid = bndry->width; - bndry->width = width; - op->apply_ddt(f); - bndry->width = oldwid; -} + return result; + } -void BoundaryWidth::apply_ddt(Field3D& f) { - int oldwid = bndry->width; - bndry->width = width; - op->apply_ddt(f); - bndry->width = oldwid; -} + void BoundaryWidth::apply(Field2D & f, BoutReal t) { + // Pointer to boundary region shared between all BoundaryOp, BoundaryModifiers + int oldwid = bndry->width; + bndry->width = width; + op->apply(f, t); + bndry->width = oldwid; + } -/////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryToFieldAligned::cloneMod(BoundaryOp* operation, - const std::list& args) { - auto* result = new BoundaryToFieldAligned(operation); + void BoundaryWidth::apply(Field3D & f, BoutReal t) { + int oldwid = bndry->width; + bndry->width = width; + op->apply(f, t); + bndry->width = oldwid; + } - if (!args.empty()) { - output << "WARNING: BoundaryToFieldAligned expected no argument\n"; - // Shouldn't we throw ? + void BoundaryWidth::apply_ddt(Field2D & f) { + int oldwid = bndry->width; + bndry->width = width; + op->apply_ddt(f); + bndry->width = oldwid; } - return result; -} + void BoundaryWidth::apply_ddt(Field3D & f) { + int oldwid = bndry->width; + bndry->width = width; + op->apply_ddt(f); + bndry->width = oldwid; + } -void BoundaryToFieldAligned::apply(Field2D& f, BoutReal t) { op->apply(f, t); } + /////////////////////////////////////////////////////////////// + BoundaryOp* BoundaryToFieldAligned::cloneMod(BoundaryOp * operation, + const std::list& args) { + auto* result = new BoundaryToFieldAligned(operation); -void BoundaryToFieldAligned::apply(Field3D &f, BoutReal t) { - ASSERT1(bndry->localmesh == f.getMesh()); + if (!args.empty()) { + output << "WARNING: BoundaryToFieldAligned expected no argument\n"; + // Shouldn't we throw ? + } - // NOTE: This is not very efficient... updating entire field - f = fromFieldAligned(f); + return result; + } - // Apply the boundary to shifted field - op->apply(f, t); + void BoundaryToFieldAligned::apply(Field2D & f, BoutReal t) { op->apply(f, t); } - // Shift back - f = toFieldAligned(f); + void BoundaryToFieldAligned::apply(Field3D & f, BoutReal t) { + ASSERT1(bndry->localmesh == f.getMesh()); - // This is inefficient -- could instead use the shiftZ just in the bndry - // but this is not portable to other parallel transforms -- we could instead - // have a flag to define the region in which we want to apply to/fromFieldAligned -} + // NOTE: This is not very efficient... updating entire field + f = fromFieldAligned(f); -void BoundaryToFieldAligned::apply_ddt(Field2D &f) { - op->apply_ddt(f); -} + // Apply the boundary to shifted field + op->apply(f, t); -void BoundaryToFieldAligned::apply_ddt(Field3D &f) { - ASSERT1(bndry->localmesh == f.getMesh()); + // Shift back + f = toFieldAligned(f); - f = fromFieldAligned(f); - ddt(f) = fromFieldAligned(ddt(f)); - op->apply_ddt(f); - ddt(f) = toFieldAligned(ddt(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 + // have a flag to define the region in which we want to apply to/fromFieldAligned + } -/////////////////////////////////////////////////////////////// -BoundaryOp* BoundaryFromFieldAligned::cloneMod(BoundaryOp* operation, - const std::list& args) { - auto* result = new BoundaryFromFieldAligned(operation); + void BoundaryToFieldAligned::apply_ddt(Field2D & f) { op->apply_ddt(f); } - if (!args.empty()) { - output << "WARNING: BoundaryFromFieldAligned expected no argument\n"; - // Shouldn't we throw ? + void BoundaryToFieldAligned::apply_ddt(Field3D & f) { + ASSERT1(bndry->localmesh == f.getMesh()); + + f = fromFieldAligned(f); + ddt(f) = fromFieldAligned(ddt(f)); + op->apply_ddt(f); + ddt(f) = toFieldAligned(ddt(f)); } - return result; -} + /////////////////////////////////////////////////////////////// + BoundaryOp* BoundaryFromFieldAligned::cloneMod(BoundaryOp * operation, + const std::list& args) { + auto* result = new BoundaryFromFieldAligned(operation); + + if (!args.empty()) { + output << "WARNING: BoundaryFromFieldAligned expected no argument\n"; + // Shouldn't we throw ? + } -void BoundaryFromFieldAligned::apply(Field2D& f, BoutReal t) { op->apply(f, t); } + return result; + } -void BoundaryFromFieldAligned::apply(Field3D &f, BoutReal t) { - ASSERT1(bndry->localmesh == f.getMesh()); + void BoundaryFromFieldAligned::apply(Field2D & f, BoutReal t) { op->apply(f, t); } - // NOTE: This is not very efficient... shifting entire field - f = toFieldAligned(f); + void BoundaryFromFieldAligned::apply(Field3D & f, BoutReal t) { + ASSERT1(bndry->localmesh == f.getMesh()); - // Apply the boundary to shifted field - op->apply(f, t); + // NOTE: This is not very efficient... shifting entire field + f = toFieldAligned(f); - // Shift back - f = fromFieldAligned(f); + // Apply the boundary to shifted field + op->apply(f, t); - // This is inefficient -- could instead use the shiftZ just in the bndry - // but this is not portable to other parallel transforms -- we could instead - // have a flag to define the region in which we want to apply to/fromFieldAligned -} + // Shift back + f = fromFieldAligned(f); -void BoundaryFromFieldAligned::apply_ddt(Field2D &f) { - op->apply_ddt(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 + // have a flag to define the region in which we want to apply to/fromFieldAligned + } -void BoundaryFromFieldAligned::apply_ddt(Field3D &f) { - ASSERT1(bndry->localmesh == f.getMesh()); + void BoundaryFromFieldAligned::apply_ddt(Field2D & f) { op->apply_ddt(f); } - f = toFieldAligned(f); - ddt(f) = toFieldAligned(ddt(f)); - op->apply_ddt(f); - ddt(f) = fromFieldAligned(ddt(f)); -} + void BoundaryFromFieldAligned::apply_ddt(Field3D & f) { + ASSERT1(bndry->localmesh == f.getMesh()); + + f = toFieldAligned(f); + ddt(f) = toFieldAligned(ddt(f)); + op->apply_ddt(f); + ddt(f) = fromFieldAligned(ddt(f)); + } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 3402338ba6..90ab83d1e0 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -27,9 +27,9 @@ namespace { /// Boundary guard cells are set by extrapolating from the grid, like /// 'free_o3' boundary conditions /// Corner guard cells are set to BoutNaN -Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, - bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* UNUSED(pt) = nullptr) { +Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, bool extrapolate_x, + bool extrapolate_y, bool no_extra_interpolate, + ParallelTransform* UNUSED(pt) = nullptr) { Mesh* localmesh = f.getMesh(); Field2D result = interp_to(f, location, "RGN_NOBNDRY"); @@ -148,39 +148,39 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, return result; } - Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, - bool extrapolate_x, bool extrapolate_y, - bool no_extra_interpolate, ParallelTransform* pt_) { - - Mesh* localmesh = f_.getMesh(); - Field3D result; - Field3D f = f_; - ParallelTransform * pt_f; - if (f.getCoordinates() == nullptr) { - pt_f = pt_; +Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, + bool extrapolate_x, bool extrapolate_y, + bool no_extra_interpolate, ParallelTransform* pt_) { + + Mesh* localmesh = f_.getMesh(); + Field3D result; + Field3D f = f_; + ParallelTransform* pt_f; + if (f.getCoordinates() == nullptr) { + pt_f = pt_; + } else { + pt_f = &f.getCoordinates()->getParallelTransform(); + } + if (f.getDirectionY() != YDirectionType::Standard) { + if (pt_f->canToFromFieldAligned()) { + f = pt_f->fromFieldAligned(f); } else { - pt_f = & f.getCoordinates()->getParallelTransform(); - } - if (f.getDirectionY() != YDirectionType::Standard) { - if (pt_f->canToFromFieldAligned()) { - f = pt_f->fromFieldAligned(f); - } else { - f.setDirectionY(YDirectionType::Standard); - } + f.setDirectionY(YDirectionType::Standard); } - if (location == CELL_YLOW){ - auto f_aligned = pt_f->toFieldAligned(f, "RGN_NOX"); - result = interp_to(f_aligned, location, "RGN_NOBNDRY"); - ParallelTransform * pt_result; - if (result.getCoordinates() == nullptr){ - pt_result = pt_; - } else { - pt_result = & result.getCoordinates()->getParallelTransform(); - } - result = pt_result->fromFieldAligned(result, "RGN_NOBNDRY"); + } + if (location == CELL_YLOW) { + auto f_aligned = pt_f->toFieldAligned(f, "RGN_NOX"); + result = interp_to(f_aligned, location, "RGN_NOBNDRY"); + ParallelTransform* pt_result; + if (result.getCoordinates() == nullptr) { + pt_result = pt_; } else { - result = interp_to(f, location, "RGN_NOBNDRY"); + pt_result = &result.getCoordinates()->getParallelTransform(); } + result = pt_result->fromFieldAligned(result, "RGN_NOBNDRY"); + } else { + result = interp_to(f, location, "RGN_NOBNDRY"); + } // Ensure result's data is unique. Otherwise result might be a duplicate of // f (if no interpolation is needed, e.g. if interpolation is in the // z-direction); then f would be communicated. Since this function is used @@ -225,21 +225,19 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, ASSERT1(bndry->bx == 0 or localmesh->xstart > 1); ASSERT1(bndry->by == 0 or localmesh->ystart > 1); // note that either bx or by is >0 here - for (int zi=0; zi < localmesh->LocalNz; ++zi){ + for (int zi = 0; zi < localmesh->LocalNz; ++zi) { result(bndry->x, bndry->y, zi) = - (9. * (f(bndry->x - bndry->bx, bndry->y - bndry->by, zi) + f(bndry->x, bndry->y, zi)) - - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, zi) - - f(bndry->x + bndry->bx, bndry->y + bndry->by, zi)) - / 16.; + (9. + * (f(bndry->x - bndry->bx, bndry->y - bndry->by, zi) + + f(bndry->x, bndry->y, zi)) + - f(bndry->x - 2 * bndry->bx, bndry->y - 2 * bndry->by, zi) + - f(bndry->x + bndry->bx, bndry->y + bndry->by, zi)) + / 16.; } - } // set boundary guard cells if ((bndry->bx != 0 && localmesh->GlobalNx - 2 * bndry->width >= 3) - || (bndry->by != 0 - && localmesh->GlobalNy - 2 * bndry->width - >= 3)) - { + || (bndry->by != 0 && localmesh->GlobalNy - 2 * bndry->width >= 3)) { if (bndry->bx != 0 && localmesh->LocalNx == 1 && bndry->width == 1) { throw BoutException( "Not enough points in the x-direction on this " @@ -258,18 +256,19 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, for (int i = extrap_start; i < bndry->width; i++) { int xi = bndry->x + i * bndry->bx; int yi = bndry->y + i * bndry->by; - for (int zi=0; zi < localmesh->LocalNz; ++zi){ - result(xi, yi, zi) = 3.0 * result(xi - bndry->bx, yi - bndry->by, zi) - - 3.0 * result(xi - 2 * bndry->bx, yi - 2 * bndry->by, zi) - + result(xi - 3 * bndry->bx, yi - 3 * bndry->by, zi); + for (int zi = 0; zi < localmesh->LocalNz; ++zi) { + result(xi, yi, zi) = + 3.0 * result(xi - bndry->bx, yi - bndry->by, zi) + - 3.0 * result(xi - 2 * bndry->bx, yi - 2 * bndry->by, zi) + + result(xi - 3 * bndry->bx, yi - 3 * bndry->by, zi); } } } else { // not enough grid points to extrapolate, set equal to last grid point for (int i = extrap_start; i < bndry->width; i++) { - for (int zi = 0; zi < localmesh->LocalNz; ++zi){ + for (int zi = 0; zi < localmesh->LocalNz; ++zi) { result(bndry->x + i * bndry->bx, bndry->y + i * bndry->by, zi) = - result(bndry->x - bndry->bx, bndry->y - bndry->by, zi); + result(bndry->x - bndry->bx, bndry->y - bndry->by, zi); } } } @@ -277,16 +276,14 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, } } #if CHECK > 0 - if (not ( - // if include_corner_cells=true, then we extrapolate valid data into the - // corner cells if they are not already filled - localmesh->include_corner_cells - - // if we are not extrapolating at all, the corner cells should contain valid - // data - or (not extrapolate_x and not extrapolate_y) - ) - ) { + if (not( + // if include_corner_cells=true, then we extrapolate valid data into the + // corner cells if they are not already filled + localmesh->include_corner_cells + + // if we are not extrapolating at all, the corner cells should contain valid + // data + or (not extrapolate_x and not extrapolate_y))) { // Invalidate corner guard cells for (int i = 0; i < localmesh->xstart; i++) { for (int j = 0; j < localmesh->ystart; j++) { @@ -304,8 +301,6 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, return result; } - - // If the CELL_CENTRE variable was read, the staggered version is required to // also exist for consistency void checkStaggeredGet(Mesh* mesh, const std::string& name, const std::string& suffix) { @@ -316,11 +311,11 @@ void checkStaggeredGet(Mesh* mesh, const std::string& name, const std::string& s } // convenience function for repeated code -int getAtLoc(Mesh* mesh, Coordinates::metric_field_type &var, const std::string& name, - const std::string& suffix, CELL_LOC location, BoutReal default_value = 0.) { +int getAtLoc(Mesh* mesh, Coordinates::metric_field_type& var, const std::string& name, + const std::string& suffix, CELL_LOC location, BoutReal default_value = 0.) { checkStaggeredGet(mesh, name, suffix); - int result = mesh->get(var, name+suffix, default_value, false); + int result = mesh->get(var, name + suffix, default_value, false); var.setLocation(location); return result; @@ -349,18 +344,17 @@ std::string getLocationSuffix(CELL_LOC location) { } } - template - void communicate(T & t, Ts&... ts) { - FieldGroup g(t,ts...); - // emulate full communicate - auto h = t.getMesh()->sendY(g); - t.getMesh()->wait(h); - h = t.getMesh()->sendX(g); - t.getMesh()->wait(h); - } - +template +void communicate(T& t, Ts&... ts) { + FieldGroup g(t, ts...); + // emulate full communicate + auto h = t.getMesh()->sendY(g); + t.getMesh()->wait(h); + h = t.getMesh()->sendX(g); + t.getMesh()->wait(h); +} -}// anonymous namespace +} // anonymous namespace Coordinates::Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2D J, Field2D Bxy, Field2D g11, Field2D g22, Field2D g33, Field2D g12, @@ -383,14 +377,15 @@ Coordinates::Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2 } Coordinates::Coordinates(Mesh* mesh, Options* options) - : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1., mesh), Bxy(1., mesh), + : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), + J(1., mesh), Bxy(1., mesh), // Identity metric tensor - g11(1., mesh), g22(1., mesh), g33(1., mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), - g_11(1., mesh), g_22(1., mesh), g_33(1., mesh), g_12(0, mesh), g_13(0, mesh), - g_23(0, mesh), G1_11(mesh), G1_22(mesh), G1_33(mesh), G1_12(mesh), G1_13(mesh), - G1_23(mesh), G2_11(mesh), G2_22(mesh), G2_33(mesh), G2_12(mesh), G2_13(mesh), - G2_23(mesh), G3_11(mesh), G3_22(mesh), G3_33(mesh), G3_12(mesh), G3_13(mesh), - G3_23(mesh), G1(mesh), G2(mesh), G3(mesh), ShiftTorsion(mesh), + g11(1., mesh), g22(1., mesh), g33(1., mesh), g12(0, mesh), g13(0, mesh), + g23(0, mesh), g_11(1., mesh), g_22(1., mesh), g_33(1., mesh), g_12(0, mesh), + g_13(0, mesh), g_23(0, mesh), G1_11(mesh), G1_22(mesh), G1_33(mesh), G1_12(mesh), + G1_13(mesh), G1_23(mesh), G2_11(mesh), G2_22(mesh), G2_33(mesh), G2_12(mesh), + G2_13(mesh), G2_23(mesh), G3_11(mesh), G3_22(mesh), G3_33(mesh), G3_12(mesh), + G3_13(mesh), G3_23(mesh), G1(mesh), G2(mesh), G3(mesh), ShiftTorsion(mesh), IntShiftTorsion(mesh), localmesh(mesh), location(CELL_CENTRE) { if (options == nullptr) { @@ -434,17 +429,20 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // required early for differentiation. setParallelTransform(options); - dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, transform.get()); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, transform.get()); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, + transform.get()); + dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, + transform.get()); if (mesh->periodicX) { communicate(dx); } - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, transform.get()); + dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, + transform.get()); -#define GET(a,b) \ - mesh->get(a, #a, b, false); \ +#define GET(a, b) \ + mesh->get(a, #a, b, false); \ a = maybeFromFieldAligned(a); // Diagonal components of metric tensor g^{ij} (default to 1) @@ -457,12 +455,18 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) GET(g13, 0.0); GET(g23, 0.0); - g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, transform.get()); - g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, transform.get()); - g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, transform.get()); - g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, transform.get()); - g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, transform.get()); - g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, transform.get()); + g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, + transform.get()); // Check input metrics // Diagonal metric components should be finite @@ -517,12 +521,18 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) } // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false, + transform.get()); // Check covariant metrics // Diagonal metric components should be finite @@ -549,7 +559,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) "\tWARNING: Jacobian 'J' not found. Calculating from metric tensor\n"); J = Jcalc; } else { - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, transform.get()); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, + transform.get()); // Compare calculated and loaded values output_warn.write("\tMaximum difference in J is {:e}\n", max(abs(J - Jcalc))); @@ -575,7 +586,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) Bxy = Bcalc; } else { - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, transform.get()); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, + transform.get()); output_warn.write("\tMaximum difference in Bxy is {:e}\n", max(abs(Bxy - Bcalc))); } @@ -594,7 +606,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) "\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); ShiftTorsion = 0.0; } - ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); + ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, + extrapolate_y, false, transform.get()); ////////////////////////////////////////////////////// @@ -602,7 +615,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) if (mesh->get(IntShiftTorsion, "IntShiftTorsion", 0.0, false)) { output_warn.write("\tWARNING: No Integrated torsion specified\n"); } - IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); + IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, + extrapolate_y, false, transform.get()); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; @@ -612,25 +626,28 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // use anonymous namespace so this utility function is not available outside this file namespace { - /// Interpolate a Field2D to a new CELL_LOC with interp_to. - /// Communicates to set internal guard cells. - /// Boundary guard cells are set equal to the nearest grid point (equivalent to - /// 2nd order accurate Neumann boundary condition). - /// Corner guard cells are set to BoutNaN +/// Interpolate a Field2D to a new CELL_LOC with interp_to. +/// Communicates to set internal guard cells. +/// Boundary guard cells are set equal to the nearest grid point (equivalent to +/// 2nd order accurate Neumann boundary condition). +/// Corner guard cells are set to BoutNaN Coordinates::metric_field_type -interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAYBE_UNUSED(CELL_LOC location), MAYBE_UNUSED(ParallelTransform * pt)) { +interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), + MAYBE_UNUSED(CELL_LOC location), + MAYBE_UNUSED(ParallelTransform* pt)) { Mesh* localmesh = f.getMesh(); Coordinates::metric_field_type result; #ifdef COORDINATES_USE_3D - if (location == CELL_YLOW){ - auto f_aligned = f.getCoordinates() == nullptr ? - pt->toFieldAligned(f, "RGN_NOX") : toFieldAligned(f, "RGN_NOX"); + if (location == CELL_YLOW) { + auto f_aligned = f.getCoordinates() == nullptr ? pt->toFieldAligned(f, "RGN_NOX") + : toFieldAligned(f, "RGN_NOX"); result = interp_to(f_aligned, location, "RGN_NOBNDRY"); - result = result.getCoordinates() == nullptr ? - pt->fromFieldAligned(result, "RGN_NOBNDRY") : fromFieldAligned(result, "RGN_NOBNDRY"); + result = result.getCoordinates() == nullptr + ? pt->fromFieldAligned(result, "RGN_NOBNDRY") + : fromFieldAligned(result, "RGN_NOBNDRY"); } else #endif - { + { result = interp_to(f, location, "RGN_NOBNDRY"); } communicate(result); @@ -644,10 +661,10 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY if (bndry->bx != 0) { // If bx!=0 we are on an x-boundary, inner if bx>0 and outer if bx<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { - for (int i = 0; i < localmesh->xstart; i++){ - for (int z=0;zxstart; i++) { + for (int z = 0; z < result.getNz(); ++z) { result(bndry->x + i * bndry->bx, bndry->y, z) = - result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); + result(bndry->x + (i - 1) * bndry->bx, bndry->y - bndry->by, z); } } } @@ -656,9 +673,9 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // If by!=0 we are on a y-boundary, upper if by>0 and lower if by<0 for (bndry->first(); !bndry->isDone(); bndry->next1d()) { for (int i = 0; i < localmesh->ystart; i++) { - for (int z=0;zx, bndry->y + i * bndry->by, z) = - result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); + result(bndry->x - bndry->bx, bndry->y + (i - 1) * bndry->by, z); } } } @@ -668,7 +685,7 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY // Set corner guard cells for (int i = 0; i < localmesh->xstart; i++) { for (int j = 0; j < localmesh->ystart; j++) { - for (int z=0;zLocalNy - 1 - j, z) = BoutNaN; result(localmesh->LocalNx - 1 - i, j, z) = BoutNaN; @@ -679,18 +696,19 @@ interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), MAY return result; } -} +} // namespace -Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, - const Coordinates* coords_in, bool force_interpolate_from_centre) - : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), J(1., mesh), Bxy(1., mesh), +Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, + const Coordinates* coords_in, bool force_interpolate_from_centre) + : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), + J(1., mesh), Bxy(1., mesh), // Identity metric tensor - g11(1., mesh), g22(1., mesh), g33(1., mesh), g12(0, mesh), g13(0, mesh), g23(0, mesh), - g_11(1., mesh), g_22(1., mesh), g_33(1., mesh), g_12(0, mesh), g_13(0, mesh), - g_23(0, mesh), G1_11(mesh), G1_22(mesh), G1_33(mesh), G1_12(mesh), G1_13(mesh), - G1_23(mesh), G2_11(mesh), G2_22(mesh), G2_33(mesh), G2_12(mesh), G2_13(mesh), - G2_23(mesh), G3_11(mesh), G3_22(mesh), G3_33(mesh), G3_12(mesh), G3_13(mesh), - G3_23(mesh), G1(mesh), G2(mesh), G3(mesh), ShiftTorsion(mesh), + g11(1., mesh), g22(1., mesh), g33(1., mesh), g12(0, mesh), g13(0, mesh), + g23(0, mesh), g_11(1., mesh), g_22(1., mesh), g_33(1., mesh), g_12(0, mesh), + g_13(0, mesh), g_23(0, mesh), G1_11(mesh), G1_22(mesh), G1_33(mesh), G1_12(mesh), + G1_13(mesh), G1_23(mesh), G2_11(mesh), G2_22(mesh), G2_33(mesh), G2_12(mesh), + G2_13(mesh), G2_23(mesh), G3_11(mesh), G3_22(mesh), G3_33(mesh), G3_12(mesh), + G3_13(mesh), G3_23(mesh), G1(mesh), G2(mesh), G3(mesh), ShiftTorsion(mesh), IntShiftTorsion(mesh), localmesh(mesh), location(loc) { std::string suffix = getLocationSuffix(location); @@ -728,32 +746,41 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } setParallelTransform(options); - dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, transform.get()); + dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, + transform.get()); getAtLoc(mesh, dx, "dx", suffix, location, 1.0); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, transform.get()); + dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, + transform.get()); if (mesh->periodicX) { communicate(dx); } getAtLoc(mesh, dy, "dy", suffix, location, 1.0); - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, transform.get()); + dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, + transform.get()); // grid data source has staggered fields, so read instead of interpolating // Diagonal components of metric tensor g^{ij} (default to 1) getAtLoc(mesh, g11, "g11", suffix, location, 1.0); - g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, transform.get()); + g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, + transform.get()); getAtLoc(mesh, g22, "g22", suffix, location, 1.0); - g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, transform.get()); + g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, + transform.get()); getAtLoc(mesh, g33, "g33", suffix, location, 1.0); - g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, transform.get()); + g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, + transform.get()); getAtLoc(mesh, g12, "g12", suffix, location, 0.0); - g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, transform.get()); + g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, + transform.get()); getAtLoc(mesh, g13, "g13", suffix, location, 0.0); - g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, transform.get()); + g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, + transform.get()); getAtLoc(mesh, g23, "g23", suffix, location, 0.0); - g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, transform.get()); + g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, + transform.get()); // Check input metrics // Diagonal metric components should be finite @@ -807,12 +834,18 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false, transform.get()); - g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false, transform.get()); + g_11 = interpolateAndExtrapolate(g_11, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_22 = interpolateAndExtrapolate(g_22, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_33 = interpolateAndExtrapolate(g_33, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_12 = interpolateAndExtrapolate(g_12, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_13 = interpolateAndExtrapolate(g_13, location, extrapolate_x, extrapolate_y, false, + transform.get()); + g_23 = interpolateAndExtrapolate(g_23, location, extrapolate_x, extrapolate_y, false, + transform.get()); // Check covariant metrics // Diagonal metric components should be finite @@ -842,7 +875,8 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, suffix.c_str()); J = Jcalc; } else { - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, transform.get()); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, + transform.get()); // Compare calculated and loaded values output_warn.write("\tMaximum difference in J is %e\n", max(abs(J - Jcalc))); @@ -865,7 +899,8 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, " from metric tensor\n", suffix.c_str()); Bxy = Bcalc; } else { - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, transform.get()); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, + transform.get()); output_warn.write("\tMaximum difference in Bxy is %e\n", max(abs(Bxy - Bcalc))); } @@ -875,23 +910,26 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, bout::checkPositive(Bxy, "Bxy" + suffix, "RGN_NOCORNERS"); checkStaggeredGet(mesh, "ShiftTorsion", suffix); - if (mesh->get(ShiftTorsion, "ShiftTorsion"+suffix, 0.0, false)) { + if (mesh->get(ShiftTorsion, "ShiftTorsion" + suffix, 0.0, false)) { output_warn.write("\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); ShiftTorsion = 0.0; } ShiftTorsion.setLocation(location); - ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); + ShiftTorsion = interpolateAndExtrapolate(ShiftTorsion, location, extrapolate_x, + extrapolate_y, false, transform.get()); ////////////////////////////////////////////////////// if (mesh->IncIntShear) { checkStaggeredGet(mesh, "IntShiftTorsion", suffix); - if (mesh->get(IntShiftTorsion, "IntShiftTorsion"+suffix, 0.0, false)) { + if (mesh->get(IntShiftTorsion, "IntShiftTorsion" + suffix, 0.0, false)) { output_warn.write("\tWARNING: No Integrated torsion specified\n"); IntShiftTorsion = 0.0; } IntShiftTorsion.setLocation(location); - IntShiftTorsion = interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, extrapolate_y, false, transform.get()); + IntShiftTorsion = + interpolateAndExtrapolate(IntShiftTorsion, location, extrapolate_x, + extrapolate_y, false, transform.get()); } else { // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; @@ -899,38 +937,55 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, } else { // Interpolate fields from coords_in - if (isConst(coords_in->dz)){ + if (isConst(coords_in->dz)) { dz = coords_in->dz; dz.setLocation(location); } else { - throw BoutException("We are asked to transform dz to get dz before we have a transform, which might require dz!\nPlease provide a dz for the staggered quantity!"); + throw BoutException( + "We are asked to transform dz to get dz before we have a transform, which " + "might require dz!\nPlease provide a dz for the staggered quantity!"); } setParallelTransform(options); - dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false, transform.get()); - dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false, transform.get()); + dx = interpolateAndExtrapolate(coords_in->dx, location, true, true, false, + transform.get()); + dy = interpolateAndExtrapolate(coords_in->dy, location, true, true, false, + transform.get()); // not really needed - we have used dz already ... - dz = interpolateAndExtrapolate(coords_in->dz, location, true, true, false, transform.get()); + dz = interpolateAndExtrapolate(coords_in->dz, location, true, true, false, + transform.get()); // Diagonal components of metric tensor g^{ij} - g11 = interpolateAndExtrapolate(coords_in->g11, location, true, true, false, transform.get()); - g22 = interpolateAndExtrapolate(coords_in->g22, location, true, true, false, transform.get()); - g33 = interpolateAndExtrapolate(coords_in->g33, location, true, true, false, transform.get()); + g11 = interpolateAndExtrapolate(coords_in->g11, location, true, true, false, + transform.get()); + g22 = interpolateAndExtrapolate(coords_in->g22, location, true, true, false, + transform.get()); + g33 = interpolateAndExtrapolate(coords_in->g33, location, true, true, false, + transform.get()); // Off-diagonal elements. - g12 = interpolateAndExtrapolate(coords_in->g12, location, true, true, false, transform.get()); - g13 = interpolateAndExtrapolate(coords_in->g13, location, true, true, false, transform.get()); - g23 = interpolateAndExtrapolate(coords_in->g23, location, true, true, false, transform.get()); + g12 = interpolateAndExtrapolate(coords_in->g12, location, true, true, false, + transform.get()); + g13 = interpolateAndExtrapolate(coords_in->g13, location, true, true, false, + transform.get()); + g23 = interpolateAndExtrapolate(coords_in->g23, location, true, true, false, + transform.get()); // 3x3 matrix inversion can exaggerate small interpolation errors, so it is // more robust to interpolate and extrapolate derived quantities directly, // rather than deriving from interpolated/extrapolated covariant metric // components - g_11 = interpolateAndExtrapolate(coords_in->g_11, location, true, true, false, transform.get()); - g_22 = interpolateAndExtrapolate(coords_in->g_22, location, true, true, false, transform.get()); - g_33 = interpolateAndExtrapolate(coords_in->g_33, location, true, true, false, transform.get()); - g_12 = interpolateAndExtrapolate(coords_in->g_12, location, true, true, false, transform.get()); - g_13 = interpolateAndExtrapolate(coords_in->g_13, location, true, true, false, transform.get()); - g_23 = interpolateAndExtrapolate(coords_in->g_23, location, true, true, false, transform.get()); + g_11 = interpolateAndExtrapolate(coords_in->g_11, location, true, true, false, + transform.get()); + g_22 = interpolateAndExtrapolate(coords_in->g_22, location, true, true, false, + transform.get()); + g_33 = interpolateAndExtrapolate(coords_in->g_33, location, true, true, false, + transform.get()); + g_12 = interpolateAndExtrapolate(coords_in->g_12, location, true, true, false, + transform.get()); + g_13 = interpolateAndExtrapolate(coords_in->g_13, location, true, true, false, + transform.get()); + g_23 = interpolateAndExtrapolate(coords_in->g_23, location, true, true, false, + transform.get()); // Check input metrics // Diagonal metric components should be finite @@ -955,23 +1010,27 @@ Coordinates::Coordinates(Mesh *mesh, Options* options, const CELL_LOC loc, bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); - J = interpolateAndExtrapolate(coords_in->J, location, true, true, false, transform.get()); - Bxy = interpolateAndExtrapolate(coords_in->Bxy, location, true, true, false, transform.get()); + J = interpolateAndExtrapolate(coords_in->J, location, true, true, false, + transform.get()); + Bxy = interpolateAndExtrapolate(coords_in->Bxy, location, true, true, false, + transform.get()); bout::checkFinite(J, "The Jacobian", "RGN_NOCORNERS"); bout::checkPositive(J, "The Jacobian", "RGN_NOCORNERS"); bout::checkFinite(Bxy, "Bxy", "RGN_NOCORNERS"); bout::checkPositive(Bxy, "Bxy", "RGN_NOCORNERS"); - ShiftTorsion = interpolateAndExtrapolate(coords_in->ShiftTorsion, location, true, true, false, transform.get()); + ShiftTorsion = interpolateAndExtrapolate(coords_in->ShiftTorsion, location, true, + true, false, transform.get()); if (mesh->IncIntShear) { - IntShiftTorsion = interpolateAndExtrapolate(coords_in->IntShiftTorsion, location, true, true, false, transform.get()); + IntShiftTorsion = interpolateAndExtrapolate(coords_in->IntShiftTorsion, location, + true, true, false, transform.get()); } } - - ShiftTorsion = interpolateAndNeumann(coords_in->ShiftTorsion, location, transform.get()); + ShiftTorsion = + interpolateAndNeumann(coords_in->ShiftTorsion, location, transform.get()); ////////////////////////////////////////////////////// /// Calculate Christoffel symbols. Needs communication @@ -1014,8 +1073,8 @@ void Coordinates::outputVars(Datafile& file) { int Coordinates::geometry(bool recalculate_staggered, bool force_interpolate_from_centre) { TRACE("Coordinates::geometry"); - communicate(dx, dy, dz, g11, g22, g33, g12, g13, g23, - g_11, g_22, g_33, g_12, g_13, g_23, J, Bxy); + communicate(dx, dy, dz, g11, g22, g33, g12, g13, g23, g_11, g_22, g_33, g_12, g_13, + g_23, J, Bxy); output_progress.write("Calculating differential geometry terms\n"); @@ -1055,7 +1114,6 @@ int Coordinates::geometry(bool recalculate_staggered, bout::checkFinite(g_13, "g_13", "RGN_NOCORNERS"); bout::checkFinite(g_23, "g_23", "RGN_NOCORNERS"); - // Calculate Christoffel symbol terms (18 independent values) // Note: This calculation is completely general: metric // tensor can be 2D or 3D. For 2D, all DDZ terms are zero @@ -1131,10 +1189,8 @@ int Coordinates::geometry(bool recalculate_staggered, // Communicate christoffel symbol terms output_progress.write("\tCommunicating connection terms\n"); - communicate(G1_11, G1_22, G1_33, G1_12, G1_13, G1_23, - G2_11, G2_22, G2_33, G2_12, G2_13, G2_23, - G3_11, G3_22, G3_33, G3_12, G3_13, G3_23, - G1, G2, G3); + communicate(G1_11, G1_22, G1_33, G1_12, G1_13, G1_23, G2_11, G2_22, G2_33, G2_12, G2_13, + G2_23, G3_11, G3_22, G3_33, G3_12, G3_13, G3_23, G1, G2, G3); // Set boundary guard cells of Christoffel symbol terms // Ideally, when location is staggered, we would set the upper/outer boundary point @@ -1176,7 +1232,8 @@ int Coordinates::geometry(bool recalculate_staggered, OPTION(Options::getRoot(), non_uniform, true); - Coordinates::metric_field_type d2x(localmesh), d2y(localmesh), d2z(localmesh); // d^2 x / d i^2 + Coordinates::metric_field_type d2x(localmesh), d2y(localmesh), + d2z(localmesh); // d^2 x / d i^2 // Read correction for non-uniform meshes std::string suffix = getLocationSuffix(location); @@ -1185,47 +1242,53 @@ int Coordinates::geometry(bool recalculate_staggered, bool extrapolate_x = not localmesh->sourceHasXBoundaryGuards(); bool extrapolate_y = not localmesh->sourceHasYBoundaryGuards(); - if (localmesh->get(d2x, "d2x"+suffix, 0.0, false)) { + if (localmesh->get(d2x, "d2x" + suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2x' not found. Calculating from dx\n"); d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) communicate(d1_dx); - d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true, transform.get()); + d1_dx = + interpolateAndExtrapolate(d1_dx, location, true, true, true, transform.get()); } else { d2x.setLocation(location); // set boundary cells if necessary - d2x = interpolateAndExtrapolate(d2x, location, extrapolate_x, extrapolate_y, false, transform.get()); + d2x = interpolateAndExtrapolate(d2x, location, extrapolate_x, extrapolate_y, false, + transform.get()); d1_dx = -d2x / (dx * dx); } - if (localmesh->get(d2y, "d2y"+suffix, 0.0, false)) { + if (localmesh->get(d2y, "d2y" + suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); d1_dy = indexDDY(1. / dy); // d/di(1/dy) communicate(d1_dy); - d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true, transform.get()); + d1_dy = + interpolateAndExtrapolate(d1_dy, location, true, true, true, transform.get()); } else { d2y.setLocation(location); // set boundary cells if necessary - d2y = interpolateAndExtrapolate(d2y, location, extrapolate_x, extrapolate_y, false, transform.get()); + d2y = interpolateAndExtrapolate(d2y, location, extrapolate_x, extrapolate_y, false, + transform.get()); d1_dy = -d2y / (dy * dy); } #ifdef COORDINATES_USE_3D - if (localmesh->get(d2z, "d2z"+suffix, 0.0, false)) { + if (localmesh->get(d2z, "d2z" + suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) communicate(d1_dz); - d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); + d1_dz = + interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); } else { d2z.setLocation(location); // set boundary cells if necessary - d2z = interpolateAndExtrapolate(d2z, location, extrapolate_x, extrapolate_y, false, transform.get()); + d2z = interpolateAndExtrapolate(d2z, location, extrapolate_x, extrapolate_y, false, + transform.get()); d1_dz = -d2z / (dz * dz); } @@ -1239,7 +1302,8 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) communicate(d1_dx); - d1_dx = interpolateAndExtrapolate(d1_dx, location, true, true, true, transform.get()); + d1_dx = + interpolateAndExtrapolate(d1_dx, location, true, true, true, transform.get()); } else { // Shift d2x to our location d2x = interpolateAndExtrapolate(d2x, location, true, true, false, transform.get()); @@ -1253,7 +1317,8 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dy = indexDDY(1. / dy); // d/di(1/dy) communicate(d1_dy); - d1_dy = interpolateAndExtrapolate(d1_dy, location, true, true, true, transform.get()); + d1_dy = + interpolateAndExtrapolate(d1_dy, location, true, true, true, transform.get()); } else { // Shift d2y to our location d2y = interpolateAndExtrapolate(d2y, location, true, true, false, transform.get()); @@ -1268,7 +1333,8 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) communicate(d1_dz); - d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); + d1_dz = + interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); } else { // Shift d2z to our location d2z = interpolateAndExtrapolate(d2z, location, true, true, false, transform.get()); @@ -1421,24 +1487,25 @@ int Coordinates::jacobian() { J = 1. / sqrt(g); // More robust to extrapolate derived quantities directly, rather than // deriving from extrapolated covariant metric components - J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, transform.get()); + J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, + transform.get()); Bxy = sqrt(g_22) / J; - Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, transform.get()); + Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, + transform.get()); return 0; } namespace { // Utility function for fixing up guard cells of zShift - void fixZShiftGuards(Field2D& zShift) { +void fixZShiftGuards(Field2D& zShift) { auto localmesh = zShift.getMesh(); // extrapolate into boundary guard cells if necessary zShift = interpolateAndExtrapolate(zShift, zShift.getLocation(), - not localmesh->sourceHasXBoundaryGuards(), - not localmesh->sourceHasYBoundaryGuards(), - false); + not localmesh->sourceHasXBoundaryGuards(), + not localmesh->sourceHasYBoundaryGuards(), false); // make sure zShift has been communicated communicate(zShift); @@ -1486,9 +1553,9 @@ void Coordinates::setParallelTransform(Options* options) { if (localmesh->sourceHasVar("dx"+suffix)) { // Grid file has variables at this location, so should be able to read checkStaggeredGet(localmesh, "zShift", suffix); - if (localmesh->get(zShift, "zShift"+suffix, 0.0, false)) { + if (localmesh->get(zShift, "zShift" + suffix, 0.0, false)) { // No zShift variable. Try qinty in BOUT grid files - if (localmesh->get(zShift, "qinty"+suffix, 0.0, false)) { + if (localmesh->get(zShift, "qinty" + suffix, 0.0, false)) { // Failed to find either variable, cannot use ShiftedMetric throw BoutException("Could not read zShift"+suffix+" from grid file"); } @@ -1506,7 +1573,8 @@ void Coordinates::setParallelTransform(Options* options) { fixZShiftGuards(zShift_centre); - zShift = interpolateAndExtrapolate(zShift_centre, location, true, true, false, transform.get()); + zShift = interpolateAndExtrapolate(zShift_centre, location, true, true, false, + transform.get()); } fixZShiftGuards(zShift); @@ -1547,8 +1615,8 @@ Coordinates::metric_field_type Coordinates::DDX(const Field2D& f, CELL_LOC loc, ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDX(f, loc, method, region) / dx; } -Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { +Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, const std::string& method, + const std::string& region) { auto result = bout::derivatives::index::DDX(f, outloc, method, region); result /= dx; @@ -1568,9 +1636,9 @@ Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, return bout::derivatives::index::DDY(f, loc, method, region) / dy; } -Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { - return indexDDY(f, outloc, method, region)/dy; +Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, + const std::string& region) { + return indexDDY(f, outloc, method, region) / dy; }; Coordinates::metric_field_type Coordinates::DDZ(const Field2D& f, CELL_LOC loc, @@ -1583,17 +1651,17 @@ Coordinates::metric_field_type Coordinates::DDZ(const Field2D& f, CELL_LOC loc, } return zeroFrom(f).setLocation(loc); } -Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { +Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, const std::string& method, + const std::string& region) { return bout::derivatives::index::DDZ(f, outloc, method, region) / dz; }; ///////////////////////////////////////////////////////// // Parallel gradient -Coordinates::metric_field_type -Coordinates::Grad_par(const Field2D& var, MAYBE_UNUSED(CELL_LOC outloc), - const std::string& UNUSED(method)) { +Coordinates::metric_field_type Coordinates::Grad_par(const Field2D& var, + MAYBE_UNUSED(CELL_LOC outloc), + const std::string& UNUSED(method)) { TRACE("Coordinates::Grad_par( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == var.getLocation())); @@ -1630,8 +1698,8 @@ Field3D Coordinates::Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC ///////////////////////////////////////////////////////// // Parallel divergence -Coordinates::metric_field_type -Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, const std::string& method) { +Coordinates::metric_field_type Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, + const std::string& method) { TRACE("Coordinates::Div_par( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1669,8 +1737,8 @@ 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 -Coordinates::metric_field_type -Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& method) { +Coordinates::metric_field_type Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, + const std::string& method) { TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); @@ -1711,8 +1779,8 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, #include // Delp2 uses same coefficients as inversion code -Coordinates::metric_field_type Coordinates::Delp2(const Field2D& f, - CELL_LOC outloc, bool UNUSED(useFFT)) { +Coordinates::metric_field_type Coordinates::Delp2(const Field2D& f, CELL_LOC outloc, + bool UNUSED(useFFT)) { TRACE("Coordinates::Delp2( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1777,7 +1845,7 @@ Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(bool } } else #endif - { + { result = G1 * ::DDX(f, outloc) + G3 * ::DDZ(f, outloc) + g11 * ::D2DX2(f, outloc) + g33 * ::D2DZ2(f, outloc) + 2 * g13 * ::D2DXDZ(f, outloc); }; @@ -1862,18 +1930,18 @@ Field3D Coordinates::Laplace_par(const Field3D& f, CELL_LOC outloc) { // Full Laplacian operator on scalar field -Coordinates::metric_field_type Coordinates::Laplace(const Field2D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_conditions, - const std::string& dfdy_dy_region) { +Coordinates::metric_field_type +Coordinates::Laplace(const Field2D& f, CELL_LOC outloc, + const std::string& dfdy_boundary_conditions, + const std::string& dfdy_dy_region) { TRACE("Coordinates::Laplace( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); - auto result = - G1 * DDX(f, outloc) + G2 * DDY(f, outloc) + g11 * D2DX2(f, outloc) - + g22 * D2DY2(f, outloc) - + 2.0 * g12 - * D2DXDY(f, outloc, "DEFAULT", "RGN_NOBNDRY", - dfdy_boundary_conditions, dfdy_dy_region); + auto result = G1 * DDX(f, outloc) + G2 * DDY(f, outloc) + g11 * D2DX2(f, outloc) + + g22 * D2DY2(f, outloc) + + 2.0 * g12 + * D2DXDY(f, outloc, "DEFAULT", "RGN_NOBNDRY", + dfdy_boundary_conditions, dfdy_dy_region); return result; } @@ -1958,25 +2026,26 @@ Field2D Coordinates::Laplace_perpXY(const Field2D& A, const Field2D& f) { } Coordinates::metric_field_type Coordinates::indexDDY(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region){ + const std::string& method, + const std::string& region) { #ifdef COORDINATES_USE_3D - if (!f.hasParallelSlices()){ + if (!f.hasParallelSlices()) { const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result); } #endif return bout::derivatives::index::DDY(f, outloc, method, region); } Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region){ + const std::string& method, const std::string& region) { #ifdef COORDINATES_USE_3D - if (!f.hasParallelSlices()){ + if (!f.hasParallelSlices()) { const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); Field3D f_aligned; - if (transform->canToFromFieldAligned()){ + if (transform->canToFromFieldAligned()) { f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; } else { Field3D f_parallel = f; @@ -1984,7 +2053,7 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, return bout::derivatives::index::DDY(f_parallel, outloc, method, region); } Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result ); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result); } #endif return bout::derivatives::index::DDY(f, outloc, method, region); diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index a8668c9ab1..78bb63d870 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -572,7 +572,7 @@ bool GridFile::readgrid_3dvar_fft(Mesh *m, const std::string &name, /// 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 = getConst(m->getCoordinates(var.getLocation())->zlength()); - + int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi // Print out which modes are going to be read in @@ -702,7 +702,7 @@ bool GridFile::readgrid_perpvar_fft(Mesh *m, const std::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 =getConst(m->getCoordinates(var.getLocation())->zlength()); + BoutReal zlength = getConst(m->getCoordinates(var.getLocation())->zlength()); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index a895322a33..156b2ffdf3 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -1,27 +1,27 @@ /************************************************************************** -* Various differential operators defined on BOUT grid -* -************************************************************************** -* 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 -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* BOUT++ is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with BOUT++. If not, see . -* -**************************************************************************/ + * Various differential operators defined on BOUT grid + * + ************************************************************************** + * 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 + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * BOUT++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with BOUT++. If not, see . + * + **************************************************************************/ #include #include @@ -46,20 +46,20 @@ *******************************************************************************/ Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -Coordinates::metric_field_type -Grad_par(const Field2D& var, const std::string& method, CELL_LOC outloc) { +Coordinates::metric_field_type Grad_par(const Field2D& var, const std::string& method, + CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -Field3D Grad_par(const Field3D &var, CELL_LOC outloc, const std::string &method) { +Field3D Grad_par(const Field3D& var, CELL_LOC outloc, const std::string& method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC outloc) { +Field3D Grad_par(const Field3D& var, const std::string& method, CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } @@ -74,7 +74,7 @@ Field3D Grad_par(const Field3D &var, const std::string &method, CELL_LOC outloc) * grid-points at the corners. *******************************************************************************/ -Field3D Grad_parP(const Field3D &apar, const Field3D &f) { +Field3D Grad_parP(const Field3D& apar, const Field3D& f) { ASSERT1_FIELDS_COMPATIBLE(apar, f); ASSERT1(f.hasParallelSlices()); @@ -92,21 +92,27 @@ Field3D Grad_parP(const Field3D &apar, const Field3D &f) { for(int x=1;x<=mesh->LocalNx-2;x++) for(int y=1;y<=mesh->LocalNy-2;y++) for(int z=0;zdy(x, y+1, z) + metric->dy(x, y, z) + 0.5*metric->dy(x, y-1, z)); + gys(x, y, z) = (f.yup()(x, y + 1, z) - f.ydown()(x, y - 1, z)) + / (0.5 * metric->dy(x, y + 1, z) + metric->dy(x, y, z) + + 0.5 * metric->dy(x, y - 1, z)); } for(int x=1;x<=mesh->LocalNx-2;x++) { for(int y=mesh->ystart;y<=mesh->yend;y++) { for(int z=0;zg_22(x, y, z)); + BoutReal by = 1. / sqrt(metric->g_22(x, y, z)); // Z indices zm and zp int zm = (z - 1 + ncz) % ncz; int zp = (z + 1) % ncz; // bx = -DDZ(apar) - BoutReal bx = (apar(x, y, zm) - apar(x, y, zp))/(0.5*metric->dz(x, y, zm) + metric->dz(x, y, z) + 0.5*metric->dz(x, y, zp)); + BoutReal bx = (apar(x, y, zm) - apar(x, y, zp)) + / (0.5 * metric->dz(x, y, zm) + metric->dz(x, y, z) + + 0.5 * metric->dz(x, y, zp)); // bz = DDX(f) - BoutReal bz = (apar(x+1, y, z) - apar(x-1, y, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)); + BoutReal bz = (apar(x + 1, y, z) - apar(x - 1, y, z)) + / (0.5 * metric->dx(x - 1, y, z) + metric->dx(x, y, z) + + 0.5 * metric->dx(x + 1, y, z)); // Now calculate (bx*d/dx + by*d/dy + bz*d/dz) f @@ -118,40 +124,56 @@ Field3D Grad_parP(const Field3D &apar, const Field3D &f) { BoutReal fp, fm; // X differencing - fp = f(x+1, y, z) - + (0.25*dl/metric->dz(x, y, z)) * bz * (f(x+1, y, zm) - f(x+1, y, zp)) - - 0.5*dl * by * gys(x+1, y, z); + fp = + f(x + 1, y, z) + + (0.25 * dl / metric->dz(x, y, z)) * bz * (f(x + 1, y, zm) - f(x + 1, y, zp)) + - 0.5 * dl * by * gys(x + 1, y, z); - fm = f(x-1, y, z) - + (0.25*dl/metric->dz(x, y, z)) * bz * (f(x-1, y, zm) - f(x-1, y, zp)) - - 0.5*dl * by * gys(x-1, y, z); + fm = + f(x - 1, y, z) + + (0.25 * dl / metric->dz(x, y, z)) * bz * (f(x - 1, y, zm) - f(x - 1, y, zp)) + - 0.5 * dl * by * gys(x - 1, y, z); - result(x, y, z) = bx * (fp - fm) / (0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)); + result(x, y, z) = bx * (fp - fm) + / (0.5 * metric->dx(x - 1, y, z) + metric->dx(x, y, z) + + 0.5 * metric->dx(x + 1, y, z)); // Z differencing - fp = f(x, y, zp) - + (0.25*dl/metric->dx(x, y, z)) * bx * (f(x-1, y, zp) - f(x+1, y, zp)) - - 0.5*dl * by * gys(x, y, zp); + fp = + f(x, y, zp) + + (0.25 * dl / metric->dx(x, y, z)) * bx * (f(x - 1, y, zp) - f(x + 1, y, zp)) + - 0.5 * dl * by * gys(x, y, zp); - fm = f(x, y, zm) - + (0.25*dl/metric->dx(x, y, z)) * bx * (f(x-1,y,zm) - f(x+1, y, zm)) - - 0.5*dl * by * gys(x, y, zm); + fm = + f(x, y, zm) + + (0.25 * dl / metric->dx(x, y, z)) * bx * (f(x - 1, y, zm) - f(x + 1, y, zm)) + - 0.5 * dl * by * gys(x, y, zm); - result(x, y, z) += bz * (fp - fm) / (0.5*metric->dz(x, y, zm) + metric->dz(x, y, z) + 0.5*metric->dz(x, y, zp)); + result(x, y, z) += bz * (fp - fm) + / (0.5 * metric->dz(x, y, zm) + metric->dz(x, y, z) + + 0.5 * metric->dz(x, y, zp)); // Y differencing - fp = f.yup()(x,y+1,z) - - 0.5*dl * bx * (f.yup()(x+1, y+1, z) - f.yup()(x-1, y+1, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)) + fp = f.yup()(x, y + 1, z) + - 0.5 * dl * bx * (f.yup()(x + 1, y + 1, z) - f.yup()(x - 1, y + 1, z)) + / (0.5 * metric->dx(x - 1, y, z) + metric->dx(x, y, z) + + 0.5 * metric->dx(x + 1, y, z)) - + (0.25*dl/metric->dz(x,y,z)) * bz * (f.yup()(x,y+1,zm) - f.yup()(x,y+1,zp)); + + (0.25 * dl / metric->dz(x, y, z)) * bz + * (f.yup()(x, y + 1, zm) - f.yup()(x, y + 1, zp)); - fm = f.ydown()(x,y-1,z) - - 0.5*dl * bx * (f.ydown()(x+1, y-1, z) - f.ydown()(x-1, y-1, z))/(0.5*metric->dx(x-1, y, z) + metric->dx(x, y, z) + 0.5*metric->dx(x+1, y, z)) - + (0.25*dl/metric->dz(x,y,z)) * bz * (f.ydown()(x,y-1,zm) - f.ydown()(x,y-1,zp)); + fm = f.ydown()(x, y - 1, z) + - 0.5 * dl * bx * (f.ydown()(x + 1, y - 1, z) - f.ydown()(x - 1, y - 1, z)) + / (0.5 * metric->dx(x - 1, y, z) + metric->dx(x, y, z) + + 0.5 * metric->dx(x + 1, y, z)) + + (0.25 * dl / metric->dz(x, y, z)) * bz + * (f.ydown()(x, y - 1, zm) - f.ydown()(x, y - 1, zp)); - result(x,y,z) += by * (fp - fm) / (0.5*metric->dy(x,y-1, z) + metric->dy(x,y,z) + 0.5*metric->dy(x,y+1,z)); + result(x, y, z) += by * (fp - fm) + / (0.5 * metric->dy(x, y - 1, z) + metric->dy(x, y, z) + + 0.5 * metric->dy(x, y + 1, z)); } } } @@ -167,22 +189,22 @@ Field3D Grad_parP(const Field3D &apar, const Field3D &f) { *******************************************************************************/ Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc, - const std::string& method) { + CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, - const std::string& method, - CELL_LOC outloc) { + const std::string& method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC outloc, + const std::string& method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, const std::string &method, CELL_LOC outloc) { +Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, const std::string& method, + CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } @@ -191,7 +213,7 @@ Field3D Vpar_Grad_par(const Field3D &v, const Field3D &f, const std::string &met * parallel divergence operator B \partial_{||} (F/B) *******************************************************************************/ Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } @@ -200,11 +222,11 @@ Coordinates::metric_field_type Div_par(const Field2D& f, const std::string& meth return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -Field3D Div_par(const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Div_par(const Field3D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -Field3D Div_par(const Field3D &f, const std::string &method, CELL_LOC outloc) { +Field3D Div_par(const Field3D& f, const std::string& method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } @@ -251,7 +273,8 @@ Field3D Div_par(const Field3D& f, const Field3D& v) { //////// Flux methods -Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Div_par_flux(const Field3D& v, const Field3D& f, CELL_LOC outloc, + const std::string& method) { Coordinates *metric = f.getCoordinates(outloc); auto Bxy_floc = f.getCoordinates()->Bxy; @@ -269,7 +292,8 @@ Field3D Div_par_flux(const Field3D &v, const Field3D &f, CELL_LOC outloc, const return metric->Bxy*FDDY(v, f_B, outloc, method)/sqrt(metric->g_22); } -Field3D Div_par_flux(const Field3D &v, const Field3D &f, const std::string &method, CELL_LOC outloc) { +Field3D Div_par_flux(const Field3D& v, const Field3D& f, const std::string& method, + CELL_LOC outloc) { return Div_par_flux(v,f, outloc, method); } @@ -283,11 +307,11 @@ Field3D Div_par_flux(const Field3D &v, const Field3D &f, const std::string &meth *******************************************************************************/ Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } -Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, const std::string &method) { +Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } @@ -297,28 +321,28 @@ Field3D Grad2_par2(const Field3D &f, CELL_LOC outloc, const std::string &method) *******************************************************************************/ Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, - CELL_LOC outloc) { + CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } -Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D &f, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } -Coordinates::metric_field_type -Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, CELL_LOC outloc) { +Coordinates::metric_field_type 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); } -Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc) { +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); } -Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc) { +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); } -Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc) { +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); } @@ -347,32 +371,32 @@ FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { *******************************************************************************/ Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { return Laplace(f, outloc, dfdy_boundary_condition, dfdy_region) - Laplace_par(f, outloc); } Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { return Laplace(f, outloc, dfdy_boundary_condition, dfdy_region) - Laplace_par(f, outloc); } /******************************************************************************* -* LaplacePar -* Full parallel Laplacian operator on scalar field -* -* LaplacePar(f) = Div( b (b dot Grad(f)) ) -* -*******************************************************************************/ + * LaplacePar + * Full parallel Laplacian operator on scalar field + * + * LaplacePar(f) = Div( b (b dot Grad(f)) ) + * + *******************************************************************************/ Coordinates::metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } -Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { +Field3D Laplace_par(const Field3D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } @@ -382,15 +406,15 @@ Field3D Laplace_par(const Field3D &f, CELL_LOC outloc) { *******************************************************************************/ Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { return f.getCoordinates(outloc)->Laplace(f, outloc, dfdy_boundary_condition, dfdy_region); } Field3D Laplace(const Field3D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { return f.getCoordinates(outloc)->Laplace(f, outloc, dfdy_boundary_condition, dfdy_region); } @@ -410,8 +434,8 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f) { * Used for ExB terms and perturbed B field using A_|| *******************************************************************************/ -Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, - const Field2D& A, CELL_LOC outloc) { +Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, + CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field2D , Field2D )"); @@ -441,7 +465,7 @@ Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, return result; } -Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc) { +Field3D b0xGrad_dot_Grad(const Field2D& phi, const Field3D& A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field2D , Field3D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -481,7 +505,7 @@ Field3D b0xGrad_dot_Grad(const Field2D &phi, const Field3D &A, CELL_LOC outloc) return result; } -Field3D b0xGrad_dot_Grad(const Field3D &p, const Field2D &A, CELL_LOC outloc) { +Field3D b0xGrad_dot_Grad(const Field3D& p, const Field2D& A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field3D , Field2D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -514,7 +538,7 @@ Field3D b0xGrad_dot_Grad(const Field3D &p, const Field2D &A, CELL_LOC outloc) { return result; } -Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc) { +Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field3D , Field3D )"); if (outloc == CELL_DEFAULT) outloc = A.getLocation(); @@ -553,8 +577,7 @@ Field3D b0xGrad_dot_Grad(const Field3D &phi, const Field3D &A, CELL_LOC outloc) return result; } - -Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { +Field3D Div_Perp_Lap_FV(const Field3D& a, const Field3D& f, CELL_LOC outloc) { Field3D result = 0.0; @@ -572,62 +595,79 @@ Field3D Div_Perp_Lap_FV(const Field3D &a, const Field3D &f, CELL_LOC outloc) { // | nD | // o --- gD --- o // - Coordinates *coords = a.getCoordinates(outloc); - Mesh *mesh = f.getMesh(); + Coordinates* coords = a.getCoordinates(outloc); + Mesh* mesh = f.getMesh(); - for(int i=mesh->xstart;i<=mesh->xend;i++) - for(int j=mesh->ystart;j<=mesh->yend;j++) - for(int k=0;kLocalNz;k++) { + for (int i = mesh->xstart; i <= mesh->xend; i++) + for (int j = mesh->ystart; j <= mesh->yend; j++) + for (int k = 0; k < mesh->LocalNz; k++) { // wrap k-index around as Z is (currently) periodic. - int kp = (k+1) % (mesh->LocalNz); - int km = (k-1+mesh->LocalNz) % (mesh->LocalNz); + int kp = (k + 1) % (mesh->LocalNz); + int km = (k - 1 + mesh->LocalNz) % (mesh->LocalNz); // Calculate gradients on cell faces -- assumes constant grid spacing - BoutReal gR = (coords->g11(i,j,k) + coords->g11(i+1,j,k)) * (f(i+1,j,k) - f(i,j,k))/(coords->dx(i+1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i,j,k) + coords->g13(i+1,j,k))*(f(i+1,j,kp) - f(i+1,j,km) + f(i,j,kp) - f(i,j,km))/(4.*coords->dz(i,j,k)); - - BoutReal gL = (coords->g11(i-1,j,k) + coords->g11(i,j,k))*(f(i,j,k) - f(i-1,j,k))/(coords->dx(i-1,j,k) + coords->dx(i,j,k)) - + 0.5*(coords->g13(i-1,j,k) + coords->g13(i,j,k))*(f(i-1,j,kp) - f(i-1,j,km) + f(i,j,kp) - f(i,j,km))/(4*coords->dz(i,j,k)); - - BoutReal gD = coords->g13(i,j,k)*(f(i+1,j,km) - f(i-1,j,km) + f(i+1,j,k) - f(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(f(i,j,k) - f(i,j,km))/coords->dz(i,j,k); - - BoutReal gU = coords->g13(i,j,k)*(f(i+1,j,kp) - f(i-1,j,kp) + f(i+1,j,k) - f(i-1,j,k))/(4.*coords->dx(i,j,k)) - + coords->g33(i,j,k)*(f(i,j,kp) - f(i,j,k))/coords->dz(i,j,k); - + BoutReal gR = + (coords->g11(i, j, k) + coords->g11(i + 1, j, k)) + * (f(i + 1, j, k) - f(i, j, k)) + / (coords->dx(i + 1, j, k) + coords->dx(i, j, k)) + + 0.5 * (coords->g13(i, j, k) + coords->g13(i + 1, j, k)) + * (f(i + 1, j, kp) - f(i + 1, j, km) + f(i, j, kp) - f(i, j, km)) + / (4. * coords->dz(i, j, k)); + + BoutReal gL = + (coords->g11(i - 1, j, k) + coords->g11(i, j, k)) + * (f(i, j, k) - f(i - 1, j, k)) + / (coords->dx(i - 1, j, k) + coords->dx(i, j, k)) + + 0.5 * (coords->g13(i - 1, j, k) + coords->g13(i, j, k)) + * (f(i - 1, j, kp) - f(i - 1, j, km) + f(i, j, kp) - f(i, j, km)) + / (4 * coords->dz(i, j, k)); + + BoutReal gD = + coords->g13(i, j, k) + * (f(i + 1, j, km) - f(i - 1, j, km) + f(i + 1, j, k) - f(i - 1, j, k)) + / (4. * coords->dx(i, j, k)) + + coords->g33(i, j, k) * (f(i, j, k) - f(i, j, km)) / coords->dz(i, j, k); + + BoutReal gU = + coords->g13(i, j, k) + * (f(i + 1, j, kp) - f(i - 1, j, kp) + f(i + 1, j, k) - f(i - 1, j, k)) + / (4. * coords->dx(i, j, k)) + + coords->g33(i, j, k) * (f(i, j, kp) - f(i, j, k)) / coords->dz(i, j, k); // Flow right - BoutReal flux = gR * 0.25*(coords->J(i+1,j,k) + coords->J(i,j,k)) *(a(i+1,j,k) + a(i,j,k)); - result(i,j,k) += flux / (coords->dx(i,j,k)*coords->J(i,j,k)); + BoutReal flux = gR * 0.25 * (coords->J(i + 1, j, k) + coords->J(i, j, k)) + * (a(i + 1, j, k) + a(i, j, k)); + result(i, j, k) += flux / (coords->dx(i, j, k) * coords->J(i, j, k)); // Flow left - flux = gL * 0.25*(coords->J(i-1,j,k) + coords->J(i,j,k)) *(a(i-1,j,k) + a(i,j,k)); - result(i,j,k) -= flux / (coords->dx(i,j,k)*coords->J(i,j,k)); - + flux = gL * 0.25 * (coords->J(i - 1, j, k) + coords->J(i, j, k)) + * (a(i - 1, j, k) + a(i, j, k)); + result(i, j, k) -= flux / (coords->dx(i, j, k) * coords->J(i, j, k)); // Flow up - flux = gU * 0.25*(coords->J(i,j,k) + coords->J(i,j,kp)) *(a(i,j,k) + a(i,j,kp)); - result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); + flux = gU * 0.25 * (coords->J(i, j, k) + coords->J(i, j, kp)) + * (a(i, j, k) + a(i, j, kp)); + result(i, j, k) += flux / (coords->dz(i, j, k) * coords->J(i, j, k)); // Flow down - flux = gD * 0.25*(coords->J(i,j,km) + coords->J(i,j,k)) *(a(i,j,km) + a(i,j,k)); - result(i,j,k) += flux / (coords->dz(i,j,k) * coords->J(i,j,k)); + flux = gD * 0.25 * (coords->J(i, j, km) + coords->J(i, j, k)) + * (a(i, j, km) + a(i, j, k)); + result(i, j, k) += flux / (coords->dz(i, j, k) * coords->J(i, j, k)); } return result; } - /******************************************************************************* * Poisson bracket * Terms of form b0 x Grad(f) dot Grad(g) / B = [f, g] *******************************************************************************/ Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, - BRACKET_METHOD method, CELL_LOC outloc, - Solver* UNUSED(solver)) { + BRACKET_METHOD method, CELL_LOC outloc, + Solver* UNUSED(solver)) { TRACE("bracket(Field2D, Field2D)"); ASSERT1_FIELDS_COMPATIBLE(f, g); @@ -649,8 +689,8 @@ Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, return result; } -Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, - CELL_LOC outloc, Solver *solver) { +Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method, + CELL_LOC outloc, Solver* solver) { TRACE("bracket(Field3D, Field2D)"); ASSERT1_FIELDS_COMPATIBLE(f, g); @@ -685,7 +725,7 @@ Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, BoutReal gp, gm; // Vx = DDZ(f) - BoutReal vx = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz(x,y,z)); + BoutReal vx = (f(x, y, zp) - f(x, y, zm)) / (2. * metric->dz(x, y, z)); // Set stability condition solver->setMaxTimestep(metric->dx(x, y, z) / (fabs(vx) + 1e-16)); @@ -789,36 +829,35 @@ Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, BOUT_OMP(parallel for) for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ - const BoutReal partialFactor = 1.0/(12 * metric->dz(jx,jy)); - const BoutReal spacingFactor = partialFactor / metric->dx(jx,jy); + const BoutReal partialFactor = 1.0 / (12 * metric->dz(jx, jy)); + const BoutReal spacingFactor = partialFactor / metric->dx(jx, jy); for (int jz = 0; jz < mesh->LocalNz; jz++) { const int jzp = jz+1 < ncz ? jz + 1 : 0; - //Above is alternative to const int jzp = (jz + 1) % ncz; - const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; - //Above is alternative to const int jzmTmp = (jz - 1 + ncz) % ncz; + // Above is alternative to const int jzp = (jz + 1) % ncz; + const int jzm = jz - 1 >= 0 ? jz - 1 : ncz - 1; + // Above is alternative to const int jzmTmp = (jz - 1 + ncz) % ncz; // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) - BoutReal Jpp = ( (f(jx,jy,jzp) - f(jx,jy,jzm))* - (g(jx+1,jy) - g(jx-1,jy)) - - (f(jx+1,jy,jz) - f(jx-1,jy,jz))* - (g(jx,jy) - g(jx,jy)) ); + BoutReal Jpp = + ((f(jx, jy, jzp) - f(jx, jy, jzm)) * (g(jx + 1, jy) - g(jx - 1, jy)) + - (f(jx + 1, jy, jz) - f(jx - 1, jy, jz)) * (g(jx, jy) - g(jx, jy))); // J+x - BoutReal Jpx = ( g(jx+1,jy)*(f(jx+1,jy,jzp)-f(jx+1,jy,jzm)) - - g(jx-1,jy)*(f(jx-1,jy,jzp)-f(jx-1,jy,jzm)) - - g(jx,jy)*(f(jx+1,jy,jzp)-f(jx-1,jy,jzp)) + - g(jx,jy)*(f(jx+1,jy,jzm)-f(jx-1,jy,jzm))); + BoutReal Jpx = (g(jx + 1, jy) * (f(jx + 1, jy, jzp) - f(jx + 1, jy, jzm)) + - g(jx - 1, jy) * (f(jx - 1, jy, jzp) - f(jx - 1, jy, jzm)) + - g(jx, jy) * (f(jx + 1, jy, jzp) - f(jx - 1, jy, jzp)) + + g(jx, jy) * (f(jx + 1, jy, jzm) - f(jx - 1, jy, jzm))); // Jx+ - BoutReal Jxp = ( g(jx+1,jy)*(f(jx,jy,jzp)-f(jx+1,jy,jz)) - - g(jx-1,jy)*(f(jx-1,jy,jz)-f(jx,jy,jzm)) - - g(jx-1,jy)*(f(jx,jy,jzp)-f(jx-1,jy,jz)) + - g(jx+1,jy)*(f(jx+1,jy,jz)-f(jx,jy,jzm))); + BoutReal Jxp = (g(jx + 1, jy) * (f(jx, jy, jzp) - f(jx + 1, jy, jz)) + - g(jx - 1, jy) * (f(jx - 1, jy, jz) - f(jx, jy, jzm)) + - g(jx - 1, jy) * (f(jx, jy, jzp) - f(jx - 1, jy, jz)) + + g(jx + 1, jy) * (f(jx + 1, jy, jz) - f(jx, jy, jzm))); result(jx,jy,jz) = (Jpp + Jpx + Jxp) * spacingFactor; - } } } + } #else throw BoutException("BRACKET_ARAKAWA_OLD not valid with 3D metrics yet."); #endif @@ -837,8 +876,8 @@ Field3D bracket(const Field3D &f, const Field2D &g, BRACKET_METHOD method, return result; } -Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, - CELL_LOC outloc, Solver *solver) { +Field3D bracket(const Field2D& f, const Field3D& g, BRACKET_METHOD method, + CELL_LOC outloc, Solver* solver) { TRACE("bracket(Field2D, Field3D)"); ASSERT1_FIELDS_COMPATIBLE(f, g); @@ -874,8 +913,8 @@ Field3D bracket(const Field2D &f, const Field3D &g, BRACKET_METHOD method, return result; } -Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, - CELL_LOC outloc, Solver *solver) { +Field3D bracket(const Field3D& f, const Field3D& g, BRACKET_METHOD method, + CELL_LOC outloc, Solver* solver) { TRACE("Field3D, Field3D"); ASSERT1_FIELDS_COMPATIBLE(f, g); @@ -921,13 +960,13 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, int zp = (z + 1) % ncz; // Vx = DDZ(f) - vx(x,z) = (f(x,y,zp) - f(x,y,zm))/(2.*metric->dz(x,y,z)); + vx(x, z) = (f(x, y, zp) - f(x, y, zm)) / (2. * metric->dz(x, y, z)); // Vz = -DDX(f) vz(x,z) = (f(x-1,y,z) - f(x+1,y,z))/(0.5*metric->dx(x-1,y) + metric->dx(x,y) + 0.5*metric->dx(x+1,y)); // Set stability condition solver->setMaxTimestep(fabs(metric->dx(x,y)) / (fabs(vx(x,z)) + 1e-16)); - solver->setMaxTimestep(metric->dz(x,y) / (fabs(vz(x,z)) + 1e-16)); + solver->setMaxTimestep(metric->dz(x, y) / (fabs(vz(x, z)) + 1e-16)); } } @@ -942,26 +981,26 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, // X differencing if (vx(x, z) > 0.0) { - gp = g(x, y, z) + - (0.5 * dt / metric->dz(x,y)) * ((vz(x, z) > 0) - ? vz(x, z) * (g(x, y, zm) - g(x, y, z)) - : vz(x, z) * (g(x, y, z) - g(x, y, zp))); + gp = g(x, y, z) + + (0.5 * dt / metric->dz(x, y)) + * ((vz(x, z) > 0) ? vz(x, z) * (g(x, y, zm) - g(x, y, z)) + : vz(x, z) * (g(x, y, z) - g(x, y, zp))); - gm = g(x - 1, y, z) + - (0.5 * dt / metric->dz(x,y)) * - ((vz(x, z) > 0) ? vz(x, z) * (g(x - 1, y, zm) - g(x - 1, y, z)) - : vz(x, z) * (g(x - 1, y, z) - g(x - 1, y, zp))); + gm = g(x - 1, y, z) + + (0.5 * dt / metric->dz(x, y)) + * ((vz(x, z) > 0) ? vz(x, z) * (g(x - 1, y, zm) - g(x - 1, y, z)) + : vz(x, z) * (g(x - 1, y, z) - g(x - 1, y, zp))); } else { - gp = g(x + 1, y, z) + - (0.5 * dt / metric->dz(x,y)) * - ((vz(x, z) > 0) ? vz(x, z) * (g(x + 1, y, zm) - g(x + 1, y, z)) - : vz[x][z] * (g(x + 1, y, z) - g(x + 1, y, zp))); - - gm = g(x, y, z) + - (0.5 * dt / metric->dz(x,y)) * ((vz(x, z) > 0) - ? vz(x, z) * (g(x, y, zm) - g(x, y, z)) - : vz(x, z) * (g(x, y, z) - g(x, y, zp))); + gp = g(x + 1, y, z) + + (0.5 * dt / metric->dz(x, y)) + * ((vz(x, z) > 0) ? vz(x, z) * (g(x + 1, y, zm) - g(x + 1, y, z)) + : vz[x][z] * (g(x + 1, y, z) - g(x + 1, y, zp))); + + gm = g(x, y, z) + + (0.5 * dt / metric->dz(x, y)) + * ((vz(x, z) > 0) ? vz(x, z) * (g(x, y, zm) - g(x, y, z)) + : vz(x, z) * (g(x, y, z) - g(x, y, zp))); } result(x, y, z) = vx(x, z) * (gp - gm) / metric->dx(x, y); @@ -989,7 +1028,7 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, : vx(x, z) * (g(x, y, z) - g(x + 1, y, z))); } - result(x, y, z) += vz(x, z) * (gp - gm) / metric->dz(x,y); + result(x, y, z) += vz(x, z) * (gp - gm) / metric->dz(x, y); } } #else @@ -1008,7 +1047,7 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, BOUT_FOR(j2D, result.getRegion2D("RGN_NOBNDRY")) { #ifndef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0/(12 * metric->dz[j2D] * metric->dx[j2D]); + const BoutReal spacingFactor = 1.0 / (12 * metric->dz[j2D] * metric->dx[j2D]); #endif const int jy = j2D.y(), jx = j2D.x(); const int xm = jx - 1, xp = jx + 1; @@ -1025,7 +1064,8 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const int jzp = 1; const int jzm = ncz - 1; #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = + 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) @@ -1047,7 +1087,8 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, for (int jz = 1; jz < mesh->LocalNz - 1; jz++) { #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = + 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif const int jzp = jz + 1; const int jzm = jz - 1; @@ -1074,7 +1115,8 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const int jzp = 0; const int jzm = ncz - 2; #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = + 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) @@ -1110,8 +1152,8 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, for(int jx=mesh->xstart;jx<=mesh->xend;jx++){ for(int jy=mesh->ystart;jy<=mesh->yend;jy++){ #ifndef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx,jy) - * metric->dx(jx, jy)); + const BoutReal spacingFactor = + 1.0 / (12 * metric->dz(jx, jy) * metric->dx(jx, jy)); #endif const BoutReal *Fxm = f_temp(jx-1, jy); const BoutReal *Fx = f_temp(jx, jy); @@ -1121,29 +1163,27 @@ Field3D bracket(const Field3D &f, const Field3D &g, BRACKET_METHOD method, const BoutReal *Gxp = g_temp(jx+1, jy); for (int jz = 0; jz < mesh->LocalNz; jz++) { #ifdef COORDINATES_USE_3D - const BoutReal spacingFactor = 1.0 / (12 * metric->dz(jx, jy, jz) - * metric->dx(jx, jy, jz)); + const BoutReal spacingFactor = + 1.0 / (12 * metric->dz(jx, jy, jz) * metric->dx(jx, jy, jz)); #endif const int jzp = jz+1 < ncz ? jz + 1 : 0; - //Above is alternative to const int jzp = (jz + 1) % ncz; - const int jzm = jz-1 >= 0 ? jz - 1 : ncz-1; - //Above is alternative to const int jzm = (jz - 1 + ncz) % ncz; + // Above is alternative to const int jzp = (jz + 1) % ncz; + const int jzm = jz - 1 >= 0 ? jz - 1 : ncz - 1; + // Above is alternative to const int jzm = (jz - 1 + ncz) % ncz; // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) - BoutReal Jpp = ((Fx[jzp] - Fx[jzm])*(Gxp[jz] - Gxm[jz]) - - (Fxp[jz] - Fxm[jz])*(Gx[jzp] - Gx[jzm])); + BoutReal Jpp = ((Fx[jzp] - Fx[jzm]) * (Gxp[jz] - Gxm[jz]) + - (Fxp[jz] - Fxm[jz]) * (Gx[jzp] - Gx[jzm])); // J+x - BoutReal Jpx = ( Gxp[jz]*(Fxp[jzp]-Fxp[jzm]) - - Gxm[jz]*(Fxm[jzp]-Fxm[jzm]) - - Gx[jzp]*(Fxp[jzp]-Fxm[jzp]) + - Gx[jzm]*(Fxp[jzm]-Fxm[jzm])) ; + BoutReal Jpx = + (Gxp[jz] * (Fxp[jzp] - Fxp[jzm]) - Gxm[jz] * (Fxm[jzp] - Fxm[jzm]) + - Gx[jzp] * (Fxp[jzp] - Fxm[jzp]) + Gx[jzm] * (Fxp[jzm] - Fxm[jzm])); // Jx+ - BoutReal Jxp = ( Gxp[jzp]*(Fx[jzp]-Fxp[jz]) - - Gxm[jzm]*(Fxm[jz]-Fx[jzm]) - - Gxm[jzp]*(Fx[jzp]-Fxm[jz]) + - Gxp[jzm]*(Fxp[jz]-Fx[jzm])); + BoutReal Jxp = + (Gxp[jzp] * (Fx[jzp] - Fxp[jz]) - Gxm[jzm] * (Fxm[jz] - Fx[jzm]) + - Gxm[jzp] * (Fx[jzp] - Fxm[jz]) + Gxp[jzm] * (Fxp[jz] - Fx[jzm])); result(jx, jy, jz) = (Jpp + Jpx + Jxp) * spacingFactor; } diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 4c56040b24..3d989ff6da 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -36,13 +36,16 @@ namespace FV { for(int j=mesh->ystart;j<=mesh->yend;j++) { for(int k=0;kLocalNz;k++) { // Calculate flux from i to i+1 - - BoutReal fout = 0.5*(a(i,j,k) + a(i+1,j,k)) * (coord->J(i,j,k)*coord->g11(i,j,k) + coord->J(i+1,j,k)*coord->g11(i+1,j,k)) * - (f(i+1,j,k) - f(i,j,k))/(coord->dx(i,j,k) + coord->dx(i+1,j,k)); - - result(i,j,k) += fout / (coord->dx(i,j,k)*coord->J(i,j,k)); - result(i+1,j,k) -= fout / (coord->dx(i+1,j,k)*coord->J(i+1,j,k)); - } + + BoutReal fout = 0.5 * (a(i, j, k) + a(i + 1, j, k)) + * (coord->J(i, j, k) * coord->g11(i, j, k) + + coord->J(i + 1, j, k) * coord->g11(i + 1, j, k)) + * (f(i + 1, j, k) - f(i, j, k)) + / (coord->dx(i, j, k) + coord->dx(i + 1, j, k)); + + result(i, j, k) += fout / (coord->dx(i, j, k) * coord->J(i, j, k)); + result(i + 1, j, k) -= fout / (coord->dx(i + 1, j, k) * coord->J(i + 1, j, k)); + } } @@ -87,39 +90,41 @@ namespace FV { int kp = (k + 1) % mesh->LocalNz; int km = (k - 1 + mesh->LocalNz) % mesh->LocalNz; - BoutReal coef = - 0.5 * (coord->g_23(i, j, k) / SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)) + - coord->g_23(i, j + 1, k) / SQ(coord->J(i, j + 1, k) * coord->Bxy(i, j + 1, k))); - + BoutReal coef = + 0.5 + * (coord->g_23(i, j, k) / SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)) + + coord->g_23(i, j + 1, k) + / SQ(coord->J(i, j + 1, k) * coord->Bxy(i, j + 1, k))); // Calculate Z derivative at y boundary - BoutReal dfdz = 0.25 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - - fup(i, j + 1, km)) / - coord->dz(i, j, k);// is this at right location? + BoutReal dfdz = + 0.25 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) + / coord->dz(i, j, k); // is this at right location? // Y derivative - BoutReal dfdy = 2. * (fup(i, j + 1, k) - fc(i, j, k)) / - (coord->dy(i, j + 1, k) + coord->dy(i, j, k)); + BoutReal dfdy = 2. * (fup(i, j + 1, k) - fc(i, j, k)) + / (coord->dy(i, j + 1, k) + coord->dy(i, j, k)); - BoutReal fout = 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) * - (coord->J(i, j, k) * coord->g23(i, j, k) + - coord->J(i, j + 1, k) * coord->g23(i, j + 1, k)) * - (dfdz - coef * dfdy); + BoutReal fout = 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) + * (coord->J(i, j, k) * coord->g23(i, j, k) + + coord->J(i, j + 1, k) * coord->g23(i, j + 1, k)) + * (dfdz - coef * dfdy); yzresult(i, j, k) = fout / (coord->dy(i, j, k) * coord->J(i, j, k)); // Calculate flux between j and j-1 - dfdz = 0.25 * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - - fdown(i, j - 1, km)) / - coord->dz(i,j,k);// is this at right location? + dfdz = + 0.25 + * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) + / coord->dz(i, j, k); // is this at right location? - dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) / - (coord->dy(i, j, k) + coord->dy(i, j - 1, k)); + dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) + / (coord->dy(i, j, k) + coord->dy(i, j - 1, k)); - fout = 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) * - (coord->J(i, j, k) * coord->g23(i, j, k) + - coord->J(i, j - 1, k) * coord->g23(i, j - 1, k)) * - (dfdz - coef * dfdy); + fout = 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) + * (coord->J(i, j, k) * coord->g23(i, j, k) + + coord->J(i, j - 1, k) * coord->g23(i, j - 1, k)) + * (dfdz - coef * dfdy); yzresult(i, j, k) -= fout / (coord->dy(i, j, k) * coord->J(i, j, k)); } @@ -135,21 +140,22 @@ namespace FV { // Calculate flux between k and k+1 int kp = (k + 1) % mesh->LocalNz; - // Coefficient in front of df/dy term - BoutReal coef = coord->g_23(i, j, k) / (coord->dy(i, j + 1, k) + 2. * coord->dy(i, j, k) + - coord->dy(i, j - 1, k)) / - SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)); - - BoutReal fout = 0.5 * (ac(i, j, k) + ac(i, j, kp)) * coord->g33(i, j, k) * - ( // df/dz - (fc(i, j, kp) - fc(i, j, k)) / coord->dz(i, j, k) - // - g_yz * df/dy / SQ(J*B) - - - coef * (fup(i, j + 1, k) + fup(i, j + 1, kp) - - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); - - yzresult(i, j, k) += fout / coord->dz(i,j,k); - yzresult(i, j, kp) -= fout / coord->dz(i,j,kp); + // Coefficient in front of df/dy term + BoutReal coef = coord->g_23(i, j, k) + / (coord->dy(i, j + 1, k) + 2. * coord->dy(i, j, k) + + coord->dy(i, j - 1, k)) + / SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)); + + BoutReal fout = 0.5 * (ac(i, j, k) + ac(i, j, kp)) * coord->g33(i, j, k) + * ( // df/dz + (fc(i, j, kp) - fc(i, j, k)) / coord->dz(i, j, k) + // - g_yz * df/dy / SQ(J*B) + - coef + * (fup(i, j + 1, k) + fup(i, j + 1, kp) + - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); + + yzresult(i, j, k) += fout / coord->dz(i, j, k); + yzresult(i, j, kp) -= fout / coord->dz(i, j, kp); } } } @@ -314,9 +320,9 @@ namespace FV { for (int k = 0; k < mesh->LocalNz; k++) { // Right boundary common factors - const BoutReal common_factor = 0.25 - * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) - * (coord->J(i, j, j) + coord->J(i, j + 1, k)); + const BoutReal common_factor = + 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, j) + coord->J(i, j + 1, k)); const BoutReal factor_rc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); @@ -325,14 +331,10 @@ namespace FV { // Not on domain boundary // 3rd derivative at right cell boundary - - const BoutReal d3fdx3 = ( - f(i,j+2,k) - - 3.*f(i,j+1,k) - + 3.*f(i,j, k) - - f(i,j-1,k) - ); - + + const BoutReal d3fdx3 = (f(i, j + 2, k) - 3. * f(i, j + 1, k) + + 3. * f(i, j, k) - f(i, j - 1, k)); + result(i,j, k) += d3fdx3 * factor_rc; result(i,j+1,k) -= d3fdx3 * factor_rp; } @@ -342,22 +344,22 @@ namespace FV { for(int k=0;kLocalNz;k++) { // Right boundary common factors - const BoutReal common_factor = 0.25 - * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) - * (coord->J(i, j, j) + coord->J(i, j + 1, k)); + const BoutReal common_factor = + 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, j) + coord->J(i, j + 1, k)); const BoutReal factor_rc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); const BoutReal factor_rp = common_factor / (coord->J(i, j + 1, k) * coord->dy(i, j + 1, k)); - const BoutReal d3fdx3 = -((16. / 5) * 0.5 * - (f(i, j + 1, k) + f(i, j, k)) // Boundary value f_b - - 6. * f(i, j, k) // f_0 - + 4. * f(i, j - 1, k) // f_1 - - (6. / 5) * f(i, j - 2, k) // f_2 - ); - + const BoutReal d3fdx3 = + -((16. / 5) * 0.5 * (f(i, j + 1, k) + f(i, j, k)) // Boundary value f_b + - 6. * f(i, j, k) // f_0 + + 4. * f(i, j - 1, k) // f_1 + - (6. / 5) * f(i, j - 2, k) // f_2 + ); + result(i,j, k) += d3fdx3 * factor_rc; result(i,j+1,k) -= d3fdx3 * factor_rp; } @@ -372,9 +374,9 @@ namespace FV { if ( j != mesh->ystart || !has_lower_boundary ) { for(int k=0;kLocalNz;k++) { - const BoutReal common_factor = 0.25 - * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) - * (coord->J(i, j, k) + coord->J(i, j - 1, k)); + const BoutReal common_factor = + 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, k) + coord->J(i, j - 1, k)); const BoutReal factor_lc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); @@ -382,20 +384,18 @@ namespace FV { common_factor / (coord->J(i, j - 1, k) * coord->dy(i, j - 1, k)); // Not on a domain boundary - const BoutReal d3fdx3 = (f(i, j + 1, k) - - 3. * f(i, j, k) - + 3. * f(i, j - 1, k) - - f(i, j - 2, k)); - + const BoutReal d3fdx3 = (f(i, j + 1, k) - 3. * f(i, j, k) + + 3. * f(i, j - 1, k) - f(i, j - 2, k)); + result(i, j , k) -= d3fdx3 * factor_lc; result(i, j - 1, k) += d3fdx3 * factor_lm; } } else { // On a domain (Y) boundary for(int k=0;kLocalNz;k++) { - const BoutReal common_factor = 0.25 - * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) - * (coord->J(i, j, k) + coord->J(i, j - 1, k)); + const BoutReal common_factor = + 0.25 * (coord->dy(i, j, k) + coord->dy(i, j + 1, k)) + * (coord->J(i, j, k) + coord->J(i, j - 1, k)); const BoutReal factor_lc = common_factor / (coord->J(i, j, k) * coord->dy(i, j, k)); @@ -406,7 +406,7 @@ namespace FV { + 6. * f(i, j, k) // f_0 - 4. * f(i, j + 1, k) // f_1 + (6. / 5) * f(i, j + 2, k) // f_2 - ); + ); result(i, j , k) -= d3fdx3 * factor_lc; result(i, j - 1, k) += d3fdx3 * factor_lm; diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index 6d8c6a06ef..a4c5a44936 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -536,14 +536,13 @@ void Mesh::createDefaultRegions(){ (getRegion3D("RGN_NOBNDRY") + getRegion3D("RGN_XGUARDS") + getRegion3D("RGN_YGUARDS") + getRegion3D("RGN_ZGUARDS")).unique()); - addRegion3D("RGN_UPPER_Y_THIN", - Region(xstart, xend, yend + 1, yend + 1, 0, LocalNz - 1, LocalNy, LocalNz, - maxregionblocksize)); - addRegion3D("RGN_LOWER_Y_THIN", - Region(xstart, xend, ystart + 1, ystart + 1, 0, LocalNz - 1, LocalNy, LocalNz, - maxregionblocksize)); - - + addRegion3D("RGN_UPPER_Y_THIN", + Region(xstart, xend, yend + 1, yend + 1, 0, LocalNz - 1, LocalNy, + LocalNz, maxregionblocksize)); + addRegion3D("RGN_LOWER_Y_THIN", + Region(xstart, xend, ystart + 1, ystart + 1, 0, LocalNz - 1, LocalNy, + LocalNz, maxregionblocksize)); + //2D regions addRegion2D("RGN_ALL", Region(0, LocalNx - 1, 0, LocalNy - 1, 0, 0, LocalNy, 1, maxregionblocksize)); @@ -572,12 +571,10 @@ void Mesh::createDefaultRegions(){ (getRegion2D("RGN_NOBNDRY") + getRegion2D("RGN_XGUARDS") + getRegion2D("RGN_YGUARDS") + getRegion2D("RGN_ZGUARDS")).unique()); - addRegion2D("RGN_UPPER_Y_THIN", - Region(xstart, xend, yend + 1, yend + 1, 0, -1, LocalNy, 1, - maxregionblocksize)); - addRegion2D("RGN_LOWER_Y_THIN", - Region(xstart, xend, ystart + 1, ystart + 1, 0, -1, LocalNy, 1, - maxregionblocksize)); + addRegion2D("RGN_UPPER_Y_THIN", Region(xstart, xend, yend + 1, yend + 1, 0, -1, + LocalNy, 1, maxregionblocksize)); + addRegion2D("RGN_LOWER_Y_THIN", Region(xstart, xend, ystart + 1, ystart + 1, 0, + -1, LocalNy, 1, maxregionblocksize)); // Perp regions addRegionPerp("RGN_ALL", Region(0, LocalNx - 1, 0, 0, 0, LocalNz - 1, 1, diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index fdd379e1e9..df73924988 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -210,7 +210,6 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* bou if ((t_z < 0.0) || (t_z > 1.0)) throw BoutException("t_z={:e} out of range at ({:d},{:d},{:d})", t_z, x, y, z); - //---------------------------------------- // Boundary stuff // @@ -262,11 +261,14 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* bou // Invert 2x2 matrix to get change in index BoutReal dx = (dZ_dz * dR - dR_dz * dZ) / det; BoutReal dz = (dR_dx * dZ - dZ_dx * dR) / det; - boundary->add_point(x, y, z, - x + dx, y + 0.5*offset, z + dz, // Intersection point in local index space - 0.5*coord.dy(x,y,z), //sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection - PI // Right-angle intersection - ); + boundary->add_point( + x, y, z, x + dx, y + 0.5 * offset, + z + dz, // Intersection point in local index space + 0.5 + * coord.dy(x, y, + z), // sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection + PI // Right-angle intersection + ); } } } diff --git a/src/sys/boutexception.cxx b/src/sys/boutexception.cxx index 1f25c32ea9..edede438c9 100644 --- a/src/sys/boutexception.cxx +++ b/src/sys/boutexception.cxx @@ -54,7 +54,8 @@ std::string BoutException::getBacktrace() const { if (dladdr(trace[i],&info)){ // Additionally, check whether this is the default offset for an executable if (info.dli_fbase != reinterpret_cast(0x400000)) - ptr=reinterpret_cast(reinterpret_cast(trace[i])-reinterpret_cast(info.dli_fbase)); + ptr = reinterpret_cast(reinterpret_cast(trace[i]) + - reinterpret_cast(info.dli_fbase)); } // Pipe stderr to /dev/null to avoid cluttering output diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index f17f1d853f..6b18615a80 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -58,7 +58,8 @@ ////////////// X DERIVATIVE ///////////////// -Field3D DDX(const Field3D &f, CELL_LOC outloc, const std::string &method, const std::string& region) { +Field3D DDX(const Field3D& f, CELL_LOC outloc, const std::string& method, + const std::string& region) { return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } @@ -75,8 +76,8 @@ Field3D DDY(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dy; } -Coordinates::metric_field_type DDY(const Field2D &f, CELL_LOC outloc, const std::string &method, - const std::string& region) { +Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { return f.getCoordinates(outloc)->DDY(f, outloc, method, region); } @@ -88,8 +89,9 @@ Field3D DDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dz; } -Coordinates::metric_field_type DDZ(const Field2D &f, CELL_LOC UNUSED(outloc), const std::string - &UNUSED(method), const std::string& UNUSED(region)) { +Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC UNUSED(outloc), + const std::string& UNUSED(method), + const std::string& UNUSED(region)) { auto tmp = Field2D(0., f.getMesh()); tmp.setLocation(f.getLocation()); return tmp; @@ -166,7 +168,8 @@ Field3D D2DX2(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { Coordinates *coords = f.getCoordinates(outloc); auto result = @@ -203,7 +206,8 @@ Field3D D2DY2(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { Coordinates *coords = f.getCoordinates(outloc); auto result = @@ -226,7 +230,8 @@ Field3D D2DZ2(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { return bout::derivatives::index::D2DZ2(f, outloc, method, region) / SQ(f.getCoordinates(outloc)->dz); } @@ -242,7 +247,8 @@ Field3D D4DX4(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { return bout::derivatives::index::D4DX4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dx)); } @@ -254,7 +260,8 @@ Field3D D4DY4(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { return bout::derivatives::index::D4DY4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dy)); } @@ -266,7 +273,8 @@ Field3D D4DZ4(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { return bout::derivatives::index::D4DZ4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dz)); } @@ -282,9 +290,11 @@ Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc, * * ** Communicates and applies boundary in X. */ -Coordinates::metric_field_type D2DXDY(const Field2D& f, CELL_LOC outloc, const std::string& method, - const std::string& region, const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { +Coordinates::metric_field_type D2DXDY(const Field2D& f, CELL_LOC outloc, + const std::string& method, + const std::string& region, + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { std::string dy_region = dfdy_region.empty() ? region : dfdy_region; // If staggering in x, take y-derivative at f's location. @@ -326,7 +336,8 @@ Field3D D2DXDY(const Field3D& f, CELL_LOC outloc, const std::string& method, } Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { #ifdef COORDINATES_USE_3D Field3D tmp{f}; return D2DXDZ(tmp, outloc, method, region); @@ -350,7 +361,8 @@ Field3D D2DXDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { + const std::string& method, + const std::string& region) { #ifdef COORDINATES_USE_3D Field3D tmp{f}; return D2DYDZ(tmp, outloc, method, region); @@ -380,8 +392,8 @@ Field3D D2DYDZ(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string ////////////// X DERIVATIVE ///////////////// /// Special case where both arguments are 2D. -Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, - CELL_LOC outloc, const std::string& method, +Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { return bout::derivatives::index::VDDX(v, f, outloc, method, region) / f.getCoordinates(outloc)->dx; @@ -397,9 +409,9 @@ Field3D VDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ////////////// Y DERIVATIVE ///////////////// // special case where both are 2D -Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, - CELL_LOC outloc, const std::string& method, - const std::string& region) { +Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, + const std::string& region) { return bout::derivatives::index::VDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; } @@ -414,16 +426,16 @@ Field3D VDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ////////////// Z DERIVATIVE ///////////////// // special case where both are 2D -Coordinates::metric_field_type VDDZ(const Field2D &v, const Field2D &f, - CELL_LOC outloc, const std::string &method, +Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { return bout::derivatives::index::VDDZ(v, f, outloc, method, region) / f.getCoordinates(outloc)->dz; } // Note that this is zero because no compression is included -Coordinates::metric_field_type VDDZ(const Field3D &v, const Field2D& f, - CELL_LOC outloc, const std::string& method, +Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { #ifdef COORDINATES_USE_3D Field3D tmp{f}; @@ -447,8 +459,8 @@ Field3D VDDZ(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str /******************************************************************************* * Flux conserving schemes *******************************************************************************/ -Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, - CELL_LOC outloc, const std::string& method, +Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { return bout::derivatives::index::FDDX(v, f, outloc, method, region) / f.getCoordinates(outloc)->dx; @@ -462,8 +474,8 @@ Field3D FDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ///////////////////////////////////////////////////////////////////////// -Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, - CELL_LOC outloc, const std::string& method, +Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { return bout::derivatives::index::FDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; @@ -477,8 +489,8 @@ Field3D FDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ///////////////////////////////////////////////////////////////////////// -Coordinates::metric_field_type FDDZ(const Field2D &v, const Field2D &f, - CELL_LOC outloc, const std::string &method, +Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method, const std::string& region) { return bout::derivatives::index::FDDZ(v, f, outloc, method, region) / f.getCoordinates(outloc)->dz; diff --git a/tests/MMS/diffusion/diffusion.cxx b/tests/MMS/diffusion/diffusion.cxx index 2e8e1f0f3b..ec0aae75a4 100644 --- a/tests/MMS/diffusion/diffusion.cxx +++ b/tests/MMS/diffusion/diffusion.cxx @@ -77,7 +77,8 @@ int physics_init(bool UNUSED(restarting)) { for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ for (int zk = 0; zk < mesh->LocalNz; zk++) { output.write("Initial condition at {:d},{:d},{:d}\n", xi, yj, zk); - N(xi, yj, zk) = MS(0.,mesh->GlobalX(xi)*Lx,mesh->GlobalY(yj)*Ly,coord->dz(xi, yj, zk)*zk); + N(xi, yj, zk) = MS(0., mesh->GlobalX(xi) * Lx, mesh->GlobalY(yj) * Ly, + coord->dz(xi, yj, zk) * zk); } } } @@ -141,7 +142,7 @@ void solution(Field3D &f, BoutReal t, BoutReal UNUSED(D)) { x = mesh->GlobalX(xi); y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - z = coord->dz(xi, yj, zk)*zk; + z = coord->dz(xi, yj, zk) * zk; output.write("Solution at {:d},{:d},{:d}\n", xi, yj, zk); f(xi, yj, zk) = MS(t,x,y,z); } diff --git a/tests/MMS/diffusion2/diffusion.cxx b/tests/MMS/diffusion2/diffusion.cxx index 8af7e1b9ef..3f228b3468 100644 --- a/tests/MMS/diffusion2/diffusion.cxx +++ b/tests/MMS/diffusion2/diffusion.cxx @@ -22,8 +22,9 @@ int physics_init(bool UNUSED(restarting)) { coords->dx = Lx/(mesh->GlobalNx - 2*mesh->xstart); coords->dy = Ly/(mesh->GlobalNy - 2*mesh->ystart); - - output.write("SIZES: {:d}, {:d}, {:e}\n", mesh->GlobalNy, (mesh->GlobalNy - 2*mesh->ystart), coords->dy(0,0,0)); + + output.write("SIZES: {:d}, {:d}, {:e}\n", mesh->GlobalNy, + (mesh->GlobalNy - 2 * mesh->ystart), coords->dy(0, 0, 0)); SAVE_ONCE2(Lx,Ly); diff --git a/tests/MMS/spatial/diffusion/diffusion.cxx b/tests/MMS/spatial/diffusion/diffusion.cxx index bb32827897..4c9568363e 100644 --- a/tests/MMS/spatial/diffusion/diffusion.cxx +++ b/tests/MMS/spatial/diffusion/diffusion.cxx @@ -23,8 +23,9 @@ int physics_init(bool UNUSED(restarting)) { coords->dx = Lx/(mesh->GlobalNx - 2*mesh->xstart); coords->dy = Ly/(mesh->GlobalNy - 2*mesh->ystart); - - output.write("SIZES: {:d}, {:d}, {:e}\n", mesh->GlobalNy, (mesh->GlobalNy - 2*mesh->ystart), coords->dy(0,0,0)); + + output.write("SIZES: {:d}, {:d}, {:e}\n", mesh->GlobalNy, + (mesh->GlobalNy - 2 * mesh->ystart), coords->dy(0, 0, 0)); SAVE_ONCE2(Lx,Ly); diff --git a/tests/MMS/wave-1d/wave.cxx b/tests/MMS/wave-1d/wave.cxx index b55710511d..6518dc56d6 100644 --- a/tests/MMS/wave-1d/wave.cxx +++ b/tests/MMS/wave-1d/wave.cxx @@ -77,8 +77,10 @@ class Wave1D : public PhysicsModel { for (int xi = mesh->xstart; xi < mesh->xend + 1; xi++) { for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ for (int zk = 0; zk < mesh->LocalNz; zk++) { - f(xi, yj, zk) = MS_f(0.,mesh->GlobalX(xi),mesh->GlobalY(yj),coord->dz(xi,yj,zk)*zk); - g(xi, yj, zk) = MS_g(0.,0.5*(mesh->GlobalX(xi)+mesh->GlobalX(xi-1)),mesh->GlobalY(yj),coord->dz(xi,yj,zk)*zk); + f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), + coord->dz(xi, yj, zk) * zk); + g(xi, yj, zk) = MS_g(0., 0.5 * (mesh->GlobalX(xi) + mesh->GlobalX(xi - 1)), + mesh->GlobalY(yj), coord->dz(xi, yj, zk) * zk); output.write("{:d}: {:e}\n", xi, g(xi, yj, zk)); } @@ -88,8 +90,10 @@ class Wave1D : public PhysicsModel { for (int xi = mesh->xstart; xi < mesh->xend + 1; xi++) { for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++) { for (int zk = 0; zk < mesh->LocalNz; zk++) { - f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), coord->dz(xi, yj, zk) * zk); - g(xi, yj, zk) = MS_g(0., mesh->GlobalX(xi), mesh->GlobalY(yj), coord->dz(xi, yj, zk) * zk); + f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), + coord->dz(xi, yj, zk) * zk); + g(xi, yj, zk) = MS_g(0., mesh->GlobalX(xi), mesh->GlobalY(yj), + coord->dz(xi, yj, zk) * zk); } } } @@ -172,7 +176,7 @@ const Field3D Wave1D::solution_f(BoutReal t) { BoutReal x = mesh->GlobalX(xi); BoutReal y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal z = coord->dz(xi,yj,zk)*zk; + BoutReal z = coord->dz(xi, yj, zk) * zk; S(xi, yj, zk) = MS_f(t,x,y,z); } } @@ -230,7 +234,7 @@ const Field3D Wave1D::solution_g(BoutReal t) { } BoutReal y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal z = coord->dz(xi,yj,zk)*zk; + BoutReal z = coord->dz(xi, yj, zk) * zk; S(xi, yj, zk) = MS_g(t,x,y,z); } } diff --git a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx index 3bd6471ead..e289007b77 100644 --- a/tests/integrated/test-laplacexy-short/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy-short/test-laplacexy.cxx @@ -62,9 +62,10 @@ int main(int argc, char** argv) { Field2D rhs, rhs_check; if (include_y_derivs) { - rhs = a*DC(Laplace_perp(f)) + DC(Grad_perp(a)*Grad_perp(f)) + b*f; + rhs = a * DC(Laplace_perp(f)) + DC(Grad_perp(a) * Grad_perp(f)) + b * f; } else { - rhs = a*DC(Delp2(f, CELL_DEFAULT, false)) + DC(coords->g11*DDX(a)*DDX(f)) + b*f; + rhs = + a * DC(Delp2(f, CELL_DEFAULT, false)) + DC(coords->g11 * DDX(a) * DDX(f)) + b * f; } laplacexy.setCoefs(a, b); @@ -78,9 +79,10 @@ int main(int argc, char** argv) { mesh->communicate(sol); if (include_y_derivs) { - rhs_check = a*DC(Laplace_perp(sol)) + DC(Grad_perp(a)*Grad_perp(sol)) + b*sol; + rhs_check = a * DC(Laplace_perp(sol)) + DC(Grad_perp(a) * Grad_perp(sol)) + b * sol; } else { - rhs_check = a*DC(Delp2(sol, CELL_DEFAULT, false)) + DC(coords->g11*DDX(a)*DDX(sol)) + b*sol; + rhs_check = a * DC(Delp2(sol, CELL_DEFAULT, false)) + + DC(coords->g11 * DDX(a) * DDX(sol)) + b * sol; } dump.add(a, "a"); diff --git a/tests/integrated/test-laplacexz/test-laplacexz.cxx b/tests/integrated/test-laplacexz/test-laplacexz.cxx index 42c126d339..79e77eb741 100644 --- a/tests/integrated/test-laplacexz/test-laplacexz.cxx +++ b/tests/integrated/test-laplacexz/test-laplacexz.cxx @@ -11,8 +11,8 @@ #include #include -#include #include +#include int main(int argc, char** argv) { BoutInitialise(argc, argv); @@ -20,21 +20,21 @@ int main(int argc, char** argv) { auto inv = LaplaceXZ::create(mesh); auto coord = bout::globals::mesh->getCoordinates(); - coord->g13 = 1.8; //test off-diagonal components with nonzero value + coord->g13 = 1.8; // test off-diagonal components with nonzero value // create some input field - Field3D f = FieldFactory::get()->create3D("f", Options::getRoot(), mesh); + Field3D f = FieldFactory::get()->create3D("f", Options::getRoot(), mesh); // Calculate the Laplacian with non-zero g13 - Field3D g = coord->g11*D2DX2(f) + coord->g13*D2DXDZ(f) + coord->g33*D2DZ2(f); + Field3D g = coord->g11 * D2DX2(f) + coord->g13 * D2DXDZ(f) + coord->g33 * D2DZ2(f); + + inv->setCoefs(Field2D(1.0), Field2D(0.0)); + + Field3D f2 = inv->solve(g, 0.0); // Invert the Laplacian. - inv->setCoefs(Field2D(1.0),Field2D(0.0)); - - Field3D f2 = inv->solve(g,0.0); // Invert the Laplacian. - - SAVE_ONCE3(f,f2,g); + SAVE_ONCE3(f, f2, g); - coord->g13 = 0.0; //reset to 0.0 for original laplacexz test + coord->g13 = 0.0; // reset to 0.0 for original laplacexz test // Now the normal test. output.write("Setting coefficients\n"); diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx b/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx index 5730bc63c3..3a1e7d365c 100644 --- a/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx +++ b/tests/integrated/test-petsc_laplace_MAST-grid/test_petsc_laplace_MAST_grid.cxx @@ -662,9 +662,9 @@ int main(int argc, char** argv) { dump.write(); dump.close(); - + output << "\nFinished running test.\n"; - + MPI_Barrier(BoutComm::get()); // Wait for all processors to write data } BoutFinalise(); diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index d483bbf162..2cf318c280 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -64,9 +64,9 @@ class GridFromOptionsTest : public ::testing::Test { &mesh_from_options); expected_metric = #ifdef COORDINATES_USE_3D - expected_3d; + expected_3d; #else - expected_2d; + expected_2d; #endif } @@ -373,11 +373,12 @@ TEST_F(GridFromOptionsTest, CoordinatesXlowInterp) { auto coords = mesh_from_options.getCoordinates(CELL_XLOW); - Coordinates::metric_field_type expected_xlow = makeField( - [](Coordinates::metric_field_type::ind_type& index) { - return index.x() - 0.5 + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; - }, - &mesh_from_options); + Coordinates::metric_field_type expected_xlow = + makeField( + [](Coordinates::metric_field_type::ind_type& index) { + return index.x() - 0.5 + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; + }, + &mesh_from_options); mesh_from_options.communicate(expected_xlow); diff --git a/tests/unit/mesh/parallel/test_shiftedmetric.cxx b/tests/unit/mesh/parallel/test_shiftedmetric.cxx index 6a2aa56eff..cdf8c6dd59 100644 --- a/tests/unit/mesh/parallel/test_shiftedmetric.cxx +++ b/tests/unit/mesh/parallel/test_shiftedmetric.cxx @@ -42,9 +42,8 @@ class ShiftedMetricTest : public ::testing::Test { Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, false)); auto coords = mesh->getCoordinates(); - coords->setParallelTransform( - bout::utils::make_unique(*mesh, CELL_CENTRE, zShift, - coords->zlength()(0,0))); + coords->setParallelTransform(bout::utils::make_unique( + *mesh, CELL_CENTRE, zShift, coords->zlength()(0, 0))); Field3D input_temp{mesh}; diff --git a/tests/unit/solver/test_solver.cxx b/tests/unit/solver/test_solver.cxx index df133d528f..0e7d33a5a2 100644 --- a/tests/unit/solver/test_solver.cxx +++ b/tests/unit/solver/test_solver.cxx @@ -256,9 +256,9 @@ TEST_F(SolverTest, AddVector2D) { Vector2D vector1{}, vector2{}; EXPECT_NO_THROW(solver.add(vector1, "vector")); #ifndef COORDINATES_USE_3D - constexpr int n2d=3, n3d=0; + constexpr int n2d = 3, n3d = 0; #else - constexpr int n2d=0, n3d=3; + constexpr int n2d = 0, n3d = 3; #endif EXPECT_EQ(solver.n2Dvars(), n2d); EXPECT_EQ(solver.n3Dvars(), n3d); @@ -274,8 +274,8 @@ TEST_F(SolverTest, AddVector2D) { vector2.covariant = false; EXPECT_NO_THROW(solver.add(vector2, "another_vector")); - EXPECT_EQ(solver.n2Dvars(), n2d*2); - EXPECT_EQ(solver.n3Dvars(), n3d*2); + EXPECT_EQ(solver.n2Dvars(), n2d * 2); + EXPECT_EQ(solver.n3Dvars(), n3d * 2); EXPECT_TRUE(IsFieldEqual(vector2.x, 8.0)); EXPECT_TRUE(IsFieldEqual(vector2.y, 9.0)); EXPECT_TRUE(IsFieldEqual(vector2.z, 10.0)); @@ -387,9 +387,9 @@ TEST_F(SolverTest, ConstraintVector2D) { Vector2D vector1{}, vector2{}; EXPECT_NO_THROW(solver.constraint(vector1, vector1, "vector")); #ifndef COORDINATES_USE_3D - constexpr int n2d=3, n3d=0; + constexpr int n2d = 3, n3d = 0; #else - constexpr int n2d=0, n3d=3; + constexpr int n2d = 0, n3d = 3; #endif EXPECT_EQ(solver.n2Dvars(), n2d); EXPECT_EQ(solver.n3Dvars(), n3d); @@ -412,8 +412,8 @@ TEST_F(SolverTest, ConstraintVector2D) { vector2.covariant = false; EXPECT_NO_THROW(solver.constraint(vector2, vector2, "another_vector")); - EXPECT_EQ(solver.n2Dvars(), n2d*2); - EXPECT_EQ(solver.n3Dvars(), n3d*2); + EXPECT_EQ(solver.n2Dvars(), n2d * 2); + EXPECT_EQ(solver.n3Dvars(), n3d * 2); const auto expected_names = std::vector{"vector", "another_vector"}; EXPECT_EQ(solver.listVector2DNames(), expected_names); From ced8eaf4e92541e40f230246c3f0faae3d418e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 26 May 2020 10:56:26 +0200 Subject: [PATCH 157/293] Update documentation for 3D metrics --- manual/sphinx/developer_docs/mesh.rst | 42 ++++++++++++---------- manual/sphinx/user_docs/input_grids.rst | 48 +++++++++++++------------ 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/manual/sphinx/developer_docs/mesh.rst b/manual/sphinx/developer_docs/mesh.rst index 396e49229b..5ad6ae7f62 100644 --- a/manual/sphinx/developer_docs/mesh.rst +++ b/manual/sphinx/developer_docs/mesh.rst @@ -261,13 +261,16 @@ index. Differencing ------------ -The mesh spacing is given by the public members `Mesh::dx`, `Mesh::dy` -and `Mesh::dx`:: +The mesh spacing is given by the public members `Coorinates::dx`, +`Coordinates::dy` and `Coordinates::dz`:: // These used for differential operators - Field2D dx, dy; - Field2D d2x, d2y; // 2nd-order correction for non-uniform meshes - BoutReal zlength, dz; // Derived from options (in radians) + FieldMetric dx, dy, dz; + FieldMetric d2x, d2y; // 2nd-order correction for non-uniform meshes + Field2D zlength(); // Computed from dz + +`Coordinates::FieldMetric` can be either `Field2D` or if BOUT++ has +been configured with `--enable-metric-3d` then a `Field3D`. Metrics ------- @@ -277,43 +280,45 @@ details are handled by `Coordinates`. The contravariant and covariant metric tensor components are public members of `Coordinates`:: // Contravariant metric tensor (g^{ij}) - Field2D g11, g22, g33, g12, g13, g23; // These are read in grid.cxx + FieldMetric g11, g22, g33, g12, g13, g23; // These are read in grid.cxx // Covariant metric tensor - Field2D g_11, g_22, g_33, g_12, g_13, g_23; + FieldMetric g_11, g_22, g_33, g_12, g_13, g_23; int calcCovariant(); // Invert contravatiant metric to get covariant int calcContravariant(); // Invert covariant metric to get contravariant If only one of these sets is modified by an external code, then -`Coordinates::calcCovariant` and `Coordinates::calcContravariant` can -be used to calculate the other (uses Gauss-Jordan currently). +`Coordinates::calcCovariant()` and `Coordinates::calcContravariant()` +can be used to calculate the other (uses Gauss-Jordan currently). From the metric tensor components, `Coordinates` calculates several other useful quantities:: int jacobian(); // Calculate J and Bxy - Field2D J; // Jacobian - Field2D Bxy; // Magnitude of B = nabla z times nabla x + FieldMetric J; // Jacobian + FieldMetric Bxy; // Magnitude of B = nabla z times nabla x /// Calculate differential geometry quantities from the metric tensor int geometry(); // Christoffel symbol of the second kind (connection coefficients) - Field2D G1_11, G1_22, G1_33, G1_12, G1_13; - Field2D G2_11, G2_22, G2_33, G2_12, G2_23; - Field2D G3_11, G3_22, G3_33, G3_13, G3_23; + FieldMetric G1_11, G1_22, G1_33, G1_12, G1_13; + FieldMetric G2_11, G2_22, G2_33, G2_12, G2_23; + FieldMetric G3_11, G3_22, G3_33, G3_13, G3_23; - Field2D G1, G2, G3; + FieldMetric G1, G2, G3; These quantities are public and accessible everywhere, but this is because they are needed in a lot of the code. They shouldn’t change -after initialisation, unless the physics model starts doing fancy things -with deforming meshes. +after initialisation, unless the physics model starts doing fancy +things with deforming meshes. In that case it is up to the user to +ensure they are updated. Miscellaneous ------------- +TODO: Check this is up-to-date! There are some public members of `Mesh` which are there for some specific task and don’t really go anywhere else (yet). @@ -337,6 +342,7 @@ twist-shift location, with ``0`` meaning FFT during communication. Since this must be 0 at the moment it’s fairly redundant and should be removed. -A (currently experimental) feature is:: +A feature is:: bool StaggerGrids; ///< Enable staggered grids (Centre, Lower). Otherwise all vars are cell centred (default). + diff --git a/manual/sphinx/user_docs/input_grids.rst b/manual/sphinx/user_docs/input_grids.rst index 501d6e57cc..7751b99be3 100644 --- a/manual/sphinx/user_docs/input_grids.rst +++ b/manual/sphinx/user_docs/input_grids.rst @@ -20,11 +20,12 @@ a simple mesh can be created using options. dx = 0.1 # X mesh spacing dy = 0.1 # Y mesh spacing -The above options will create a :math:`260\times 256` mesh in X and Y -(MZ option sets Z resolution), with mesh spacing of :math:`0.1` in both -directions. By default the coordinate system is Cartesian (metric tensor -is the identity matrix), but this can be changed by specifying the -metric tensor components. +The above options will create a :math:`256\times 256` mesh in X and Y, +assuming there are 2 guard cells in X direction. The Z resolution can +be specified with MZ. The mesh spacing of :math:`0.1` in both +directions. By default the coordinate system is Cartesian (metric +tensor is the identity matrix), but this can be changed by specifying +the metric tensor components. Integer quantities such as ``nx`` can be numbers (like “260”), or expressions (like “256 + 2\*MXG”). @@ -40,15 +41,15 @@ boundary but ``z`` does not (since it is usually periodic): mxg = 2 -Note that the variable ``nz`` can be used before its definition; all -variables are first read, and then processed afterwards. +Note that the order of the defintion within a section isn't important, +variables can be used before they are defined. All variables are first +read, and only processed if they are used. -All expressions are calculated in floating point and then -converted to an integer. The conversion is -done by rounding to the nearest integer, but throws an error if the -floating point value is not within 1e-3 of an integer. This is to minimise -unexpected behaviour. If you want to round any result to an integer, -use the ``round`` function: +All expressions are calculated in floating point and then converted to +an integer. The conversion is done by rounding to the nearest integer, +but throws an error if the floating point value is not within 1e-3 of +an integer. This is to minimise unexpected behaviour. If you want to +round any result to an integer, use the ``round`` function: .. code-block:: cfg @@ -102,15 +103,19 @@ not found, a warning will be printed and the default values used. - X and Y grid sizes (integers) ``nx`` and ``ny`` **REQUIRED** -- Differencing quantities in 2D arrays ``dx[nx][ny]`` and - ``dy[nx][ny]``. If these are not found they will be set to 1. +- Differencing quantities in 2D/3D arrays ``dx(nx,ny[,nz])``, + ``dy(nx,ny[,nz])`` and ``dz(nx,ny[,nz])``. If these are not found + they will be set to 1. Note that in earlier versions of BOUT++, + `dz` was a constant. To allow variation in `z` direction, BOUT++ + has to be configured `--enable-metric-3d`, otherwise 2D fields are + used for the metric fields. -- Diagonal terms of the metric tensor :math:`g^{ij}` ``g11[nx][ny]``, - ``g22[nx][ny]``, and ``g33[nx][ny]``. If not found, these will be set +- Diagonal terms of the metric tensor :math:`g^{ij}` ``g11(nx,ny[,nz])``, + ``g22(nx,ny[,nz])``, and ``g33(nx,ny[,nz])``. If not found, these will be set to 1. -- Off-diagonal metric tensor :math:`g^{ij}` elements ``g12[nx][ny]``, - ``g13[nx][ny]``, and ``g23[nx][ny]``. If not found, these will be set +- Off-diagonal metric tensor :math:`g^{ij}` elements ``g12(nx,ny[,nz])``, + ``g13(nx,ny[,nz])``, and ``g23(nx,ny[,nz])``. If not found, these will be set to 0. - Z shift for interpolation between field-aligned coordinates and @@ -119,7 +124,7 @@ not found, a warning will be printed and the default values used. ``ShiftXderivs`` in ``mesh/mesh.hxx`` is enabled. ``ShiftXderivs`` can be set in the root section of ``BOUT.inp`` as ``ShiftXderivs = true``. The shifts must be provided in the gridfile - in a field ``zshift[nx][ny]``. If not found, ``zshift`` is set to + in a field ``zshift(nx,ny)``. If not found, ``zshift`` is set to zero. The remaining quantities determine the topology of the grid. These are @@ -152,8 +157,7 @@ you’re not interested in tokamaks then you can skip to the next section. The directory ``tokamak_grids`` contains code to generate input grid files for tokamaks. These can be used by the ``2fluid`` and -``highbeta_reduced`` modules, and are (mostly) compatible with inputs to -the BOUT-06 code. +``highbeta_reduced`` modules. .. _sec-bout-topology: From 0030cf89f7e70aad809fa1ca322dffef46cacac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 13:19:50 +0200 Subject: [PATCH 158/293] Revert blobl2d-laplacexz changes This reverts blob2d-laplacexz part of commit 724fed77a39f04134a7d99a492c1b4eeb242f35e. --- examples/blob2d-laplacexz/blob2d.cxx | 24 +++++------------------- examples/blob2d-laplacexz/data/BOUT.inp | 5 ++--- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/examples/blob2d-laplacexz/blob2d.cxx b/examples/blob2d-laplacexz/blob2d.cxx index 72f673f582..8382b75ba3 100644 --- a/examples/blob2d-laplacexz/blob2d.cxx +++ b/examples/blob2d-laplacexz/blob2d.cxx @@ -110,7 +110,6 @@ class Blob2D : public PhysicsModel { } int rhs(BoutReal UNUSED(t)) { - // Coordinates *coord = mesh->getCoordinates(); // Run communications //////////////////////////////////////////////////////////////////////////// @@ -140,15 +139,8 @@ class Blob2D : public PhysicsModel { ///////////////////////////////////////////////////////////////////////////// ddt(n) = -bracket(phi, n, BRACKET_SIMPLE) // ExB term - + 2 * DDZ(n) * (rho_s / R_c); // Curvature term - ddt(n) += D_n * Delp2(n, CELL_DEFAULT, false); - - // if(coord->is3D()){ - // ddt(n) += Div_Perp_Lap_FV(D_n, n); // Diffusion term - // }else{ - // ddt(n) += D_n*Delp2(n); - // } - + + 2 * DDZ(n) * (rho_s / R_c) // Curvature term + + D_n * Delp2(n); // Diffusion term if (compressible) { ddt(n) -= 2 * n * DDZ(phi) * (rho_s / R_c); // ExB Compression term } @@ -162,15 +154,9 @@ class Blob2D : public PhysicsModel { ///////////////////////////////////////////////////////////////////////////// ddt(omega) = -bracket(phi, omega, BRACKET_SIMPLE) // ExB term - + 2 * DDZ(n) * (rho_s / R_c) / n; // Curvature term - ddt(omega) += - D_vort * Delp2(omega, CELL_DEFAULT, false) / n; // Viscous diffusion term - - // if(coord->is3D()){ - // ddt(omega) += Div_Perp_Lap_FV(D_vort ,omega) / n ; // Viscous diffusion term - // }else{ - // ddt(omega) += D_vort * Delp2(omega)/n; // Viscous diffusion term - // } + + 2 * DDZ(n) * (rho_s / R_c) / n // Curvature term + + D_vort * Delp2(omega) / n // Viscous diffusion term + ; if (sheath) { ddt(omega) += phi * (rho_s / L_par); diff --git a/examples/blob2d-laplacexz/data/BOUT.inp b/examples/blob2d-laplacexz/data/BOUT.inp index 70eb1360e8..a11be5d365 100644 --- a/examples/blob2d-laplacexz/data/BOUT.inp +++ b/examples/blob2d-laplacexz/data/BOUT.inp @@ -9,12 +9,12 @@ NOUT = 50 # number of time-steps TIMESTEP = 1e2 # time between outputs MXG = 2 -MYG = 2 # No y derivatives, so no guard cells needed in y +MYG = 0 # No y derivatives, so no guard cells needed in y [mesh] nx = 68 -ny = 2 +ny = 1 nz = 64 dx = 2.0 @@ -71,7 +71,6 @@ factor_package = superlu_dist type = petsc inner_boundary_flags=2 - ################################################## # general settings for the model From b446982aec96ffc356a4be83743d3cb0d17d1499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 13:33:15 +0200 Subject: [PATCH 159/293] Remove some outdated documentation --- manual/sphinx/developer_docs/mesh.rst | 32 --------------------------- 1 file changed, 32 deletions(-) diff --git a/manual/sphinx/developer_docs/mesh.rst b/manual/sphinx/developer_docs/mesh.rst index 5ad6ae7f62..8909dac288 100644 --- a/manual/sphinx/developer_docs/mesh.rst +++ b/manual/sphinx/developer_docs/mesh.rst @@ -314,35 +314,3 @@ because they are needed in a lot of the code. They shouldn’t change after initialisation, unless the physics model starts doing fancy things with deforming meshes. In that case it is up to the user to ensure they are updated. - -Miscellaneous -------------- - -TODO: Check this is up-to-date! -There are some public members of `Mesh` which are there for some -specific task and don’t really go anywhere else (yet). - -To perform radial derivatives in tokamak geometry, interpolation is -needed in the Z direction. This is done by shifting in Z by a phase -factor, performing the derivatives, then shifting back. The following -public variables are currently used for this:: - - bool ShiftXderivs; // Use shifted X derivatives - int ShiftOrder; // Order of shifted X derivative interpolation - Field2D zShift; // Z shift for each point (radians) - - Field2D ShiftTorsion; // d / dx. Needed for vector differentials (Curl) - Field2D IntShiftTorsion; // Integrated shear (I in BOUT notation) - bool IncIntShear; // Include integrated shear (if shifting X) - - int TwistOrder; // Order of twist-shift interpolation - -This determines what order method to use for the interpolation at the -twist-shift location, with ``0`` meaning FFT during communication. Since -this must be 0 at the moment it’s fairly redundant and should be -removed. - -A feature is:: - - bool StaggerGrids; ///< Enable staggered grids (Centre, Lower). Otherwise all vars are cell centred (default). - From 5fc0a7f0eb6d2784768ed4d05f92cfde5e150c63 Mon Sep 17 00:00:00 2001 From: johnomotani Date: Sun, 31 May 2020 13:40:43 +0200 Subject: [PATCH 160/293] Improve docs --- manual/sphinx/user_docs/input_grids.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/manual/sphinx/user_docs/input_grids.rst b/manual/sphinx/user_docs/input_grids.rst index 7751b99be3..57b570f4fb 100644 --- a/manual/sphinx/user_docs/input_grids.rst +++ b/manual/sphinx/user_docs/input_grids.rst @@ -119,13 +119,11 @@ not found, a warning will be printed and the default values used. to 0. - Z shift for interpolation between field-aligned coordinates and - shifted coordinates (see ``manual/coordinates.pdf``). Perpendicular - differential operators are calculated in shifted coordinates when - ``ShiftXderivs`` in ``mesh/mesh.hxx`` is enabled. ``ShiftXderivs`` - can be set in the root section of ``BOUT.inp`` as - ``ShiftXderivs = true``. The shifts must be provided in the gridfile - in a field ``zshift(nx,ny)``. If not found, ``zshift`` is set to - zero. + non-aligned coordinates (see ``manual/coordinates.pdf``). Parallel + differential operators are calculated using a shift to field-aligned + values when `paralleltransform:type = shifted` (or `shiftedinterp`). + The shifts must be provided in the gridfile in a field ``zshift(nx,ny)``. + If not found, ``zshift`` is set to zero. The remaining quantities determine the topology of the grid. These are based on tokamak single/double-null configurations, but can be adapted From e0b39af683d2d47a7a1ddcbd389c338917a95ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 13:49:16 +0200 Subject: [PATCH 161/293] revert part of clang-format --- src/field/fieldgenerators.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 7a884bb053..977b6fd551 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -89,11 +89,13 @@ BoutReal FieldBallooning::generate(const Context& ctx) { for (int i = 1; i <= ball_n; i++) { // y - i * 2pi - value += arg->generate(Context(ctx).set("y", ctx.y() - i * TWOPI, "z", - ctx.z() + i * ts * TWOPI / zlength)); + // clang-format off + value += arg->generate(Context(ctx).set("y", ctx.y() - i * TWOPI, + "z", ctx.z() + i * ts * TWOPI / zlength)); - value += arg->generate(Context(ctx).set("y", ctx.y() + i * TWOPI, "z", - ctx.z() - i * ts * TWOPI / zlength)); + value += arg->generate(Context(ctx).set("y", ctx.y() + i * TWOPI, + "z", ctx.z() - i * ts * TWOPI / zlength)); + // clang-format on } return value; } From d940767f03e12c69c538d746094124e8978ba0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 14:33:16 +0200 Subject: [PATCH 162/293] Update printing and fix vector saving --- src/fileio/datafile.cxx | 16 ++++++++-------- src/mesh/coordinates.cxx | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/fileio/datafile.cxx b/src/fileio/datafile.cxx index 27127cbcd8..92b878a0bd 100644 --- a/src/fileio/datafile.cxx +++ b/src/fileio/datafile.cxx @@ -818,20 +818,20 @@ void Datafile::add(Vector2D &f, const char *name, bool save_repeat) { if(floats) file->setLowPrecision(); + // Add variables to file + auto dname = d.covar ? d.name + "_" : d.name; #ifdef COORDINATES_USE_3D // Add variables to file - if (!file->addVarField3D(d.name + "_x", save_repeat)) { - throw BoutException("Failed to add Vector2D variable %s to Datafile", name); + if (!file->addVarField3D(dname + "x", save_repeat)) { + throw BoutException("Failed to add Vector2D variable {:s} to Datafile", dname); } - if (!file->addVarField3D(d.name + "_y", save_repeat)) { - throw BoutException("Failed to add Vector2D variable %s to Datafile", name); + if (!file->addVarField3D(dname + "y", save_repeat)) { + throw BoutException("Failed to add Vector2D variable {:s} to Datafile", dname); } - if (!file->addVarField3D(d.name + "_z", save_repeat)) { - throw BoutException("Failed to add Vector2D variable %s to Datafile", name); + if (!file->addVarField3D(dname + "z", save_repeat)) { + throw BoutException("Failed to add Vector2D variable {:s} to Datafile", dname); } #else - // Add variables to file - auto dname = d.covar ? d.name + "_" : d.name; if (!file->addVarField2D(dname + "x", save_repeat)) { throw BoutException("Failed to add Vector2D variable {:s} to Datafile", dname); } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 90ab83d1e0..8bbe613f9b 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -871,8 +871,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, auto Jcalc = J; if (getAtLoc(mesh, J, "J", suffix, location)) { output_warn.write( - "\tWARNING: Jacobian 'J_%s' not found. Calculating from metric tensor\n", - suffix.c_str()); + "\tWARNING: Jacobian 'J_{:s}' not found. Calculating from metric tensor\n", + suffix); J = Jcalc; } else { J = interpolateAndExtrapolate(J, location, extrapolate_x, extrapolate_y, false, @@ -889,14 +889,14 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, bout::checkFinite(J, "J" + suffix, "RGN_NOCORNERS"); bout::checkPositive(J, "J" + suffix, "RGN_NOCORNERS"); if (min(abs(J)) < 1.0e-10) { - throw BoutException("\tERROR: Jacobian%s becomes very small\n", suffix.c_str()); + throw BoutException("\tERROR: Jacobian{:s} becomes very small\n", suffix); } // Attempt to read Bxy from the grid file auto Bcalc = Bxy; if (getAtLoc(mesh, Bxy, "Bxy", suffix, location)) { - output_warn.write("\tWARNING: Magnitude of B field 'Bxy_%s' not found. Calculating " - " from metric tensor\n", suffix.c_str()); + output_warn.write("\tWARNING: Magnitude of B field 'Bxy_{:s}' not found. Calculating " + " from metric tensor\n", suffix); Bxy = Bcalc; } else { Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, From 7d2a4b3be52411325d952d353e624655dd03d1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 14:38:20 +0200 Subject: [PATCH 163/293] Minimize difference between branches --- src/fileio/datafile.cxx | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/fileio/datafile.cxx b/src/fileio/datafile.cxx index 92b878a0bd..64e9b9c5a6 100644 --- a/src/fileio/datafile.cxx +++ b/src/fileio/datafile.cxx @@ -1188,27 +1188,6 @@ bool Datafile::write() { } // 2D vectors -#ifdef COORDINATES_USE_3D - for (const auto& var : v2d_arr) { - if (var.covar) { - // Writing covariant vector - Vector2D v = *(var.ptr); - v.toCovariant(); - - write_f3d(var.name + "_x", &(v.x), var.save_repeat); - write_f3d(var.name + "_y", &(v.y), var.save_repeat); - write_f3d(var.name + "_z", &(v.z), var.save_repeat); - } else { - // Writing contravariant vector - Vector2D v = *(var.ptr); - v.toContravariant(); - - write_f3d(var.name + "x", &(v.x), var.save_repeat); - write_f3d(var.name + "y", &(v.y), var.save_repeat); - write_f3d(var.name + "z", &(v.z), var.save_repeat); - } - } -#else for(const auto& var : v2d_arr) { Vector2D v = *(var.ptr); auto name = var.name; @@ -1222,11 +1201,16 @@ bool Datafile::write() { v.toContravariant(); } +#ifdef COORDINATES_USE_3D + write_f3d(name+"x", &(v.x), var.save_repeat); + write_f3d(name+"y", &(v.y), var.save_repeat); + write_f3d(name+"z", &(v.z), var.save_repeat); +#else write_f2d(name+"x", &(v.x), var.save_repeat); write_f2d(name+"y", &(v.y), var.save_repeat); write_f2d(name+"z", &(v.z), var.save_repeat); - } #endif + } // 3D vectors for(const auto& var : v3d_arr) { From 034890bfd07c82fa9082e7f761d4b8fcb186fb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 14:42:10 +0200 Subject: [PATCH 164/293] Improve formating --- .../laplace/impls/petsc/petsc_laplace.cxx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index 6c2b1462a2..212b610ac2 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -690,19 +690,19 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { MatA); } else { -// // Second Order Accuracy on Boundary -// Element(i,x,z, 0, 0, 3.0 / (2.0*coords->dx(x,y)), MatA ); -// Element(i,x,z, -1, 0, -2.0 / coords->dx(x,y), MatA ); -// Element(i,x,z, -2, 0, 1.0 / (2.0*coords->dx(x,y)), MatA ); -// // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now -// // Element(i,x,z, -4, 0, 0.0, MatA ); - // Second Order Accuracy on Boundary, set half-way between grid points -Element(i, x, z, 0, 0, 1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); -Element(i, x, z, -1, 0, -1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); -Element(i, x, z, -2, 0, 0.0, MatA); -// Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now -// Element(i,x,z, -4, 0, 0.0, MatA ); - } + // // Second Order Accuracy on Boundary + // Element(i,x,z, 0, 0, 3.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, -1, 0, -2.0 / coords->dx(x,y), MatA ); + // Element(i,x,z, -2, 0, 1.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, -4, 0, 0.0, MatA ); + // Second Order Accuracy on Boundary, set half-way between grid points + Element(i, x, z, 0, 0, 1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); + Element(i, x, z, -1, 0, -1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); + Element(i, x, z, -2, 0, 0.0, MatA); + // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now + // Element(i,x,z, -4, 0, 0.0, MatA ); + } } else { if (fourth_order) { From 856f1b8b7029983a416f25e9ef5b093f938d4fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 14:45:55 +0200 Subject: [PATCH 165/293] move parts out of loop --- src/invert/laplace/impls/serial_band/serial_band.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index daa51c15f2..ef8a9baad4 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -121,6 +121,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { xend = localmesh->LocalNx-2; } + const auto kwave_fac = TWOPI / coords->zlength(); // wave number is 1/[rad] for(int iz=0;iz<=maxmode;iz++) { // solve differential equation in x @@ -128,7 +129,7 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { ///////// PERFORM INVERSION ///////// // shift freqs according to FFT convention - const Field2D kwave_ = iz * TWOPI / coords->zlength(); // wave number is 1/[rad] + const Field2D kwave_ = iz * kwave_fac; // set bk1d for(int ix=0;ixLocalNx;ix++) From 8825a534ad0658ffc35c5fabb5d6f9d1ee00dadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Sun, 31 May 2020 15:17:45 +0200 Subject: [PATCH 166/293] Move Div_Perp_Lap_FV to FV namespace --- include/bout/fv_ops.hxx | 6 +++ include/difops.hxx | 6 --- src/mesh/difops.cxx | 83 ----------------------------------------- src/mesh/fv_ops.cxx | 83 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 89 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 5f54274226..86a8f8024d 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -508,5 +508,11 @@ namespace FV { } return result + fromFieldAligned(yresult, "RGN_NOBNDRY"); } + + /*! + * X-Z Finite Volume diffusion operator + */ + Field3D Div_Perp_Lap(const Field3D& a, const Field3D& f, + CELL_LOC outloc = CELL_DEFAULT); } #endif // __FV_OPS_H__ diff --git a/include/difops.hxx b/include/difops.hxx index 41daa122a2..206a9fa58f 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -391,12 +391,6 @@ Field3D b0xGrad_dot_Grad(const Field2D& phi, const Field3D& A, Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, CELL_LOC outloc = CELL_DEFAULT); -/*! - * X-Z Finite Volume diffusion operator - */ -Field3D Div_Perp_Lap_FV(const Field3D& a, const Field3D& f, - CELL_LOC outloc = CELL_DEFAULT); - /*! * Poisson bracket methods */ diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 156b2ffdf3..12091e56bc 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -577,89 +577,6 @@ Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, CELL_LOC outloc) return result; } -Field3D Div_Perp_Lap_FV(const Field3D& a, const Field3D& f, CELL_LOC outloc) { - - Field3D result = 0.0; - - ////////////////////////////////////////// - // X-Z diffusion - // - // Z - // | - // - // o --- gU --- o - // | nU | - // | | - // gL nL nR gR -> X - // | | - // | nD | - // o --- gD --- o - // - Coordinates* coords = a.getCoordinates(outloc); - Mesh* mesh = f.getMesh(); - - for (int i = mesh->xstart; i <= mesh->xend; i++) - for (int j = mesh->ystart; j <= mesh->yend; j++) - for (int k = 0; k < mesh->LocalNz; k++) { - - // wrap k-index around as Z is (currently) periodic. - int kp = (k + 1) % (mesh->LocalNz); - int km = (k - 1 + mesh->LocalNz) % (mesh->LocalNz); - - // Calculate gradients on cell faces -- assumes constant grid spacing - - BoutReal gR = - (coords->g11(i, j, k) + coords->g11(i + 1, j, k)) - * (f(i + 1, j, k) - f(i, j, k)) - / (coords->dx(i + 1, j, k) + coords->dx(i, j, k)) - + 0.5 * (coords->g13(i, j, k) + coords->g13(i + 1, j, k)) - * (f(i + 1, j, kp) - f(i + 1, j, km) + f(i, j, kp) - f(i, j, km)) - / (4. * coords->dz(i, j, k)); - - BoutReal gL = - (coords->g11(i - 1, j, k) + coords->g11(i, j, k)) - * (f(i, j, k) - f(i - 1, j, k)) - / (coords->dx(i - 1, j, k) + coords->dx(i, j, k)) - + 0.5 * (coords->g13(i - 1, j, k) + coords->g13(i, j, k)) - * (f(i - 1, j, kp) - f(i - 1, j, km) + f(i, j, kp) - f(i, j, km)) - / (4 * coords->dz(i, j, k)); - - BoutReal gD = - coords->g13(i, j, k) - * (f(i + 1, j, km) - f(i - 1, j, km) + f(i + 1, j, k) - f(i - 1, j, k)) - / (4. * coords->dx(i, j, k)) - + coords->g33(i, j, k) * (f(i, j, k) - f(i, j, km)) / coords->dz(i, j, k); - - BoutReal gU = - coords->g13(i, j, k) - * (f(i + 1, j, kp) - f(i - 1, j, kp) + f(i + 1, j, k) - f(i - 1, j, k)) - / (4. * coords->dx(i, j, k)) - + coords->g33(i, j, k) * (f(i, j, kp) - f(i, j, k)) / coords->dz(i, j, k); - - // Flow right - BoutReal flux = gR * 0.25 * (coords->J(i + 1, j, k) + coords->J(i, j, k)) - * (a(i + 1, j, k) + a(i, j, k)); - result(i, j, k) += flux / (coords->dx(i, j, k) * coords->J(i, j, k)); - - // Flow left - flux = gL * 0.25 * (coords->J(i - 1, j, k) + coords->J(i, j, k)) - * (a(i - 1, j, k) + a(i, j, k)); - result(i, j, k) -= flux / (coords->dx(i, j, k) * coords->J(i, j, k)); - - // Flow up - flux = gU * 0.25 * (coords->J(i, j, k) + coords->J(i, j, kp)) - * (a(i, j, k) + a(i, j, kp)); - result(i, j, k) += flux / (coords->dz(i, j, k) * coords->J(i, j, k)); - - // Flow down - flux = gD * 0.25 * (coords->J(i, j, km) + coords->J(i, j, k)) - * (a(i, j, km) + a(i, j, k)); - result(i, j, k) += flux / (coords->dz(i, j, k) * coords->J(i, j, k)); - } - - return result; -} - /******************************************************************************* * Poisson bracket * Terms of form b0 x Grad(f) dot Grad(g) / B = [f, g] diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 3d989ff6da..fb07b3cdb9 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -465,4 +465,87 @@ namespace FV { } } + Field3D Div_Perp_Lap(const Field3D& a, const Field3D& f, CELL_LOC outloc) { + + Field3D result = 0.0; + + ////////////////////////////////////////// + // X-Z diffusion + // + // Z + // | + // + // o --- gU --- o + // | nU | + // | | + // gL nL nR gR -> X + // | | + // | nD | + // o --- gD --- o + // + Coordinates* coords = a.getCoordinates(outloc); + Mesh* mesh = f.getMesh(); + + for (int i = mesh->xstart; i <= mesh->xend; i++) + for (int j = mesh->ystart; j <= mesh->yend; j++) + for (int k = 0; k < mesh->LocalNz; k++) { + + // wrap k-index around as Z is (currently) periodic. + int kp = (k + 1) % (mesh->LocalNz); + int km = (k - 1 + mesh->LocalNz) % (mesh->LocalNz); + + // Calculate gradients on cell faces -- assumes constant grid spacing + + BoutReal gR = + (coords->g11(i, j, k) + coords->g11(i + 1, j, k)) + * (f(i + 1, j, k) - f(i, j, k)) + / (coords->dx(i + 1, j, k) + coords->dx(i, j, k)) + + 0.5 * (coords->g13(i, j, k) + coords->g13(i + 1, j, k)) + * (f(i + 1, j, kp) - f(i + 1, j, km) + f(i, j, kp) - f(i, j, km)) + / (4. * coords->dz(i, j, k)); + + BoutReal gL = + (coords->g11(i - 1, j, k) + coords->g11(i, j, k)) + * (f(i, j, k) - f(i - 1, j, k)) + / (coords->dx(i - 1, j, k) + coords->dx(i, j, k)) + + 0.5 * (coords->g13(i - 1, j, k) + coords->g13(i, j, k)) + * (f(i - 1, j, kp) - f(i - 1, j, km) + f(i, j, kp) - f(i, j, km)) + / (4 * coords->dz(i, j, k)); + + BoutReal gD = + coords->g13(i, j, k) + * (f(i + 1, j, km) - f(i - 1, j, km) + f(i + 1, j, k) - f(i - 1, j, k)) + / (4. * coords->dx(i, j, k)) + + coords->g33(i, j, k) * (f(i, j, k) - f(i, j, km)) / coords->dz(i, j, k); + + BoutReal gU = + coords->g13(i, j, k) + * (f(i + 1, j, kp) - f(i - 1, j, kp) + f(i + 1, j, k) - f(i - 1, j, k)) + / (4. * coords->dx(i, j, k)) + + coords->g33(i, j, k) * (f(i, j, kp) - f(i, j, k)) / coords->dz(i, j, k); + + // Flow right + BoutReal flux = gR * 0.25 * (coords->J(i + 1, j, k) + coords->J(i, j, k)) + * (a(i + 1, j, k) + a(i, j, k)); + result(i, j, k) += flux / (coords->dx(i, j, k) * coords->J(i, j, k)); + + // Flow left + flux = gL * 0.25 * (coords->J(i - 1, j, k) + coords->J(i, j, k)) + * (a(i - 1, j, k) + a(i, j, k)); + result(i, j, k) -= flux / (coords->dx(i, j, k) * coords->J(i, j, k)); + + // Flow up + flux = gU * 0.25 * (coords->J(i, j, k) + coords->J(i, j, kp)) + * (a(i, j, k) + a(i, j, kp)); + result(i, j, k) += flux / (coords->dz(i, j, k) * coords->J(i, j, k)); + + // Flow down + flux = gD * 0.25 * (coords->J(i, j, km) + coords->J(i, j, k)) + * (a(i, j, km) + a(i, j, k)); + result(i, j, k) += flux / (coords->dz(i, j, k) * coords->J(i, j, k)); + } + + return result; + } + } // Namespace FV From 81f3e222047200978946ae0cb74d724488d27584 Mon Sep 17 00:00:00 2001 From: dschwoerer Date: Sun, 31 May 2020 14:37:46 +0100 Subject: [PATCH 167/293] Apply suggestions from code review Co-authored-by: johnomotani Co-authored-by: Peter Hill --- examples/elm-pb/elm_pb.cxx | 4 ++-- include/bout/coordinates.hxx | 8 ++++---- manual/sphinx/developer_docs/mesh.rst | 3 +-- manual/sphinx/user_docs/input_grids.rst | 5 ++--- src/field/field3d.cxx | 2 +- src/invert/laplace/invert_laplace.cxx | 4 +++- src/mesh/coordinates.cxx | 2 +- tests/integrated/test-backtrace/makefile | 4 ++-- tests/integrated/test-io/runtest | 2 +- tests/requirements/requirements.py | 1 - 10 files changed, 17 insertions(+), 18 deletions(-) diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index 5549e881eb..86d4f1320d 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -29,8 +29,8 @@ class ELMpb : public PhysicsModel { Field2D beta; // Used for Vpar terms Coordinates::metric_field_type gradparB; Field2D phi0; // When diamagnetic terms used - Field2D Psixy, x; // 0th vorticity of equilibrium flow, - Coordinates::metric_field_type U0; + Field2D Psixy, x; + Coordinates::metric_field_type U0; // 0th vorticity of equilibrium flow, // radial flux coordinate, normalized radial flux coordinate bool constn0; diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 13547e00cc..a9fa4c9f56 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -103,8 +103,8 @@ public: /// True if corrections for non-uniform mesh spacing should be included in operators bool non_uniform; - metric_field_type d1_dx, d1_dy, - d1_dz; ///< 2nd-order correction for non-uniform meshes d/di(1/dx) and d/di(1/dy) + /// 2nd-order correction for non-uniform meshes d/di(1/dx), d/di(1/dy) and d/di(1/dz) + metric_field_type d1_dx, d1_dy, d1_dz; metric_field_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz @@ -123,8 +123,8 @@ public: metric_field_type G1, G2, G3; - metric_field_type - ShiftTorsion; ///< d pitch angle / dx. Needed for vector differentials (Curl) + /// d pitch angle / dx. Needed for vector differentials (Curl) + metric_field_type ShiftTorsion; metric_field_type IntShiftTorsion; ///< Integrated shear (I in BOUT notation) diff --git a/manual/sphinx/developer_docs/mesh.rst b/manual/sphinx/developer_docs/mesh.rst index 5ad6ae7f62..aa0b1dd923 100644 --- a/manual/sphinx/developer_docs/mesh.rst +++ b/manual/sphinx/developer_docs/mesh.rst @@ -261,7 +261,7 @@ index. Differencing ------------ -The mesh spacing is given by the public members `Coorinates::dx`, +The mesh spacing is given by the public members `Coordinates::dx`, `Coordinates::dy` and `Coordinates::dz`:: // These used for differential operators @@ -345,4 +345,3 @@ removed. A feature is:: bool StaggerGrids; ///< Enable staggered grids (Centre, Lower). Otherwise all vars are cell centred (default). - diff --git a/manual/sphinx/user_docs/input_grids.rst b/manual/sphinx/user_docs/input_grids.rst index 7751b99be3..3aeab1668c 100644 --- a/manual/sphinx/user_docs/input_grids.rst +++ b/manual/sphinx/user_docs/input_grids.rst @@ -22,7 +22,7 @@ a simple mesh can be created using options. The above options will create a :math:`256\times 256` mesh in X and Y, assuming there are 2 guard cells in X direction. The Z resolution can -be specified with MZ. The mesh spacing of :math:`0.1` in both +be specified with MZ. The mesh spacing is :math:`0.1` in both directions. By default the coordinate system is Cartesian (metric tensor is the identity matrix), but this can be changed by specifying the metric tensor components. @@ -156,7 +156,7 @@ This section describes how to generate inputs for tokamak equilibria. If you’re not interested in tokamaks then you can skip to the next section. The directory ``tokamak_grids`` contains code to generate input grid -files for tokamaks. These can be used by the ``2fluid`` and +files for tokamaks. These can be used by, for example, the ``2fluid`` and ``highbeta_reduced`` modules. .. _sec-bout-topology: @@ -765,4 +765,3 @@ with the following formula: where :math:`R_0` is the major radius, :math:`a` is the minor radius, :math:`\epsilon` is the elongation (``elong``), :math:`\delta` the triangularity (``triang``), and :math:`b` the indentation (``indent``). - diff --git a/src/field/field3d.cxx b/src/field/field3d.cxx index a9af3ed37e..e30597d1e5 100644 --- a/src/field/field3d.cxx +++ b/src/field/field3d.cxx @@ -206,7 +206,7 @@ Field3D &Field3D::ynext(int dir) { bool Field3D::requiresTwistShift(bool twist_shift_enabled) { // Workaround for 3D coordinates. - // We need to communicate in the coordinates constructure in that + // We need to communicate in the coordinates constructor in that // case a Field3D, but coordinates isn't valid yet. As such we // disable twist-shift in that case. if (getCoordinates() == nullptr) { diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index 230e605d2a..056514143d 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -270,7 +270,9 @@ void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, dcomplex &a, dcomplex &b, dcomplex &c, const Field2D *c1coef, const Field2D *c2coef, const Field2D *d, CELL_LOC loc) { -#ifndef COORDINATES_USE_3D +#ifdef COORDINATES_USE_3D + throw BoutException("Laplacian::tridagCoefs() does not support 3d metrics."); +#else /* Function: Laplacian::tridagCoef * Purpose: - Set the matrix components of A in Ax=b, solving * diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 90ab83d1e0..764838a9a8 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -626,7 +626,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // use anonymous namespace so this utility function is not available outside this file namespace { -/// Interpolate a Field2D to a new CELL_LOC with interp_to. +/// Interpolate a metric_field_type to a new CELL_LOC with interp_to. /// Communicates to set internal guard cells. /// Boundary guard cells are set equal to the nearest grid point (equivalent to /// 2nd order accurate Neumann boundary condition). diff --git a/tests/integrated/test-backtrace/makefile b/tests/integrated/test-backtrace/makefile index 58ab427bc3..e04ffbcf91 100644 --- a/tests/integrated/test-backtrace/makefile +++ b/tests/integrated/test-backtrace/makefile @@ -1,6 +1,6 @@ -BOUT_TOP = ../../.. +BOUT_TOP = ../../.. -SOURCEC = boutexcept.cxx +SOURCEC = boutexcept.cxx include $(BOUT_TOP)/make.config diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index 898d8b1ffb..6bb725808c 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -100,7 +100,7 @@ for nproc in [1,2,4]: print(" %d processor...." % (nproc) + extra_args) s, out = launch_safe(cmd, nproc=nproc, pipe=True) with open("run.log."+str(nproc), "w") as f: - f.write(out) + f.write(out) # Check processor splitting if split is not None: diff --git a/tests/requirements/requirements.py b/tests/requirements/requirements.py index 21d22f5dd2..e867a3c747 100755 --- a/tests/requirements/requirements.py +++ b/tests/requirements/requirements.py @@ -37,7 +37,6 @@ def __init__(self, path=None, verbose=False): requirements_list = [x for x in os.listdir(path) if not (("#" in x) or ("~" in x) or (x[0] == ".") or (".py" in x))] - if verbose: print("======= Requirement checks ========") From 54e042fcd186e5093edcf435e86bd088e6f2e9df Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 31 May 2020 14:01:56 +0000 Subject: [PATCH 168/293] [clang-format-command] fixes --- include/bout/fv_ops.hxx | 2 +- src/fileio/datafile.cxx | 6 +-- .../impls/multigrid/multigrid_laplace.cxx | 2 +- .../laplace/impls/petsc/petsc_laplace.cxx | 33 +++++++------ src/mesh/boundary_standard.cxx | 46 +++++++++---------- src/mesh/coordinates.cxx | 6 ++- src/mesh/difops.cxx | 4 +- 7 files changed, 54 insertions(+), 45 deletions(-) diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 86a8f8024d..85fae6ad80 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -514,5 +514,5 @@ namespace FV { */ Field3D Div_Perp_Lap(const Field3D& a, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); -} + } // namespace FV #endif // __FV_OPS_H__ diff --git a/src/fileio/datafile.cxx b/src/fileio/datafile.cxx index 64e9b9c5a6..65e590733a 100644 --- a/src/fileio/datafile.cxx +++ b/src/fileio/datafile.cxx @@ -1202,9 +1202,9 @@ bool Datafile::write() { } #ifdef COORDINATES_USE_3D - write_f3d(name+"x", &(v.x), var.save_repeat); - write_f3d(name+"y", &(v.y), var.save_repeat); - write_f3d(name+"z", &(v.z), var.save_repeat); + write_f3d(name + "x", &(v.x), var.save_repeat); + write_f3d(name + "y", &(v.y), var.save_repeat); + write_f3d(name + "z", &(v.z), var.save_repeat); #else write_f2d(name+"x", &(v.x), var.save_repeat); write_f2d(name+"y", &(v.y), var.save_repeat); diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index 7f633dbadc..5495046f2b 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -592,7 +592,7 @@ BOUT_OMP(for collapse(2)) D(i2, yindex, k2) * 2. * coords->g13(i2, yindex) / coords->dx(i2, yindex) / dz; // coefficient of mixed derivative stencil (could assume zero, at least initially, // if easier; then check this is true in constructor) - + BoutReal dxd = (D(i2, yindex, k2)*coords->G1(i2, yindex) + coords->g11(i2, yindex)*ddx_C + coords->g13(i2, yindex)*ddz_C // (could assume zero, at least initially, if easier; then check this is true in constructor) diff --git a/src/invert/laplace/impls/petsc/petsc_laplace.cxx b/src/invert/laplace/impls/petsc/petsc_laplace.cxx index a43be20002..92cde52394 100644 --- a/src/invert/laplace/impls/petsc/petsc_laplace.cxx +++ b/src/invert/laplace/impls/petsc/petsc_laplace.cxx @@ -691,19 +691,26 @@ FieldPerp LaplacePetsc::solve(const FieldPerp& b, const FieldPerp& x0) { MatA); } else { - // // Second Order Accuracy on Boundary - // Element(i,x,z, 0, 0, 3.0 / (2.0*coords->dx(x,y)), MatA ); - // Element(i,x,z, -1, 0, -2.0 / coords->dx(x,y), MatA ); - // Element(i,x,z, -2, 0, 1.0 / (2.0*coords->dx(x,y)), MatA ); - // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now - // Element(i,x,z, -4, 0, 0.0, MatA ); - // Second Order Accuracy on Boundary, set half-way between grid points - Element(i, x, z, 0, 0, 1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); - Element(i, x, z, -1, 0, -1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), MatA); - Element(i, x, z, -2, 0, 0.0, MatA); - // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 in case 4th order flag was used previously: not allowed now - // Element(i,x,z, -4, 0, 0.0, MatA ); - } + // // Second Order Accuracy on Boundary + // Element(i,x,z, 0, 0, 3.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, -1, 0, -2.0 / coords->dx(x,y), MatA ); + // Element(i,x,z, -2, 0, 1.0 / (2.0*coords->dx(x,y)), MatA ); + // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 + // in case 4th order flag was used previously: not allowed now + // Element(i,x,z, -4, 0, 0.0, MatA ); + // Second Order Accuracy on Boundary, set half-way between grid + // points + Element(i, x, z, 0, 0, + 1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, -1, 0, + -1.0 / coords->dx(x, y, z) / sqrt(coords->g_11(x, y, z)), + MatA); + Element(i, x, z, -2, 0, 0.0, MatA); + // Element(i,x,z, -3, 0, 0.0, MatA ); // Reset these elements to 0 + // in case 4th order flag was used previously: not allowed now + // Element(i,x,z, -4, 0, 0.0, MatA ); + } } else { if (fourth_order) { diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 86fd031f6f..56e1f19aa2 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1887,8 +1887,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2126,9 +2126,9 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + bndry->by * metric->dy(bndry->x, bndry->y, zk); #else - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) - + bndry->by * metric->dy(bndry->x, bndry->y); - for (int zk = 0; zk < mesh->LocalNz; zk++) { + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) + + bndry->by * metric->dy(bndry->x, bndry->y); + for (int zk = 0; zk < mesh->LocalNz; zk++) { #endif if (fg) { val = fg->generate(Context(bndry, zk, loc, t, mesh)); @@ -2223,8 +2223,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2328,8 +2328,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { // cell } #else - throw BoutException( - "void BoundaryNeumann_4thOrder::apply(Field2D& f) not implemented with 3D metrics"); + throw BoutException("void BoundaryNeumann_4thOrder::apply(Field2D& f) not " + "implemented with 3D metrics"); #endif } @@ -2397,8 +2397,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { * sqrt(metric->g_22(bndry->x, bndry->y) / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2549,8 +2549,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2610,8 +2610,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field3D not compatible with 3D metrics in ZeroLaplace case."); + throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " + "ZeroLaplace case."); #endif } @@ -2652,8 +2652,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2710,8 +2710,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " - "ZeroLaplace2 case."); + throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " + "ZeroLaplace2 case."); #endif } @@ -2825,8 +2825,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " - "ConstLaplace case."); + throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " + "ConstLaplace case."); #endif } @@ -2937,8 +2937,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Vector3D not compatible with 3D metrics in DivCurl."); + throw BoutException( + "Applying boundary to Vector3D not compatible with 3D metrics in DivCurl."); #endif } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index c830c34ae8..698e38cc16 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -895,8 +895,10 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, // Attempt to read Bxy from the grid file auto Bcalc = Bxy; if (getAtLoc(mesh, Bxy, "Bxy", suffix, location)) { - output_warn.write("\tWARNING: Magnitude of B field 'Bxy_{:s}' not found. Calculating " - " from metric tensor\n", suffix); + output_warn.write( + "\tWARNING: Magnitude of B field 'Bxy_{:s}' not found. Calculating " + " from metric tensor\n", + suffix); Bxy = Bcalc; } else { Bxy = interpolateAndExtrapolate(Bxy, location, extrapolate_x, extrapolate_y, false, diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 098e58ced5..d75794fc99 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -782,11 +782,11 @@ Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method, result(jx,jy,jz) = (Jpp + Jpx + Jxp) * spacingFactor; } } - } + } #else throw BoutException("BRACKET_ARAKAWA_OLD not valid with 3D metrics yet."); #endif - break; + break; } case BRACKET_SIMPLE: { // Use a subset of terms for comparison to BOUT-06 From fe412c95703678bce5086c7c4ea1fdc3805358c5 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 1 Jun 2020 10:14:15 +0100 Subject: [PATCH 169/293] Fix extra const on definition of functions --- src/mesh/difops.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index d75794fc99..e4e78033fb 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -336,19 +336,19 @@ Coordinates::metric_field_type Div_par_K_Grad_par(const Field2D& kY, const Field 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(const Field2D& kY, const Field3D& f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(const Field3D& kY, const Field2D& f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(const Field3D& kY, const Field3D& f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); From d724982298f2bd96e8cbedca9c8572a35f8d0a23 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 1 Jun 2020 10:19:16 +0100 Subject: [PATCH 170/293] Fix some unused parameter warnings --- src/physics/smoothing.cxx | 2 +- src/sys/derivs.cxx | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/physics/smoothing.cxx b/src/physics/smoothing.cxx index 22e719548a..2a53eaedc3 100644 --- a/src/physics/smoothing.cxx +++ b/src/physics/smoothing.cxx @@ -320,7 +320,7 @@ BoutReal Average_XY(const Field2D &var) { return Vol_Glb; } -BoutReal Average_XY(const Field3D& var) { +BoutReal Average_XY(const Field3D&) { AUTO_TRACE(); throw BoutException("Average_XY(Field3D) not yet implemented."); } diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index 6b18615a80..7915b6cf8f 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -336,8 +336,8 @@ Field3D D2DXDY(const Field3D& f, CELL_LOC outloc, const std::string& method, } Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + MAYBE_UNUSED(const std::string& method), + MAYBE_UNUSED(const std::string& region)) { #ifdef COORDINATES_USE_3D Field3D tmp{f}; return D2DXDZ(tmp, outloc, method, region); @@ -361,8 +361,8 @@ Field3D D2DXDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + MAYBE_UNUSED(const std::string& method), + MAYBE_UNUSED(const std::string& region)) { #ifdef COORDINATES_USE_3D Field3D tmp{f}; return D2DYDZ(tmp, outloc, method, region); @@ -434,9 +434,10 @@ Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, CELL_LOC } // Note that this is zero because no compression is included -Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { +Coordinates::metric_field_type VDDZ(MAYBE_UNUSED(const Field3D& v), const Field2D& f, + CELL_LOC outloc, + MAYBE_UNUSED(const std::string& method), + MAYBE_UNUSED(const std::string& region)) { #ifdef COORDINATES_USE_3D Field3D tmp{f}; return bout::derivatives::index::VDDZ(v, tmp, outloc, method, region) From 3db5a09b1199ab7137004d90110c118e586e1a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 15 Jul 2020 11:10:32 +0200 Subject: [PATCH 171/293] rename *Const -> *Uniform Avoid confusion with the const keywork of C++ --- include/field.hxx | 23 +++++-------------- src/field/fieldgenerators.cxx | 2 +- .../laplace/impls/cyclic/cyclic_laplace.cxx | 8 +++---- src/invert/laplace/impls/pdd/pdd.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 +- .../impls/cyclic/laplacexz-cyclic.cxx | 2 +- src/invert/parderiv/impls/cyclic/cyclic.cxx | 2 +- src/mesh/boundary_standard.cxx | 2 +- src/mesh/coordinates.cxx | 4 ++-- src/mesh/data/gridfromfile.cxx | 4 ++-- 12 files changed, 22 insertions(+), 33 deletions(-) diff --git a/include/field.hxx b/include/field.hxx index fb79acb042..77b3e7ef2c 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -383,10 +383,11 @@ inline BoutReal min(const T& f, bool allpe, REGION rgn) { } template > -inline bool isConst(const T& f, bool allpe = false, +inline bool isUniform(const T& f, bool allpe = false, const std::string& region = "RGN_ALL") { bool result = true; auto element = f[*f.getRegion(region).begin()]; + // TODO: maybe parallise this loop, as the early return is unlikely BOUT_FOR_SERIAL(i, f.getRegion(region)) { if (f[i] != element) { result = false; @@ -401,26 +402,14 @@ inline bool isConst(const T& f, bool allpe = false, } template > -inline BoutReal getConst(const T& f, bool allpe = false, +inline BoutReal getUniform(const T& f, bool allpe = false, const std::string& region = "RGN_ALL") { - bool is_const = true; - auto element = f[*f.getRegion(region).begin()]; #if CHECK > 1 - BOUT_FOR_SERIAL(i, f.getRegion(region)) { - if (f[i] != element) { - is_const = false; - break; - } - } - if (allpe) { - bool local_is_const = is_const; - MPI_Allreduce(&local_is_const, &is_const, 1, MPI_C_BOOL, MPI_LOR, BoutComm::get()); - } - if (!is_const) { - throw BoutException("Requested getConst but Field is not const"); + if (! isUniform(f, allpe, region)) { + throw BoutException("Requested getUniform({}, {}, {}) but Field is not const", f.name, allpe, region); } #endif - return element; + return f[*f.getRegion(region).begin()]; } template> diff --git a/src/field/fieldgenerators.cxx b/src/field/fieldgenerators.cxx index 977b6fd551..bd369d1ab2 100644 --- a/src/field/fieldgenerators.cxx +++ b/src/field/fieldgenerators.cxx @@ -81,7 +81,7 @@ BoutReal FieldBallooning::generate(const Context& ctx) { / (localmesh->xend - localmesh->xstart); int jx = ROUND((ctx.x() - localmesh->GlobalX(0)) / dx); - const BoutReal zlength = getConst(coords->zlength()); + const BoutReal zlength = getUniform(coords->zlength()); if (localmesh->periodicY(jx, ts)) { // Start with the value at this point diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index 20714346f7..5b37023a8b 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -145,7 +145,7 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { // Get elements of the tridiagonal matrix // including boundary conditions - BoutReal zlen = getConst(coords->dz) * (localmesh->LocalNz - 3); + BoutReal zlen = getUniform(coords->dz) * (localmesh->LocalNz - 3); BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { BoutReal kwave = @@ -213,7 +213,7 @@ FieldPerp LaplaceCyclic::solve(const FieldPerp& rhs, const FieldPerp& x0) { // Get elements of the tridiagonal matrix // including boundary conditions - const BoutReal zlength = getConst(coords->zlength()); + const BoutReal zlength = getUniform(coords->zlength()); BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { BoutReal kwave = kz * 2.0 * PI / zlength; // wave number is 1/[rad] @@ -344,7 +344,7 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { // Get elements of the tridiagonal matrix // including boundary conditions - const BoutReal zlen = getConst(coords->dz) * (localmesh->LocalNz - 3); + const BoutReal zlen = getUniform(coords->dz) * (localmesh->LocalNz - 3); BOUT_OMP(for nowait) for (int ind = 0; ind < nsys; ind++) { // ind = (iy - ys) * nmode + kz @@ -425,7 +425,7 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { // Get elements of the tridiagonal matrix // including boundary conditions - const BoutReal zlength = getConst(coords->zlength()); + const BoutReal zlength = getUniform(coords->zlength()); BOUT_OMP(for nowait) for (int ind = 0; ind < nsys; ind++) { // ind = (iy - ys) * nmode + kz diff --git a/src/invert/laplace/impls/pdd/pdd.cxx b/src/invert/laplace/impls/pdd/pdd.cxx index 2bf1986c04..bfbfe98a0a 100644 --- a/src/invert/laplace/impls/pdd/pdd.cxx +++ b/src/invert/laplace/impls/pdd/pdd.cxx @@ -165,7 +165,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 / getConst(coords->zlength()); + BoutReal kwaveFactor = 2.0 * PI / getUniform(coords->zlength()); /// Set matrix elements for (int kz = 0; kz <= maxmode; kz++) { diff --git a/src/invert/laplace/impls/serial_tri/serial_tri.cxx b/src/invert/laplace/impls/serial_tri/serial_tri.cxx index 0f77154290..a8dea637da 100644 --- a/src/invert/laplace/impls/serial_tri/serial_tri.cxx +++ b/src/invert/laplace/impls/serial_tri/serial_tri.cxx @@ -83,7 +83,7 @@ FieldPerp LaplaceSerialTri::solve(const FieldPerp& b, const FieldPerp& x0) { int ncz = localmesh->LocalNz; // No of z pnts int ncx = localmesh->LocalNx; // No of x pnts - BoutReal kwaveFactor = 2.0 * PI / getConst(coords->zlength()); + BoutReal kwaveFactor = 2.0 * PI / getUniform(coords->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 ae61eb7710..813c8f4c06 100644 --- a/src/invert/laplace/impls/shoot/shoot_laplace.cxx +++ b/src/invert/laplace/impls/shoot/shoot_laplace.cxx @@ -129,7 +129,7 @@ FieldPerp LaplaceShoot::solve(const FieldPerp& rhs) { // kc and kp now set to result at x and x+1 respectively // Use b at x to get km at x-1 // Loop inwards from edge - const BoutReal zlength = getConst(coords->zlength()); + const BoutReal zlength = getUniform(coords->zlength()); for(int ix=xe; ix >= xs; ix--) { rfft(rhs[ix], localmesh->LocalNz, std::begin(rhsk)); diff --git a/src/invert/laplace/impls/spt/spt.cxx b/src/invert/laplace/impls/spt/spt.cxx index 193ab1c525..4dc5fd0486 100644 --- a/src/invert/laplace/impls/spt/spt.cxx +++ b/src/invert/laplace/impls/spt/spt.cxx @@ -291,7 +291,7 @@ int LaplaceSPT::start(const FieldPerp &b, SPT_data &data) { data.bk(kz, ix) = dc1d[kz]; } - BoutReal kwaveFactor = 2.0 * PI / getConst(coords->zlength()); + BoutReal kwaveFactor = 2.0 * PI / getUniform(coords->zlength()); /// Set matrix elements for (int kz = 0; kz <= maxmode; kz++) { diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 01497bc41b..94d8533d36 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -76,7 +76,7 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { ASSERT2(max(abs(coord->g13)) < 1e-5); int ind = 0; - const BoutReal zlength = getConst(coord->zlength()); + const BoutReal zlength = getUniform(coord->zlength()); for(int y=localmesh->ystart; y <= localmesh->yend; y++) { for(int kz = 0; kz < nmode; kz++) { BoutReal kwave = kz * 2.0 * PI / zlength; diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 5f14122757..c7b36e175c 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -96,7 +96,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { auto b = Matrix(nsys, size); auto c = Matrix(nsys, size); - auto zlength = getConst(coord->zlength()); + auto zlength = getUniform(coord->zlength()); // Loop over flux-surfaces for (surf.first(); !surf.isDone(); surf.next()) { int x = surf.xpos; diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 86fd031f6f..040abd1d80 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -2811,7 +2811,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { * metric->dx(x - bx, y); for (int jz = 1; jz <= ncz / 2; jz++) { BoutReal kwave = - jz * 2.0 * PI / getConst(metric->zlength()); // wavenumber in [rad^-1] + jz * 2.0 * PI / getUniform(metric->zlength()); // wavenumber in [rad^-1] c0[jz] *= exp(coef * kwave); // The decaying solution only // Add the particular solution c2[jz] = c0[jz] - c1[jz] / (metric->g33(x - bx, y) * kwave * kwave); diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index c830c34ae8..f9d1e5bd8d 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -937,7 +937,7 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, } else { // Interpolate fields from coords_in - if (isConst(coords_in->dz)) { + if (isUniform(coords_in->dz)) { dz = coords_in->dz; dz.setLocation(location); } else { @@ -1581,7 +1581,7 @@ void Coordinates::setParallelTransform(Options* options) { if (ptstr == "shifted") { transform = bout::utils::make_unique(*localmesh, location, zShift, - getConst(zlength())); + getUniform(zlength())); } else if (ptstr == "shiftedinterp") { transform = bout::utils::make_unique(*localmesh, location, zShift); diff --git a/src/mesh/data/gridfromfile.cxx b/src/mesh/data/gridfromfile.cxx index 78bb63d870..4e9f947818 100644 --- a/src/mesh/data/gridfromfile.cxx +++ b/src/mesh/data/gridfromfile.cxx @@ -571,7 +571,7 @@ bool GridFile::readgrid_3dvar_fft(Mesh *m, const std::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 = getConst(m->getCoordinates(var.getLocation())->zlength()); + BoutReal zlength = getUniform(m->getCoordinates(var.getLocation())->zlength()); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi @@ -702,7 +702,7 @@ bool GridFile::readgrid_perpvar_fft(Mesh *m, const std::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 = getConst(m->getCoordinates(var.getLocation())->zlength()); + BoutReal zlength = getUniform(m->getCoordinates(var.getLocation())->zlength()); int zperiod = ROUND(TWOPI / zlength); /// Number of periods in 2pi From fab98205a1784458f93fe17bb2ecc2bfb153c204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 15 Jul 2020 11:10:47 +0200 Subject: [PATCH 172/293] Avoid returning const objects --- src/mesh/difops.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 098e58ced5..c678146166 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -336,19 +336,19 @@ Coordinates::metric_field_type Div_par_K_Grad_par(const Field2D& kY, const Field 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(const Field2D &kY, const Field3D &f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(const Field3D &kY, const Field2D &f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); 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, CELL_LOC outloc) { +Field3D Div_par_K_Grad_par(const Field3D &kY, const Field3D &f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); From b3acaa1cd0309ef64c67d0dd4b840bf401a48979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 15 Jul 2020 17:25:39 +0200 Subject: [PATCH 173/293] Fix references in documentation --- manual/sphinx/user_docs/input_grids.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/manual/sphinx/user_docs/input_grids.rst b/manual/sphinx/user_docs/input_grids.rst index ab5c903f79..287dc65825 100644 --- a/manual/sphinx/user_docs/input_grids.rst +++ b/manual/sphinx/user_docs/input_grids.rst @@ -93,7 +93,7 @@ variables are defined doesn’t matter, so ``L`` could be defined below ``dy``, but circular dependencies are not allowed. If the variables are defined in the same section (as ``dy`` and ``L``) then no section prefix is required. To refer to a variable in a different section, prefix the -variable with the section name e.g. “``section:variable``”. +variable with the section name e.g. “``mesh:dx``”. More complex meshes can be created by supplying an input grid file to describe the grid points, geometry, and starting profiles. Currently @@ -105,10 +105,10 @@ not found, a warning will be printed and the default values used. - Differencing quantities in 2D/3D arrays ``dx(nx,ny[,nz])``, ``dy(nx,ny[,nz])`` and ``dz(nx,ny[,nz])``. If these are not found - they will be set to 1. Note that in earlier versions of BOUT++, - `dz` was a constant. To allow variation in `z` direction, BOUT++ - has to be configured `--enable-metric-3d`, otherwise 2D fields are - used for the metric fields. + they will be set to 1. To allow variation in ``z`` direction, BOUT++ + has to be configured ``--enable-metric-3d``, otherwise 2D fields are + used for the metric fields. Note that prior to BOUT++ version 5 + ``dz`` was a constant. - Diagonal terms of the metric tensor :math:`g^{ij}` ``g11(nx,ny[,nz])``, ``g22(nx,ny[,nz])``, and ``g33(nx,ny[,nz])``. If not found, these will be set @@ -119,9 +119,9 @@ not found, a warning will be printed and the default values used. to 0. - Z shift for interpolation between field-aligned coordinates and - non-aligned coordinates (see ``manual/coordinates.pdf``). Parallel + non-aligned coordinates (see :ref:`sec-field-aligned-coordinates`). Parallel differential operators are calculated using a shift to field-aligned - values when `paralleltransform:type = shifted` (or `shiftedinterp`). + values when ``paralleltransform:type = shifted`` (or ``shiftedinterp``). The shifts must be provided in the gridfile in a field ``zshift(nx,ny)``. If not found, ``zshift`` is set to zero. From 1a1aacb712699d080c243291f09c85dc747e055e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 15 Jul 2020 17:47:01 +0200 Subject: [PATCH 174/293] escape $ for sub-shell invocation --- manual/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manual/Makefile b/manual/Makefile index 6788b60454..1e1d674a3f 100644 --- a/manual/Makefile +++ b/manual/Makefile @@ -20,15 +20,15 @@ sphinx-pdf: doxygen PYTHONPATH=$(BOUT_TOP)/tools/pylib:$$PYTHONPATH $(sphinx-build) -b latex sphinx/ build/ cd build && latexmk -pdf BOUT -interaction=batchmode test -e BOUT.pdf || ln -s build/BOUT.pdf . - @echo "Documentation is available in $(pwd)/BOUT.pdf" + @echo "Documentation is available in $$(pwd)/BOUT.pdf" sphinx-html: doxygen PYTHONPATH=$(BOUT_TOP)/tools/pylib:$$PYTHONPATH $(sphinx-build) -b html sphinx/ html/ - @echo "Documentation available in file://$(pwd)/html/index.html" + @echo "Documentation available in file://$$(pwd)/html/index.html" sphinx-man: doxygen PYTHONPATH=$(BOUT_TOP)/tools/pylib:$$PYTHONPATH $(sphinx-build) -b man sphinx/ man/ - @echo "Documentation available in $(pwd)/man/bout.1" + @echo "Documentation available in $$(pwd)/man/bout.1" # Run doxygen, ignore if it fails (leading '-') doxygen: From a64fb1b739867d68ace52cf32ad204724a400257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 16 Jul 2020 09:52:34 +0200 Subject: [PATCH 175/293] auto-fix autoconf_build_defines.hxx.in auto(re)conf adds some non-bout related undefs to `autoconf_build_defines.hxx.in`. This patch removes them during configure - so autoconf && ./configure is giving the same results as just ./configure --- configure | 8 ++++++++ configure.ac | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/configure b/configure index dd1c3e9e94..055db82bf1 100755 --- a/configure +++ b/configure @@ -2769,6 +2769,14 @@ file_formats="" # Record which file formats are being supported # Delete the build log from last time rm -f config-build.log +# only keep BOUT related undefs +if ! grep -q 'NOTE TO DEVEL' autoconf_build_defines.hxx.in ; then + grep 'undef BOUT' -B 4 -A 1 autoconf_build_defines.hxx.in > autoconf_build_defines.hxx.in.tmp + echo '// NOTE TO DEVELOPERS: PLEASE KEEP THIS LINE AND DELETE AUTOGENERATED CONTENT BELOW!' >> autoconf_build_defines.hxx.in.tmp + mv autoconf_build_defines.hxx.in.tmp autoconf_build_defines.hxx.in +fi + + diff --git a/configure.ac b/configure.ac index 28c1d1271a..2865874fa4 100644 --- a/configure.ac +++ b/configure.ac @@ -104,6 +104,14 @@ file_formats="" # Record which file formats are being supported # Delete the build log from last time rm -f config-build.log +# only keep BOUT related undefs +if ! grep -q 'NOTE TO DEVEL' autoconf_build_defines.hxx.in ; then + grep 'undef BOUT' -B 4 -A 1 autoconf_build_defines.hxx.in > autoconf_build_defines.hxx.in.tmp + echo '// NOTE TO DEVELOPERS: PLEASE KEEP THIS LINE AND DELETE AUTOGENERATED CONTENT BELOW!' >> autoconf_build_defines.hxx.in.tmp + mv autoconf_build_defines.hxx.in.tmp autoconf_build_defines.hxx.in +fi + + AC_ARG_VAR(CXXFLAGS,[Extra compile flags]) AC_ARG_VAR(LDFLAGS,[Extra linking flags]) AC_ARG_VAR(LIBS,[Extra linking libraries]) From d426de4bfd21922ee471848e7b8c7c37703db450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 10:45:36 +0100 Subject: [PATCH 176/293] Fix unit tests The check must be after the value is defined --- tests/unit/field/test_vector2d.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/field/test_vector2d.cxx b/tests/unit/field/test_vector2d.cxx index 1e70072f5e..a036edcff8 100644 --- a/tests/unit/field/test_vector2d.cxx +++ b/tests/unit/field/test_vector2d.cxx @@ -1,7 +1,7 @@ -#if not(BOUT_USE_METRIC_3D) #include "gtest/gtest.h" #include "boutexception.hxx" +#if not(BOUT_USE_METRIC_3D) #include "output.hxx" #include "test_extras.hxx" #include "unused.hxx" From 87f879aa7d1bf67129de5549658306a2a8be84d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 10:46:02 +0100 Subject: [PATCH 177/293] fix the boutcore library New flags in new location ... --- tools/pylib/_boutcore_build/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pylib/_boutcore_build/common.sh b/tools/pylib/_boutcore_build/common.sh index a449f13a5b..2e53564780 100644 --- a/tools/pylib/_boutcore_build/common.sh +++ b/tools/pylib/_boutcore_build/common.sh @@ -21,7 +21,7 @@ makelist () { # What is the metric type? coords_is() { - if grep ^BOUT_FLAGS ../../../make.config| grep COORDINATES_USE_3D -q + if grep '^#define BOUT_USE_METRIC_3D 1' ../../../include/bout/build_defines.hxx -q then echo "f3d" else From 0e94f79c12a5d18608d60c2840fbffd88351e7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 12:15:08 +0100 Subject: [PATCH 178/293] fix bout-config --- bin/bout-config.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/bout-config.in b/bin/bout-config.in index e52ed36c79..f8da9fc803 100755 --- a/bin/bout-config.in +++ b/bin/bout-config.in @@ -44,7 +44,7 @@ has_fftw="@BOUT_HAS_FFTW@" petsc_has_sundials="@PETSC_HAS_SUNDIALS@" -metric_type="@METRIC_TYPE@" +metric_type="@BOUT_METRIC_TYPE@" usage() { From 93d879591532dac3c74327093a91ec838386ff8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 14:40:35 +0100 Subject: [PATCH 179/293] bout::build::use_metric_3d provide and use the constexpr bout::build::use_metric_3d --- include/bout/build_config.hxx | 1 + include/bout/coordinates.hxx | 6 +----- src/mesh/coordinates.cxx | 12 ++++-------- tests/unit/mesh/data/test_gridfromoptions.cxx | 7 +------ 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/include/bout/build_config.hxx b/include/bout/build_config.hxx index 138fbdd8e2..ebb7ca22f6 100644 --- a/include/bout/build_config.hxx +++ b/include/bout/build_config.hxx @@ -30,6 +30,7 @@ constexpr auto use_output_debug = static_cast(BOUT_USE_OUTPUT_DEBUG); constexpr auto use_sigfpe = static_cast(BOUT_USE_SIGFPE); constexpr auto use_signal = static_cast(BOUT_USE_SIGNAL); constexpr auto use_track = static_cast(BOUT_USE_TRACK); +constexpr auto use_metric_3d = static_cast(BOUT_USE_METRIC_3D); } // namespace build } // namespace bout diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 25091bcb1d..e5a88f9227 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -140,11 +140,7 @@ public: /// Return if the metrics are 3D // needs to be static for old gcc static constexpr bool is3D() { -#if BOUT_USE_METRIC_3D - return true; -#else - return false; -#endif + return bout::build::use_metric_3d; } /////////////////////////////////////////////////////////// diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 2c8e064d1a..c8a517c0f3 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1760,10 +1760,9 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, } ASSERT1(location == outloc); - auto sg = sqrt(g_22); - auto invSg = 1.0 / sg; + auto invSg = 1.0 / sqrt(g_22); communicate(invSg); - sg = DDY(invSg, outloc, method) * invSg; + auto sg = DDY(invSg, outloc, method) * invSg; Field3D result = ::DDY(f, outloc, method); @@ -1809,8 +1808,7 @@ Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(bool Field3D result{emptyFrom(f).setLocation(outloc)}; -#if not(BOUT_USE_METRIC_3D) - if (useFFT) { + if (useFFT and not bout::build::use_metric_3d) { int ncz = localmesh->LocalNz; // Allocate memory @@ -1845,9 +1843,7 @@ Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(bool irfft(&delft(jx, 0), ncz, &result(jx, jy, 0)); } } - } else -#endif - { + } else { result = G1 * ::DDX(f, outloc) + G3 * ::DDZ(f, outloc) + g11 * ::D2DX2(f, outloc) + g33 * ::D2DZ2(f, outloc) + 2 * g13 * ::D2DXDZ(f, outloc); }; diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index d824769182..aeefc44122 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -62,12 +62,7 @@ class GridFromOptionsTest : public ::testing::Test { return index.x() + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; }, &mesh_from_options); - expected_metric = -#if BOUT_USE_METRIC_3D - expected_3d; -#else - expected_2d; -#endif + expected_metric = bout::build::use_metric_3d ? expected_3d : expected_2d; } ~GridFromOptionsTest() override { From 535a29d8d938da8b93897d653a17d172e8d3771e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 15:21:17 +0100 Subject: [PATCH 180/293] rename metric_field_type to FieldMetric --- examples/elm-pb/elm_pb.cxx | 4 +- examples/gyro-gem/gem.cxx | 2 +- examples/lapd-drift/lapd_drift.cxx | 8 +- include/bout/coordinates.hxx | 64 +++++++-------- include/derivs.hxx | 78 +++++++++---------- include/difops.hxx | 52 ++++++------- include/vecops.hxx | 6 +- include/vector2d.hxx | 8 +- src/field/vecops.cxx | 10 +-- src/field/vector2d.cxx | 10 +-- src/mesh/coordinates.cxx | 34 ++++---- src/mesh/difops.cxx | 52 ++++++------- src/sys/derivs.cxx | 38 ++++----- tests/unit/mesh/data/test_gridfromoptions.cxx | 8 +- 14 files changed, 187 insertions(+), 187 deletions(-) diff --git a/examples/elm-pb/elm_pb.cxx b/examples/elm-pb/elm_pb.cxx index 86d4f1320d..e31d3b914c 100644 --- a/examples/elm-pb/elm_pb.cxx +++ b/examples/elm-pb/elm_pb.cxx @@ -27,10 +27,10 @@ class ELMpb : public PhysicsModel { Field2D J0, P0; // Current and pressure Vector2D b0xcv; // Curvature term Field2D beta; // Used for Vpar terms - Coordinates::metric_field_type gradparB; + Coordinates::FieldMetric gradparB; Field2D phi0; // When diamagnetic terms used Field2D Psixy, x; - Coordinates::metric_field_type U0; // 0th vorticity of equilibrium flow, + Coordinates::FieldMetric U0; // 0th vorticity of equilibrium flow, // radial flux coordinate, normalized radial flux coordinate bool constn0; diff --git a/examples/gyro-gem/gem.cxx b/examples/gyro-gem/gem.cxx index 285455050d..3039110965 100644 --- a/examples/gyro-gem/gem.cxx +++ b/examples/gyro-gem/gem.cxx @@ -58,7 +58,7 @@ class GEM : public PhysicsModel { Vector3D B0vec; // Equilibrium B field vector Field2D logB; // For curvature - Coordinates::metric_field_type Grad_par_logB; // Grad_par(log(B)) + Coordinates::FieldMetric Grad_par_logB; // Grad_par(log(B)) Field2D Ni0, Ne0; // Gyro-center densities Field2D Ti0, Te0; // Starting isotropic temperatures diff --git a/examples/lapd-drift/lapd_drift.cxx b/examples/lapd-drift/lapd_drift.cxx index 356ffefa6b..78e207fee9 100644 --- a/examples/lapd-drift/lapd_drift.cxx +++ b/examples/lapd-drift/lapd_drift.cxx @@ -21,7 +21,7 @@ class LAPDdrift : public PhysicsModel { private: // 2D initial profiles Field2D Ni0, Ti0, Te0, Vi0, phi0, Ve0, Ajpar0, src_ni0; - Coordinates::metric_field_type rho0; + Coordinates::FieldMetric rho0; Vector2D b0xcv; // for curvature terms // 3D evolving fields @@ -728,7 +728,7 @@ class LAPDdrift : public PhysicsModel { /****************SPECIAL DIFFERENTIAL OPERATORS******************/ - Coordinates::metric_field_type Perp_Grad_dot_Grad(const Field2D& p, const Field2D& f) { + Coordinates::FieldMetric Perp_Grad_dot_Grad(const Field2D& p, const Field2D& f) { return DDX(p)*DDX(f)*mesh->getCoordinates()->g11; } @@ -738,8 +738,8 @@ class LAPDdrift : public PhysicsModel { // ExB terms. These routines allow comparisons with BOUT-06 // if bout_exb=true is set in BOUT.inp ///////////////////////////////////////////////////////////////// - Coordinates::metric_field_type vE_Grad(const Field2D& f, const Field2D& p) { - Coordinates::metric_field_type result; + Coordinates::FieldMetric vE_Grad(const Field2D& f, const Field2D& p) { + Coordinates::FieldMetric result; if (bout_exb) { // Use a subset of terms for comparison to BOUT-06 result = 0.0; diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index e5a88f9227..df126b1d34 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -51,9 +51,9 @@ class Mesh; class Coordinates { public: #if BOUT_USE_METRIC_3D - using metric_field_type = Field3D; + using FieldMetric = Field3D; #else - using metric_field_type = Field2D; + using FieldMetric = Field2D; #endif /// Standard constructor from input @@ -88,7 +88,7 @@ public: */ void outputVars(Datafile &file); - metric_field_type dx, dy, dz; ///< Mesh spacing in x and y + FieldMetric dx, dy, dz; ///< Mesh spacing in x and y // BoutReal dz; ///< Mesh spacing in Z Field2D zlength() const { @@ -104,29 +104,29 @@ public: /// True if corrections for non-uniform mesh spacing should be included in operators bool non_uniform; /// 2nd-order correction for non-uniform meshes d/di(1/dx), d/di(1/dy) and d/di(1/dz) - metric_field_type d1_dx, d1_dy, d1_dz; + FieldMetric d1_dx, d1_dy, d1_dz; - metric_field_type J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz + FieldMetric J; ///< Coordinate system Jacobian, so volume of cell is J*dx*dy*dz - metric_field_type Bxy; ///< Magnitude of B = nabla z times nabla x + FieldMetric Bxy; ///< Magnitude of B = nabla z times nabla x /// Contravariant metric tensor (g^{ij}) - metric_field_type g11, g22, g33, g12, g13, g23; + FieldMetric g11, g22, g33, g12, g13, g23; /// Covariant metric tensor - metric_field_type g_11, g_22, g_33, g_12, g_13, g_23; + FieldMetric g_11, g_22, g_33, g_12, g_13, g_23; /// Christoffel symbol of the second kind (connection coefficients) - metric_field_type G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; - metric_field_type G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; - metric_field_type G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; + FieldMetric G1_11, G1_22, G1_33, G1_12, G1_13, G1_23; + FieldMetric G2_11, G2_22, G2_33, G2_12, G2_13, G2_23; + FieldMetric G3_11, G3_22, G3_33, G3_12, G3_13, G3_23; - metric_field_type G1, G2, G3; + FieldMetric G1, G2, G3; /// d pitch angle / dx. Needed for vector differentials (Curl) - metric_field_type ShiftTorsion; + FieldMetric ShiftTorsion; - metric_field_type IntShiftTorsion; ///< Integrated shear (I in BOUT notation) + FieldMetric IntShiftTorsion; ///< Integrated shear (I in BOUT notation) /// Calculate differential geometry quantities from the metric tensor int geometry(bool recalculate_staggered = true, @@ -196,20 +196,20 @@ public: } #endif - metric_field_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); - DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, metric_field_type, Field2D); + DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, FieldMetric, Field2D); - metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); - DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, metric_field_type, Field2D); + DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, FieldMetric, Field2D); - metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); - DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, metric_field_type, Field2D); + DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, FieldMetric, Field2D); Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", @@ -224,22 +224,22 @@ public: const std::string& region = "RGN_NOBNDRY"); /// Gradient along magnetic field b.Grad(f) - metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - GRAD_FUNC_REGION_ENUM_TO_STRING(Grad_par, metric_field_type, Field2D); + GRAD_FUNC_REGION_ENUM_TO_STRING(Grad_par, FieldMetric, Field2D); Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Grad_par, Field3D, Field3D); /// Advection along magnetic field V*b.Grad(f) - metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, + FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); [[deprecated( "Please use Coordinates::Vpar_Grad_par(const Field2D& v, " "const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " - "const std::string& method = \"DEFAULT\") instead")]] inline metric_field_type + "const std::string& method = \"DEFAULT\") instead")]] inline FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } @@ -255,18 +255,18 @@ public: } /// Divergence along magnetic field Div(b*f) = B.Grad(f/B) - metric_field_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - GRAD_FUNC_REGION_ENUM_TO_STRING(Div_par, metric_field_type, Field2D); + GRAD_FUNC_REGION_ENUM_TO_STRING(Div_par, FieldMetric, Field2D); Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Div_par, Field3D, Field3D); // Second derivative along magnetic field - metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); - GRAD_FUNC_REGION_ENUM_TO_STRING(Grad2_par2, metric_field_type, Field2D); + GRAD_FUNC_REGION_ENUM_TO_STRING(Grad2_par2, FieldMetric, Field2D); Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); @@ -278,18 +278,18 @@ public: // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code // since it makes use of the same coefficients and FFT routines - metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); // Full parallel Laplacian operator on scalar field // Laplace_par(f) = Div( b (b dot Grad(f)) ) - metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); + FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Laplace_par(const Field3D &f, CELL_LOC outloc=CELL_DEFAULT); // Full Laplacian operator on scalar field - metric_field_type Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_conditions = "free_o3", const std::string& dfdy_dy_region = ""); Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, @@ -335,7 +335,7 @@ private: /// A wrapper for index:DDY derivative that is able to tranform /// fields before the constructor is finished. - Coordinates::metric_field_type indexDDY(const Field2D& f, + Coordinates::FieldMetric indexDDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); diff --git a/include/derivs.hxx b/include/derivs.hxx index b49d9353e7..95939b5c09 100644 --- a/include/derivs.hxx +++ b/include/derivs.hxx @@ -106,10 +106,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, Field2D, Coordinates::FieldMetric) /// Calculate first partial derivative in Y /// @@ -139,10 +139,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field2D, Coordinates::FieldMetric) /// Calculate first partial derivative in Z /// @@ -172,10 +172,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field2D, Coordinates::FieldMetric) /// Calculate first partial derivative in Z /// @@ -239,10 +239,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field2D, Coordinates::FieldMetric) /// Calculate second partial derivative in Y /// @@ -272,10 +272,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field2D, Coordinates::FieldMetric) /// Calculate second partial derivative in Z /// @@ -305,10 +305,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field2D, Coordinates::FieldMetric) ////////// FOURTH DERIVATIVES ////////// @@ -340,10 +340,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field2D, Coordinates::FieldMetric) /// Calculate forth partial derivative in Y /// @@ -373,10 +373,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field2D, Coordinates::FieldMetric) /// Calculate forth partial derivative in Z /// @@ -406,10 +406,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field2D, Coordinates::FieldMetric) /// For terms of form v * grad(f) /// @@ -441,11 +441,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Coordinates::metric_field_type, Field2D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Coordinates::FieldMetric, Field2D, Field2D) /// For terms of form v * grad(f) /// @@ -477,11 +477,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Coordinates::metric_field_type, Field2D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Coordinates::FieldMetric, Field2D, Field2D) /// For terms of form v * grad(f) /// @@ -513,11 +513,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::metric_field_type, Field2D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::FieldMetric, Field2D, Field2D) /// For terms of form v * grad(f) /// @@ -532,11 +532,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::metric_field_type, Field2D, /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type VDDZ(const Field3D& v, const Field2D& f, +Coordinates::FieldMetric VDDZ(const Field3D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::metric_field_type, Field3D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::FieldMetric, Field3D, Field2D) /// for terms of form div(v * f) /// @@ -568,11 +568,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Coordinates::metric_field_type, Field2D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Coordinates::FieldMetric, Field2D, Field2D) /// for terms of form div(v * f) /// @@ -604,11 +604,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Coordinates::metric_field_type, Field2D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Coordinates::FieldMetric, Field2D, Field2D) /// for terms of form div(v * f) /// @@ -640,11 +640,11 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Field3D, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Coordinates::metric_field_type, Field2D, Field2D) +VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Coordinates::FieldMetric, Field2D, Field2D) /// Calculate mixed partial derivative in x and y /// @@ -707,7 +707,7 @@ D2DXDY(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RG /// (default) then the same as the region for the calculation as a /// whole. If dfdy_region < region in size then this will cause /// errors. -Coordinates::metric_field_type +Coordinates::FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY", const std::string& dfdy_boundary_condition = "free_o3", @@ -716,7 +716,7 @@ D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, "Please use D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " "const std::string& method = \"DEFAULT\", const std::string& region = \"RGN_ALL\", " "const std::string& dfdy_boundary_condition) instead")]] inline Coordinates:: - metric_field_type + FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc, const std::string& method, REGION region, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = "") { @@ -727,7 +727,7 @@ D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, "Please use D2DXDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " "const std::string& method = \"DEFAULT\", const std::string& region = \"RGN_ALL\", " "const std::string& dfdy_boundary_condition) instead")]] inline Coordinates:: - metric_field_type + FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method, REGION region = RGN_NOBNDRY, const std::string& dfdy_boundary_condition = "free_o3", @@ -764,10 +764,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field2D, Coordinates::FieldMetric) /// Calculate mixed partial derivative in y and z /// @@ -797,10 +797,10 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field3D, Field3D) /// If not given, defaults to DIFF_DEFAULT /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY -Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); -DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field2D, Coordinates::metric_field_type) +DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field2D, Coordinates::FieldMetric) #undef DERIV_FUNC_REGION_ENUM_TO_STRING #undef VDERIV_FUNC_REGION_ENUM_TO_STRING diff --git a/include/difops.hxx b/include/difops.hxx index 206a9fa58f..73eb5b7631 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -53,17 +53,17 @@ * enabled) * @param[in] method The method to use. The default is set in the options. */ -Coordinates::metric_field_type Grad_par(const Field2D& var, +Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -DEPRECATED(Coordinates::metric_field_type Grad_par(const Field2D& var, +DEPRECATED(Coordinates::FieldMetric Grad_par(const Field2D& var, const std::string& method, CELL_LOC outloc = CELL_DEFAULT)); -inline Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, +inline Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc, DIFF_METHOD method) { return Grad_par(var, outloc, toString(method)); } -DEPRECATED(inline Coordinates::metric_field_type Grad_par(const Field2D& var, +DEPRECATED(inline Coordinates::FieldMetric Grad_par(const Field2D& var, DIFF_METHOD method, CELL_LOC outloc)) { return Grad_par(var, outloc, toString(method)); @@ -108,18 +108,18 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f); * @param[in] method The numerical method to use. The default is set in the options * */ -Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -DEPRECATED(Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, +DEPRECATED(Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, const std::string& method, CELL_LOC outloc = CELL_DEFAULT)); -inline Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, +inline Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } -DEPRECATED(inline Coordinates::metric_field_type Vpar_Grad_par( +DEPRECATED(inline Coordinates::FieldMetric Vpar_Grad_par( const Field2D& v, const Field2D& f, DIFF_METHOD method, CELL_LOC outloc)) { return Vpar_Grad_par(v, f, outloc, toString(method)); } @@ -150,16 +150,16 @@ DEPRECATED(inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, * @param[in] method The numerical method to use * */ -Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -DEPRECATED(Coordinates::metric_field_type Div_par(const Field2D& f, +DEPRECATED(Coordinates::FieldMetric Div_par(const Field2D& f, const std::string& method, CELL_LOC outloc = CELL_DEFAULT)); -inline Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, +inline Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Div_par(f, outloc, toString(method)); } -DEPRECATED(inline Coordinates::metric_field_type Div_par(const Field2D& f, +DEPRECATED(inline Coordinates::FieldMetric Div_par(const Field2D& f, DIFF_METHOD method, CELL_LOC outloc)) { return Div_par(f, outloc, toString(method)); @@ -211,10 +211,10 @@ DEPRECATED(inline Field3D Div_par_flux(const Field3D& v, const Field3D& f, * @param[in] f The field to be differentiated * @param[in] outloc The cell location of the result */ -Coordinates::metric_field_type Grad2_par2(const Field2D& f, +Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -inline Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, +inline Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Grad2_par2(f, outloc, toString(method)); } @@ -236,7 +236,7 @@ Grad_par_CtoL(const Field3D& var) { return Grad_par(var, CELL_YLOW); } [[deprecated("Grad_par_CtoL is deprecated. Staggering is now supported in " - "Grad_par.")]] inline Coordinates::metric_field_type + "Grad_par.")]] inline Coordinates::FieldMetric Grad_par_CtoL(const Field2D& var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Grad_par(var, CELL_YLOW); @@ -263,7 +263,7 @@ Grad_par_LtoC(const Field3D& var) { return Grad_par(var, CELL_CENTRE); } [[deprecated("Grad_par_LtoC is deprecated. Staggering is now supported in " - "Grad_par.")]] inline Coordinates::metric_field_type + "Grad_par.")]] inline Coordinates::FieldMetric Grad_par_LtoC(const Field2D& var) { ASSERT2(var.getLocation() == CELL_YLOW); return Grad_par(var, CELL_CENTRE); @@ -275,7 +275,7 @@ Div_par_LtoC(const Field3D& var) { return Div_par(var, CELL_CENTRE); } [[deprecated("Div_par_LtoC is deprecated. Staggering is now supported in " - "Grad_par.")]] inline Coordinates::metric_field_type + "Grad_par.")]] inline Coordinates::FieldMetric Div_par_LtoC(const Field2D& var) { ASSERT2(var.getLocation() == CELL_YLOW); return Div_par(var, CELL_CENTRE); @@ -287,7 +287,7 @@ Div_par_CtoL(const Field3D& var) { return Div_par(var, CELL_YLOW); } [[deprecated("Div_par_CtoL is deprecated. Staggering is now supported in " - "Grad_par.")]] inline Coordinates::metric_field_type + "Grad_par.")]] inline Coordinates::FieldMetric Div_par_CtoL(const Field2D& var) { ASSERT2(var.getLocation() == CELL_CENTRE); return Div_par(var, CELL_YLOW); @@ -303,10 +303,10 @@ Div_par_CtoL(const Field2D& var) { * @param[in] kY The diffusion coefficient * @param[in] f The field whose gradient drives a flux */ -Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, +Coordinates::FieldMetric Div_par_K_Grad_par(BoutReal kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); -Coordinates::metric_field_type Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, +Coordinates::FieldMetric Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Div_par_K_Grad_par(const Field2D& kY, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); @@ -324,7 +324,7 @@ Field3D Div_par_K_Grad_par(const Field3D& kY, const Field3D& f, * * For the full perpendicular Laplacian, use Laplace_perp */ -Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, +Coordinates::FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); @@ -334,7 +334,7 @@ FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT * * */ -Coordinates::metric_field_type +Coordinates::FieldMetric Laplace_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -346,14 +346,14 @@ Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, * Parallel Laplacian operator * */ -Coordinates::metric_field_type Laplace_par(const Field2D& f, +Coordinates::FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Laplace_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); /*! * Full Laplacian operator (par + perp) */ -Coordinates::metric_field_type +Coordinates::FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -370,7 +370,7 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); * Terms of form b0 x Grad(phi) dot Grad(A) * */ -Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, +Coordinates::FieldMetric b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc = CELL_DEFAULT); /*! @@ -423,7 +423,7 @@ constexpr BRACKET_METHOD BRACKET_ARAKAWA_OLD = BRACKET_METHOD::arakawa_old; * @param[in] solver Pointer to the time integration solver * */ -Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, +Coordinates::FieldMetric bracket(const Field2D& f, const Field2D& g, BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); diff --git a/include/vecops.hxx b/include/vecops.hxx index deae65ed03..d852ad4c2c 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -87,13 +87,13 @@ const Vector2D Grad_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, /// @param[in] outloc The cell location where the result is desired /// @param[in] method The method to use. The default is set in the options. /// -const Coordinates::metric_field_type Div(const Vector2D& v, +const Coordinates::FieldMetric Div(const Vector2D& v, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); const Field3D Div(const Vector3D& v, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); -const Coordinates::metric_field_type Div(const Vector2D& v, const Field2D& f, +const Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT"); @@ -134,7 +134,7 @@ const Vector3D Curl(const Vector3D &v); /// /// The vector and the field must be at the same location, which /// cannot be CELL_VSHIFT -const Coordinates::metric_field_type V_dot_Grad(const Vector2D& v, const Field2D& f); +const Coordinates::FieldMetric 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); diff --git a/include/vector2d.hxx b/include/vector2d.hxx index f886f2121d..f6751247bd 100644 --- a/include/vector2d.hxx +++ b/include/vector2d.hxx @@ -57,7 +57,7 @@ public: ~Vector2D() override; - Coordinates::metric_field_type x, y, z; ///< components + Coordinates::FieldMetric x, y, z; ///< components bool covariant{true}; ///< true if the components are covariant (default) @@ -128,7 +128,7 @@ public: const Vector2D operator/(const Field2D &rhs) const; ///< Divides all components by \p rhs const Vector3D operator/(const Field3D &rhs) const; ///< Divides all components by \p rhs - const Coordinates::metric_field_type + const Coordinates::FieldMetric operator*(const Vector2D& rhs) const; ///< Dot product const Field3D operator*(const Vector3D &rhs) const; ///< Dot product @@ -181,12 +181,12 @@ const Vector3D cross(const Vector2D & lhs, const Vector3D &rhs); * * |v| = sqrt( v dot v ) */ -const Coordinates::metric_field_type abs(const Vector2D& v, +const Coordinates::FieldMetric abs(const Vector2D& v, const std::string& region = "RGN_ALL"); [[deprecated( "Please use Vector2D abs(const Vector2D& f, " "const std::string& region = \"RGN_ALL\") instead")]] inline const Coordinates:: - metric_field_type + FieldMetric abs(const Vector2D& v, REGION region) { return abs(v, toString(region)); } diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 27856eb840..f8e1eec0bd 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -143,7 +143,7 @@ const Vector2D Grad_perp(const Field2D &f, CELL_LOC outloc, const std::string& m * Divergence operators **************************************************************************/ -const Coordinates::metric_field_type Div(const Vector2D& v, CELL_LOC outloc, +const Coordinates::FieldMetric Div(const Vector2D& v, CELL_LOC outloc, const std::string& method) { TRACE("Div( Vector2D )"); SCOREP0(); @@ -161,7 +161,7 @@ const Coordinates::metric_field_type Div(const Vector2D& v, CELL_LOC outloc, Vector2D vcn = v; vcn.toContravariant(); - Coordinates::metric_field_type result = DDX(metric->J * vcn.x, outloc, method); + Coordinates::FieldMetric result = DDX(metric->J * vcn.x, outloc, method); result += DDY(metric->J*vcn.y, outloc, method); result += DDZ(metric->J*vcn.z, outloc, method); result /= metric->J; @@ -204,7 +204,7 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) * Divergence operators for flux methods **************************************************************************/ -const Coordinates::metric_field_type Div(const Vector2D& v, const Field2D& f, +const Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method) { TRACE("Div( Vector2D, Field2D )"); SCOREP0(); @@ -222,7 +222,7 @@ const Coordinates::metric_field_type Div(const Vector2D& v, const Field2D& f, Vector2D vcn = v; vcn.toContravariant(); - Coordinates::metric_field_type result = + Coordinates::FieldMetric 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); @@ -319,7 +319,7 @@ const Vector3D Curl(const Vector3D &v) { /************************************************************************** * Upwinding operators **************************************************************************/ -const Coordinates::metric_field_type V_dot_Grad(const Vector2D& v, const Field2D& f) { +const Coordinates::FieldMetric V_dot_Grad(const Vector2D& v, const Field2D& f) { TRACE("V_dot_Grad( Vector2D , Field2D )"); SCOREP0(); diff --git a/src/field/vector2d.cxx b/src/field/vector2d.cxx index 96568e75f3..860989e913 100644 --- a/src/field/vector2d.cxx +++ b/src/field/vector2d.cxx @@ -94,7 +94,7 @@ void Vector2D::toCovariant() { const auto metric = localmesh->getCoordinates(location); // Need to use temporary arrays to store result - Coordinates::metric_field_type gx{emptyFrom(x)}, gy{emptyFrom(y)}, gz{emptyFrom(z)}; + Coordinates::FieldMetric gx{emptyFrom(x)}, gy{emptyFrom(y)}, gz{emptyFrom(z)}; BOUT_FOR(i, x.getRegion("RGN_ALL")) { gx[i] = metric->g_11[i]*x[i] + metric->g_12[i]*y[i] + metric->g_13[i]*z[i]; @@ -146,7 +146,7 @@ void Vector2D::toContravariant() { const auto metric = localmesh->getCoordinates(location); // Need to use temporary arrays to store result - Coordinates::metric_field_type gx{emptyFrom(x)}, gy{emptyFrom(y)}, gz{emptyFrom(z)}; + Coordinates::FieldMetric gx{emptyFrom(x)}, gy{emptyFrom(y)}, gz{emptyFrom(z)}; BOUT_FOR(i, x.getRegion("RGN_ALL")) { gx[i] = metric->g11[i]*x[i] + metric->g12[i]*y[i] + metric->g13[i]*z[i]; @@ -371,11 +371,11 @@ const Vector3D Vector2D::operator/(const Field3D &rhs) const { ////////////////// DOT PRODUCT /////////////////// -const Coordinates::metric_field_type Vector2D::operator*(const Vector2D& rhs) const { +const Coordinates::FieldMetric Vector2D::operator*(const Vector2D& rhs) const { ASSERT2(location == rhs.getLocation()); Mesh *localmesh = x.getMesh(); - Coordinates::metric_field_type result{emptyFrom(x)}; + Coordinates::FieldMetric result{emptyFrom(x)}; if(rhs.covariant ^ covariant) { // Both different - just multiply components @@ -474,7 +474,7 @@ const Vector3D operator*(const Field3D &lhs, const Vector2D &rhs) { ***************************************************************/ // Return the magnitude of a vector -const Coordinates::metric_field_type abs(const Vector2D& v, const std::string& region) { +const Coordinates::FieldMetric abs(const Vector2D& v, const std::string& region) { return sqrt(v*v, region); } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index c8a517c0f3..e509247956 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -311,7 +311,7 @@ void checkStaggeredGet(Mesh* mesh, const std::string& name, const std::string& s } // convenience function for repeated code -int getAtLoc(Mesh* mesh, Coordinates::metric_field_type& var, const std::string& name, +int getAtLoc(Mesh* mesh, Coordinates::FieldMetric& var, const std::string& name, const std::string& suffix, CELL_LOC location, BoutReal default_value = 0.) { checkStaggeredGet(mesh, name, suffix); @@ -626,17 +626,17 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // use anonymous namespace so this utility function is not available outside this file namespace { -/// Interpolate a metric_field_type to a new CELL_LOC with interp_to. +/// Interpolate a FieldMetric to a new CELL_LOC with interp_to. /// Communicates to set internal guard cells. /// Boundary guard cells are set equal to the nearest grid point (equivalent to /// 2nd order accurate Neumann boundary condition). /// Corner guard cells are set to BoutNaN -Coordinates::metric_field_type -interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::metric_field_type& f), +Coordinates::FieldMetric +interpolateAndNeumann(MAYBE_UNUSED(const Coordinates::FieldMetric& f), MAYBE_UNUSED(CELL_LOC location), MAYBE_UNUSED(ParallelTransform* pt)) { Mesh* localmesh = f.getMesh(); - Coordinates::metric_field_type result; + Coordinates::FieldMetric result; #if BOUT_USE_METRIC_3D if (location == CELL_YLOW) { auto f_aligned = f.getCoordinates() == nullptr ? pt->toFieldAligned(f, "RGN_NOX") @@ -1234,7 +1234,7 @@ int Coordinates::geometry(bool recalculate_staggered, OPTION(Options::getRoot(), non_uniform, true); - Coordinates::metric_field_type d2x(localmesh), d2y(localmesh), + Coordinates::FieldMetric d2x(localmesh), d2y(localmesh), d2z(localmesh); // d^2 x / d i^2 // Read correction for non-uniform meshes @@ -1611,7 +1611,7 @@ void Coordinates::setParallelTransform(Options* options) { * *******************************************************************************/ -Coordinates::metric_field_type Coordinates::DDX(const Field2D& f, CELL_LOC loc, +Coordinates::FieldMetric Coordinates::DDX(const Field2D& f, CELL_LOC loc, const std::string& method, const std::string& region) { ASSERT1(location == loc || loc == CELL_DEFAULT); @@ -1631,7 +1631,7 @@ Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, const std::string& m return result; }; -Coordinates::metric_field_type Coordinates::DDY(const Field2D& f, CELL_LOC loc, +Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, const std::string& method, const std::string& region) { ASSERT1(location == loc || loc == CELL_DEFAULT); @@ -1643,7 +1643,7 @@ Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& m return indexDDY(f, outloc, method, region) / dy; }; -Coordinates::metric_field_type Coordinates::DDZ(const Field2D& f, CELL_LOC loc, +Coordinates::FieldMetric Coordinates::DDZ(const Field2D& f, CELL_LOC loc, const std::string& UNUSED(method), const std::string& UNUSED(region)) { ASSERT1(location == loc || loc == CELL_DEFAULT); @@ -1661,7 +1661,7 @@ Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, const std::string& m ///////////////////////////////////////////////////////// // Parallel gradient -Coordinates::metric_field_type Coordinates::Grad_par(const Field2D& var, +Coordinates::FieldMetric Coordinates::Grad_par(const Field2D& var, MAYBE_UNUSED(CELL_LOC outloc), const std::string& UNUSED(method)) { TRACE("Coordinates::Grad_par( Field2D )"); @@ -1683,7 +1683,7 @@ Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, // Vpar_Grad_par // vparallel times the parallel derivative along unperturbed B-field -Coordinates::metric_field_type +Coordinates::FieldMetric Coordinates::Vpar_Grad_par(const Field2D& v, const Field2D& f, MAYBE_UNUSED(CELL_LOC outloc), const std::string& UNUSED(method)) { @@ -1700,7 +1700,7 @@ Field3D Coordinates::Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC ///////////////////////////////////////////////////////// // Parallel divergence -Coordinates::metric_field_type Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Div_par( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1739,7 +1739,7 @@ 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 -Coordinates::metric_field_type Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& method) { TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); @@ -1780,7 +1780,7 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, #include // Delp2 uses same coefficients as inversion code -Coordinates::metric_field_type Coordinates::Delp2(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Coordinates::Delp2(const Field2D& f, CELL_LOC outloc, bool UNUSED(useFFT)) { TRACE("Coordinates::Delp2( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1915,7 +1915,7 @@ FieldPerp Coordinates::Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { return result; } -Coordinates::metric_field_type Coordinates::Laplace_par(const Field2D& f, +Coordinates::FieldMetric Coordinates::Laplace_par(const Field2D& f, CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * DDY(f, outloc) / J; @@ -1928,7 +1928,7 @@ Field3D Coordinates::Laplace_par(const Field3D& f, CELL_LOC outloc) { // Full Laplacian operator on scalar field -Coordinates::metric_field_type +Coordinates::FieldMetric Coordinates::Laplace(const Field2D& f, CELL_LOC outloc, const std::string& dfdy_boundary_conditions, const std::string& dfdy_dy_region) { @@ -2023,7 +2023,7 @@ Field2D Coordinates::Laplace_perpXY(const Field2D& A, const Field2D& f) { #endif } -Coordinates::metric_field_type Coordinates::indexDDY(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Coordinates::indexDDY(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { #if BOUT_USE_METRIC_3D diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index cc2e2ab85c..13bbb57747 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -47,12 +47,12 @@ * The parallel derivative along unperturbed B-field *******************************************************************************/ -Coordinates::metric_field_type Grad_par(const Field2D& var, CELL_LOC outloc, +Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc, const std::string& method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } -Coordinates::metric_field_type Grad_par(const Field2D& var, const std::string& method, +Coordinates::FieldMetric Grad_par(const Field2D& var, const std::string& method, CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } @@ -190,12 +190,12 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f) { * vparallel times the parallel derivative along unperturbed B-field *******************************************************************************/ -Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } -Coordinates::metric_field_type Vpar_Grad_par(const Field2D& v, const Field2D& f, +Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, const std::string& method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } @@ -214,12 +214,12 @@ Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, const std::string& met * Div_par * parallel divergence operator B \partial_{||} (F/B) *******************************************************************************/ -Coordinates::metric_field_type Div_par(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } -Coordinates::metric_field_type Div_par(const Field2D& f, const std::string& method, +Coordinates::FieldMetric Div_par(const Field2D& f, const std::string& method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } @@ -308,7 +308,7 @@ Field3D Div_par_flux(const Field3D& v, const Field3D& f, const std::string& meth * Note: For parallel Laplacian use LaplacePar *******************************************************************************/ -Coordinates::metric_field_type Grad2_par2(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } @@ -322,7 +322,7 @@ Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, const std::string& method) * Parallel divergence of diffusive flux, K*Grad_par *******************************************************************************/ -Coordinates::metric_field_type Div_par_K_Grad_par(BoutReal kY, const Field2D& f, +Coordinates::FieldMetric Div_par_K_Grad_par(BoutReal kY, const Field2D& f, CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } @@ -331,7 +331,7 @@ Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } -Coordinates::metric_field_type Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, +Coordinates::FieldMetric Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); @@ -361,7 +361,7 @@ Field3D Div_par_K_Grad_par(const Field3D& kY, const Field3D& f, CELL_LOC outloc) * perpendicular Laplacian operator *******************************************************************************/ -Coordinates::metric_field_type Delp2(const Field2D& f, CELL_LOC outloc, bool useFFT) { +Coordinates::FieldMetric Delp2(const Field2D& f, CELL_LOC outloc, bool useFFT) { return f.getCoordinates(outloc)->Delp2(f, outloc, useFFT); } @@ -380,7 +380,7 @@ FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { * Laplace_perp = Laplace - Laplace_par *******************************************************************************/ -Coordinates::metric_field_type Laplace_perp(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Laplace_perp(const Field2D& f, CELL_LOC outloc, const std::string& dfdy_boundary_condition, const std::string& dfdy_region) { return Laplace(f, outloc, dfdy_boundary_condition, dfdy_region) @@ -402,7 +402,7 @@ Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc, * *******************************************************************************/ -Coordinates::metric_field_type Laplace_par(const Field2D& f, CELL_LOC outloc) { +Coordinates::FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc) { return f.getCoordinates(outloc)->Laplace_par(f, outloc); } @@ -415,7 +415,7 @@ Field3D Laplace_par(const Field3D& f, CELL_LOC outloc) { * Full Laplacian operator on scalar field *******************************************************************************/ -Coordinates::metric_field_type Laplace(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric Laplace(const Field2D& f, CELL_LOC outloc, const std::string& dfdy_boundary_condition, const std::string& dfdy_region) { return f.getCoordinates(outloc)->Laplace(f, outloc, dfdy_boundary_condition, @@ -444,7 +444,7 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f) { * Used for ExB terms and perturbed B field using A_|| *******************************************************************************/ -Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, +Coordinates::FieldMetric b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field2D , Field2D )"); @@ -456,15 +456,15 @@ Coordinates::metric_field_type b0xGrad_dot_Grad(const Field2D& phi, const Field2 Coordinates *metric = phi.getCoordinates(outloc); // Calculate phi derivatives - Coordinates::metric_field_type dpdx = DDX(phi, outloc); - Coordinates::metric_field_type dpdy = DDY(phi, outloc); + Coordinates::FieldMetric dpdx = DDX(phi, outloc); + Coordinates::FieldMetric dpdy = DDY(phi, outloc); // Calculate advection velocity - Coordinates::metric_field_type vx = -metric->g_23 * dpdy; - Coordinates::metric_field_type vy = metric->g_23 * dpdx; + Coordinates::FieldMetric vx = -metric->g_23 * dpdy; + Coordinates::FieldMetric vy = metric->g_23 * dpdx; // Upwind A using these velocities - Coordinates::metric_field_type result = VDDX(vx, A, outloc) + VDDY(vy, A, outloc); + Coordinates::FieldMetric result = VDDX(vx, A, outloc) + VDDY(vy, A, outloc); result /= metric->J*sqrt(metric->g_22); ASSERT1(result.getLocation() == outloc); @@ -487,13 +487,13 @@ Field3D b0xGrad_dot_Grad(const Field2D& phi, const Field3D& A, CELL_LOC outloc) Coordinates *metric = phi.getCoordinates(outloc); // Calculate phi derivatives - Coordinates::metric_field_type dpdx = DDX(phi, outloc); - Coordinates::metric_field_type dpdy = DDY(phi, outloc); + Coordinates::FieldMetric dpdx = DDX(phi, outloc); + Coordinates::FieldMetric dpdy = DDY(phi, outloc); // Calculate advection velocity - Coordinates::metric_field_type vx = -metric->g_23 * dpdy; - Coordinates::metric_field_type vy = metric->g_23 * dpdx; - Coordinates::metric_field_type vz = metric->g_12 * dpdy - metric->g_22 * dpdx; + Coordinates::FieldMetric vx = -metric->g_23 * dpdy; + Coordinates::FieldMetric vy = metric->g_23 * dpdx; + Coordinates::FieldMetric vz = metric->g_12 * dpdy - metric->g_22 * dpdx; if(mesh->IncIntShear) { // BOUT-06 style differencing @@ -592,7 +592,7 @@ Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, CELL_LOC outloc) * Terms of form b0 x Grad(f) dot Grad(g) / B = [f, g] *******************************************************************************/ -Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, +Coordinates::FieldMetric bracket(const Field2D& f, const Field2D& g, BRACKET_METHOD method, CELL_LOC outloc, Solver* UNUSED(solver)) { TRACE("bracket(Field2D, Field2D)"); @@ -603,7 +603,7 @@ Coordinates::metric_field_type bracket(const Field2D& f, const Field2D& g, } ASSERT1(outloc == g.getLocation()); - Coordinates::metric_field_type result{emptyFrom(f)}; + Coordinates::FieldMetric result{emptyFrom(f)}; if( (method == BRACKET_SIMPLE) || (method == BRACKET_ARAKAWA)) { // Use a subset of terms for comparison to BOUT-06 diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index 3c3a6ad6bc..8871de14c1 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -63,7 +63,7 @@ Field3D DDX(const Field3D& f, CELL_LOC outloc, const std::string& method, return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } -Coordinates::metric_field_type DDX(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } @@ -76,7 +76,7 @@ Field3D DDY(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dy; } -Coordinates::metric_field_type DDY(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric DDY(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return f.getCoordinates(outloc)->DDY(f, outloc, method, region); } @@ -89,7 +89,7 @@ Field3D DDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dz; } -Coordinates::metric_field_type DDZ(const Field2D& f, CELL_LOC UNUSED(outloc), +Coordinates::FieldMetric DDZ(const Field2D& f, CELL_LOC UNUSED(outloc), const std::string& UNUSED(method), const std::string& UNUSED(region)) { auto tmp = Field2D(0., f.getMesh()); @@ -167,7 +167,7 @@ Field3D D2DX2(const Field3D &f, CELL_LOC outloc, const std::string &method, return result; } -Coordinates::metric_field_type D2DX2(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D2DX2(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { Coordinates *coords = f.getCoordinates(outloc); @@ -205,7 +205,7 @@ Field3D D2DY2(const Field3D &f, CELL_LOC outloc, const std::string &method, return result; } -Coordinates::metric_field_type D2DY2(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D2DY2(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { Coordinates *coords = f.getCoordinates(outloc); @@ -229,7 +229,7 @@ Field3D D2DZ2(const Field3D &f, CELL_LOC outloc, const std::string &method, / SQ(f.getCoordinates(outloc)->dz); } -Coordinates::metric_field_type D2DZ2(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D2DZ2(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::D2DZ2(f, outloc, method, region) @@ -246,7 +246,7 @@ Field3D D4DX4(const Field3D &f, CELL_LOC outloc, const std::string &method, / SQ(SQ(f.getCoordinates(outloc)->dx)); } -Coordinates::metric_field_type D4DX4(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D4DX4(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::D4DX4(f, outloc, method, region) @@ -259,7 +259,7 @@ Field3D D4DY4(const Field3D &f, CELL_LOC outloc, const std::string &method, / SQ(SQ(f.getCoordinates(outloc)->dy)); } -Coordinates::metric_field_type D4DY4(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D4DY4(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::D4DY4(f, outloc, method, region) @@ -272,7 +272,7 @@ Field3D D4DZ4(const Field3D &f, CELL_LOC outloc, const std::string &method, / SQ(SQ(f.getCoordinates(outloc)->dz)); } -Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::D4DZ4(f, outloc, method, region) @@ -290,7 +290,7 @@ Coordinates::metric_field_type D4DZ4(const Field2D& f, CELL_LOC outloc, * * ** Communicates and applies boundary in X. */ -Coordinates::metric_field_type D2DXDY(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region, const std::string& dfdy_boundary_condition, @@ -335,7 +335,7 @@ Field3D D2DXDY(const Field3D& f, CELL_LOC outloc, const std::string& method, return DDX(dfdy, outloc, method, region); } -Coordinates::metric_field_type D2DXDZ(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D2DXDZ(const Field2D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string& method), MAYBE_UNUSED(const std::string& region)) { #if BOUT_USE_METRIC_3D @@ -360,7 +360,7 @@ Field3D D2DXDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, return DDZ(DDX(f, x_location, method, region), outloc, method, region); } -Coordinates::metric_field_type D2DYDZ(const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric D2DYDZ(const Field2D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string& method), MAYBE_UNUSED(const std::string& region)) { #if BOUT_USE_METRIC_3D @@ -392,7 +392,7 @@ Field3D D2DYDZ(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string ////////////// X DERIVATIVE ///////////////// /// Special case where both arguments are 2D. -Coordinates::metric_field_type VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::VDDX(v, f, outloc, method, region) @@ -409,7 +409,7 @@ Field3D VDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ////////////// Y DERIVATIVE ///////////////// // special case where both are 2D -Coordinates::metric_field_type VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::VDDY(v, f, outloc, method, region) @@ -426,7 +426,7 @@ Field3D VDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ////////////// Z DERIVATIVE ///////////////// // special case where both are 2D -Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::VDDZ(v, f, outloc, method, region) @@ -434,7 +434,7 @@ Coordinates::metric_field_type VDDZ(const Field2D& v, const Field2D& f, CELL_LOC } // Note that this is zero because no compression is included -Coordinates::metric_field_type VDDZ(MAYBE_UNUSED(const Field3D& v), const Field2D& f, +Coordinates::FieldMetric VDDZ(MAYBE_UNUSED(const Field3D& v), const Field2D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string& method), MAYBE_UNUSED(const std::string& region)) { @@ -460,7 +460,7 @@ Field3D VDDZ(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str /******************************************************************************* * Flux conserving schemes *******************************************************************************/ -Coordinates::metric_field_type FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::FDDX(v, f, outloc, method, region) @@ -475,7 +475,7 @@ Field3D FDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ///////////////////////////////////////////////////////////////////////// -Coordinates::metric_field_type FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::FDDY(v, f, outloc, method, region) @@ -490,7 +490,7 @@ Field3D FDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ///////////////////////////////////////////////////////////////////////// -Coordinates::metric_field_type FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, +Coordinates::FieldMetric FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { return bout::derivatives::index::FDDZ(v, f, outloc, method, region) diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index aeefc44122..9cfeb0a337 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -83,7 +83,7 @@ class GridFromOptionsTest : public ::testing::Test { std::string expected_string{"x + y + z + 3"}; Field2D expected_2d; Field3D expected_3d; - Coordinates::metric_field_type expected_metric; + Coordinates::FieldMetric expected_metric; FakeMesh mesh_from_options{nx, ny, nz}; }; @@ -368,9 +368,9 @@ TEST_F(GridFromOptionsTest, CoordinatesXlowInterp) { auto coords = mesh_from_options.getCoordinates(CELL_XLOW); - Coordinates::metric_field_type expected_xlow = - makeField( - [](Coordinates::metric_field_type::ind_type& index) { + Coordinates::FieldMetric expected_xlow = + makeField( + [](Coordinates::FieldMetric::ind_type& index) { return index.x() - 0.5 + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; }, &mesh_from_options); From 23da002ebb222bfea2d609f233d47b664fc5b221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 15:23:59 +0100 Subject: [PATCH 181/293] getAtLocAndFillGuards merge getAtLoc and interpolateAndExtrapolate to cleanup In some cases the merge isn't usefull, thus getAtLoc is still used there --- src/mesh/coordinates.cxx | 48 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index e509247956..bcea8ca0dd 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -321,6 +321,16 @@ int getAtLoc(Mesh* mesh, Coordinates::FieldMetric& var, const std::string& name, return result; } +int getAtLocAndFillGuards(Mesh* mesh, Coordinates::FieldMetric& var, + const std::string& name, const std::string& suffix, + CELL_LOC location, BoutReal default_value, bool extrapolate_x, + bool extrapolate_y, bool no_extra_interpolate, + ParallelTransform* pt) { + auto ret = getAtLoc(mesh, var, name, suffix, location, default_value); + var = interpolateAndExtrapolate(var, location, extrapolate_x, extrapolate_y, false, pt); + return ret; +} + std::string getLocationSuffix(CELL_LOC location) { switch (location) { case CELL_CENTRE: { @@ -749,38 +759,30 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, transform.get()); - getAtLoc(mesh, dx, "dx", suffix, location, 1.0); - dx = interpolateAndExtrapolate(dx, location, extrapolate_x, extrapolate_y, false, + getAtLocAndFillGuards(mesh, dx, "dx", suffix, location, 1.0, extrapolate_x, extrapolate_y, false, transform.get()); if (mesh->periodicX) { communicate(dx); } - getAtLoc(mesh, dy, "dy", suffix, location, 1.0); - dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, - transform.get()); + getAtLocAndFillGuards(mesh, dy, "dy", suffix, location, 1.0, extrapolate_x, + extrapolate_y, false, transform.get()); // grid data source has staggered fields, so read instead of interpolating // Diagonal components of metric tensor g^{ij} (default to 1) - getAtLoc(mesh, g11, "g11", suffix, location, 1.0); - g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, - transform.get()); - getAtLoc(mesh, g22, "g22", suffix, location, 1.0); - g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, - transform.get()); - getAtLoc(mesh, g33, "g33", suffix, location, 1.0); - g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, - transform.get()); - getAtLoc(mesh, g12, "g12", suffix, location, 0.0); - g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, - transform.get()); - getAtLoc(mesh, g13, "g13", suffix, location, 0.0); - g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, - transform.get()); - getAtLoc(mesh, g23, "g23", suffix, location, 0.0); - g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, - transform.get()); + getAtLocAndFillGuards(mesh, g11, "g11", suffix, location, 1.0, extrapolate_x, + extrapolate_y, false, transform.get()); + getAtLocAndFillGuards(mesh, g22, "g22", suffix, location, 1.0, extrapolate_x, + extrapolate_y, false, transform.get()); + getAtLocAndFillGuards(mesh, g33, "g33", suffix, location, 1.0, extrapolate_x, + extrapolate_y, false, transform.get()); + getAtLocAndFillGuards(mesh, g12, "g12", suffix, location, 0.0, extrapolate_x, + extrapolate_y, false, transform.get()); + getAtLocAndFillGuards(mesh, g13, "g13", suffix, location, 0.0, extrapolate_x, + extrapolate_y, false, transform.get()); + getAtLocAndFillGuards(mesh, g23, "g23", suffix, location, 0.0, extrapolate_x, + extrapolate_y, false, transform.get()); // Check input metrics // Diagonal metric components should be finite From c4beed99ba773447d07030eee41c1db1fb3990fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 17 Jul 2020 16:05:19 +0100 Subject: [PATCH 182/293] Do not use ternary expression with constexpr Both parts need to be compilable, not just the true branch --- tests/unit/mesh/data/test_gridfromoptions.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index 9cfeb0a337..556b9a46f6 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -62,7 +62,12 @@ class GridFromOptionsTest : public ::testing::Test { return index.x() + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; }, &mesh_from_options); - expected_metric = bout::build::use_metric_3d ? expected_3d : expected_2d; + expected_metric = +#if BOUT_USE_METRIC_3D + expected_3d; +#else + expected_2d; +#endif } ~GridFromOptionsTest() override { From 00cf931ee50c72d3d67e46b029b4b93253e1c65e Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 20 Jul 2020 15:42:26 +0200 Subject: [PATCH 183/293] Add zlow coordinates for 3d metrics --- src/mesh/coordinates.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index bcea8ca0dd..5c00c04e2f 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -343,9 +343,8 @@ std::string getLocationSuffix(CELL_LOC location) { return "_ylow"; } case CELL_ZLOW: { - // geometrical quantities are Field2D, so CELL_ZLOW version is the same - // as CELL_CENTRE - return ""; + // in 2D metric, same as CELL_CENTRE + return bout::build::use_metric_3d ? "_zlow" : ""; } default: { throw BoutException("Incorrect location passed to " From 1f872c5194d1cf146d35daefed4cb4500bfbc82e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 20 Jul 2020 17:31:16 +0200 Subject: [PATCH 184/293] pass no_extra_interpolate on --- 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 5c00c04e2f..96bb773709 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -327,7 +327,7 @@ int getAtLocAndFillGuards(Mesh* mesh, Coordinates::FieldMetric& var, bool extrapolate_y, bool no_extra_interpolate, ParallelTransform* pt) { auto ret = getAtLoc(mesh, var, name, suffix, location, default_value); - var = interpolateAndExtrapolate(var, location, extrapolate_x, extrapolate_y, false, pt); + var = interpolateAndExtrapolate(var, location, extrapolate_x, extrapolate_y, no_extra_interpolate, pt); return ret; } From a625943c8566c756009e436fb201a4d2d55755f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 20 Jul 2020 17:31:29 +0200 Subject: [PATCH 185/293] Fix unit test --- tests/unit/mesh/data/test_gridfromoptions.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index 556b9a46f6..ae71de75b1 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -351,6 +351,7 @@ TEST_F(GridFromOptionsTest, CoordinatesCentre) { EXPECT_TRUE(IsFieldEqual(coords->g23, expected_metric)); } +#if not(BOUT_USE_METRIC_3D) TEST_F(GridFromOptionsTest, CoordinatesZlow) { auto coords = mesh_from_options.getCoordinates(CELL_ZLOW); @@ -363,6 +364,9 @@ TEST_F(GridFromOptionsTest, CoordinatesZlow) { EXPECT_TRUE(IsFieldEqual(coords->g13, expected_metric + 1.)); EXPECT_TRUE(IsFieldEqual(coords->g23, expected_metric)); } +#else +// Maybe replace by MMS test, because we need a periodic function in z. +#endif TEST_F(GridFromOptionsTest, CoordinatesXlowInterp) { // *_xlow fields not present in options, Coordinates will be interpolated From 47a512a851a43bfa5734c996524f29c82fe02bfc Mon Sep 17 00:00:00 2001 From: BS Date: Wed, 12 Aug 2020 10:31:15 +0200 Subject: [PATCH 186/293] Update zoidberg for W7-X vacuum fields. --- tools/pylib/zoidberg/field.py | 283 ++++++++++++++++++++++++++++++- tools/pylib/zoidberg/zoidberg.py | 6 +- 2 files changed, 285 insertions(+), 4 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 0e6174e003..b9ab5ad731 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -36,6 +36,7 @@ class MagneticField(object): Slab : A straight field in normal Cartesian coordinates CurvedSlab : A field in curvilinear coordinates StraightStellarator : A rotating ellipse stellarator without curvature + RotatingEllipse : A rotating ellipse stellarator with curvature VMEC : A numerical field from a VMEC equilibrium file GEQDSK : A numerical field from an EFIT g-file @@ -190,7 +191,7 @@ def field_direction(self, pos, ycoord, flatten=False): if np.amin(np.abs(By)) < 1e-8: # Very small By print(x,z,ycoord, By) - raise ValueError("Small By") + # raise ValueError("Small By") R_By = Rmaj / By # Rate of change of x location [m] with y angle [radians] @@ -913,3 +914,283 @@ def pressure(self, x, z, phi): return np.reshape(self.p_spl(np.ravel(psinorm)),psinorm.shape) return f_spl(psinorm) + +class W7X_vacuum(MagneticField): + def __init__(self,nx=512,ny=32,nz=512,xmin=4.05,zmin=-1.35, phimax=2.*np.pi, configuration=0, plot_poincare=False,include_plasma_field=False, wout_file='wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc'): + from scipy.interpolate import griddata, RegularGridInterpolator + import numpy as np + ## create 1D arrays of cylindrical coordinates + r = np.linspace(xmin,xmin+2.5,nx) + phi = np.linspace(0,phimax,ny) + z = np.linspace(zmin,-zmin,nz) + + ## make those 1D arrays 3D + rarray,yarray,zarray = np.meshgrid(r,phi,z,indexing='ij') + + ## call vacuum field values + b_vac = W7X_vacuum.field_values(rarray,yarray,zarray,configuration,plot_poincare) + Bx_vac = b_vac[0] + By_vac = b_vac[1] + Bz_vac = b_vac[2] + + if(include_plasma_field): + b_plasma = W7X_vacuum.plasma_field(rarray,yarray,zarray,wout_file=wout_file) + Bx_plasma = b_plasma[0] + By_plasma = b_plasma[1] + Bz_plasma = b_plasma[2] + else: + Bx_plasma = 0 + By_plasma = 0 + Bz_plasma = 0 + + Bx = Bx_vac + Bx_plasma + By = By_vac + By_plasma + Bz = Bz_vac + Bz_plasma + + # Now we have a field and regular grid in (R,Z,phi) so + # we can get an interpolation function in 3D + points = (r,phi,z) + + self.br_interp = RegularGridInterpolator(points, Bx, bounds_error=False, fill_value=0.0) + self.bz_interp = RegularGridInterpolator(points, Bz, bounds_error=False, fill_value=0.0) + self.bphi_interp = RegularGridInterpolator(points, By, bounds_error=False, fill_value=1.0) + + # if you want non-interpolated, 3D arrays, make this your return function: + # return Bx,By,Bz + + # return points, br_interp, bphi_interp, bz_interp + + ################## Vacuum field service ######################## + # This uses the webservices field line tracer to get # + # the vacuum magnetic field given 3d arrrays for R, phi, and Z # + # http://webservices.ipp-hgw.mpg.de/docs/fieldlinetracer.html # + # Only works on IPP network # + # Contact brendan.shanahan@ipp.mpg.de for questions # + ################################################################ + + def field_values(r, phi, z, configuration=0, plot_poincare=False): + from osa import Client + import os.path + import sys + import pickle + import matplotlib.pyplot as plt + + tracer = Client('http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl') + + nx = r.shape[0] + ny = phi.shape[1] + nz = z.shape[2] + + ### create (standardized) file name for saving/loading magnetic field. + fname = "B.w7x."+str(nx)+"."+str(ny)+"."+str(nz)\ + +"."+"{:.2f}".format(r[0,0,0]) +"-"+"{:.2f}".format(r[-1,0,0])\ + +"."+"{:.2f}".format(phi[0,0,0])+"-"+"{:.2f}".format(phi[0,-1,0])\ + +"."+"{:.2f}".format(z[0,0,0]) +"-"+"{:.2f}".format(z[0,0,-1])+".dat" + + if(os.path.isfile(fname)): + if sys.version_info >= (3, 0): + print ("Saved field found, loading from: ", fname) + f = open(fname, "rb") + Br, Bphi, Bz = pickle.load(f) + f.close + else: + print ("Saved field found, loading from: ", fname) + f = open(fname, 'r') + Br, Bphi, Bz = pickle.load(f) ## error here means you pickled with v3+ re-do. + f.close + else: + print ("No saved field found -- (re)calculating (must be on IPP network for this to work...)") + print ("Calculating field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) + + ## Create configuration objects + config = tracer.types.MagneticConfig() + config.configIds = configuration + + Br = np.zeros((nx,ny,nz)) + Bphi = np.ones((nx,ny,nz)) + Bz = np.zeros((nx,ny,nz)) + pos = tracer.types.Points3D() + + pos.x1 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.cos(phi)) #x in Cartesian (real-space) + pos.x2 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.sin(phi)) #y in Cartesian (real-space) + pos.x3 = np.ndarray.flatten(z) #z in Cartesian (real-space) + + ## Call tracer service + res = tracer.service.magneticField(pos, config) + + ## Reshape to 3d array + Bx = np.ndarray.reshape(np.asarray(res.field.x1),(nx,ny,nz)) + By = np.ndarray.reshape(np.asarray(res.field.x2),(nx,ny,nz)) + Bz = np.ndarray.reshape(np.asarray(res.field.x3), (nx,ny,nz)) + + ## Convert to cylindrical coordinates + Br = Bx*np.cos(phi) + By*np.sin(phi) + Bphi = -Bx*np.sin(phi) + By*np.cos(phi) + + ## Save so we don't have to do this every time. + if sys.version_info >= (3, 0): + f = open(fname, "wb") + pickle.dump([Br,Bphi,Bz],f) + f.close() + else: + f = open(fname, 'w') + pickle.dump([Br,Bphi,Bz],f) + f.close() + + if(plot_poincare): + ## Poincare plot as done on the web services + ## Independent of the previously-made field. + + print( "Making poincare plot (only works on IPP network)...") + ## Create configuration objects + config = tracer.types.MagneticConfig() + config.configIds = configuration + pos = tracer.types.Points3D() + + pos.x1 = np.linspace(5.6, 6.2, 80) + pos.x2 = np.zeros(80) + pos.x3 = np.zeros(80) + + poincare = tracer.types.PoincareInPhiPlane() + poincare.numPoints = 200 + poincare.phi0 = [0.] ## This is where the poincare plane is (bean=0, triangle = pi/5.) + + task = tracer.types.Task() + task.step = 0.2 + task.poincare = poincare + + res = tracer.service.trace(pos, config, task, None, None) + + for i in range(0, len(res.surfs)): + plt.scatter(res.surfs[i].points.x1, res.surfs[i].points.x3, color="black", s=0.1) + plt.show() + + return Br, Bphi, Bz + + + ################## Plasma field service ######################## + # This uses EXTENDER via the webservices to get # + # the magnetic field from the plasma given 3d arrrays # + # for R, phi, and Z # + # http://webservices.ipp-hgw.mpg.de/docs/extender.html # + # Only works on IPP network # + # Contact brendan.shanahan@ipp.mpg.de for questions # + ################################################################ + + def plasma_field(r, phi, z, wout_file='wout.nc'): + from osa import Client + import os.path + import sys + import pickle + import matplotlib.pyplot as plt + from boututils.datafile import DataFile + + cl = Client('http://esb.ipp-hgw.mpg.de:8280/services/Extender?wsdl') + # print (os.path.isfile(wout_file)) + # if not (os.path.isfile(wout_file)): + #vmecURL = 'http://svvmec1.ipp-hgw.mpg.de:8080/vmecrest/v1/run/test42/wout.nc' + vmecURL = "http://svvmec1.ipp-hgw.mpg.de:8080/vmecrest/v1/w7x_ref_1/wout.nc" + # else: + # f = DataFile(wout_file) + # wout = f + # f.close() + + nx = r.shape[0] + ny = phi.shape[1] + nz = z.shape[2] + + ### create (standardized) file name for saving/loading magnetic field. + fname = "B.w7x_plasma_field."+str(nx)+"."+str(ny)+"."+str(nz)\ + +"."+"{:.2f}".format(r[0,0,0]) +"-"+"{:.2f}".format(r[-1,0,0])\ + +"."+"{:.2f}".format(phi[0,0,0])+"-"+"{:.2f}".format(phi[0,-1,0])\ + +"."+"{:.2f}".format(z[0,0,0]) +"-"+"{:.2f}".format(z[0,0,-1])+".dat" + + if(os.path.isfile(fname)): + if sys.version_info >= (3, 0): + print ("Saved field found, loading from: ", fname) + f = open(fname, "rb") + Br, Bphi, Bz = pickle.load(f) + f.close + else: + print ("Saved field found, loading from: ", fname) + f = open(fname, 'r') + Br, Bphi, Bz = pickle.load(f) ## error here means you pickled with v3+ re-do. + f.close + else: + print ("No saved plasma field found -- (re)calculating (must be on IPP network for this to work...)") + print ("Calculating plasma field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) + print ("This part takes AGES... estimate: ",nx*ny*nz/52380., " minutes.") + + points = cl.types.Points3D() + + ## Extender uses cylindrical coordinates, no need to convert, just flatten. + points.x1 = np.ndarray.flatten(r) #x in Cylindrical + points.x2 = np.ndarray.flatten(phi) #y in Cylindrical + points.x3 = np.ndarray.flatten(z) #z in Cylindrical + + ## call EXTENDER on web services + # if not (os.path.isfile(wout_file)): + plasmafield = cl.service.getPlasmaField(None, vmecURL, points, None) + # else: + # plasmafield = cl.service.getPlasmaField(wout, None, points, None) + + ## Reshape to 3d array + Br = np.ndarray.reshape(np.asarray(plasmafield.x1),(nx,ny,nz)) + Bphi = np.ndarray.reshape(np.asarray(plasmafield.x2),(nx,ny,nz)) + Bz = np.ndarray.reshape(np.asarray(plasmafield.x3), (nx,ny,nz)) + + ## Save so we don't have to do this every time. + if sys.version_info >= (3, 0): + f = open(fname, "wb") + pickle.dump([Br,Bphi,Bz],f) + f.close() + else: + f = open(fname, 'w') + pickle.dump([Br,Bphi,Bz],f) + f.close() + + return Br, Bphi, Bz + + def magnetic_axis(self, phi_axis=0,configuration=0): + from osa import Client + import os.path + import sys + import pickle + import matplotlib.pyplot as plt + + tracer = Client('http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl') + + config = tracer.types.MagneticConfig() + config.configIds = configuration + settings = tracer.types.AxisSettings() + res = tracer.service.findAxis(0.05, config, settings) + + magnetic_axis_x = np.asarray(res.axis.vertices.x1)# (m) + magnetic_axis_y = np.asarray(res.axis.vertices.x2)# (m) -- REAL SPACE from an arbitrary start point + magnetic_axis_z = np.asarray(res.axis.vertices.x3)# (m) + magnetic_axis_rmaj = np.sqrt(magnetic_axis_x**2 + magnetic_axis_y**2 + magnetic_axis_z**2) + + magnetic_axis_r = np.sqrt(np.asarray(magnetic_axis_x)**2 + np.asarray(magnetic_axis_y**2)) + magnetic_axis_phi = np.arctan(magnetic_axis_y/magnetic_axis_x) + + index = np.where((magnetic_axis_phi >= 0.97*phi_axis ) & (magnetic_axis_phi <= 1.03*phi_axis) ) + index = index[0] + + return np.asarray([magnetic_axis_r[index],magnetic_axis_z[index]])[:,0] + + def Bxfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + return self.br_interp((x,phi,z)) + + def Bzfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + return self.bz_interp((x,phi,z)) + + def Byfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + # Interpolate to get flux surface normalised psi + return self.bphi_interp((x,phi,z)) + + def Rfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + return x diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index 2f21167a7e..dd27a7af64 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -243,9 +243,9 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', with bdata.DataFile(gridfile, write=True, create=True, format=format) as f: ixseps = nx+1 - f.write('nx', nx) - f.write('ny', ny) - f.write('nz', nz) + f.write("nx", nx) + f.write("ny", ny) + f.write("nz", nz) f.write("dx", metric["dx"]) f.write("dy", metric["dy"]) From 9291838e3f4f5ac9bf907c0e03d08faab9d3fb6a Mon Sep 17 00:00:00 2001 From: BS Date: Wed, 12 Aug 2020 14:43:38 +0200 Subject: [PATCH 187/293] Update test-laplacexz * correctly import build_and_log in runtest * add tolerances, hyper preconditioner to input * fix calls to global mesh in model --- tests/integrated/test-laplacexz/data/BOUT.inp | 9 ++++++--- tests/integrated/test-laplacexz/runtest | 2 +- tests/integrated/test-laplacexz/test-laplacexz.cxx | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/integrated/test-laplacexz/data/BOUT.inp b/tests/integrated/test-laplacexz/data/BOUT.inp index 68d61ffec2..96b85c8948 100644 --- a/tests/integrated/test-laplacexz/data/BOUT.inp +++ b/tests/integrated/test-laplacexz/data/BOUT.inp @@ -14,12 +14,15 @@ nz = 32 dx = 1 dz = 1 -[laplace] -type = petscamg # Use PETSc implementation +[laplacexz] +type = petsc # Use PETSc implementation + +rtol=1e-11 +atol=1e-11 ksptype = gmres # Linear iterative method -pctype = lu # Preconditioner. Direct "lu" or "ilu"; iterative "jacobi", "sor" +pctype = hypre # Preconditioner. Direct "lu" or "ilu"; iterative "jacobi", "sor" # Set package to perform factorisation for direct solves # "petsc" built-in solver only serial diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index ee21d1149a..f1b8151e57 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -17,7 +17,7 @@ except: tol = 1e-10 # Absolute tolerance -from boututils.run_wrapper import shell, shell_safe, launch_safe, getmpirun +from boututils.run_wrapper import shell, shell_safe, launch_safe, getmpirun, build_and_log from boutdata.collect import collect import numpy as np from sys import stdout, exit diff --git a/tests/integrated/test-laplacexz/test-laplacexz.cxx b/tests/integrated/test-laplacexz/test-laplacexz.cxx index 79e77eb741..2fb237af8f 100644 --- a/tests/integrated/test-laplacexz/test-laplacexz.cxx +++ b/tests/integrated/test-laplacexz/test-laplacexz.cxx @@ -17,13 +17,13 @@ int main(int argc, char** argv) { BoutInitialise(argc, argv); - auto inv = LaplaceXZ::create(mesh); + auto inv = LaplaceXZ::create(bout::globals::mesh); auto coord = bout::globals::mesh->getCoordinates(); coord->g13 = 1.8; // test off-diagonal components with nonzero value // create some input field - Field3D f = FieldFactory::get()->create3D("f", Options::getRoot(), mesh); + Field3D f = FieldFactory::get()->create3D("f", Options::getRoot(), bout::globals::mesh); // Calculate the Laplacian with non-zero g13 Field3D g = coord->g11 * D2DX2(f) + coord->g13 * D2DXDZ(f) + coord->g33 * D2DZ2(f); @@ -43,7 +43,7 @@ int main(int argc, char** argv) { output.write("First solve\n"); - Field3D rhs = FieldFactory::get()->create3D("rhs", Options::getRoot(), mesh); + Field3D rhs = FieldFactory::get()->create3D("rhs", Options::getRoot(), bout::globals::mesh); Field3D x = inv->solve(rhs, 0.0); SAVE_ONCE2(rhs, x); @@ -52,11 +52,11 @@ int main(int argc, char** argv) { inv->setCoefs(Field3D(2.0),Field3D(0.1)); - Field3D rhs2 = FieldFactory::get()->create3D("rhs", Options::getRoot(), mesh); + Field3D rhs2 = FieldFactory::get()->create3D("rhs", Options::getRoot(), bout::globals::mesh); Field3D x2 = inv->solve(rhs2, 0.0); SAVE_ONCE2(rhs2, x2); - dump.write(); + bout::globals::dump.write(); BoutFinalise(); return 0; From ae3fcedfdbe2b0b1d5b5b3a5064c9ab125e19dcd Mon Sep 17 00:00:00 2001 From: BS Date: Thu, 13 Aug 2020 09:53:57 +0200 Subject: [PATCH 188/293] Fix typo in vecops::Div() --- src/field/vecops.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index f8e1eec0bd..9c99f52fc7 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -188,7 +188,7 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) vcn.toContravariant(); Field3D vcnJy = vcn.y.getCoordinates()->J * vcn.y; - if (!vcn.y.hasParallelSlices()) { + if (!vcnJy.hasParallelSlices()) { localmesh->communicate(vcnJy); } Field3D result = DDY(vcnJy, outloc, method); From 4eb766e4ede4119b0cfe9122ef654a91dca75f7d Mon Sep 17 00:00:00 2001 From: BS Date: Thu, 13 Aug 2020 10:44:58 +0200 Subject: [PATCH 189/293] Implement a better check for Div() in vecops --- src/field/vecops.cxx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 9c99f52fc7..b407392baa 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -187,11 +187,14 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) Vector3D vcn = v; vcn.toContravariant(); - Field3D vcnJy = vcn.y.getCoordinates()->J * vcn.y; - if (!vcnJy.hasParallelSlices()) { - localmesh->communicate(vcnJy); + auto vcnJy = vcn.y.getCoordinates()->J * vcn.y; + if (v.y.hasParallelSlices()) { + // If v.y has parallel slices then we are using ShiftedMetric (with + // mesh:calcParallelSlices_on_communicate=true) or FCI, so we should calculate + // parallel slices for vcnJy in order to calculate the parallel derivative DDY + vcnJy.calcParallelSlices(); } - Field3D result = DDY(vcnJy, outloc, method); + auto result = DDY(vcnJy, outloc, method); result += DDX(vcn.x.getCoordinates()->J * vcn.x, outloc, method); result += DDZ(vcn.z.getCoordinates()->J * vcn.z, outloc, method); From 64b79df1945b1a8cf0094ca29106a4e1a541ace7 Mon Sep 17 00:00:00 2001 From: BS Date: Thu, 20 Aug 2020 13:31:38 +0200 Subject: [PATCH 190/293] Set sg as FieldMetric type in cyclic invert_par * Fixes configure error --- src/invert/parderiv/impls/cyclic/cyclic.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/parderiv/impls/cyclic/cyclic.hxx b/src/invert/parderiv/impls/cyclic/cyclic.hxx index ef892e6f93..e9dcfc8e2e 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.hxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.hxx @@ -79,7 +79,7 @@ public: private: Field2D A, B, C, D, E; - Field2D sg; // Coefficient of DDY contribution to Grad2_par2 + Coordinates::FieldMetric sg; // Coefficient of DDY contribution to Grad2_par2 int nsys; }; From 59dd735183df238460e5322f611a4bc53643a00a Mon Sep 17 00:00:00 2001 From: BS Date: Thu, 20 Aug 2020 13:48:57 +0200 Subject: [PATCH 191/293] Move metric dependence for cyclic invert_par out of header --- src/invert/parderiv/impls/cyclic/cyclic.cxx | 3 ++- src/invert/parderiv/impls/cyclic/cyclic.hxx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index d4d406305f..554da81a86 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -53,13 +53,14 @@ InvertParCR::InvertParCR(Options *opt, Mesh *mesh_in) : InvertPar(opt, mesh_in), A(1.0), B(0.0), C(0.0), D(0.0), E(0.0) { #if BOUT_USE_METRIC_3D throw BoutException("Parallel cyclic solver does not support 3D metric yet."); -#endif +#else // Number of k equations to solve for each x location nsys = 1 + (localmesh->LocalNz)/2; sg = sqrt(localmesh->getCoordinates()->g_22); sg = DDY(1. / sg) / sg; +#endif } const Field3D InvertParCR::solve(const Field3D &f) { diff --git a/src/invert/parderiv/impls/cyclic/cyclic.hxx b/src/invert/parderiv/impls/cyclic/cyclic.hxx index e9dcfc8e2e..ef892e6f93 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.hxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.hxx @@ -79,7 +79,7 @@ public: private: Field2D A, B, C, D, E; - Coordinates::FieldMetric sg; // Coefficient of DDY contribution to Grad2_par2 + Field2D sg; // Coefficient of DDY contribution to Grad2_par2 int nsys; }; From 839fe77dcd4e05e1f8cf4171cbb75b6709b13be6 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Thu, 20 Aug 2020 16:26:50 +0100 Subject: [PATCH 192/293] Print more useful message when monitor fails/signals to quit Error message wasn't being printed, making debugging difficult. Now prints error message before propagating error upwards. --- src/solver/solver.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solver/solver.cxx b/src/solver/solver.cxx index 192385abb9..8967f7eaa8 100644 --- a/src/solver/solver.cxx +++ b/src/solver/solver.cxx @@ -696,14 +696,14 @@ int Solver::call_monitors(BoutReal simtime, int iter, int NOUT) { int ret = monitor->call(this, simtime, iter / monitor->period - 1, NOUT / monitor->period); if (ret) - throw BoutException(_("Monitor signalled to quit")); + throw BoutException(_("Monitor signalled to quit (return code {})"), ret); } } - } catch (const BoutException&) { + } catch (const BoutException &e) { for (const auto& it : monitors) { it->cleanup(); } - output_error.write(_("Monitor signalled to quit\n")); + output_error.write(_("Monitor signalled to quit (exception {})\n"), e.what()); throw; } From 7ba9337a3ffbbf805e5913e4f866a9ecbe480cdd Mon Sep 17 00:00:00 2001 From: BS Date: Fri, 21 Aug 2020 11:40:57 +0200 Subject: [PATCH 193/293] Update Div_a_Laplace_perp to 3D metrics --- src/mesh/fv_ops.cxx | 117 +++++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 29 deletions(-) diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index fb07b3cdb9..bf38151a08 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -55,16 +55,33 @@ namespace FV { Field3D fup(mesh), fdown(mesh); Field3D aup(mesh), adown(mesh); + + Field3D g23up(mesh), g23down(mesh); + Field3D g_23up(mesh), g_23down(mesh); + Field3D Jup(mesh), Jdown(mesh); + Field3D dyup(mesh), dydown(mesh); + Field3D dzup(mesh), dzdown(mesh); + Field3D Bxyup(mesh), Bxydown(mesh); + + // Values on this y slice (centre). // This is needed because toFieldAligned may modify the field Field3D fc = f; Field3D ac = a; + Field3D g23c = coord->g23; + Field3D g_23c = coord->g_23; + Field3D Jc = coord->J; + Field3D dyc = coord->dy; + Field3D dzc = coord->dz; + Field3D Bxyc = coord->Bxy; + + // Result of the Y and Z fluxes Field3D yzresult(mesh); yzresult.allocate(); - if (f.hasParallelSlices() && a.hasParallelSlices()) { + if (f.hasParallelSlices() && a.hasParallelSlices() ) { // Both inputs have yup and ydown fup = f.yup(); @@ -78,9 +95,50 @@ namespace FV { fup = fdown = fc = toFieldAligned(f); aup = adown = ac = toFieldAligned(a); + yzresult.setDirectionY(YDirectionType::Aligned); } + if (bout::build::use_metric_3d) { + // 3D Metric, need yup/ydown fields. + // Requires previous communication of metrics + // -- should insert communication here? + if (!coord->g23.hasParallelSlices() || !coord->J.hasParallelSlices() || + !coord->dy.hasParallelSlices() || !coord->dz.hasParallelSlices() || + !coord->Bxy.hasParallelSlices() ) { + throw BoutException("metrics have no yup/down: Maybe communicate in init?"); + } + + g23up = coord->g23.yup(); + g23down = coord->g23.ydown(); + + g_23up = coord->g_23.yup(); + g_23down = coord->g_23.ydown(); + + Jup = coord->J.yup(); + Jdown = coord->J.ydown(); + + dyup = coord->dy.yup(); + dydown = coord->dy.ydown(); + + dzup = coord->dz.yup(); + dzdown = coord->dz.ydown(); + + Bxyup = coord->Bxy.yup(); + Bxydown = coord->Bxy.ydown(); + + } else { + // No 3D metrics + // Need to shift to/from field aligned coordinates + g23up = g23down = g23c = toFieldAligned(coord->g23); + g_23up = g_23down = g_23c = toFieldAligned(coord->g_23); + Jup = Jdown = Jc = toFieldAligned(coord->J); + dyup = dydown = dyc = toFieldAligned(coord->dy); + dzup = dzdown = dzc = toFieldAligned(coord->dz); + Bxyup = Bxydown = Bxyc = toFieldAligned(coord->Bxy); + + } + // Y flux for (int i = mesh->xstart; i <= mesh->xend; i++) { @@ -92,41 +150,41 @@ namespace FV { BoutReal coef = 0.5 - * (coord->g_23(i, j, k) / SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)) - + coord->g_23(i, j + 1, k) - / SQ(coord->J(i, j + 1, k) * coord->Bxy(i, j + 1, k))); + * (g_23c(i, j, k) / SQ(Jc(i, j, k) * Bxyc(i, j, k)) + + g_23up(i, j + 1, k) + / SQ(Jup(i, j + 1, k) * Bxyup(i, j + 1, k))); // Calculate Z derivative at y boundary BoutReal dfdz = - 0.25 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) - / coord->dz(i, j, k); // is this at right location? + 0.5 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) + / (dzc(i, j, k) + dzup(i, j+1, k)); // Y derivative BoutReal dfdy = 2. * (fup(i, j + 1, k) - fc(i, j, k)) - / (coord->dy(i, j + 1, k) + coord->dy(i, j, k)); + / (dyup(i, j + 1, k) + dyc(i, j, k)); BoutReal fout = 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) - * (coord->J(i, j, k) * coord->g23(i, j, k) - + coord->J(i, j + 1, k) * coord->g23(i, j + 1, k)) + * (Jc(i, j, k) * g23c(i, j, k) + + Jup(i, j + 1, k) * g23up(i, j + 1, k)) * (dfdz - coef * dfdy); - yzresult(i, j, k) = fout / (coord->dy(i, j, k) * coord->J(i, j, k)); + yzresult(i, j, k) = fout / (dyc(i, j, k) * Jc(i, j, k)); // Calculate flux between j and j-1 dfdz = - 0.25 + 0.5 * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) - / coord->dz(i, j, k); // is this at right location? + / (dzc(i, j, k) + dzdown(i, j-1, k)); dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) - / (coord->dy(i, j, k) + coord->dy(i, j - 1, k)); + / (dyc(i, j, k) + dydown(i, j - 1, k)); fout = 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) - * (coord->J(i, j, k) * coord->g23(i, j, k) - + coord->J(i, j - 1, k) * coord->g23(i, j - 1, k)) + * (Jc(i, j, k) * g23c(i, j, k) + + Jdown(i, j - 1, k) * g23down(i, j - 1, k)) * (dfdz - coef * dfdy); - yzresult(i, j, k) -= fout / (coord->dy(i, j, k) * coord->J(i, j, k)); + yzresult(i, j, k) -= fout / (dyc(i, j, k) * Jc(i, j, k)); } } } @@ -141,21 +199,22 @@ namespace FV { int kp = (k + 1) % mesh->LocalNz; // Coefficient in front of df/dy term - BoutReal coef = coord->g_23(i, j, k) - / (coord->dy(i, j + 1, k) + 2. * coord->dy(i, j, k) - + coord->dy(i, j - 1, k)) - / SQ(coord->J(i, j, k) * coord->Bxy(i, j, k)); + BoutReal coef = g_23c(i, j, k) + / (dyup(i, j + 1, k) + 2. * dyc(i, j, k) + + dydown(i, j - 1, k)) + / SQ(Jc(i, j, k) * Bxyc(i, j, k)); - BoutReal fout = 0.5 * (ac(i, j, k) + ac(i, j, kp)) * coord->g33(i, j, k) + BoutReal fout = 0.25 * (ac(i, j, k) + ac(i, j, kp)) * + (Jc(i, j, k) * coord->g33(i, j, k) + Jc(i, j, kp) * coord->g33(i, j, kp)) * ( // df/dz - (fc(i, j, kp) - fc(i, j, k)) / coord->dz(i, j, k) - // - g_yz * df/dy / SQ(J*B) - - coef - * (fup(i, j + 1, k) + fup(i, j + 1, kp) - - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); - - yzresult(i, j, k) += fout / coord->dz(i, j, k); - yzresult(i, j, kp) -= fout / coord->dz(i, j, kp); + (fc(i, j, kp) - fc(i, j, k)) / dzc(i, j, k) + // - g_yz * df/dy / SQ(J*B) + - coef + * (fup(i, j + 1, k) + fup(i, j + 1, kp) + - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); + + yzresult(i, j, k) += fout / (Jc(i, j, k) * dzc(i, j, k)); + yzresult(i, j, kp) -= fout / (Jc(i, j, kp) * dzc(i, j, kp)); } } } From 46fc48e9335676af4061947a2575fafd4b618f30 Mon Sep 17 00:00:00 2001 From: BS Date: Fri, 21 Aug 2020 15:33:44 +0200 Subject: [PATCH 194/293] Add outer X boundaries to Zoidberg --- tools/pylib/zoidberg/zoidberg.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index dd27a7af64..d49cf1247f 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -66,6 +66,9 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): nx = pol.nx nz = pol.nz + # Get number of guard cells (default 2) + mxg = kwargs.get("MXG", 2) + shape = (nx, ny, nz) # Coordinates of each grid point @@ -146,6 +149,12 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): xind[outside] = -1 zind[outside] = -1 + # Check if xind is outside of the domain + for i in np.arange(0,xind.shape[0]): + for k in np.arange(0,xind.shape[-1]): + if (xind[i,k] > xind.shape[0]-mxg) : + xind[i,k] = -1 + parallel_slice.xt_prime[:, j, :] = xind parallel_slice.zt_prime[:, j, :] = zind From 6474bef9fd34bb9fb549488d466e614c7fc3695e Mon Sep 17 00:00:00 2001 From: Brendan Date: Wed, 26 Aug 2020 15:57:09 +0200 Subject: [PATCH 195/293] Add support for bndry_par_yx_xx * allows for parallel boundaries to be set different for xin/xout. * also added a more complete check in FV::div_a_laplace_perp --- include/boundary_region.hxx | 12 +++-- src/mesh/boundary_factory.cxx | 16 ++++-- src/mesh/fv_ops.cxx | 6 +-- src/mesh/parallel/fci.cxx | 60 +++++++++++++++++++++-- src/mesh/parallel/fci.hxx | 20 +++++--- src/mesh/parallel/shiftedmetricinterp.cxx | 53 +++++++++++++++++--- tools/pylib/zoidberg/zoidberg.py | 2 +- 7 files changed, 137 insertions(+), 32 deletions(-) diff --git a/include/boundary_region.hxx b/include/boundary_region.hxx index eda8c3944f..dd24f48d3a 100644 --- a/include/boundary_region.hxx +++ b/include/boundary_region.hxx @@ -20,15 +20,19 @@ enum class BndryLoc {xin, ydown, yup, all, - par_fwd, // Don't include parallel boundaries - par_bkwd}; + par_fwd_xin, // Don't include parallel boundaries + par_bkwd_xin, + par_fwd_xout, // Don't include parallel boundaries + par_bkwd_xout}; constexpr BndryLoc BNDRY_XIN = BndryLoc::xin; constexpr BndryLoc BNDRY_XOUT = BndryLoc::xout; constexpr BndryLoc BNDRY_YDOWN = BndryLoc::ydown; constexpr BndryLoc BNDRY_YUP = BndryLoc::yup; constexpr BndryLoc BNDRY_ALL = BndryLoc::all; -constexpr BndryLoc BNDRY_PAR_FWD = BndryLoc::par_fwd; -constexpr BndryLoc BNDRY_PAR_BKWD = BndryLoc::par_bkwd; +constexpr BndryLoc BNDRY_PAR_FWD_XIN = BndryLoc::par_fwd_xin; +constexpr BndryLoc BNDRY_PAR_BKWD_XIN = BndryLoc::par_bkwd_xin; +constexpr BndryLoc BNDRY_PAR_FWD_XOUT = BndryLoc::par_fwd_xout; +constexpr BndryLoc BNDRY_PAR_BKWD_XOUT = BndryLoc::par_bkwd_xout; class BoundaryRegionBase { public: diff --git a/src/mesh/boundary_factory.cxx b/src/mesh/boundary_factory.cxx index 7819dd2d22..14d05a68b2 100644 --- a/src/mesh/boundary_factory.cxx +++ b/src/mesh/boundary_factory.cxx @@ -234,12 +234,20 @@ BoundaryOpBase* BoundaryFactory::createFromOptions(const string &varname, Bounda side = "yup"; break; } - case BNDRY_PAR_FWD: { - side = "par_yup"; + case BNDRY_PAR_FWD_XIN: { + side = "par_yup_xin"; break; } - case BNDRY_PAR_BKWD: { - side = "par_ydown"; + case BNDRY_PAR_FWD_XOUT: { + side = "par_yup_xout"; + break; + } + case BNDRY_PAR_BKWD_XIN: { + side = "par_ydown_xin"; + break; + } + case BNDRY_PAR_BKWD_XOUT: { + side = "par_ydown_xout"; break; } default: { diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index bf38151a08..3ebaa26595 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -103,9 +103,9 @@ namespace FV { // 3D Metric, need yup/ydown fields. // Requires previous communication of metrics // -- should insert communication here? - if (!coord->g23.hasParallelSlices() || !coord->J.hasParallelSlices() || - !coord->dy.hasParallelSlices() || !coord->dz.hasParallelSlices() || - !coord->Bxy.hasParallelSlices() ) { + if (!coord->g23.hasParallelSlices() || !coord->g_23.hasParallelSlices() || + !coord->dy.hasParallelSlices() || !coord->dz.hasParallelSlices() || + !coord->Bxy.hasParallelSlices() || !coord->J.hasParallelSlices() ) { throw BoutException("metrics have no yup/down: Maybe communicate in init?"); } diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index df73924988..a17be9d6a9 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -47,8 +47,8 @@ #include -FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* boundary, - bool zperiodic) +FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* inner_boundary, + BoundaryRegionPar* outer_boundary, bool zperiodic) : map_mesh(mesh), offset(offset_), boundary_mask(map_mesh), corner_boundary_mask(map_mesh) { @@ -218,7 +218,7 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* bou // are set to -1 if (xt_prime(x, y, z) < 0.0) { - // Hit a boundary + // Hit an inner boundary // Set to false to not skip this point boundary_mask(x, y, z) = false; @@ -261,7 +261,59 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* bou // Invert 2x2 matrix to get change in index BoutReal dx = (dZ_dz * dR - dR_dz * dZ) / det; BoutReal dz = (dR_dx * dZ - dZ_dx * dR) / det; - boundary->add_point( + inner_boundary->add_point( + x, y, z, x + dx, y + 0.5 * offset, + z + dz, // Intersection point in local index space + 0.5 + * coord.dy(x, y, + z), // sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection + PI // Right-angle intersection + ); + } else if (xt_prime(x, y, z) > map_mesh.xend) { + // Hit an outer boundary + + // Set to false to not skip this point + boundary_mask(x, y, z) = false; + + // Need to specify the index of the boundary intersection, but + // this may not be defined in general. + // We do however have the real-space (R,Z) coordinates. Here we extrapolate, + // using the change in R and Z to calculate the change in (x,z) indices + // + // ( dR ) = ( dR/dx dR/dz ) ( dx ) + // ( dZ ) ( dZ/dx dZ/dz ) ( dz ) + // + // where (dR,dZ) is the change in (R,Z) along the field, + // (dx,dz) is the change in (x,z) index along the field, + // and the gradients dR/dx etc. are evaluated at (x,y,z) + + BoutReal dR_dx = 0.5 * (R(x + 1, y, z) - R(x - 1, y, z)); + BoutReal dZ_dx = 0.5 * (Z(x + 1, y, z) - Z(x - 1, y, z)); + + BoutReal dR_dz, dZ_dz; + // Handle the edge cases in Z + if (z == 0) { + dR_dz = R(x, y, z + 1) - R(x, y, z); + dZ_dz = Z(x, y, z + 1) - Z(x, y, z); + + } else if (z == map_mesh.LocalNz - 1) { + dR_dz = R(x, y, z) - R(x, y, z - 1); + dZ_dz = Z(x, y, z) - Z(x, y, z - 1); + + } else { + dR_dz = 0.5 * (R(x, y, z + 1) - R(x, y, z - 1)); + dZ_dz = 0.5 * (Z(x, y, z + 1) - Z(x, y, z - 1)); + } + + BoutReal det = dR_dx * dZ_dz - dR_dz * dZ_dx; // Determinant of 2x2 matrix + + BoutReal dR = R_prime(x, y, z) - R(x, y, z); + BoutReal dZ = Z_prime(x, y, z) - Z(x, y, z); + + // Invert 2x2 matrix to get change in index + BoutReal dx = (dZ_dz * dR - dR_dz * dZ) / det; + BoutReal dz = (dR_dx * dZ - dZ_dx * dR) / det; + outer_boundary->add_point( x, y, z, x + dx, y + 0.5 * offset, z + dz, // Intersection point in local index space 0.5 diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index 6f8c5ed916..1c3666e7eb 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -44,8 +44,8 @@ class FCIMap { public: FCIMap() = delete; - FCIMap(Mesh& mesh, Options& options, int offset, BoundaryRegionPar* boundary, bool - zperiodic); + FCIMap(Mesh& mesh, Options& options, int offset, BoundaryRegionPar* inner_boundary, + BoundaryRegionPar* outer_boundary, bool zperiodic); // The mesh this map was created on Mesh& map_mesh; @@ -77,17 +77,21 @@ public: // check the coordinate system used for the grid data source FCITransform::checkInputGrid(); - auto forward_boundary = new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD, +1, &mesh); - auto backward_boundary = new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD, -1, &mesh); + auto forward_boundary_xin = new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD_XIN, +1, &mesh); + auto backward_boundary_xin = new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD_XIN, -1, &mesh); + auto forward_boundary_xout = new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD_XOUT, +1, &mesh); + auto backward_boundary_xout = new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD_XOUT, -1, &mesh); // Add the boundary region to the mesh's vector of parallel boundaries - mesh.addBoundaryPar(forward_boundary); - mesh.addBoundaryPar(backward_boundary); + mesh.addBoundaryPar(forward_boundary_xin); + mesh.addBoundaryPar(backward_boundary_xin); + mesh.addBoundaryPar(forward_boundary_xout); + mesh.addBoundaryPar(backward_boundary_xout); field_line_maps.reserve(mesh.ystart * 2); for (int offset = 1; offset < mesh.ystart + 1; ++offset) { - field_line_maps.emplace_back(mesh, options, offset, forward_boundary, zperiodic); - field_line_maps.emplace_back(mesh, options, -offset, backward_boundary, zperiodic); + field_line_maps.emplace_back(mesh, options, offset, forward_boundary_xin, forward_boundary_xout, zperiodic); + field_line_maps.emplace_back(mesh, options, -offset, backward_boundary_xin, backward_boundary_xout, zperiodic); } } diff --git a/src/mesh/parallel/shiftedmetricinterp.cxx b/src/mesh/parallel/shiftedmetricinterp.cxx index f40bfe0b53..70c671c0a9 100644 --- a/src/mesh/parallel/shiftedmetricinterp.cxx +++ b/src/mesh/parallel/shiftedmetricinterp.cxx @@ -116,11 +116,11 @@ ShiftedMetricInterp::ShiftedMetricInterp(Mesh& mesh, CELL_LOC location_in, // Create regions for parallel boundary conditions Field2D dy; mesh.get(dy, "dy", 1.); - auto forward_boundary = - new BoundaryRegionPar("parallel_forward", BNDRY_PAR_FWD, +1, &mesh); + auto forward_boundary_xin = + new BoundaryRegionPar("parallel_forward_xin", BNDRY_PAR_FWD_XIN, +1, &mesh); for (auto it = mesh.iterateBndryUpperY(); not it.isDone(); it.next()) { for (int z = mesh.zstart; z <= mesh.zend; z++) { - forward_boundary->add_point( + forward_boundary_xin->add_point( it.ind, mesh.yend, z, mesh.GlobalX(it.ind), // x 2. * PI * mesh.GlobalY(mesh.yend + 0.5), // y @@ -133,11 +133,46 @@ ShiftedMetricInterp::ShiftedMetricInterp(Mesh& mesh, CELL_LOC location_in, ); } } - auto backward_boundary = - new BoundaryRegionPar("parallel_backward", BNDRY_PAR_BKWD, -1, &mesh); + auto backward_boundary_xin = + new BoundaryRegionPar("parallel_backward_xin", BNDRY_PAR_BKWD_XIN, -1, &mesh); for (auto it = mesh.iterateBndryLowerY(); not it.isDone(); it.next()) { for (int z = mesh.zstart; z <= mesh.zend; z++) { - backward_boundary->add_point( + backward_boundary_xin->add_point( + it.ind, mesh.ystart, z, + mesh.GlobalX(it.ind), // x + 2. * PI * mesh.GlobalY(mesh.ystart - 0.5), // y + 2. * PI * BoutReal(z) / BoutReal(mesh.GlobalNz) // z + + 0.5 * (zShift(it.ind, mesh.ystart) - zShift(it.ind, mesh.ystart - 1)), + 0.25 + * (dy(it.ind, mesh.ystart - 1) // dy/2 + + dy(it.ind, mesh.ystart)), + 0. // angle? + ); + } + } + // Create regions for parallel boundary conditions + auto forward_boundary_xout = + new BoundaryRegionPar("parallel_forward_xout", BNDRY_PAR_FWD_XOUT, +1, &mesh); + for (auto it = mesh.iterateBndryUpperY(); not it.isDone(); it.next()) { + for (int z = mesh.zstart; z <= mesh.zend; z++) { + forward_boundary_xout->add_point( + it.ind, mesh.yend, z, + mesh.GlobalX(it.ind), // x + 2. * PI * mesh.GlobalY(mesh.yend + 0.5), // y + 2. * PI * BoutReal(z) / BoutReal(mesh.GlobalNz) // z + + 0.5 * (zShift(it.ind, mesh.yend + 1) - zShift(it.ind, mesh.yend)), + 0.25 + * (dy(it.ind, mesh.yend) // dy/2 + + dy(it.ind, mesh.yend + 1)), + 0. // angle? + ); + } + } + auto backward_boundary_xout = + new BoundaryRegionPar("parallel_backward_xout", BNDRY_PAR_BKWD_XOUT, -1, &mesh); + for (auto it = mesh.iterateBndryLowerY(); not it.isDone(); it.next()) { + for (int z = mesh.zstart; z <= mesh.zend; z++) { + backward_boundary_xout->add_point( it.ind, mesh.ystart, z, mesh.GlobalX(it.ind), // x 2. * PI * mesh.GlobalY(mesh.ystart - 0.5), // y @@ -152,8 +187,10 @@ ShiftedMetricInterp::ShiftedMetricInterp(Mesh& mesh, CELL_LOC location_in, } // Add the boundary region to the mesh's vector of parallel boundaries - mesh.addBoundaryPar(forward_boundary); - mesh.addBoundaryPar(backward_boundary); + mesh.addBoundaryPar(forward_boundary_xin); + mesh.addBoundaryPar(backward_boundary_xin); + mesh.addBoundaryPar(forward_boundary_xout); + mesh.addBoundaryPar(backward_boundary_xout); } void ShiftedMetricInterp::checkInputGrid() { diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index d49cf1247f..01d7eb97b5 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -153,7 +153,7 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): for i in np.arange(0,xind.shape[0]): for k in np.arange(0,xind.shape[-1]): if (xind[i,k] > xind.shape[0]-mxg) : - xind[i,k] = -1 + xind[i,k] = xind.shape[0] parallel_slice.xt_prime[:, j, :] = xind parallel_slice.zt_prime[:, j, :] = zind From a6216b78e7be64ca50ca8c601f7976c3a857f1aa Mon Sep 17 00:00:00 2001 From: Brendan Date: Fri, 28 Aug 2020 19:57:22 +0200 Subject: [PATCH 196/293] Fix logic for outer parallel boundaries * Fix an error that did not factor in non-integer xt_prime * Update Zoidberg for outer boundaries -- should fix integrated test. --- src/mesh/parallel/fci.cxx | 3 +-- tools/pylib/zoidberg/zoidberg.py | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index a17be9d6a9..6bd5f9b669 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -269,9 +269,8 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* inn z), // sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection PI // Right-angle intersection ); - } else if (xt_prime(x, y, z) > map_mesh.xend) { + } else if (xt_prime(x, y, z) >= map_mesh.xend+1) { // Hit an outer boundary - // Set to false to not skip this point boundary_mask(x, y, z) = false; diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index 01d7eb97b5..c9efd536e3 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -149,12 +149,6 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): xind[outside] = -1 zind[outside] = -1 - # Check if xind is outside of the domain - for i in np.arange(0,xind.shape[0]): - for k in np.arange(0,xind.shape[-1]): - if (xind[i,k] > xind.shape[0]-mxg) : - xind[i,k] = xind.shape[0] - parallel_slice.xt_prime[:, j, :] = xind parallel_slice.zt_prime[:, j, :] = zind @@ -288,6 +282,7 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', # Magnetic field f.write("B", Bmag) + f.write("Bxy", Bmag) # Pressure f.write("pressure", pressure) From dba03392c89fd90f655d7e5031a9620acc95718c Mon Sep 17 00:00:00 2001 From: BS Date: Fri, 11 Sep 2020 13:57:32 +0200 Subject: [PATCH 197/293] Update Zoidberg for Screwpinch fields, fix W7-X calls --- tools/pylib/zoidberg/field.py | 106 +++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index b9ab5ad731..7a4c574d8b 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -489,7 +489,32 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, def Rfunc(self, x, z, phi): return np.full(x.shape, x) + + class Screwpinch(MagneticField): + + def __init__(self, xcentre=1.5, zcentre=0.0, shear = 0, yperiod=2*np.pi, Btor=1.0): + self.x = Symbol('x') + self.z = Symbol('z') + self.y = Symbol('y') + self.r = Symbol('r') + self.r = ((self.x-xcentre)**2 + (self.z-zcentre)**2)**(0.5) + + self.phi = Symbol('phi') + alpha = shear + self.theta = atan2(self.z - zcentre, self.x - xcentre) + A = alpha*self.r**2 + Bx = -alpha*self.r*self.r*sin(self.theta) + Bz = alpha*self.r*self.r*cos(self.theta) + By = Btor/self.x + + self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") + self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") + self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") + self.Byfunc = lambdify((self.x, self.z, self.phi), By, "numpy") + def Rfunc(self, x, z, phi): + return np.full(x.shape, x) + except ImportError: class StraightStellarator(MagneticField): """ @@ -511,6 +536,16 @@ class RotatingEllipse(MagneticField): """ def __init__(self, *args, **kwargs): raise ImportError("No Sympy module: Can't generate RotatingEllipse fields") + + class Screwpinch(MagneticField): + """ + Invalid screwpinch, since no Sympy module. + Rather than printing an error on startup, which may + be missed or ignored, this raises + an exception if StraightStellarator is ever used. + """ + def __init__(self, *args, **kwargs): + raise ImportError("No Sympy module: Can't generate screwpinch fields") class VMEC(MagneticField): """A numerical magnetic field from a VMEC equilibrium file @@ -916,13 +951,13 @@ def pressure(self, x, z, phi): return f_spl(psinorm) class W7X_vacuum(MagneticField): - def __init__(self,nx=512,ny=32,nz=512,xmin=4.05,zmin=-1.35, phimax=2.*np.pi, configuration=0, plot_poincare=False,include_plasma_field=False, wout_file='wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc'): + def __init__(self,nx=128,ny=32,nz=128,x_range=[4.05,6.55],z_range=[-1.35,1,35], phimax=2.*np.pi, configuration=0, plot_poincare=False,include_plasma_field=False, wout_file='wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc'): from scipy.interpolate import griddata, RegularGridInterpolator import numpy as np ## create 1D arrays of cylindrical coordinates - r = np.linspace(xmin,xmin+2.5,nx) + r = np.linspace(x_range[0],x_range[-1],nx) phi = np.linspace(0,phimax,ny) - z = np.linspace(zmin,-zmin,nz) + z = np.linspace(z_range[0],z_range[-1],nz) ## make those 1D arrays 3D rarray,yarray,zarray = np.meshgrid(r,phi,z,indexing='ij') @@ -1194,3 +1229,68 @@ def Byfunc(self, x, z, phi): def Rfunc(self, x, z, phi): phi = np.mod(phi, 2.*np.pi) return x + +class W7X_VMEC(MagneticField): + def __init__(self,nx=512,ny=32,nz=512,x_range=[4.05,6.55],z_range=[-1.35,1,35], phi_range=[0,2*np.pi], vmec_id='w7x_ref_171'): + from scipy.interpolate import griddata, RegularGridInterpolator + import numpy as np + ## create 1D arrays of cylindrical coordinates + r = np.linspace(x_range[0], x_range[-1], nx) + phi = np.linspace(phi_range[0], phi_range[-1],ny) + z = np.linspace(z_range[0], z_range[-1], nz) + + ## make those 1D arrays 3D + rarray,yarray,zarray = np.meshgrid(r,phi,z,indexing='ij') + + ## call vacuum field values + b_vmec = W7X_VMEC.field_values(rarray,yarray,zarray,vmec_id) + Bx_vmec = b_vmec[0] + By_vmec = b_vmec[1] + Bz_vmec = b_vmec[2] + + # Now we have a field and regular grid in (R,Z,phi) so + # we can get an interpolation function in 3D + points = (r,phi,z) + + self.br_interp = RegularGridInterpolator(points, Bx, bounds_error=False, fill_value=0.0) + self.bz_interp = RegularGridInterpolator(points, Bz, bounds_error=False, fill_value=0.0) + self.bphi_interp = RegularGridInterpolator(points, By, bounds_error=False, fill_value=1.0) + + def field_values(r,phi,z, vmec_id='w7x_ref_171'): + from osa import Client + vmec = Client('http://esb:8280/services/vmec_v5?wsdl') + + pos = vmec.types.Points3D() + + pos.x1 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.cos(phi)) #x in Cartesian (real-space) + pos.x2 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.sin(phi)) #y in Cartesian (real-space) + pos.x3 = np.ndarray.flatten(z) #z in Cartesian (real-space) + b = vmec.service.magneticField(str(vmec_id), p) + + ## Reshape to 3d array + Bx = np.ndarray.reshape(np.asarray(b.field.x1),(nx,ny,nz)) + By = np.ndarray.reshape(np.asarray(b.field.x2),(nx,ny,nz)) + Bz = np.ndarray.reshape(np.asarray(b.field.x3), (nx,ny,nz)) + + ## Convert to cylindrical coordinates + Br = Bx*np.cos(phi) + By*np.sin(phi) + Bphi = -Bx*np.sin(phi) + By*np.cos(phi) + + return Br, Bphi, Bz + + def Bxfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + return self.br_interp((x,phi,z)) + + def Bzfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + return self.bz_interp((x,phi,z)) + + def Byfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + # Interpolate to get flux surface normalised psi + return self.bphi_interp((x,phi,z)) + + def Rfunc(self, x, z, phi): + phi = np.mod(phi, 2.*np.pi) + return x From 5a875126211120409d4672ccc98fcb590f0f6355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 23 Sep 2020 13:59:45 +0200 Subject: [PATCH 198/293] Don't save Bxy twice reverts part of a6216b78e7 --- tools/pylib/zoidberg/zoidberg.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index c9efd536e3..019ec26349 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -282,7 +282,6 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', # Magnetic field f.write("B", Bmag) - f.write("Bxy", Bmag) # Pressure f.write("pressure", pressure) From 2e3c793f3d452e5be0f3635183c4cd0172be56ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 23 Sep 2020 14:04:27 +0200 Subject: [PATCH 199/293] Update .gitignore --- .gitignore | 12 ++---------- tests/integrated/.gitignore | 12 ++++++++++++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 5daa3eb4b4..38a8b321e5 100644 --- a/.gitignore +++ b/.gitignore @@ -42,16 +42,6 @@ src/.libfast .BOUT.pid.* build/ build*/ -/tests/integrated/test-griddata-yboundary-guards/test_griddata -/tests/integrated/test-laplacexz/test-laplacexz -/tests/integrated/test-twistshift-staggered/test-twistshift -/tests/integrated/test-twistshift/test-twistshift -/tests/integrated/test-griddata-yboundary-guards/*/*.nc -/tests/integrated/test-options-netcdf/*.nc -/tests/integrated/test-options-netcdf/test-options-netcdf -/tests/integrated/test-options-netcdf/*.ini -/tools/pylib/boututils/bout_config.py -/tests/integrated/test-snb/test_snb /.vs /CMakeSettings.json /CppProperties.json @@ -65,3 +55,5 @@ src/fmt/format.cxx /include/bout/build_config.hxx /include/bout/revision.hxx /include/bout/version.hxx +/include/bout/build_defines.hxx +/tools/pylib/boutconfig/__init__.py diff --git a/tests/integrated/.gitignore b/tests/integrated/.gitignore index 0e28280d36..d9b91f9dec 100644 --- a/tests/integrated/.gitignore +++ b/tests/integrated/.gitignore @@ -37,3 +37,15 @@ BOUT.settings /test-stopCheck/test_stopCheck /test-yupdown/test_yupdown /test-coordinates-initialization/test-coordinates-initialization +/test-griddata-yboundary-guards/test_griddata +/test-laplacexz/test-laplacexz +/test-twistshift-staggered/test-twistshift +/test-twistshift/test-twistshift +/test-griddata-yboundary-guards/*/*.nc +/test-options-netcdf/*.nc +/test-options-netcdf/test-options-netcdf +/test-options-netcdf/*.ini +/test-snb/test_snb +/test-communications/test-communications +/test-interpolate-z/test_interpolate +/test-yupdown-weights/test_yupdown_weights From 139a99cab7a116bca9a975a3e71c02ffe478ff55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 23 Sep 2020 14:18:38 +0200 Subject: [PATCH 200/293] Always add Rxy and Bxy to metric --- tools/pylib/zoidberg/zoidberg.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index 019ec26349..d12e807c11 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -243,6 +243,10 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', # Add Rxy, Bxy metric["Rxy"] = maps["R"][:, :, 0] metric["Bxy"] = Bmag[:, :, 0] + else: + metric["Rxy"] = maps["R"] + metric["Bxy"] = Bmag + with bdata.DataFile(gridfile, write=True, create=True, format=format) as f: ixseps = nx+1 From bea4ab19c973c57cc0e2bd4a2917e32c2e1b797f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 23 Sep 2020 14:38:27 +0200 Subject: [PATCH 201/293] fix bad merge zlength is a variable set above --- src/invert/parderiv/impls/cyclic/cyclic.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index abadd9a33c..0e2047a5e0 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -148,7 +148,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { // Set up tridiagonal system for (int k = 0; k < nsys; k++) { - BoutReal kwave = k * 2.0 * PI / zlength(); // wave number is 1/length + BoutReal kwave = k * 2.0 * PI / zlength; // wave number is 1/length for (int y = 0; y < localmesh->LocalNy - localmesh->ystart - local_ystart; y++) { BoutReal acoef = A(x, y + local_ystart); // Constant From 45602bbadaba8ced5ae9ff25f4c2f9b9f0a6cc2e Mon Sep 17 00:00:00 2001 From: BS Date: Mon, 19 Oct 2020 14:50:29 +0200 Subject: [PATCH 202/293] Add Dommaschk Potential zoidberg field object. --- tools/pylib/zoidberg/field.py | 301 +++++++++++++++++++++++++++++++++- 1 file changed, 300 insertions(+), 1 deletion(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 7a4c574d8b..90a51aec78 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -312,7 +312,7 @@ def Rfunc(self, x, z, phi): return np.full(x.shape, self.Rmaj) try: - from sympy import Symbol, atan2, cos, sin, log, pi, sqrt, lambdify + from sympy import Symbol, atan2, cos, sin, log, pi, sqrt, lambdify, Piecewise, Sum, gamma, And, factorial, symbols, Add, symarray, diff class StraightStellarator(MagneticField): """A "rotating ellipse" stellarator without curvature @@ -489,6 +489,305 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, def Rfunc(self, x, z, phi): return np.full(x.shape, x) + + class DommaschkPotentials(MagneticField): + """A magnetic field generator using the Dommaschk potentials. + Parameters + ---------- + A: Coefficient matrix for the torodial and polidial harmonics. Form: (m,l,(a,b,c,d)) + R_0: major radius [m] + B_0: magnetic field on axis [T] + + Important Methods + ----------------- + Bxfunc/Byfunc/Bzfunc(x,z,y): Returns magnetic field in radial/torodial/z-direction + Sfunc(x,z,y): Returns approximate magnetic surface invariant for Dommaschk potentials. Use this to visualize flux surfaces + + + + """ + + + def __init__(self, A, R_0=1.0, B_0=1.0): + + self.R_0 = R_0 + self.B_0 = B_0 + + + self.R = Symbol('R') + self.phi = Symbol('phi') + self.Z = Symbol('Z') + + + self.m = Symbol('m') + self.l = Symbol('l') + self.n = Symbol('n') + self.k = Symbol('k') + + self.A = A + + + self.P = self.U(self.A).doit().subs([(self.R, self.R/self.R_0), (self.Z, self.Z/R_0)]) + self.P_hat = self.U_hat(self.A).doit().subs([(self.R, self.R/self.R_0), (self.Z, self.Z/R_0)]) + + S = (0.5*(log(self.R/self.R_0)**2 + (self.Z/R_0)**2) - self.R/self.R_0 * (log(self.R/self.R_0)*self.R_0*diff(self.P_hat, self.R) + self.Z*self.R/self.R_0*diff(self.P_hat, self.Z)))#.subs([(self.R, self.R/self.R_0), (self.Z, self.Z)]) + + + Bx = R_0*diff(self.P, self.R) + By = R_0/self.R * diff(self.P, self.phi) + Bz = diff(self.P, self.Z) + + self.Sf = lambdify((self.R, self.phi, self.Z), S, "numpy") + + self.Bxf = lambdify((self.R, self.phi, self.Z), Bx, "numpy") + self.Byf = lambdify((self.R, self.phi, self.Z), By, "numpy") + self.Bzf = lambdify((self.R, self.phi, self.Z), Bz, "numpy") + + def Bxfunc(self, x, z, y): + + return self.Bxf(x, y, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + + def Byfunc(self, x, z, y): + + + return self.Byf(x, y, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + + def Bzfunc(self, x, z, y): + + return self.Bzf(x, y, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + + def Sfunc(self, x, z, y): + """ + Parameters + ---------- + x: radial coordinates normalized to R_0 + z: binormal coordinate + y: torodial angle normalized to 2*pi + + Returns + ------- + Approximate magnetic surface invariant S at location (x,z,y). This is from the original Dommaschk paper. Use to visualize flux surfaces + """ + return self.Sf(x,y,z) + + def Rfunc(self, x, z, y): + """ + Parameters + ---------- + x: radial coordinates normalized to R_0 + z: binormal coordinate + y: torodial angle normalized to 2*pi + + Returns + ------- + Radial coordinate x + """ + + return x + + + + def CD(self, m, k): + """ + Parameters + ---------- + m: torodial harmonic + k: summation index in D + + Returns: + -------- + Sympy function CD_mk (R) (Dirichlet boudary conditions) + """ + + n = Symbol('n') + b = Symbol('b') + i = Symbol('i') + + alpha = Piecewise(((((-1)**n)/(gamma(b + n + 1) * gamma(n + 1) * 2**(2 * n + b) )), n >= 0), (0, True)) + alpha_st = Piecewise((alpha * (2*n + b), n >= 0), (0, True)) + + + beta = Piecewise(((gamma(b - n))/(gamma(n + 1) * 2**(2*n - b + 1)), And(n >= 0, n < b)), (0, True)) + beta_st = Piecewise((beta * (2*n - b), And(n >= 0, n < b)), (0, True)) + + + delta = Piecewise((alpha/2 * Sum(1/i + 1/(b + i), (i, 1, n+1)), n > 0), (0, True)) + delta_st = Piecewise((delta * (2 * n + b), n > 0), (0, True)) + + j = Symbol('j') + + CD = Sum(-( alpha.subs([(n, j), (b,m)]) * ( alpha_st.subs([(n, k - m - j), (b, m)]) * log(self.R) + delta_st.subs([(n, k - m - j), (b, m)]) - alpha.subs([(n, k - m - j), (b, m)]) ) - delta.subs([(n, j), (b,m)]) * alpha_st.subs([(n, k - m - j), (b, m)]) + alpha.subs([(n, j), (b,m)]) * beta_st.subs([(n, k - j), (b, m)])) * self.R**(2*j + m)\ + + beta.subs([(n, j), (b, m)]) * alpha_st.subs([(n, k - j), (b, m)]) * self.R**(2*j - m), (j, 0, k)) + + return CD + + + def CN(self, m, k): + """ + Parameters + ---------- + m: torodial harmonic + k: summation index in N + + Returns: + -------- + Sympy function CN_mk (R) (Neumann boundary conditions) + """ + + + n = Symbol('n') + b = Symbol('b') + i = Symbol('i') + + + alpha = Piecewise(((((-1)**n)/(gamma(b + n + 1) * gamma(n + 1) * 2**(2 * n + b) )), n >= 0), (0, True)) + alpha_st = Piecewise((alpha * (2*n + b), n >= 0), (0, True)) + + + beta = Piecewise(((gamma(b - n))/(gamma(n + 1) * 2**(2*n - b + 1)), And(n >= 0, n < b)), (0, True)) + beta_st = Piecewise((beta * (2*n - b), And(n >= 0, n < b)), (0, True)) + + + delta = Piecewise((alpha/2 * Sum(1/i + 1/(b + i), (i, 1, n+1)), n > 0), (0, True)) + delta_st = Piecewise((delta * (2 * n + b), n > 0), (0, True)) + + j = Symbol('j') + + CN = Sum(( alpha.subs([(n, j), (b,m)]) * ( alpha.subs( [(n, k - m - j), (b, m)] ) * log(self.R) + delta.subs([(n, k - m - j), (b, m)])) - delta.subs([(n, j), (b,m)]) * alpha.subs( [(n, k - m - j), (b, m)] ) + alpha.subs([(n, j), (b,m)]) * beta.subs([(n, k - j), (b, m)]) ) * self.R**( 2*j + m )\ + - beta.subs([(n, j), (b,m)]) * alpha.subs([(n, k-j),(b, m)]) * self.R**(2*j - m), (j, 0, k)) + + + + return CN + + + def D(self, m, n): + """ + Parameters + ---------- + m: torodial mode number + n: summation index in V + + Returns: + -------- + Sympy function D_mn (R, Z) (Dirichlet boundary conditions) + """ + + i = Symbol('i') + D = log(1) + k_arr = np.arange(0,int(n/2)+1,1) + CD_f = self.CD(m, i) + + + for k in k_arr: + D += ((self.Z**(n - 2*k))/factorial(n-2*k)*CD_f.subs(i,k)) + + + return D + + + + def N(self, m, n): + """ + Parameters + ---------- + m: torodial mode number + n: summation index in V + + Returns: + -------- + Sympy function N_mn (R, Z) (Neumann boundary conditions) + """ + + i = Symbol('i') + N = log(1) + k_arr = np.arange(0, int(n/2)+1, 1) + CN_f = self.CN(m, i) + for k in k_arr: + N += ((self.Z**(n - 2*k))/factorial(n-2*k)*CN_f.subs(i,k)) + + return N + + + def V(self, m, l, a, b, c, d): + """ + Parameters + ---------- + m: torodial mode number + l: polodial mode number + a,b,c,d: Coefficients for m,l-th Dommaschk potential (elements of matrix A) + + Returns: + -------- + Sympy function V_ml + """ + + V = ( a*cos(m*self.phi) + b*sin(m*self.phi) ) * self.D(m, l) + ( c*cos(m*self.phi) + d*sin(m*self.phi) ) * self.N(m, l-1) + + return V + + + + def U(self, A): + """ + Parameters + ---------- + A: Coefficient matrix for the torodial and polidial harmonics. Form: (m,l,(a,b,c,d)) + + Returns + ----------------- + U: Superposition of all modes given in A + + """ + U = self.phi + for i in range(A.shape[0]): + for j in range(A.shape[1]): + if A[i,j,0] or A[i,j,1] or A[i,j,2] or A[i,j,3] != 0: + + U += self.V(i, j, A[i,j,0], A[i,j,1], A[i,j,2], A[i,j,3]) + + return U + + def V_hat(self, m, l, a, b, c, d): + """ + Parameters + ---------- + m: torodial mode number + l: polodial mode number + a,b,c,d: Coefficients for m,l-th Dommaschk potential (elements of matrix A) + + Returns: + -------- + Sympy function V_hat_ml; Similar to V; needed for calculation of magnetic surface invariant S + """ + + V = ( a*cos(m*(self.phi-np.pi/(2*m))) + b*sin(m*(self.phi-np.pi/(2*m)) ) ) * self.D(m, l) + ( c*cos(m*(self.phi-np.pi/(2*m))) + d*sin(m*(self.phi-np.pi/(2*m)) ) ) * self.N(m, l-1) + + + return V + + def U_hat(self, A): + """ + Parameters + ---------- + A: Coefficient matrix for the torodial and polidial harmonics. Form: (m,l,(a,b,c,d)) + + Returns + ----------------- + U: Superposition of all modes given in A + + """ + + U = log(1) + for i in range(A.shape[0]): + for j in range(A.shape[1]): + if A[i,j,0] or A[i,j,1] or A[i,j,2] or A[i,j,3] != 0: + U += self.V_hat(i, j, A[i,j,0], A[i,j,1], A[i,j,2], A[i,j,3]) * Piecewise((self.phi, i==0), (1/i, i>0)) + + return U + + + class Screwpinch(MagneticField): From 0c544ec353471156ecdd778c10498f4012392ab7 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 21 Oct 2020 13:37:50 +0100 Subject: [PATCH 203/293] CMake: Add CONFLICTS to bout_add_integrated_test Disables a test if it conflicts with some variable --- CMakeLists.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ebd42198b..c5ef8c1b53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -641,6 +641,10 @@ endmacro() # - EXTRA_FILES: any extra files that are required to run the test # # - REQUIRES: list of variables that must be truthy to enable test +# (note: use `CONFLICTS` to negate the variable, rather than `NOT +# VARIABLE`) +# +# - CONFLICTS: list of variables that must be falsey to enable test # # - EXECUTABLE_NAME: name of the executable, if different from the # first source name @@ -648,7 +652,7 @@ endmacro() function(bout_add_integrated_test TESTNAME) set(options USE_RUNTEST USE_DATA_BOUT_INP) set(oneValueArgs EXECUTABLE_NAME) - set(multiValueArgs SOURCES EXTRA_FILES REQUIRES) + set(multiValueArgs SOURCES EXTRA_FILES REQUIRES CONFLICTS) cmake_parse_arguments(BOUT_TEST_OPTIONS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) foreach (REQUIREMENT IN LISTS BOUT_TEST_OPTIONS_REQUIRES) @@ -658,6 +662,13 @@ function(bout_add_integrated_test TESTNAME) endif() endforeach() + foreach (CONFLICT IN LISTS BOUT_TEST_OPTIONS_CONFLICTS) + if (${CONFLICT}) + message(STATUS "Not building test ${TESTNAME}, conflicts with: ${CONFLICT}") + return() + endif() + endforeach() + add_executable(${TESTNAME} ${BOUT_TEST_OPTIONS_SOURCES}) target_link_libraries(${TESTNAME} bout++) target_include_directories(${TESTNAME} PRIVATE $) From 920143ffcb35c99fd8886b86bf1cd61579303cd4 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 21 Oct 2020 13:39:09 +0100 Subject: [PATCH 204/293] CMake: Replace `REQUIRES NOT` with `CONFLICTS` --- .../integrated/test-drift-instability-staggered/CMakeLists.txt | 2 +- tests/integrated/test-drift-instability/CMakeLists.txt | 2 +- tests/integrated/test-fieldgroupComm/CMakeLists.txt | 2 +- tests/integrated/test-gyro/CMakeLists.txt | 2 +- tests/integrated/test-interchange-instability/CMakeLists.txt | 2 +- tests/integrated/test-invertable-operator/CMakeLists.txt | 2 +- tests/integrated/test-invpar/CMakeLists.txt | 2 +- tests/integrated/test-io_hdf5/CMakeLists.txt | 2 +- tests/integrated/test-laplace/CMakeLists.txt | 2 +- tests/integrated/test-multigrid_laplace/CMakeLists.txt | 2 +- tests/integrated/test-naulin-laplace/CMakeLists.txt | 2 +- tests/integrated/test-snb/CMakeLists.txt | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/integrated/test-drift-instability-staggered/CMakeLists.txt b/tests/integrated/test-drift-instability-staggered/CMakeLists.txt index e87f88c6d8..5db527c207 100644 --- a/tests/integrated/test-drift-instability-staggered/CMakeLists.txt +++ b/tests/integrated/test-drift-instability-staggered/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-drift-instability-staggered SOURCES 2fluid.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES runtest.py uedge.grd_std.cdl diff --git a/tests/integrated/test-drift-instability/CMakeLists.txt b/tests/integrated/test-drift-instability/CMakeLists.txt index d533a79446..6e62b842f3 100644 --- a/tests/integrated/test-drift-instability/CMakeLists.txt +++ b/tests/integrated/test-drift-instability/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-drift-instability SOURCES 2fluid.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES runtest.py uedge.grd_std.cdl diff --git a/tests/integrated/test-fieldgroupComm/CMakeLists.txt b/tests/integrated/test-fieldgroupComm/CMakeLists.txt index 6266c560a4..cd429129fd 100644 --- a/tests/integrated/test-fieldgroupComm/CMakeLists.txt +++ b/tests/integrated/test-fieldgroupComm/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-fieldgroupComm SOURCES test_fieldgroupcomm.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES cyclone_68x32.nc diff --git a/tests/integrated/test-gyro/CMakeLists.txt b/tests/integrated/test-gyro/CMakeLists.txt index 28b65c010f..04fb989438 100644 --- a/tests/integrated/test-gyro/CMakeLists.txt +++ b/tests/integrated/test-gyro/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-gyro SOURCES test_gyro.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES cyclone_68x32.nc data/benchmark.0.nc diff --git a/tests/integrated/test-interchange-instability/CMakeLists.txt b/tests/integrated/test-interchange-instability/CMakeLists.txt index ef6b403fac..284a71ef62 100644 --- a/tests/integrated/test-interchange-instability/CMakeLists.txt +++ b/tests/integrated/test-interchange-instability/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-interchange-instability SOURCES 2fluid.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST EXTRA_FILES slab.6b5.r1.cdl slab.6b5.r10.cdl data_1/BOUT.inp data_10/BOUT.inp ) diff --git a/tests/integrated/test-invertable-operator/CMakeLists.txt b/tests/integrated/test-invertable-operator/CMakeLists.txt index 10b4f0ec76..c35a1407f3 100644 --- a/tests/integrated/test-invertable-operator/CMakeLists.txt +++ b/tests/integrated/test-invertable-operator/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-invertable-operator SOURCES invertable_operator.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP REQUIRES BOUT_HAS_PETSC diff --git a/tests/integrated/test-invpar/CMakeLists.txt b/tests/integrated/test-invpar/CMakeLists.txt index b1c28e2be1..f7cbc10b17 100644 --- a/tests/integrated/test-invpar/CMakeLists.txt +++ b/tests/integrated/test-invpar/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-invpar SOURCES test_invpar.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP ) diff --git a/tests/integrated/test-io_hdf5/CMakeLists.txt b/tests/integrated/test-io_hdf5/CMakeLists.txt index 0b9dd50102..4c613e47d7 100644 --- a/tests/integrated/test-io_hdf5/CMakeLists.txt +++ b/tests/integrated/test-io_hdf5/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-io-hdf5 SOURCES test_io_hdf5.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP EXTRA_FILES test_io.grd.hdf5 data/benchmark.out.0.hdf5 diff --git a/tests/integrated/test-laplace/CMakeLists.txt b/tests/integrated/test-laplace/CMakeLists.txt index 7cebde10f2..50a445520a 100644 --- a/tests/integrated/test-laplace/CMakeLists.txt +++ b/tests/integrated/test-laplace/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-laplace SOURCES test_laplace.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D EXTRA_FILES test_laplace.grd.nc data/benchmark.0.nc USE_RUNTEST USE_DATA_BOUT_INP diff --git a/tests/integrated/test-multigrid_laplace/CMakeLists.txt b/tests/integrated/test-multigrid_laplace/CMakeLists.txt index 13bf202554..6bf744dc7c 100644 --- a/tests/integrated/test-multigrid_laplace/CMakeLists.txt +++ b/tests/integrated/test-multigrid_laplace/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-multigrid-laplace SOURCES test_multigrid_laplace.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP ) diff --git a/tests/integrated/test-naulin-laplace/CMakeLists.txt b/tests/integrated/test-naulin-laplace/CMakeLists.txt index 3055d8395c..086212d7d8 100644 --- a/tests/integrated/test-naulin-laplace/CMakeLists.txt +++ b/tests/integrated/test-naulin-laplace/CMakeLists.txt @@ -1,6 +1,6 @@ bout_add_integrated_test(test-naulin-laplace SOURCES test_naulin_laplace.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_RUNTEST USE_DATA_BOUT_INP ) diff --git a/tests/integrated/test-snb/CMakeLists.txt b/tests/integrated/test-snb/CMakeLists.txt index 80a6ea761a..5814956f8f 100644 --- a/tests/integrated/test-snb/CMakeLists.txt +++ b/tests/integrated/test-snb/CMakeLists.txt @@ -1,5 +1,5 @@ bout_add_integrated_test(test-snb SOURCES test_snb.cxx - REQUIRES NOT BOUT_USE_METRIC_3D + CONFLICTS BOUT_USE_METRIC_3D USE_DATA_BOUT_INP ) From 2945bf7d340cc3ab82ad98dfa9632019dbd4c153 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Tue, 8 Dec 2020 09:24:52 +0000 Subject: [PATCH 205/293] Remove c_get/set_dz from BoutCore Assumes that dz is a BoutReal. Should this be replaced with a Field, or just removed? There doesn't seem to be anything similar for dx and dy. --- tools/pylib/_boutcore_build/boutcore.pyx.in | 15 --------------- tools/pylib/_boutcore_build/helper.h.in | 7 ------- 2 files changed, 22 deletions(-) diff --git a/tools/pylib/_boutcore_build/boutcore.pyx.in b/tools/pylib/_boutcore_build/boutcore.pyx.in index b80e2d04dd..c40011d7e3 100755 --- a/tools/pylib/_boutcore_build/boutcore.pyx.in +++ b/tools/pylib/_boutcore_build/boutcore.pyx.in @@ -672,8 +672,6 @@ cdef extern from "helper.h": void c_laplacian_solve(c.Laplacian *, c.Field3D *, c.Field3D*) c.Field3D c_Grad_perp_dot_Grad_perp(c.Field3D,c.Field3D); void c_mesh_normalise(c.Mesh* , double) - void c_set_dz(c.Coordinates*, double) - double c_get_dz(c.Coordinates*) c.Datafile * c_get_global_datafile() cdef class Mesh: @@ -851,19 +849,6 @@ do echo " self.${f} = ${metric_fdd}FromPtr(&self.cobj.${f})" done cat <<"EOF" - cdef getDz(self): - return c_get_dz(self.cobj) - - cdef setDz(self, val): - c_set_dz(self.cobj, val) - - @property - def dz(self): - return self.getDz() - - @dz.setter - def dz(self, val): - self.setDz(val) def __dealloc__(self): self.__mydealloc__() diff --git a/tools/pylib/_boutcore_build/helper.h.in b/tools/pylib/_boutcore_build/helper.h.in index 433d4ba01b..7131d21a83 100644 --- a/tools/pylib/_boutcore_build/helper.h.in +++ b/tools/pylib/_boutcore_build/helper.h.in @@ -126,11 +126,4 @@ Datafile * c_get_global_datafile(){ return &bout::globals::dump; } -double c_get_dz(Coordinates * coords) { - return coords->dz; -} -void c_set_dz(Coordinates * coords, double val) { - coords->dz = val; -} - EOF From baa9d6ff4c45f1206331cdca54576a9691e8333f Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 10 Dec 2020 15:45:30 +0000 Subject: [PATCH 206/293] Register 3D metric-incompatible implementations as unavailable This allows for some improved handling of incompatible implementations, for example listing of available implementations --- include/invert_parderiv.hxx | 2 ++ .../laplace/impls/cyclic/cyclic_laplace.cxx | 12 ++++++----- .../laplace/impls/cyclic/cyclic_laplace.hxx | 15 +++++++++++++- .../laplace/impls/multigrid/multigrid_alg.cxx | 6 ++++++ .../impls/multigrid/multigrid_laplace.cxx | 14 +++++-------- .../impls/multigrid/multigrid_laplace.hxx | 15 +++++++++++++- .../impls/multigrid/multigrid_solver.cxx | 6 ++++++ .../laplace/impls/serial_band/serial_band.cxx | 14 ++++++------- .../laplace/impls/serial_band/serial_band.hxx | 15 +++++++++++++- .../impls/cyclic/laplacexz-cyclic.cxx | 15 +++++--------- .../impls/cyclic/laplacexz-cyclic.hxx | 20 ++++++++++++++++++- src/invert/parderiv/impls/cyclic/cyclic.cxx | 16 +++++++-------- src/invert/parderiv/impls/cyclic/cyclic.hxx | 12 +++++++++++ 13 files changed, 117 insertions(+), 45 deletions(-) diff --git a/include/invert_parderiv.hxx b/include/invert_parderiv.hxx index 2d438fd204..a4e2ad756f 100644 --- a/include/invert_parderiv.hxx +++ b/include/invert_parderiv.hxx @@ -69,6 +69,8 @@ public: } }; +using RegisterUnavailableInvertPar = RegisterUnavailableInFactory; + /// Base class for parallel inversion solvers /*! * diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index 473dfb8933..2df2e70953 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -33,6 +33,11 @@ * */ +#include "bout/build_config.hxx" +#include "cyclic_laplace.hxx" + +#if not BOUT_USE_METRIC_3D + #include #include #include @@ -42,13 +47,8 @@ #include #include -#include "cyclic_laplace.hxx" - LaplaceCyclic::LaplaceCyclic(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), Acoef(0.0), C1coef(1.0), C2coef(1.0), Dcoef(1.0) { -#if BOUT_USE_METRIC_3D - throw BoutException("Laplacian cyclic solver does not support 3D metric yet."); -#endif Acoef.setLocation(location); C1coef.setLocation(location); @@ -482,3 +482,5 @@ Field3D LaplaceCyclic::solve(const Field3D& rhs, const Field3D& x0) { return x; } + +#endif // BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx index 9e1161ecd8..1a718d4918 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx @@ -31,7 +31,18 @@ class LaplaceCyclic; #ifndef __LAP_CYCLIC_H__ #define __LAP_CYCLIC_H__ -#include +#include "bout/build_config.hxx" +#include "invert_laplace.hxx" + +#if BOUT_USE_METRIC_3D + +namespace{ +RegisterUnavailableLaplace registerlaplacecycle(LAPLACE_CYCLIC, + "BOUT++ was configured with 3D metrics"); +} + +#else + #include #include #include @@ -107,4 +118,6 @@ private: CyclicReduce *cr; ///< Tridiagonal solver }; +#endif // BOUT_USE_METRIC_3D + #endif // __SPT_H__ diff --git a/src/invert/laplace/impls/multigrid/multigrid_alg.cxx b/src/invert/laplace/impls/multigrid/multigrid_alg.cxx index 6cfdee1b47..10ac88ad2c 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_alg.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_alg.cxx @@ -27,6 +27,10 @@ * **************************************************************************/ +#include "bout/build_config.hxx" + +#if not BOUT_USE_METRIC_3D + #include "multigrid_laplace.hxx" #include #include "unused.hxx" @@ -760,3 +764,5 @@ BOUT_OMP(for) fflush(stdout); } } + +#endif diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index 53072df75b..dc6fd4ec4b 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -27,7 +27,11 @@ * **************************************************************************/ +#include "bout/build_config.hxx" #include "multigrid_laplace.hxx" + +#if not BOUT_USE_METRIC_3D + #include #include #include @@ -41,9 +45,6 @@ BoutReal soltime=0.0,settime=0.0; LaplaceMultigrid::LaplaceMultigrid(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), A(0.0), C1(1.0), C2(1.0), D(1.0) { -#if BOUT_USE_METRIC_3D - throw BoutException("Laplace multigrid solver does not support 3D metric yet."); -#endif TRACE("LaplaceMultigrid::LaplaceMultigrid(Options *opt)"); @@ -205,7 +206,6 @@ BOUT_OMP(master) } FieldPerp LaplaceMultigrid::solve(const FieldPerp& b_in, const FieldPerp& x0) { -#if not(BOUT_USE_METRIC_3D) TRACE("LaplaceMultigrid::solve(const FieldPerp, const FieldPerp)"); @@ -550,13 +550,9 @@ BOUT_OMP(for) checkData(result); return result; -#else - return FieldPerp{}; -#endif } void LaplaceMultigrid::generateMatrixF(int level) { -#if not(BOUT_USE_METRIC_3D) TRACE("LaplaceMultigrid::generateMatrixF(int)"); // Set (fine-level) matrix entries @@ -695,6 +691,6 @@ BOUT_OMP(for) } } } -#endif } +#endif // BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx index 3a14cabe1b..0d5ac653f8 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx @@ -31,12 +31,23 @@ #ifndef __MULTIGRID_LAPLACE_H__ #define __MULTIGRID_LAPLACE_H__ +#include "bout/build_config.hxx" +#include "invert_laplace.hxx" + +#if BOUT_USE_METRIC_3D + +namespace { +RegisterUnavailableLaplace + registerlaplacemultigrid(LAPLACE_MULTIGRID, "BOUT++ was configured with 3D metrics"); +} + +#else + #include #include #include #include -#include #include #include @@ -239,4 +250,6 @@ namespace { RegisterLaplace registerlaplacemultigrid(LAPLACE_MULTIGRID); } +#endif // BOUT_USE_METRIC_3D + #endif // __MULTIGRID_LAPLACE_H__ diff --git a/src/invert/laplace/impls/multigrid/multigrid_solver.cxx b/src/invert/laplace/impls/multigrid/multigrid_solver.cxx index 8a477a1569..a1892f09cd 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_solver.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_solver.cxx @@ -27,6 +27,10 @@ * **************************************************************************/ +#include "bout/build_config.hxx" + +#if not BOUT_USE_METRIC_3D + #include "multigrid_laplace.hxx" #include "unused.hxx" #include @@ -723,3 +727,5 @@ MultigridSerial::MultigridSerial(int level, int gx, int gz, MPI_Comm comm, int c } } } + +#endif diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index 83c33b4398..bbeb202d99 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -24,9 +24,12 @@ * **************************************************************************/ -#include +#include "bout/build_config.hxx" #include "serial_band.hxx" +#if not BOUT_USE_METRIC_3D + +#include #include #include #include @@ -41,9 +44,6 @@ LaplaceSerialBand::LaplaceSerialBand(Options *opt, const CELL_LOC loc, Mesh *mesh_in) : Laplacian(opt, loc, mesh_in), Acoef(0.0), Ccoef(1.0), Dcoef(1.0) { -#if BOUT_USE_METRIC_3D - throw BoutException("Laplacian serial band solver does not support 3D metric yet."); -#endif Acoef.setLocation(location); Ccoef.setLocation(location); Dcoef.setLocation(location); @@ -82,7 +82,6 @@ LaplaceSerialBand::LaplaceSerialBand(Options *opt, const CELL_LOC loc, Mesh *mes FieldPerp LaplaceSerialBand::solve(const FieldPerp& b) { return solve(b, b); } FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { -#if not(BOUT_USE_METRIC_3D) ASSERT1(localmesh == b.getMesh() && localmesh == x0.getMesh()); ASSERT1(b.getLocation() == location); ASSERT1(x0.getLocation() == location); @@ -429,7 +428,6 @@ FieldPerp LaplaceSerialBand::solve(const FieldPerp& b, const FieldPerp& x0) { checkData(x); return x; -#else - return FieldPerp{}; -#endif } + +#endif // BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/serial_band/serial_band.hxx b/src/invert/laplace/impls/serial_band/serial_band.hxx index 99842f3e27..aeea2d172e 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.hxx +++ b/src/invert/laplace/impls/serial_band/serial_band.hxx @@ -29,7 +29,18 @@ class LaplaceSerialBand; #ifndef __SERIAL_BAND_H__ #define __SERIAL_BAND_H__ -#include +#include "bout/build_config.hxx" +#include "invert_laplace.hxx" + +#if BOUT_USE_METRIC_3D + +namespace { +RegisterUnavailableLaplace + registerlaplaceserialband(LAPLACE_BAND, "BOUT++ was configured with 3D metrics"); +} + +#else + #include #include #include @@ -80,4 +91,6 @@ private: Array bk1d, xk1d; }; +#endif // BOUT_USE_METRIC_3D + #endif // __SERIAL_BAND_H__ diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index ac7ac39b06..6bb3e90e67 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -1,5 +1,8 @@ +#include "bout/build_config.hxx" #include "laplacexz-cyclic.hxx" +#if not BOUT_USE_METRIC_3D + #include #include #include @@ -9,10 +12,6 @@ #include LaplaceXZcyclic::LaplaceXZcyclic(Mesh *m, Options *options, const CELL_LOC loc) : LaplaceXZ(m, options, loc) { -#if BOUT_USE_METRIC_3D - throw BoutException("LaplaceXZ cyclic solver does not support 3D metric yet."); -#endif - // Number of Z Fourier modes, including DC nmode = (m->LocalNz) / 2 + 1; @@ -59,7 +58,6 @@ LaplaceXZcyclic::LaplaceXZcyclic(Mesh *m, Options *options, const CELL_LOC loc) } void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { -#if not(BOUT_USE_METRIC_3D) TRACE("LaplaceXZcyclic::setCoefs"); Timer timer("invert"); @@ -161,11 +159,9 @@ void LaplaceXZcyclic::setCoefs(const Field2D &A2D, const Field2D &B2D) { } // Set coefficients in tridiagonal solver cr->setCoefs(acoef, bcoef, ccoef); -#endif } Field3D LaplaceXZcyclic::solve(const Field3D &rhs, const Field3D &x0) { -#if not(BOUT_USE_METRIC_3D) Timer timer("invert"); ASSERT1(rhs.getMesh() == localmesh); @@ -273,7 +269,6 @@ Field3D LaplaceXZcyclic::solve(const Field3D &rhs, const Field3D &x0) { } return result; -#else - return Field3D{}; -#endif } + +#endif // BOUT_USE_METRIC_3D diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx index 5a66afa11e..0b6a24156b 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.hxx @@ -1,4 +1,18 @@ -#include +#ifndef LAPLACEXZ_CYCLIC_HXX +#define LAPLACEXZ_CYCLIC_HXX + +#include "bout/build_config.hxx" +#include "bout/invert/laplacexz.hxx" + +#if BOUT_USE_METRIC_3D + +namespace { +RegisterUnavailableLaplaceXZ registerlaplacexzcylic{ + "cyclic", "BOUT++ was configured with 3D metrics"}; +} // namespace + +#else + #include #include #include @@ -29,3 +43,7 @@ private: namespace { RegisterLaplaceXZ registerlaplacexzcylic{"cyclic"}; } // namespace + +#endif // BOUT_USE_METRIC_3D + +#endif // LAPLACEXZ_CYCLIC_HXX diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 0e2047a5e0..db16930210 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -35,10 +35,14 @@ * ************************************************************************/ +#include "bout/build_config.hxx" +#include "cyclic.hxx" + +#if not BOUT_USE_METRIC_3D + #include #include #include -#include "cyclic.hxx" #include #include #include @@ -51,19 +55,14 @@ InvertParCR::InvertParCR(Options *opt, CELL_LOC location, Mesh *mesh_in) : InvertPar(opt, location, mesh_in), A(1.0), B(0.0), C(0.0), D(0.0), E(0.0) { -#if BOUT_USE_METRIC_3D - throw BoutException("Parallel cyclic solver does not support 3D metric yet."); -#else // Number of k equations to solve for each x location nsys = 1 + (localmesh->LocalNz)/2; sg = sqrt(localmesh->getCoordinates(location)->g_22); sg = DDY(1. / sg) / sg; -#endif } const Field3D InvertParCR::solve(const Field3D &f) { -#if not(BOUT_USE_METRIC_3D) TRACE("InvertParCR::solve(Field3D)"); ASSERT1(localmesh == f.getMesh()); ASSERT1(location == f.getLocation()); @@ -240,7 +239,6 @@ const Field3D InvertParCR::solve(const Field3D &f) { } return fromFieldAligned(result, "RGN_NOBNDRY"); -#else - return Field3D{}; -#endif }; + +#endif // BOUT_USE_METRIC_3D diff --git a/src/invert/parderiv/impls/cyclic/cyclic.hxx b/src/invert/parderiv/impls/cyclic/cyclic.hxx index e838515b35..f1fa8c7021 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.hxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.hxx @@ -42,7 +42,17 @@ #ifndef __INV_PAR_CR_H__ #define __INV_PAR_CR_H__ +#include "bout/build_config.hxx" #include "invert_parderiv.hxx" + +#if BOUT_USE_METRIC_3D + +namespace { +RegisterUnavailableInvertPar registerinvertparcyclic{PARDERIVCYCLIC, "BOUT++ was configured with 3D metrics"}; +} + +#else + #include "dcomplex.hxx" #include #include "utils.hxx" @@ -97,4 +107,6 @@ namespace { RegisterInvertPar registerinvertparcyclic{PARDERIVCYCLIC}; } +#endif // BOUT_USE_METRIC_3D + #endif // __INV_PAR_CR_H__ From 9387de694e34a40dae2ada62f9676da65f36c361 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 27 Oct 2020 14:47:18 +0000 Subject: [PATCH 207/293] Use FieldMetric in Coordinates test constructor --- include/bout/coordinates.hxx | 9 ++- src/mesh/coordinates.cxx | 13 ++-- tests/unit/mesh/test_coordinates.cxx | 110 ++++++++++++++++++++++----- 3 files changed, 101 insertions(+), 31 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index df126b1d34..00a8e2c984 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -71,10 +71,11 @@ public: /// A constructor useful for testing purposes. To use it, inherit /// from Coordinates. If \p calculate_geometry is true (default), /// calculate the non-uniform variables, Christoffel symbols - Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2D J, Field2D Bxy, - Field2D g11, Field2D g22, Field2D g33, Field2D g12, Field2D g13, - Field2D g23, Field2D g_11, Field2D g_22, Field2D g_33, Field2D g_12, - Field2D g_13, Field2D g_23, Field2D ShiftTorsion, Field2D IntShiftTorsion, + Coordinates(Mesh* mesh, FieldMetric dx, FieldMetric dy, FieldMetric dz, FieldMetric J, + FieldMetric Bxy, FieldMetric g11, FieldMetric g22, FieldMetric g33, + FieldMetric g12, FieldMetric g13, FieldMetric g23, FieldMetric g_11, + FieldMetric g_22, FieldMetric g_33, FieldMetric g_12, FieldMetric g_13, + FieldMetric g_23, FieldMetric ShiftTorsion, FieldMetric IntShiftTorsion, bool calculate_geometry = true); Coordinates& operator=(Coordinates&&) = default; diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 9df16d121a..71604b37aa 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -365,12 +365,13 @@ void communicate(T& t, Ts&... ts) { } // anonymous namespace -Coordinates::Coordinates(Mesh* mesh, Field2D dx, Field2D dy, BoutReal dz, Field2D J, - Field2D Bxy, Field2D g11, Field2D g22, Field2D g33, Field2D g12, - Field2D g13, Field2D g23, Field2D g_11, Field2D g_22, - Field2D g_33, Field2D g_12, Field2D g_13, Field2D g_23, - Field2D ShiftTorsion, Field2D IntShiftTorsion, - bool calculate_geometry) +Coordinates::Coordinates(Mesh* mesh, FieldMetric dx, FieldMetric dy, FieldMetric dz, + FieldMetric J, FieldMetric Bxy, FieldMetric g11, FieldMetric g22, + FieldMetric g33, FieldMetric g12, FieldMetric g13, + FieldMetric g23, FieldMetric g_11, FieldMetric g_22, + FieldMetric g_33, FieldMetric g_12, FieldMetric g_13, + FieldMetric g_23, FieldMetric ShiftTorsion, + FieldMetric IntShiftTorsion, bool calculate_geometry) : dx(std::move(dx)), dy(std::move(dy)), dz(dz), J(std::move(J)), Bxy(std::move(Bxy)), g11(std::move(g11)), g22(std::move(g22)), g33(std::move(g33)), g12(std::move(g12)), g13(std::move(g13)), g23(std::move(g23)), g_11(std::move(g_11)), diff --git a/tests/unit/mesh/test_coordinates.cxx b/tests/unit/mesh/test_coordinates.cxx index f984bae46a..bd92abf736 100644 --- a/tests/unit/mesh/test_coordinates.cxx +++ b/tests/unit/mesh/test_coordinates.cxx @@ -15,24 +15,60 @@ extern Mesh* mesh; using bout::globals::mesh; -using CoordinatesTest = FakeMeshFixture; +class CoordinatesTest : public FakeMeshFixture { +public: + using FieldMetric = Coordinates::FieldMetric; + CoordinatesTest() : FakeMeshFixture() {} +}; TEST_F(CoordinatesTest, ZLength) { - Coordinates coords{ - mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{1.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, false}; + Coordinates coords{mesh, + FieldMetric{1.0}, // dx + FieldMetric{1.0}, // dy + FieldMetric{1.0}, // dz + FieldMetric{1.0}, // J + FieldMetric{1.0}, // Bxy + FieldMetric{1.0}, // g11 + FieldMetric{1.0}, // g22 + FieldMetric{1.0}, // g33 + FieldMetric{0.0}, // g12 + FieldMetric{0.0}, // g13 + FieldMetric{0.0}, // g23 + FieldMetric{1.0}, // g_11 + FieldMetric{1.0}, // g_22 + FieldMetric{1.0}, // g_23 + FieldMetric{0.0}, // g_12 + FieldMetric{0.0}, // g_13 + FieldMetric{0.0}, // g_23 + FieldMetric{0.0}, // ShiftTorsion + FieldMetric{0.0}, // IntShiftTorsion + false}; // calculate_geometry EXPECT_TRUE(IsFieldEqual(coords.zlength(), 7.0)); } TEST_F(CoordinatesTest, Jacobian) { - Coordinates coords{ - mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{1.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, false}; + Coordinates coords{mesh, + FieldMetric{1.0}, // dx + FieldMetric{1.0}, // dy + FieldMetric{1.0}, // dz + FieldMetric{1.0}, // J + FieldMetric{1.0}, // Bxy + FieldMetric{1.0}, // g11 + FieldMetric{1.0}, // g22 + FieldMetric{1.0}, // g33 + FieldMetric{0.0}, // g12 + FieldMetric{0.0}, // g13 + FieldMetric{0.0}, // g23 + FieldMetric{1.0}, // g_11 + FieldMetric{1.0}, // g_22 + FieldMetric{1.0}, // g_23 + FieldMetric{0.0}, // g_12 + FieldMetric{0.0}, // g_13 + FieldMetric{0.0}, // g_23 + FieldMetric{0.0}, // ShiftTorsion + FieldMetric{0.0}, // IntShiftTorsion + false}; // calculate_geometry EXPECT_NO_THROW(coords.jacobian()); @@ -43,11 +79,27 @@ TEST_F(CoordinatesTest, Jacobian) { /// To do generalise these tests #if not(BOUT_USE_METRIC_3D) TEST_F(CoordinatesTest, CalcContravariant) { - Coordinates coords{ - mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, false}; + Coordinates coords{mesh, + FieldMetric{1.0}, // dx + FieldMetric{1.0}, // dy + FieldMetric{1.0}, // dz + FieldMetric{0.0}, // J + FieldMetric{0.0}, // Bxy + FieldMetric{1.0}, // g11 + FieldMetric{1.0}, // g22 + FieldMetric{1.0}, // g33 + FieldMetric{0.0}, // g12 + FieldMetric{0.0}, // g13 + FieldMetric{0.0}, // g23 + FieldMetric{0.0}, // g_11 + FieldMetric{0.0}, // g_22 + FieldMetric{0.0}, // g_23 + FieldMetric{0.0}, // g_12 + FieldMetric{0.0}, // g_13 + FieldMetric{0.0}, // g_23 + FieldMetric{0.0}, // ShiftTorsion + FieldMetric{0.0}, // IntShiftTorsion + false}; // calculate_geometry output_info.disable(); coords.calcCovariant(); @@ -62,11 +114,27 @@ TEST_F(CoordinatesTest, CalcContravariant) { } TEST_F(CoordinatesTest, CalcCovariant) { - Coordinates coords{ - mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, false}; + Coordinates coords{mesh, + FieldMetric{1.0}, // dx + FieldMetric{1.0}, // dy + FieldMetric{1.0}, // dz + FieldMetric{0.0}, // J + FieldMetric{0.0}, // Bxy + FieldMetric{0.0}, // g11 + FieldMetric{0.0}, // g22 + FieldMetric{0.0}, // g33 + FieldMetric{0.0}, // g12 + FieldMetric{0.0}, // g13 + FieldMetric{0.0}, // g23 + FieldMetric{1.0}, // g_11 + FieldMetric{1.0}, // g_22 + FieldMetric{1.0}, // g_23 + FieldMetric{0.0}, // g_12 + FieldMetric{0.0}, // g_13 + FieldMetric{0.0}, // g_23 + FieldMetric{0.0}, // ShiftTorsion + FieldMetric{0.0}, // IntShiftTorsion + false}; // calculate_geometry output_info.disable(); coords.calcContravariant(); From 0fed8fb22612f916336e9f79d9bcf08d4e3d777b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 27 Oct 2020 14:54:03 +0000 Subject: [PATCH 208/293] Add unit test for Coordinates::zlength in 3D metrics --- tests/unit/mesh/test_coordinates.cxx | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/unit/mesh/test_coordinates.cxx b/tests/unit/mesh/test_coordinates.cxx index bd92abf736..5ffdd1d7a2 100644 --- a/tests/unit/mesh/test_coordinates.cxx +++ b/tests/unit/mesh/test_coordinates.cxx @@ -1,5 +1,6 @@ #include "gtest/gtest.h" +#include "bout/build_config.hxx" #include "bout/coordinates.hxx" #include "bout/mesh.hxx" #include "output.hxx" @@ -47,6 +48,40 @@ TEST_F(CoordinatesTest, ZLength) { EXPECT_TRUE(IsFieldEqual(coords.zlength(), 7.0)); } +#if BOUT_USE_METRIC_3D +TEST_F(CoordinatesTest, ZLength3D) { + auto dz = makeField([](const Ind3D& i) -> BoutReal { + return static_cast(i.x() + i.y()) / nz; + }); + auto expected = + makeField([](const Ind2D& i) -> BoutReal { return i.x() + i.y(); }); + + Coordinates coords{mesh, + FieldMetric{1.0}, // dx + FieldMetric{1.0}, // dy + dz, // dz + FieldMetric{1.0}, // J + FieldMetric{1.0}, // Bxy + FieldMetric{1.0}, // g11 + FieldMetric{1.0}, // g22 + FieldMetric{1.0}, // g33 + FieldMetric{0.0}, // g12 + FieldMetric{0.0}, // g13 + FieldMetric{0.0}, // g23 + FieldMetric{1.0}, // g_11 + FieldMetric{1.0}, // g_22 + FieldMetric{1.0}, // g_23 + FieldMetric{0.0}, // g_12 + FieldMetric{0.0}, // g_13 + FieldMetric{0.0}, // g_23 + FieldMetric{0.0}, // ShiftTorsion + FieldMetric{0.0}, // IntShiftTorsion + false}; // calculate_geometry + + EXPECT_TRUE(IsFieldEqual(coords.zlength(), expected)); +} +#endif + TEST_F(CoordinatesTest, Jacobian) { Coordinates coords{mesh, FieldMetric{1.0}, // dx From 6543926c3934aa1dbbc322a2e68e52843ea19b4a Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 27 Oct 2020 15:11:33 +0000 Subject: [PATCH 209/293] Add unit tests + docstrings for is/getUniform --- include/field.hxx | 24 ++++++++++++++--- tests/unit/field/test_field.cxx | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/include/field.hxx b/include/field.hxx index 77f840ef1c..86c1c5d74c 100644 --- a/include/field.hxx +++ b/include/field.hxx @@ -384,9 +384,16 @@ inline BoutReal min(const T& f, bool allpe, REGION rgn) { return min(f, allpe, toString(rgn)); } +/// Returns true if all elements of \p f over \p region are equal. By +/// default only checks the local processor, use \p allpe to check +/// globally +/// +/// @param[in] f The field to check +/// @param[in] allpe Check over all processors +/// @param[in] region The region to check for uniformity over template > inline bool isUniform(const T& f, bool allpe = false, - const std::string& region = "RGN_ALL") { + const std::string& region = "RGN_ALL") { bool result = true; auto element = f[*f.getRegion(region).begin()]; // TODO: maybe parallise this loop, as the early return is unlikely @@ -403,12 +410,21 @@ inline bool isUniform(const T& f, bool allpe = false, return result; } +/// Returns the value of the first element of \p f (in the region \p +/// region if given). If checks are enabled, then throws an exception +/// if \p f is not uniform over \p region. By default only checks the +/// local processor, use \p allpe to check globally +/// +/// @param[in] f The field to check +/// @param[in] allpe Check over all processors +/// @param[in] region The region to assume is uniform template > inline BoutReal getUniform(const T& f, bool allpe = false, - const std::string& region = "RGN_ALL") { + const std::string& region = "RGN_ALL") { #if CHECK > 1 - if (! isUniform(f, allpe, region)) { - throw BoutException("Requested getUniform({}, {}, {}) but Field is not const", f.name, allpe, region); + if (not isUniform(f, allpe, region)) { + throw BoutException("Requested getUniform({}, {}, {}) but Field is not const", f.name, + allpe, region); } #endif return f[*f.getRegion(region).begin()]; diff --git a/tests/unit/field/test_field.cxx b/tests/unit/field/test_field.cxx index 0e90014484..2aa6dc73f7 100644 --- a/tests/unit/field/test_field.cxx +++ b/tests/unit/field/test_field.cxx @@ -184,3 +184,51 @@ TEST_F(FieldTest, filledFromConstInd3D) { ASSERT_DOUBLE_EQ( result[i], i.x() * i.y()); } } + +TEST_F(FieldTest, IsUniformTrue3D) { + Field3D uniform{1.0}; + EXPECT_TRUE(isUniform(uniform)); +} + +TEST_F(FieldTest, IsUniformFalse3D) { + Field3D nonuniform{2.0}; + nonuniform(1, 2, 3) = 3.0; + EXPECT_FALSE(isUniform(nonuniform)); +} + +TEST_F(FieldTest, IsUniformTrue2D) { + Field2D uniform{4.0}; + EXPECT_TRUE(isUniform(uniform)); +} + +TEST_F(FieldTest, IsUniformFalse2D) { + Field2D nonuniform{5.0}; + nonuniform(2, 1) = 6.0; + EXPECT_FALSE(isUniform(nonuniform)); +} + +TEST_F(FieldTest, GetUniformTrue3D) { + Field3D uniform{10.0}; + EXPECT_EQ(getUniform(uniform), 10.0); +} + +TEST_F(FieldTest, GetUniformFalse3D) { + Field3D nonuniform{20.0}; + nonuniform(1, 2, 3) = 30.0; +#if CHECK > 1 + EXPECT_THROW(getUniform(nonuniform), BoutException); +#endif +} + +TEST_F(FieldTest, GetUniformTrue2D) { + Field2D uniform{40.0}; + EXPECT_EQ(getUniform(uniform), 40.0); +} + +TEST_F(FieldTest, GetUniformFalse2D) { + Field2D nonuniform{50.0}; + nonuniform(2, 1) = 60.0; +#if CHECK > 1 + EXPECT_THROW(getUniform(nonuniform), BoutException); +#endif +} From 8e1926be7b8d2e99736c6c24727b2a06ad94206d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 27 Oct 2020 15:35:37 +0000 Subject: [PATCH 210/293] Add unit test for DC(Field2D) --- tests/unit/field/test_field2d.cxx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/unit/field/test_field2d.cxx b/tests/unit/field/test_field2d.cxx index ea0f5919ca..451b7e043a 100644 --- a/tests/unit/field/test_field2d.cxx +++ b/tests/unit/field/test_field2d.cxx @@ -1485,4 +1485,11 @@ TEST_F(Field2DTest, ZeroFrom) { EXPECT_TRUE(field2.isAllocated()); EXPECT_TRUE(IsFieldEqual(field2, 0.)); } + +TEST_F(Field2DTest, DC) { + Field2D field = + makeField([](const Ind2D& i) -> BoutReal { return i.x() * i.y(); }); + EXPECT_EQ(DC(field), field); +} + #pragma GCC diagnostic pop From 55963209c3be5c877781e50d1fa4e433068871f2 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 14:44:00 +0000 Subject: [PATCH 211/293] CMake: Skip building example if PETSc missing rather than error --- examples/invertable_operator/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/invertable_operator/CMakeLists.txt b/examples/invertable_operator/CMakeLists.txt index 83f7c74e7a..b1da449652 100644 --- a/examples/invertable_operator/CMakeLists.txt +++ b/examples/invertable_operator/CMakeLists.txt @@ -7,7 +7,12 @@ if (NOT TARGET bout++::bout++) endif() if(NOT BOUT_HAS_PETSC) - message(FATAL_ERROR "This example requires PETSc. Please compile BOUT++ with PETSc") + if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") + message(STATUS "The invertable operator example requires PETSc. Please compile BOUT++ with PETSc to use it") + return() + else() + message(FATAL_ERROR "The invertable operator example requires PETSc. Please compile BOUT++ with PETSc to use it") + endif() endif() bout_add_example(invertable_operator SOURCES invertable_operator.cxx) From 1236bba13ac5d3f601fa2e93db4e972cf8415482 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 15:16:50 +0000 Subject: [PATCH 212/293] CMake: Move METRIC_3D option with rest of feature options Needs to come before adding the tests in order for conflicting tests to be disabled --- CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dcda8cfca..f7a445c158 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -485,6 +485,14 @@ endif() message(STATUS "Enable OpenMP: ${BOUT_ENABLE_OPENMP}") set(BOUT_USE_OPENMP ${BOUT_ENABLE_OPENMP}) +option(BOUT_ENABLE_METRIC_3D "Enable 3D metric support" OFF) +if(BOUT_ENABLE_METRIC_3D) + set(BOUT_METRIC_TYPE "3D") +else() + set(BOUT_METRIC_TYPE "2D") +endif() +set(BOUT_USE_METRIC_3D ${BOUT_ENABLE_METRIC_3D}) + # Optional dependencies option(BOUT_USE_PVODE "Enable support for bundled PVODE" ON) @@ -787,14 +795,6 @@ if(PACKAGE_TESTS) add_dependencies(check check-unit-tests check-integrated-tests) endif() -option(BOUT_ENABLE_METRIC_3D "Enable 3D metric support" OFF) -if(BOUT_ENABLE_METRIC_3D) - set(BOUT_METRIC_TYPE "3D") -else() - set(BOUT_METRIC_TYPE "2D") -endif() -set(BOUT_USE_METRIC_3D ${BOUT_ENABLE_METRIC_3D}) - option(BOUT_BUILD_EXAMPLES "Build the examples" OFF) if(BOUT_BUILD_EXAMPLES) add_subdirectory(examples) From 86b6c68d87507943c471a5380a727b70e9e69132 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 15:21:39 +0000 Subject: [PATCH 213/293] Silence clang-tidy warnings on AUTO_TRACE --- include/msg_stack.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/msg_stack.hxx b/include/msg_stack.hxx index 917feedfe8..f0c78a14aa 100644 --- a/include/msg_stack.hxx +++ b/include/msg_stack.hxx @@ -217,6 +217,6 @@ private: * * } // Scope ends, message popped */ -#define AUTO_TRACE() TRACE(__thefunc__) +#define AUTO_TRACE() TRACE(__thefunc__) // NOLINT #endif // __MSG_STACK_H__ From e6b53e92ed3254a7674993cb3af6e41ada893a65 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 15:30:11 +0000 Subject: [PATCH 214/293] Add back boutconfig import from bad merge --- tests/integrated/test-io/runtest | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index 1d857b5710..03eea6ab3a 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -6,6 +6,7 @@ # requires: netcdf # cores: 4 +from boutconfig import isMetric3D from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect from boututils.datafile import DataFile @@ -75,7 +76,7 @@ def check_output(): # Compare benchmark and output if np.shape(bmk[v]) != np.shape(result): - if (conf.isMetric3D() and v.startswith('v2d') + if (isMetric3D() and v.startswith('v2d') and bmk[v].shape == result.shape[:-1]): result = result[...,0] else: From d51c913086fe448761875c19ecdbf9049cc77fd0 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 15:51:02 +0000 Subject: [PATCH 215/293] Fix test-io for change in Field type of Vector2D with 3D metrics --- tests/integrated/test-io/runtest | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index 03eea6ab3a..c5db74e69c 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -98,6 +98,11 @@ def check_output(): success = False continue + if (isMetric3D() and v.startswith('v2d')): + # Vector2Ds are based on Field3Ds for 3D metrics + bmk[v].attributes["bout_type"] = "Field3D_t" + bmk[v].attributes["direction_z"] = "Standard" + for attrname in bmk[v].attributes: bmkattr = bmk[v].attributes[attrname] resattr = result.attributes[attrname] From 2cf1104582fba0d3568a7876a0b99443029e998b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 16:40:17 +0000 Subject: [PATCH 216/293] Simplify nested if statements in Coordinate::maybeFromFieldAligned --- include/bout/coordinates.hxx | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 00a8e2c984..20caa8716c 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -317,16 +317,13 @@ private: const std::string& region = "RGN_ALL") { ASSERT1(location == f.getLocation()); ASSERT1(localmesh == f.getMesh()); - if (f.getDirectionY() != YDirectionType::Standard) { - if (this->getParallelTransform().canToFromFieldAligned()) { - return this->getParallelTransform().fromFieldAligned(f, region); - } else { - Field3D f_ = f; - f_.setDirectionY(YDirectionType::Standard); - return f_; - } + if (f.getDirectionY() == YDirectionType::Standard) { + return f; } - return f; + if (this->getParallelTransform().canToFromFieldAligned()) { + return this->getParallelTransform().fromFieldAligned(f, region); + } + return copy(f).setDirectionY(YDirectionType::Standard); } inline Field2D maybeFromFieldAligned(const Field2D& f, From 6b100861223cd5503ce017609256e082829aa068 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 16:41:07 +0000 Subject: [PATCH 217/293] Silence warnings on some optimised code in `bracket` --- src/mesh/difops.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index bf12a33236..6b91a9c83c 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -1095,15 +1095,18 @@ Field3D bracket(const Field3D& f, const Field3D& g, BRACKET_METHOD method, // Above is alternative to const int jzm = (jz - 1 + ncz) % ncz; // J++ = DDZ(f)*DDX(g) - DDX(f)*DDZ(g) + // NOLINTNEXTLINE BoutReal Jpp = ((Fx[jzp] - Fx[jzm]) * (Gxp[jz] - Gxm[jz]) - (Fxp[jz] - Fxm[jz]) * (Gx[jzp] - Gx[jzm])); // J+x + // NOLINTNEXTLINE BoutReal Jpx = (Gxp[jz] * (Fxp[jzp] - Fxp[jzm]) - Gxm[jz] * (Fxm[jzp] - Fxm[jzm]) - Gx[jzp] * (Fxp[jzp] - Fxm[jzp]) + Gx[jzm] * (Fxp[jzm] - Fxm[jzm])); // Jx+ + // NOLINTNEXTLINE BoutReal Jxp = (Gxp[jzp] * (Fx[jzp] - Fxp[jz]) - Gxm[jzm] * (Fxm[jz] - Fx[jzm]) - Gxm[jzp] * (Fx[jzp] - Fxm[jz]) + Gxp[jzm] * (Fxp[jz] - Fx[jzm])); From fef1be746cb4114d0a61dc57ebdc7041e33ae846 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 9 Dec 2020 16:42:46 +0000 Subject: [PATCH 218/293] Remove `const` from return type on vector operations --- include/vecops.hxx | 66 +++++++++++++++++++++----------------------- src/field/vecops.cxx | 42 ++++++++++++++-------------- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/include/vecops.hxx b/include/vecops.hxx index d852ad4c2c..2ce88fdb66 100644 --- a/include/vecops.hxx +++ b/include/vecops.hxx @@ -44,7 +44,6 @@ class Vector3D; #include "vector2d.hxx" #include "vector3d.hxx" - /// Gradient of scalar field \p f, returning a covariant vector /// /// All locations supported @@ -53,10 +52,10 @@ class Vector3D; /// @param[in] outloc The location where the result is desired /// By default this is the same location as the input \p f /// @param[in] method The method to use. The default is set in the options. -const Vector2D Grad(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -const Vector3D Grad(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Vector2D Grad(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +Vector3D Grad(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); /// Perpendicular gradient of scalar field \p f /// @@ -70,13 +69,13 @@ const Vector3D Grad(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, /// @param[in] outloc The cell location where the result is desired /// @param[in] method The method to use. The default is set in the options. /// -const Vector3D Grad_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -inline const Vector3D Grad_perp(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { +Vector3D Grad_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +inline Vector3D Grad_perp(const Field3D& f, CELL_LOC outloc, DIFF_METHOD method) { return Grad_perp(f, outloc, toString(method)); } -const Vector2D Grad_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Vector2D Grad_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); /// Divergence of a vector \p v, returning a scalar /// @@ -87,29 +86,28 @@ const Vector2D Grad_perp(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, /// @param[in] outloc The cell location where the result is desired /// @param[in] method The method to use. The default is set in the options. /// -const Coordinates::FieldMetric Div(const Vector2D& v, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -const Field3D Div(const Vector3D& v, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Coordinates::FieldMetric Div(const Vector2D& v, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +Field3D Div(const Vector3D& v, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); -const Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); -const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); DEPRECATED(inline const Field3D Div(const Vector3D& v, const Field3D& f, const std::string& method, CELL_LOC outloc = CELL_DEFAULT)) { return Div(v, f, outloc, method); } -inline const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, - DIFF_METHOD method = DIFF_DEFAULT) { +inline Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, + DIFF_METHOD method = DIFF_DEFAULT) { return Div(v, f, outloc, toString(method)); } -DEPRECATED(inline const Field3D Div(const Vector3D& v, const Field3D& f, - DIFF_METHOD method, CELL_LOC outloc = CELL_DEFAULT)) { +DEPRECATED(inline Field3D Div(const Vector3D& v, const Field3D& f, DIFF_METHOD method, + CELL_LOC outloc = CELL_DEFAULT)) { return Div(v, f, outloc, toString(method)); } @@ -125,8 +123,8 @@ DEPRECATED(inline const Field3D Div(const Vector3D& v, const Field3D& f, /// /// @param[in] v The vector to differentiate /// -const Vector2D Curl(const Vector2D &v); -const Vector3D Curl(const Vector3D &v); +Vector2D Curl(const Vector2D& v); +Vector3D Curl(const Vector3D& v); // Upwinding routines @@ -134,17 +132,17 @@ const Vector3D Curl(const Vector3D &v); /// /// The vector and the field must be at the same location, which /// cannot be CELL_VSHIFT -const Coordinates::FieldMetric 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); +Coordinates::FieldMetric V_dot_Grad(const Vector2D& v, const Field2D& f); +Field3D V_dot_Grad(const Vector2D& v, const Field3D& f); +Field3D V_dot_Grad(const Vector3D& v, const Field2D& f); +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); -const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a); +Vector2D V_dot_Grad(const Vector2D& v, const Vector2D& a); +Vector3D V_dot_Grad(const Vector2D& v, const Vector3D& a); +Vector3D V_dot_Grad(const Vector3D& v, const Vector2D& a); +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 b407392baa..978fba84f5 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -38,7 +38,7 @@ * Gradient operators **************************************************************************/ -const Vector2D Grad(const Field2D& f, CELL_LOC outloc, const std::string& method) { +Vector2D Grad(const Field2D& f, CELL_LOC outloc, const std::string& method) { TRACE("Grad( Field2D )"); SCOREP0(); CELL_LOC outloc_x, outloc_y, outloc_z; @@ -67,7 +67,7 @@ const Vector2D Grad(const Field2D& f, CELL_LOC outloc, const std::string& method return result; } -const Vector3D Grad(const Field3D &f, CELL_LOC outloc, const std::string& method) { +Vector3D Grad(const Field3D &f, CELL_LOC outloc, const std::string& method) { TRACE("Grad( Field3D )"); SCOREP0(); CELL_LOC outloc_x, outloc_y, outloc_z; @@ -96,7 +96,7 @@ const Vector3D Grad(const Field3D &f, CELL_LOC outloc, const std::string& method return result; } -const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc, const std::string& method) { +Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc, const std::string& method) { TRACE("Grad_perp( Field3D )"); SCOREP0(); ASSERT1(outloc == CELL_DEFAULT || outloc == f.getLocation()); @@ -118,7 +118,7 @@ const Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc, const std::string& m return result; } -const Vector2D Grad_perp(const Field2D &f, CELL_LOC outloc, const std::string& method) { +Vector2D Grad_perp(const Field2D &f, CELL_LOC outloc, const std::string& method) { AUTO_TRACE(); SCOREP0(); ASSERT1(outloc == CELL_DEFAULT || outloc == f.getLocation()); @@ -143,8 +143,8 @@ const Vector2D Grad_perp(const Field2D &f, CELL_LOC outloc, const std::string& m * Divergence operators **************************************************************************/ -const Coordinates::FieldMetric Div(const Vector2D& v, CELL_LOC outloc, - const std::string& method) { +Coordinates::FieldMetric Div(const Vector2D& v, CELL_LOC outloc, + const std::string& method) { TRACE("Div( Vector2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -169,7 +169,7 @@ const Coordinates::FieldMetric Div(const Vector2D& v, CELL_LOC outloc, return result; } -const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) { +Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) { TRACE("Div( Vector3D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -207,8 +207,8 @@ const Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) * Divergence operators for flux methods **************************************************************************/ -const Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, - CELL_LOC outloc, const std::string& method) { +Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, CELL_LOC outloc, + const std::string& method) { TRACE("Div( Vector2D, Field2D )"); SCOREP0(); if (outloc == CELL_DEFAULT) { @@ -234,8 +234,8 @@ const Coordinates::FieldMetric Div(const Vector2D& v, const Field2D& f, return result; } -const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, - const std::string& method) { +Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, + const std::string& method) { TRACE("Div( Vector3D, Field3D )"); if (outloc == CELL_DEFAULT) { @@ -263,7 +263,7 @@ const Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, * Curl operators **************************************************************************/ -const Vector2D Curl(const Vector2D &v) { +Vector2D Curl(const Vector2D &v) { TRACE("Curl( Vector2D )"); @@ -291,7 +291,7 @@ const Vector2D Curl(const Vector2D &v) { return result; } -const Vector3D Curl(const Vector3D &v) { +Vector3D Curl(const Vector3D &v) { TRACE("Curl( Vector3D )"); SCOREP0(); ASSERT1(v.getLocation() != CELL_VSHIFT); @@ -322,7 +322,7 @@ const Vector3D Curl(const Vector3D &v) { /************************************************************************** * Upwinding operators **************************************************************************/ -const Coordinates::FieldMetric V_dot_Grad(const Vector2D& v, const Field2D& f) { +Coordinates::FieldMetric V_dot_Grad(const Vector2D& v, const Field2D& f) { TRACE("V_dot_Grad( Vector2D , Field2D )"); SCOREP0(); @@ -333,7 +333,7 @@ const Coordinates::FieldMetric V_dot_Grad(const Vector2D& v, const Field2D& f) { return VDDX(vcn.x, f) + VDDY(vcn.y, f) + VDDZ(vcn.z, f); } -const Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { +Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { TRACE("V_dot_Grad( Vector2D , Field3D )"); SCOREP0(); @@ -344,7 +344,7 @@ const Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { return VDDX(vcn.x, f) + VDDY(vcn.y, f) + VDDZ(vcn.z, f); } -const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { +Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { TRACE("V_dot_Grad( Vector3D , Field2D )"); SCOREP0(); @@ -355,7 +355,7 @@ const Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { return VDDX(vcn.x, f) + VDDY(vcn.y, f) + VDDZ(vcn.z, f); } -const Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { +Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { TRACE("V_dot_Grad( Vector3D , Field3D )"); SCOREP0(); @@ -440,15 +440,15 @@ R V_dot_Grad(const T &v, const F &a) { } // Implement vector-vector operation in terms of templated routine above -const Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { +Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { return V_dot_Grad(v, a); } -const Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { +Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { return V_dot_Grad(v, a); } -const Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a) { +Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a) { return V_dot_Grad(v, a); } -const Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a) { +Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a) { return V_dot_Grad(v, a); } From e61fb2d0aa68782727ae4c14cf215e55854b6ae4 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 10 Dec 2020 16:15:22 +0000 Subject: [PATCH 219/293] GHA: Add 3D metrics build --- .github/workflows/tests.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index abd3397e92..4f9feaeae6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -82,6 +82,18 @@ jobs: -DSUNDIALS_ROOT=/home/runner/local" omp_num_threads: 2 + - name: "CMake, shared, Ubuntu 20.04, 3D metrics" + os: ubuntu-20.04 + cmake_options: "-DBUILD_SHARED_LIBS=ON + -DBOUT_ENABLE_METRIC_3D=ON + -DBOUT_ENABLE_OPENMP=ON + -DBOUT_USE_PETSC=ON + -DBOUT_USE_SLEPC=ON + -DBOUT_USE_HDF5=ON + -DBOUT_USE_SUNDIALS=ON + -DSUNDIALS_ROOT=/home/runner/local" + omp_num_threads: 2 + - name: "Coverage" os: ubuntu-18.04 configure_options: "--enable-shared From cfe29e6c289c50a092303e6a11825d599e1b6825 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 10 Dec 2020 17:02:44 +0000 Subject: [PATCH 220/293] Replace macro with lambdas --- src/mesh/coordinates.cxx | 56 ++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 71604b37aa..b410f146f7 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -451,32 +451,29 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) dy = interpolateAndExtrapolate(dy, location, extrapolate_x, extrapolate_y, false, transform.get()); -#define GET(a, b) \ - mesh->get(a, #a, b, false); \ - a = maybeFromFieldAligned(a); + auto getUnaligned = [this](auto& field, const std::string& name, + BoutReal default_value) { + localmesh->get(field, name, default_value, false); + return maybeFromFieldAligned(field); + }; + + auto getUnalignedAtLocation = [this, extrapolate_x, extrapolate_y, + getUnaligned](auto& field, const std::string& name, + BoutReal default_value) { + field = getUnaligned(field, name, default_value); + return interpolateAndExtrapolate(field, location, extrapolate_x, extrapolate_y, false, + transform.get()); + }; // Diagonal components of metric tensor g^{ij} (default to 1) - GET(g11, 1.0); - GET(g22, 1.0); - GET(g33, 1.0); + g11 = getUnalignedAtLocation(g11, "g11", 1.0); + g22 = getUnalignedAtLocation(g22, "g22", 1.0); + g33 = getUnalignedAtLocation(g33, "g33", 1.0); // Off-diagonal elements. Default to 0 - GET(g12, 0.0); - GET(g13, 0.0); - GET(g23, 0.0); - - g11 = interpolateAndExtrapolate(g11, location, extrapolate_x, extrapolate_y, false, - transform.get()); - g22 = interpolateAndExtrapolate(g22, location, extrapolate_x, extrapolate_y, false, - transform.get()); - g33 = interpolateAndExtrapolate(g33, location, extrapolate_x, extrapolate_y, false, - transform.get()); - g12 = interpolateAndExtrapolate(g12, location, extrapolate_x, extrapolate_y, false, - transform.get()); - g13 = interpolateAndExtrapolate(g13, location, extrapolate_x, extrapolate_y, false, - transform.get()); - g23 = interpolateAndExtrapolate(g23, location, extrapolate_x, extrapolate_y, false, - transform.get()); + g12 = getUnalignedAtLocation(g12, "g12", 0.0); + g13 = getUnalignedAtLocation(g13, "g13", 0.0); + g23 = getUnalignedAtLocation(g23, "g23", 0.0); // Check input metrics // Diagonal metric components should be finite @@ -503,14 +500,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // Check that all components are present if (std::all_of(begin(covariant_component_names), end(covariant_component_names), source_has_component)) { - GET(g_11, 1.0); - GET(g_22, 1.0); - GET(g_33, 1.0); - GET(g_12, 0.0); - GET(g_13, 0.0); - GET(g_23, 0.0); - -#undef GET + g_11 = getUnaligned(g_11, "g_11", 1.0); + g_22 = getUnaligned(g_22, "g_22", 1.0); + g_33 = getUnaligned(g_33, "g_33", 1.0); + g_12 = getUnaligned(g_12, "g_12", 0.0); + g_13 = getUnaligned(g_13, "g_13", 0.0); + g_23 = getUnaligned(g_23, "g_23", 0.0); output_warn.write("\tWARNING! Covariant components of metric tensor set manually. " "Contravariant components NOT recalculated\n"); @@ -631,7 +626,6 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) // IntShiftTorsion will not be used, but set to zero to avoid uninitialized field IntShiftTorsion = 0.; } - } // use anonymous namespace so this utility function is not available outside this file From 46d4ecd18f7e49d2328ca9db4e4f60ddadd84171 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 10 Dec 2020 17:12:28 +0000 Subject: [PATCH 221/293] Move Coordinates::maybeFromFieldAligned out of header, add docstring --- include/bout/coordinates.hxx | 28 ++++++++-------------------- src/mesh/coordinates.cxx | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 20caa8716c..f763101e7a 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -313,30 +313,18 @@ private: /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); - inline Field3D maybeFromFieldAligned(const Field3D& f, - const std::string& region = "RGN_ALL") { - ASSERT1(location == f.getLocation()); - ASSERT1(localmesh == f.getMesh()); - if (f.getDirectionY() == YDirectionType::Standard) { - return f; - } - if (this->getParallelTransform().canToFromFieldAligned()) { - return this->getParallelTransform().fromFieldAligned(f, region); - } - return copy(f).setDirectionY(YDirectionType::Standard); - } + /// Alternative implementation for `fromFieldAligned` that can be + /// called before the `Coordinates` constructor is finisehd + Field3D maybeFromFieldAligned(const Field3D& f, const std::string& region = "RGN_ALL"); - inline Field2D maybeFromFieldAligned(const Field2D& f, - const std::string& UNUSED(region) = "RGN_ALL") { - return f; - } + Field2D maybeFromFieldAligned(const Field2D& f, + const std::string& UNUSED(region) = "RGN_ALL"); /// A wrapper for index:DDY derivative that is able to tranform /// fields before the constructor is finished. - Coordinates::FieldMetric indexDDY(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + FieldMetric indexDDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); Field3D indexDDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& method = "DEFAULT", const std::string& region = "RGN_NOBNDRY"); diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index b410f146f7..04cf9d0463 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -2054,3 +2054,20 @@ Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, #endif return bout::derivatives::index::DDY(f, outloc, method, region); } + +Field3D Coordinates::maybeFromFieldAligned(const Field3D& f, const std::string& region) { + ASSERT1(location == f.getLocation()); + ASSERT1(localmesh == f.getMesh()); + if (f.getDirectionY() == YDirectionType::Standard) { + return f; + } + if (this->getParallelTransform().canToFromFieldAligned()) { + return this->getParallelTransform().fromFieldAligned(f, region); + } + return copy(f).setDirectionY(YDirectionType::Standard); +} + +Field2D Coordinates::maybeFromFieldAligned(const Field2D& f, + const std::string& UNUSED(region)) { + return f; +} From d1f15f2b7e8efa66cadd377a1a58b53dca74c2b3 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 10 Dec 2020 17:37:51 +0000 Subject: [PATCH 222/293] Silence some unused parameter warnings when compiling with 3D metric --- src/invert/laplace/invert_laplace.cxx | 29 +++++++++++++++++++-------- src/mesh/coordinates.cxx | 3 ++- src/mesh/difops.cxx | 4 ++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index 021f069be2..2957ce85d4 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -265,13 +265,18 @@ void Laplacian::tridagCoefs(int jx, int jy, int jz, ccoef, d, loc); } +#if BOUT_USE_METRIC_3D +void Laplacian::tridagCoefs(int /* jx */, int /* jy */, BoutReal /* kwave */, + dcomplex& /* a */, dcomplex& /* b */, dcomplex& /* c */, + const Field2D* /* c1coef */, const Field2D* /* c2coef */, + const Field2D* /* d */, CELL_LOC /* loc */) { + throw BoutException("Laplacian::tridagCoefs() does not support 3d metrics."); +} +#else void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, dcomplex &a, dcomplex &b, dcomplex &c, const Field2D *c1coef, const Field2D *c2coef, const Field2D *d, CELL_LOC loc) { -#if BOUT_USE_METRIC_3D - throw BoutException("Laplacian::tridagCoefs() does not support 3d metrics."); -#else /* Function: Laplacian::tridagCoef * Purpose: - Set the matrix components of A in Ax=b, solving * @@ -362,8 +367,8 @@ void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, a = dcomplex(coef1 - coef4,-kwave*coef3); b = dcomplex(-2.0*coef1 - SQ(kwave)*coef2,kwave*coef5); c = dcomplex(coef1 + coef4,kwave*coef3); -#endif } +#endif /*! * Set the matrix components of A in Ax=b @@ -402,13 +407,22 @@ void Laplacian::tridagCoefs(int jx, int jy, BoutReal kwave, * \param[out] cvec The upper diagonal. * DO NOT CONFUSE WITH "C" (called ccoef here) */ +#if BOUT_USE_METRIC_3D +void Laplacian::tridagMatrix(dcomplex* /*avec*/, dcomplex* /*bvec*/, dcomplex* /*cvec*/, + dcomplex* /*bk*/, int /*jy*/, int /*kz*/, BoutReal /*kwave*/, + int /*global_flags*/, int /*inner_boundary_flags*/, + int /*outer_boundary_flags*/, const Field2D* /*a*/, + const Field2D* /*c1coef*/, const Field2D* /*c2coef*/, + const Field2D* /*d*/, bool /*includeguards*/) { + throw BoutException("Error: tridagMatrix does not yet work with 3D metric."); +} +#else void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, dcomplex *bk, int jy, int kz, BoutReal kwave, int global_flags, int inner_boundary_flags, int outer_boundary_flags, const Field2D *a, const Field2D *c1coef, const Field2D *c2coef, const Field2D *d, bool includeguards) { -#if not(BOUT_USE_METRIC_3D) ASSERT1(a->getLocation() == location); ASSERT1(c1coef->getLocation() == location); ASSERT1(c2coef->getLocation() == location); @@ -728,10 +742,9 @@ void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, } } } -#else - throw BoutException("Error: tridagMatrix does not yet work with 3D metric."); -#endif } +#endif + /********************************************************************************** * LEGACY INTERFACE diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 04cf9d0463..a336350b8b 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1962,7 +1962,8 @@ Field3D Coordinates::Laplace(const Field3D& f, CELL_LOC outloc, // Full perpendicular Laplacian, in form of inverse of Laplacian operator in LaplaceXY // solver -Field2D Coordinates::Laplace_perpXY(const Field2D& A, const Field2D& f) { +Field2D Coordinates::Laplace_perpXY(MAYBE_UNUSED(const Field2D& A), + MAYBE_UNUSED(const Field2D& f)) { TRACE("Coordinates::Laplace_perpXY( Field2D )"); #if not(BOUT_USE_METRIC_3D) Field2D result; diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 6b91a9c83c..578629d34e 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -622,7 +622,7 @@ Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method, } ASSERT1(outloc == g.getLocation()); - Mesh *mesh = f.getMesh(); + MAYBE_UNUSED(Mesh *mesh) = f.getMesh(); Field3D result{emptyFrom(f).setLocation(outloc)}; @@ -837,7 +837,7 @@ Field3D bracket(const Field2D& f, const Field3D& g, BRACKET_METHOD method, } Field3D bracket(const Field3D& f, const Field3D& g, BRACKET_METHOD method, - CELL_LOC outloc, Solver* solver) { + CELL_LOC outloc, MAYBE_UNUSED(Solver* solver)) { TRACE("Field3D, Field3D"); ASSERT1_FIELDS_COMPATIBLE(f, g); From 6426a3aa11932d2021c0b5faeeaa350277051800 Mon Sep 17 00:00:00 2001 From: BS Date: Fri, 11 Dec 2020 09:40:31 +0100 Subject: [PATCH 223/293] Fix typos in coordinates and fv_ops headers * Add suggested changes (and bugfix) in zoidberg.field.W7X_VMEC --- include/bout/coordinates.hxx | 5 ++--- include/bout/fv_ops.hxx | 2 +- tools/pylib/zoidberg/field.py | 26 ++++++++++++++------------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index f763101e7a..04eb43d342 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -89,8 +89,7 @@ public: */ void outputVars(Datafile &file); - FieldMetric dx, dy, dz; ///< Mesh spacing in x and y - // BoutReal dz; ///< Mesh spacing in Z + FieldMetric dx, dy, dz; ///< Mesh spacing in x, y and z Field2D zlength() const { #if BOUT_USE_METRIC_3D @@ -314,7 +313,7 @@ private: void setParallelTransform(Options* options); /// Alternative implementation for `fromFieldAligned` that can be - /// called before the `Coordinates` constructor is finisehd + /// called before the `Coordinates` constructor is finished Field3D maybeFromFieldAligned(const Field3D& f, const std::string& region = "RGN_ALL"); Field2D maybeFromFieldAligned(const Field2D& f, diff --git a/include/bout/fv_ops.hxx b/include/bout/fv_ops.hxx index 09d2f356c2..574681511c 100644 --- a/include/bout/fv_ops.hxx +++ b/include/bout/fv_ops.hxx @@ -514,5 +514,5 @@ namespace FV { */ Field3D Div_Perp_Lap(const Field3D& a, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); - } // namespace FV +} // namespace FV #endif // __FV_OPS_H__ diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 69446e09c9..2a935bf4ee 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -1531,8 +1531,10 @@ def Rfunc(self, x, z, phi): class W7X_VMEC(MagneticField): def __init__(self,nx=512,ny=32,nz=512,x_range=[4.05,6.55],z_range=[-1.35,1,35], phi_range=[0,2*np.pi], vmec_id='w7x_ref_171'): - from scipy.interpolate import griddata, RegularGridInterpolator - import numpy as np + from scipy.interpolate import RegularGridInterpolator + self.nx = nx + self.ny = ny + self.nz = nz ## create 1D arrays of cylindrical coordinates r = np.linspace(x_range[0], x_range[-1], nx) phi = np.linspace(phi_range[0], phi_range[-1],ny) @@ -1542,7 +1544,7 @@ def __init__(self,nx=512,ny=32,nz=512,x_range=[4.05,6.55],z_range=[-1.35,1,35], rarray,yarray,zarray = np.meshgrid(r,phi,z,indexing='ij') ## call vacuum field values - b_vmec = W7X_VMEC.field_values(rarray,yarray,zarray,vmec_id) + b_vmec = self.field_values(rarray,yarray,zarray,vmec_id) Bx_vmec = b_vmec[0] By_vmec = b_vmec[1] Bz_vmec = b_vmec[2] @@ -1551,9 +1553,9 @@ def __init__(self,nx=512,ny=32,nz=512,x_range=[4.05,6.55],z_range=[-1.35,1,35], # we can get an interpolation function in 3D points = (r,phi,z) - self.br_interp = RegularGridInterpolator(points, Bx, bounds_error=False, fill_value=0.0) - self.bz_interp = RegularGridInterpolator(points, Bz, bounds_error=False, fill_value=0.0) - self.bphi_interp = RegularGridInterpolator(points, By, bounds_error=False, fill_value=1.0) + self.br_interp = RegularGridInterpolator(points, Bx_vmec, bounds_error=False, fill_value=0.0) + self.bz_interp = RegularGridInterpolator(points, Bz_vmec, bounds_error=False, fill_value=0.0) + self.bphi_interp = RegularGridInterpolator(points, By_vmec, bounds_error=False, fill_value=1.0) def field_values(r,phi,z, vmec_id='w7x_ref_171'): from osa import Client @@ -1561,15 +1563,15 @@ def field_values(r,phi,z, vmec_id='w7x_ref_171'): pos = vmec.types.Points3D() - pos.x1 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.cos(phi)) #x in Cartesian (real-space) - pos.x2 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.sin(phi)) #y in Cartesian (real-space) + pos.x1 = np.ndarray.flatten(np.ones((self.nx,self.ny,self.nz))*r*np.cos(phi)) #x in Cartesian (real-space) + pos.x2 = np.ndarray.flatten(np.ones((self.nx,self.ny,self.nz))*r*np.sin(phi)) #y in Cartesian (real-space) pos.x3 = np.ndarray.flatten(z) #z in Cartesian (real-space) - b = vmec.service.magneticField(str(vmec_id), p) + b = vmec.service.magneticField(str(vmec_id), pos) ## Reshape to 3d array - Bx = np.ndarray.reshape(np.asarray(b.field.x1),(nx,ny,nz)) - By = np.ndarray.reshape(np.asarray(b.field.x2),(nx,ny,nz)) - Bz = np.ndarray.reshape(np.asarray(b.field.x3), (nx,ny,nz)) + Bx = np.ndarray.reshape(np.asarray(b.field.x1),(self.nx,self.ny,self.nz)) + By = np.ndarray.reshape(np.asarray(b.field.x2),(self.nx,self.ny,self.nz)) + Bz = np.ndarray.reshape(np.asarray(b.field.x3), (self.nx,self.ny,self.nz)) ## Convert to cylindrical coordinates Br = Bx*np.cos(phi) + By*np.sin(phi) From 11ba0371e58f843d130b30c40a730c29839f0d52 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 Dec 2020 13:29:12 +0000 Subject: [PATCH 224/293] Move calls to Coordinates::geometry() out of constructor --- include/bout/coordinates.hxx | 3 +-- src/mesh/coordinates.cxx | 22 ++----------------- src/mesh/mesh.cxx | 8 +++++-- tests/unit/fake_parallel_mesh.hxx | 3 ++- tests/unit/field/test_field_factory.cxx | 3 ++- tests/unit/field/test_vector2d.cxx | 3 ++- tests/unit/field/test_vector3d.cxx | 3 ++- .../unit/include/bout/test_petsc_indexer.cxx | 3 ++- .../unit/mesh/parallel/test_shiftedmetric.cxx | 3 ++- tests/unit/mesh/test_coordinates.cxx | 20 ++++++++--------- tests/unit/mesh/test_interpolation.cxx | 6 +++-- tests/unit/test_extras.hxx | 7 +++--- 12 files changed, 39 insertions(+), 45 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 04eb43d342..9c285ac60a 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -75,8 +75,7 @@ public: FieldMetric Bxy, FieldMetric g11, FieldMetric g22, FieldMetric g33, FieldMetric g12, FieldMetric g13, FieldMetric g23, FieldMetric g_11, FieldMetric g_22, FieldMetric g_33, FieldMetric g_12, FieldMetric g_13, - FieldMetric g_23, FieldMetric ShiftTorsion, FieldMetric IntShiftTorsion, - bool calculate_geometry = true); + FieldMetric g_23, FieldMetric ShiftTorsion, FieldMetric IntShiftTorsion); Coordinates& operator=(Coordinates&&) = default; diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index a336350b8b..ce1bcdd61a 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -371,20 +371,14 @@ Coordinates::Coordinates(Mesh* mesh, FieldMetric dx, FieldMetric dy, FieldMetric FieldMetric g23, FieldMetric g_11, FieldMetric g_22, FieldMetric g_33, FieldMetric g_12, FieldMetric g_13, FieldMetric g_23, FieldMetric ShiftTorsion, - FieldMetric IntShiftTorsion, bool calculate_geometry) + FieldMetric IntShiftTorsion) : dx(std::move(dx)), dy(std::move(dy)), dz(dz), J(std::move(J)), Bxy(std::move(Bxy)), g11(std::move(g11)), g22(std::move(g22)), g33(std::move(g33)), g12(std::move(g12)), g13(std::move(g13)), g23(std::move(g23)), g_11(std::move(g_11)), g_22(std::move(g_22)), g_33(std::move(g_33)), g_12(std::move(g_12)), g_13(std::move(g_13)), g_23(std::move(g_23)), ShiftTorsion(std::move(ShiftTorsion)), IntShiftTorsion(std::move(IntShiftTorsion)), nz(mesh->LocalNz), localmesh(mesh), - location(CELL_CENTRE) { - if (calculate_geometry) { - if (geometry()) { - throw BoutException("Differential geometry failed\n"); - } - } -} + location(CELL_CENTRE) {} Coordinates::Coordinates(Mesh* mesh, Options* options) : dx(1., mesh), dy(1., mesh), dz(1., mesh), d1_dx(mesh), d1_dy(mesh), d1_dz(mesh), @@ -600,12 +594,6 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) bout::checkFinite(Bxy, "Bxy", "RGN_NOCORNERS"); bout::checkPositive(Bxy, "Bxy", "RGN_NOCORNERS"); - ////////////////////////////////////////////////////// - /// Calculate Christoffel symbols. Needs communication - if (geometry()) { - throw BoutException("Differential geometry failed\n"); - } - if (mesh->get(ShiftTorsion, "ShiftTorsion", 0.0, false)) { output_warn.write( "\tWARNING: No Torsion specified for zShift. Derivatives may not be correct\n"); @@ -1029,12 +1017,6 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, ShiftTorsion = interpolateAndNeumann(coords_in->ShiftTorsion, location, transform.get()); - - ////////////////////////////////////////////////////// - /// Calculate Christoffel symbols. Needs communication - if (geometry(false, force_interpolate_from_centre)) { - throw BoutException("Differential geometry failed while constructing staggered Coordinates"); - } } void Coordinates::outputVars(Datafile& file) { diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index a4c5a44936..b394718139 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -433,11 +433,15 @@ std::shared_ptr Mesh::createDefaultCoordinates(const CELL_LOC locat if (location == CELL_CENTRE || location == CELL_DEFAULT) { // Initialize coordinates from input - return std::make_shared(this, options); + auto result = std::make_shared(this, options); + result->geometry(); + return result; } else { // Interpolate coordinates from CELL_CENTRE version - return std::make_shared(this, options, location, + auto result = std::make_shared(this, options, location, getCoordinates(CELL_CENTRE), force_interpolate_from_centre); + result->geometry(false, force_interpolate_from_centre); + return result; } } diff --git a/tests/unit/fake_parallel_mesh.hxx b/tests/unit/fake_parallel_mesh.hxx index aa7f930ae8..d32450ea5f 100644 --- a/tests/unit/fake_parallel_mesh.hxx +++ b/tests/unit/fake_parallel_mesh.hxx @@ -297,7 +297,8 @@ std::vector createFakeProcessors(int nx, int ny, int nz, int n bout::globals::mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, false); + Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}); + // No call to Coordinates::geometry() needed here static_cast(&meshes[j + i * nype])->setCoordinates(test_coords); test_coords->setParallelTransform( bout::utils::make_unique(*bout::globals::mesh)); diff --git a/tests/unit/field/test_field_factory.cxx b/tests/unit/field/test_field_factory.cxx index 0ae75d8f27..3bef98307a 100644 --- a/tests/unit/field/test_field_factory.cxx +++ b/tests/unit/field/test_field_factory.cxx @@ -577,7 +577,8 @@ TYPED_TEST(FieldFactoryCreationTest, CreateOnMesh) { &localmesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, false)); + Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0})); + // No call to Coordinates::geometry() needed here localmesh.getCoordinates()->setParallelTransform( bout::utils::make_unique(localmesh)); diff --git a/tests/unit/field/test_vector2d.cxx b/tests/unit/field/test_vector2d.cxx index a036edcff8..4b7ca10e13 100644 --- a/tests/unit/field/test_vector2d.cxx +++ b/tests/unit/field/test_vector2d.cxx @@ -50,7 +50,8 @@ class Vector2DTest : public ::testing::Test { mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{2.0}, Field2D{3.0}, Field2D{4.0}, Field2D{5.0}, Field2D{6.0}, Field2D{1.0}, Field2D{2.0}, Field2D{3.0}, Field2D{4.0}, - Field2D{5.0}, Field2D{6.0}, Field2D{0.0}, Field2D{0.0}, false)); + Field2D{5.0}, Field2D{6.0}, Field2D{0.0}, Field2D{0.0})); + // No call to Coordinates::geometry() needed here delete mesh_staggered; mesh_staggered = new FakeMesh(nx, ny, nz); diff --git a/tests/unit/field/test_vector3d.cxx b/tests/unit/field/test_vector3d.cxx index 9ebdf3d8cc..37f01edb51 100644 --- a/tests/unit/field/test_vector3d.cxx +++ b/tests/unit/field/test_vector3d.cxx @@ -48,7 +48,8 @@ class Vector3DTest : public ::testing::Test { mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{2.0}, Field2D{3.0}, Field2D{4.0}, Field2D{5.0}, Field2D{6.0}, Field2D{1.0}, Field2D{2.0}, Field2D{3.0}, Field2D{4.0}, - Field2D{5.0}, Field2D{6.0}, Field2D{0.0}, Field2D{0.0}, false)); + Field2D{5.0}, Field2D{6.0}, Field2D{0.0}, Field2D{0.0})); + // No call to Coordinates::geometry() needed here delete mesh_staggered; mesh_staggered = new FakeMesh(nx, ny, nz); diff --git a/tests/unit/include/bout/test_petsc_indexer.cxx b/tests/unit/include/bout/test_petsc_indexer.cxx index 6b45c30a80..15d510ae48 100644 --- a/tests/unit/include/bout/test_petsc_indexer.cxx +++ b/tests/unit/include/bout/test_petsc_indexer.cxx @@ -51,7 +51,8 @@ class IndexerTest : public FakeMeshFixture { bout::globals::mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, false); + Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}); + // No call to Coordinates::geometry() needed here mesh2.setCoordinates(test_coords); // May need a ParallelTransform to create fields, because create3D calls // fromFieldAligned diff --git a/tests/unit/mesh/parallel/test_shiftedmetric.cxx b/tests/unit/mesh/parallel/test_shiftedmetric.cxx index 8d66538dfe..b177d75267 100644 --- a/tests/unit/mesh/parallel/test_shiftedmetric.cxx +++ b/tests/unit/mesh/parallel/test_shiftedmetric.cxx @@ -41,7 +41,8 @@ class ShiftedMetricTest : public ::testing::Test { mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, false)); + Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0})); + // No call to Coordinates::geometry() needed here auto coords = mesh->getCoordinates(); coords->setParallelTransform(bout::utils::make_unique( diff --git a/tests/unit/mesh/test_coordinates.cxx b/tests/unit/mesh/test_coordinates.cxx index 5ffdd1d7a2..a8fbbc4dbd 100644 --- a/tests/unit/mesh/test_coordinates.cxx +++ b/tests/unit/mesh/test_coordinates.cxx @@ -42,8 +42,8 @@ TEST_F(CoordinatesTest, ZLength) { FieldMetric{0.0}, // g_13 FieldMetric{0.0}, // g_23 FieldMetric{0.0}, // ShiftTorsion - FieldMetric{0.0}, // IntShiftTorsion - false}; // calculate_geometry + FieldMetric{0.0}}; // IntShiftTorsion + // No call to Coordinates::geometry() needed here EXPECT_TRUE(IsFieldEqual(coords.zlength(), 7.0)); } @@ -75,8 +75,8 @@ TEST_F(CoordinatesTest, ZLength3D) { FieldMetric{0.0}, // g_13 FieldMetric{0.0}, // g_23 FieldMetric{0.0}, // ShiftTorsion - FieldMetric{0.0}, // IntShiftTorsion - false}; // calculate_geometry + FieldMetric{0.0}}; // IntShiftTorsion + // No call to Coordinates::geometry() needed here EXPECT_TRUE(IsFieldEqual(coords.zlength(), expected)); } @@ -102,8 +102,8 @@ TEST_F(CoordinatesTest, Jacobian) { FieldMetric{0.0}, // g_13 FieldMetric{0.0}, // g_23 FieldMetric{0.0}, // ShiftTorsion - FieldMetric{0.0}, // IntShiftTorsion - false}; // calculate_geometry + FieldMetric{0.0}}; // IntShiftTorsion + // No call to Coordinates::geometry() needed here EXPECT_NO_THROW(coords.jacobian()); @@ -133,8 +133,8 @@ TEST_F(CoordinatesTest, CalcContravariant) { FieldMetric{0.0}, // g_13 FieldMetric{0.0}, // g_23 FieldMetric{0.0}, // ShiftTorsion - FieldMetric{0.0}, // IntShiftTorsion - false}; // calculate_geometry + FieldMetric{0.0}}; // IntShiftTorsion + // No call to Coordinates::geometry() needed here output_info.disable(); coords.calcCovariant(); @@ -168,8 +168,8 @@ TEST_F(CoordinatesTest, CalcCovariant) { FieldMetric{0.0}, // g_13 FieldMetric{0.0}, // g_23 FieldMetric{0.0}, // ShiftTorsion - FieldMetric{0.0}, // IntShiftTorsion - false}; // calculate_geometry + FieldMetric{0.0}}; // IntShiftTorsion + // No call to Coordinates::geometry() needed here output_info.disable(); coords.calcContravariant(); diff --git a/tests/unit/mesh/test_interpolation.cxx b/tests/unit/mesh/test_interpolation.cxx index 27df2c62ed..94bd181eab 100644 --- a/tests/unit/mesh/test_interpolation.cxx +++ b/tests/unit/mesh/test_interpolation.cxx @@ -72,8 +72,9 @@ class Field3DInterpToTest : public ::testing::Test { Field2D{0.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, - Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, false), + Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}), location); + // No call to Coordinates::geometry() needed here mesh->getCoordinates(location)->setParallelTransform( bout::utils::make_unique(*mesh)); } @@ -315,8 +316,9 @@ class Field2DInterpToTest : public ::testing::Test { Field2D{0.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{1.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, - Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}, false), + Field2D{0.0, mesh}, Field2D{0.0, mesh}, Field2D{0.0, mesh}), location); + // No call to Coordinates::geometry() needed here mesh->getCoordinates(location)->setParallelTransform( bout::utils::make_unique(*mesh)); } diff --git a/tests/unit/test_extras.hxx b/tests/unit/test_extras.hxx index f1f5f921f0..2e3697a82a 100644 --- a/tests/unit/test_extras.hxx +++ b/tests/unit/test_extras.hxx @@ -423,8 +423,8 @@ public: bout::globals::mesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, - false); + Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}); + // No call to Coordinates::geometry() needed here static_cast(bout::globals::mesh)->setCoordinates(test_coords); static_cast(bout::globals::mesh)->setGridDataSource( new FakeGridDataSource()); @@ -452,7 +452,8 @@ public: Field2D{1.0, mesh_staggered}, Field2D{1.0, mesh_staggered}, Field2D{1.0, mesh_staggered}, Field2D{0.0, mesh_staggered}, Field2D{0.0, mesh_staggered}, Field2D{0.0, mesh_staggered}, - Field2D{0.0, mesh_staggered}, Field2D{0.0, mesh_staggered}, false); + Field2D{0.0, mesh_staggered}, Field2D{0.0, mesh_staggered}); + // No call to Coordinates::geometry() needed here test_coords_staggered->setParallelTransform( bout::utils::make_unique(*mesh_staggered)); } From 91174cc715a25e909b592576a6a43462f0823c49 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 Dec 2020 17:18:48 +0000 Subject: [PATCH 225/293] Add Field2D versions of to/fromFieldAligned() to ParallelTransform ParallelTransform::toFieldAligned(const Field2D&) and ParallelTransform::fromFieldAligned(const Field2D&) do nothing (since Field2D are axisymmetric quantities) but simplify treating Coordinates::FieldMetric quantities (which might be Field2D or Field3D depending on configure options) in the same way. --- include/bout/paralleltransform.hxx | 11 +++++++++++ include/field2d.hxx | 18 ------------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index cc6f5ffc08..e206f06e9f 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -77,6 +77,17 @@ public: return fromFieldAligned(f, toString(region)); } + /// Field2D are axisymmetric, so transformation to or from field-aligned coordinates is + /// a null operation. + virtual const Field2D toFieldAligned(const Field2D &f, + const std::string& UNUSED(region) = "RGN_ALL") { + return f; + } + virtual const Field2D fromFieldAligned(const Field2D &f, + const std::string& UNUSED(region) = "RGN_ALL") { + return f; + } + virtual bool canToFromFieldAligned() = 0; struct PositionsAndWeights { diff --git a/include/field2d.hxx b/include/field2d.hxx index 29d330b971..b1cbcc283d 100644 --- a/include/field2d.hxx +++ b/include/field2d.hxx @@ -334,24 +334,6 @@ Field2D operator-(const Field2D &f); // Non-member functions -inline Field2D toFieldAligned(const Field2D& f, const std::string& UNUSED(region) = "RGN_ALL") { - return f; -} -[[deprecated("Please use toFieldAligned(const Field2D& f, " - "const std::string& region = \"RGN_ALL\") instead")]] -inline Field2D toFieldAligned(const Field2D& f, REGION region) { - return toFieldAligned(f, toString(region)); -} - -inline Field2D fromFieldAligned(const Field2D& f, const std::string& UNUSED(region) = "RGN_ALL") { - return f; -} -[[deprecated("Please use fromFieldAligned(const Field2D& f, " - "const std::string& region = \"RGN_ALL\") instead")]] -inline Field2D fromFieldAligned(const Field2D& f, REGION region) { - return fromFieldAligned(f, toString(region)); -} - #if CHECK > 0 /// Throw an exception if \p f is not allocated or if any /// elements are non-finite (for CHECK > 2). From 5a77878a0e40b6bbb077e6d1bcbf912dba865ce0 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 Dec 2020 17:21:17 +0000 Subject: [PATCH 226/293] Remove derivative workarounds in Coordinates All derivatives used while creating Coordinates objects are in the geometry() method. There was a problem that standard versions of the derivatives need a Coordinates pointer in the Fields passed in. By moving the call to geometry() out of the constructor, we have removed the need for workarounds to take derivatives before there is a valid Coordinates pointer. --- src/mesh/coordinates.cxx | 64 ++++++---------------------------------- 1 file changed, 9 insertions(+), 55 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index ce1bcdd61a..56ab21dee2 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -448,7 +448,12 @@ Coordinates::Coordinates(Mesh* mesh, Options* options) auto getUnaligned = [this](auto& field, const std::string& name, BoutReal default_value) { localmesh->get(field, name, default_value, false); - return maybeFromFieldAligned(field); + if (field.getDirectionY() == YDirectionType::Aligned + and transform->canToFromFieldAligned()) { + return transform->fromFieldAligned(field); + } else { + return field.setDirectionY(YDirectionType::Standard); + } }; auto getUnalignedAtLocation = [this, extrapolate_x, extrapolate_y, @@ -1242,7 +1247,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2y, "d2y" + suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = indexDDY(1. / dy); // d/di(1/dy) + d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) communicate(d1_dy); d1_dy = @@ -1294,7 +1299,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2y, "d2y", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = indexDDY(1. / dy); // d/di(1/dy) + d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) communicate(d1_dy); d1_dy = @@ -1618,7 +1623,7 @@ Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { - return indexDDY(f, outloc, method, region) / dy; + return bout::derivatives::index::DDY(f, outloc, method, region) / dy; }; Coordinates::FieldMetric Coordinates::DDZ(const Field2D& f, CELL_LOC loc, @@ -2003,54 +2008,3 @@ Field2D Coordinates::Laplace_perpXY(MAYBE_UNUSED(const Field2D& A), throw BoutException("Coordinates::Laplace_perpXY for 3D metric not implemented"); #endif } - -Coordinates::FieldMetric Coordinates::indexDDY(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { -#if BOUT_USE_METRIC_3D - if (!f.hasParallelSlices()) { - const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; - Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result); - } -#endif - return bout::derivatives::index::DDY(f, outloc, method, region); -} - -Field3D Coordinates::indexDDY(const Field3D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { -#if BOUT_USE_METRIC_3D - if (!f.hasParallelSlices()) { - const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - Field3D f_aligned; - if (transform->canToFromFieldAligned()) { - f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; - } else { - Field3D f_parallel = f; - transform->calcParallelSlices(f_parallel); - return bout::derivatives::index::DDY(f_parallel, outloc, method, region); - } - Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result); - } -#endif - return bout::derivatives::index::DDY(f, outloc, method, region); -} - -Field3D Coordinates::maybeFromFieldAligned(const Field3D& f, const std::string& region) { - ASSERT1(location == f.getLocation()); - ASSERT1(localmesh == f.getMesh()); - if (f.getDirectionY() == YDirectionType::Standard) { - return f; - } - if (this->getParallelTransform().canToFromFieldAligned()) { - return this->getParallelTransform().fromFieldAligned(f, region); - } - return copy(f).setDirectionY(YDirectionType::Standard); -} - -Field2D Coordinates::maybeFromFieldAligned(const Field2D& f, - const std::string& UNUSED(region)) { - return f; -} From 8d30f3ceba1c04c7904d99e1f139246f00de7c61 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 Dec 2020 18:29:30 +0000 Subject: [PATCH 227/293] Check for Field2D in interp_to, don't shift to/from field-aligned Field2Ds are axisymmetric and don't need to shift to or from field-aligned. With the recent change removing the special toFieldAligned override in field2d.hxx, instead relying on the templates in field.hxx and the ParallelTransform::toFieldAligned(Field2D) and ParallelTransform::fromFieldAligned(Field2D) methods, interp_to would fail on a Field2D when constructing a ShiftedMetric transform by interpolating zShift. Skipping the to/from field-aligned transformations entirely for Field2D avoids this. --- include/interpolation.hxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/interpolation.hxx b/include/interpolation.hxx index 60b38dd864..0486672dac 100644 --- a/include/interpolation.hxx +++ b/include/interpolation.hxx @@ -119,7 +119,10 @@ const T interp_to(const T& var, CELL_LOC loc, const std::string region = "RGN_AL ASSERT0(fieldmesh->ystart >= 2); // We can't interpolate in y unless we're field-aligned - const bool is_unaligned = (var.getDirectionY() == YDirectionType::Standard); + // Field2D doesn't need to shift to/from field-aligned because it is axisymmetric, + // so always set is_unaligned=false for Field2D. + const bool is_unaligned = std::is_same::value ? false + : (var.getDirectionY() == YDirectionType::Standard); const T var_fa = is_unaligned ? toFieldAligned(var, "RGN_NOX") : var; if (not std::is_base_of::value) { From 9e58e8a6f7f0094dccd2a8f9886372b71cb32f37 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Mon, 14 Dec 2020 18:32:24 +0000 Subject: [PATCH 228/293] Exception creating ShiftedMetric by interpolating with 3d metrics When using 3d metrics it is not possible to construct a ShiftedMetric transform by interpolating zShift to CELL_YLOW, because the interpolation would require a shift from field-aligned coordinates using the ShiftedMetric which is being constructed (since zShift is not axisymmetric when 3d metrics are allowed). Now throw an exception in this case, and suggest creating zShift_CELL_YLOW in the grid file as a solution. --- src/mesh/coordinates.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 56ab21dee2..a61ece97ff 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1547,12 +1547,17 @@ void Coordinates::setParallelTransform(Options* options) { } zShift.setLocation(location); } else { + if (location == CELL_YLOW and bout::build::use_metric_3d) { + throw BoutException("Cannot interpolate zShift to construct ShiftedMetric when " + "using 3d metrics. You must provide zShift_CELL_YLOW in the " + "grid file."); + } Field2D zShift_centre; if (localmesh->get(zShift_centre, "zShift", 0.0, false)) { // No zShift variable. Try qinty in BOUT grid files if (localmesh->get(zShift_centre, "qinty", 0.0, false)) { // Failed to find either variable, cannot use ShiftedMetric - throw BoutException("Could not read zShift"+suffix+" from grid file"); + throw BoutException("Could not read zShift from grid file"); } } From 6a9e00b1553ed9414402677937aef53c5e4fe45b Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 12:28:26 +0000 Subject: [PATCH 229/293] Only call geometry() after Coordinates are added to Mesh::coords_map Ensures we don't get a nullptr from field->getCoordinates(). --- include/bout/mesh.hxx | 1 + src/mesh/mesh.cxx | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index ccf9e087ad..ebfe44078c 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -667,6 +667,7 @@ class Mesh { // (circular dependency between Mesh and Coordinates) auto inserted = coords_map.emplace(location, nullptr); inserted.first->second = createDefaultCoordinates(location); + inserted.first->second->geometry(false); return inserted.first->second; } diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index b394718139..6f110a43ff 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -434,13 +434,11 @@ std::shared_ptr Mesh::createDefaultCoordinates(const CELL_LOC locat if (location == CELL_CENTRE || location == CELL_DEFAULT) { // Initialize coordinates from input auto result = std::make_shared(this, options); - result->geometry(); return result; } else { // Interpolate coordinates from CELL_CENTRE version auto result = std::make_shared(this, options, location, getCoordinates(CELL_CENTRE), force_interpolate_from_centre); - result->geometry(false, force_interpolate_from_centre); return result; } } @@ -626,6 +624,7 @@ void Mesh::recalculateStaggeredCoordinates() { } *coords_map[location] = std::move(*createDefaultCoordinates(location, true)); + coords_map[location]->geometry(false, true); } } From a84789f4dd39a763dc684df4c6e87a642f7f9e73 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 15:33:23 +0000 Subject: [PATCH 230/293] test-laplacexy-fv not compatible with 3d metrics Requires the Laplace_perpXY operator, which is not implemented for 3d metrics. --- tests/integrated/test-laplacexy-fv/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-laplacexy-fv/CMakeLists.txt b/tests/integrated/test-laplacexy-fv/CMakeLists.txt index d2c30f366b..d52a1dd9c6 100644 --- a/tests/integrated/test-laplacexy-fv/CMakeLists.txt +++ b/tests/integrated/test-laplacexy-fv/CMakeLists.txt @@ -1,6 +1,7 @@ bout_add_integrated_test(test-laplacexy-fv SOURCES test-laplacexy.cxx REQUIRES BOUT_HAS_PETSC + CONFLICTS BOUT_USE_METRIC_3D # Test requires Laplace_perpXY operator, which is not implemented for 3d metrics USE_RUNTEST USE_DATA_BOUT_INP ) From 865d2749a32af95575f8286bd807bf8edb03ee60 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 15:38:49 +0000 Subject: [PATCH 231/293] test-petsc_laplace not compatible with 3d metrics Default preconditioner uses the 'cyclic' Laplace solver, which is not implemented for 3d metrics. --- tests/integrated/test-petsc_laplace/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-petsc_laplace/CMakeLists.txt b/tests/integrated/test-petsc_laplace/CMakeLists.txt index 6a4a670098..6f3a617f0b 100644 --- a/tests/integrated/test-petsc_laplace/CMakeLists.txt +++ b/tests/integrated/test-petsc_laplace/CMakeLists.txt @@ -1,6 +1,7 @@ bout_add_integrated_test(test-petsc-laplace SOURCES test_petsc_laplace.cxx REQUIRES BOUT_HAS_PETSC + CONFLICTS BOUT_USE_METRIC_3D # default preconditioner uses 'cyclic' Laplace solver which is not available with 3d metrics USE_RUNTEST USE_DATA_BOUT_INP ) From cd0500f6acbc485e270a9702151cf2d00c80bbfa Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 15:48:09 +0000 Subject: [PATCH 232/293] Correct exception message for staggered zShift --- src/mesh/coordinates.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index a61ece97ff..6ae1b20960 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1549,8 +1549,8 @@ void Coordinates::setParallelTransform(Options* options) { } else { if (location == CELL_YLOW and bout::build::use_metric_3d) { throw BoutException("Cannot interpolate zShift to construct ShiftedMetric when " - "using 3d metrics. You must provide zShift_CELL_YLOW in the " - "grid file."); + "using 3d metrics. You must provide zShift_ylow in the grid " + "file."); } Field2D zShift_centre; if (localmesh->get(zShift_centre, "zShift", 0.0, false)) { From c0fda0677117400eba5b6e21e70a84f21b6350ed Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 19:15:46 +0000 Subject: [PATCH 233/293] Don't interpolate if not necessary Transformation to field-aligned coordinates in interpolateAndExtrapolate(Field3D) gets rid of guard and boundary cells. Skip doing this if we don't need the interpolation. Allows the case where Coordinates are initialised from input file expressions (where extrapolation is disabled) to work more often, since we keep valid boundary cell values. --- 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 6ae1b20960..c3e0d587ad 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -168,7 +168,7 @@ Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, f.setDirectionY(YDirectionType::Standard); } } - if (location == CELL_YLOW) { + if (location == CELL_YLOW and f.getLocation() != CELL_YLOW) { auto f_aligned = pt_f->toFieldAligned(f, "RGN_NOX"); result = interp_to(f_aligned, location, "RGN_NOBNDRY"); ParallelTransform* pt_result; From 98cbe71af485aa794bacae1a928c3a2501d3c9d9 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 21:43:03 +0000 Subject: [PATCH 234/293] test-laplacexy-short not compatible with 3d metrics Preconditioner uses the 'cyclic' Laplace solver, which is not implemented for 3d metrics. --- tests/integrated/test-laplacexy-short/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integrated/test-laplacexy-short/CMakeLists.txt b/tests/integrated/test-laplacexy-short/CMakeLists.txt index 0f97dba818..d9a01cf3a4 100644 --- a/tests/integrated/test-laplacexy-short/CMakeLists.txt +++ b/tests/integrated/test-laplacexy-short/CMakeLists.txt @@ -1,6 +1,7 @@ bout_add_integrated_test(test-laplacexy-short SOURCES test-laplacexy.cxx REQUIRES BOUT_HAS_PETSC + CONFLICTS BOUT_USE_METRIC_3D # Test uses cyclic Laplace solver as a preconditioner, which is not available with 3d metrics USE_RUNTEST USE_DATA_BOUT_INP ) From ff6b801b798c0ba96a98de8121903ca4c36cfb00 Mon Sep 17 00:00:00 2001 From: John Omotani Date: Tue, 15 Dec 2020 21:44:04 +0000 Subject: [PATCH 235/293] Fix test-twistshift-staggered Give _ylow variables in [mesh] section of BOUT.inp, so test-twistshift-staggered can read them and does not need to interpolate. This is necessary when using 3d metrics. --- tests/integrated/test-twistshift-staggered/data/BOUT.inp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/integrated/test-twistshift-staggered/data/BOUT.inp b/tests/integrated/test-twistshift-staggered/data/BOUT.inp index c2d285ff87..3aa7925224 100644 --- a/tests/integrated/test-twistshift-staggered/data/BOUT.inp +++ b/tests/integrated/test-twistshift-staggered/data/BOUT.inp @@ -9,7 +9,10 @@ nx = 5 ny = 7 nz = 5 +dx = 1.0 +dx_ylow = 1.0 # Needed so BOUT++ recognises that _ylow quantities are present zShift = (y-0.5) * (x+1) +zShift_ylow = (y-0.5) * (x+1) ShiftAngle = 2*pi*(x+1) [mesh:paralleltransform] From 7b5246836392c108786f7fc669e05d6233e7da13 Mon Sep 17 00:00:00 2001 From: johnomotani Date: Tue, 5 Jan 2021 12:54:16 +0000 Subject: [PATCH 236/293] Remove partially-reverted changes to Mesh::createDefaultCoordinates() --- src/mesh/mesh.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index 22a789bd74..33c88654fb 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -438,13 +438,11 @@ std::shared_ptr Mesh::createDefaultCoordinates(const CELL_LOC locat if (location == CELL_CENTRE || location == CELL_DEFAULT) { // Initialize coordinates from input - auto result = std::make_shared(this, options); - return result; + return std::make_shared(this, options); } else { // Interpolate coordinates from CELL_CENTRE version - auto result = std::make_shared(this, options, location, + return std::make_shared(this, options, location, getCoordinates(CELL_CENTRE), force_interpolate_from_centre); - return result; } } From 716333a8918f20cfbacde1ddb563632e8436bf66 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 10 Dec 2020 11:56:42 +0000 Subject: [PATCH 237/293] Fix BoutException::what() returning pointer to temporary This was not brought in properly on the previous merge of `next` into the 3D branch --- include/boutexception.hxx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/boutexception.hxx b/include/boutexception.hxx index 39a29394cd..c62926bd8a 100644 --- a/include/boutexception.hxx +++ b/include/boutexception.hxx @@ -30,11 +30,6 @@ public: ~BoutException() override; const char* what() const noexcept override { - if (getenv("BOUT_SHOW_BACKTRACE") != nullptr) { - getBacktrace(); - return (backtrace_message + "\n" + message).c_str(); - } - return message.c_str(); } void DEPRECATED(Backtrace()) {}; From 77bf02349bfd74d2cf73ee788a2cac3313252190 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 5 Jan 2021 15:33:48 +0000 Subject: [PATCH 238/293] Fix conflict with IPT solver and 3D metrics It's possible that IPT will work with 3D metrics with some changes --- .../iterative_parallel_tri.cxx | 8 +++++++- .../iterative_parallel_tri.hxx | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx index fc69261f3f..36b2064c2d 100644 --- a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx +++ b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx @@ -24,7 +24,11 @@ * **************************************************************************/ +#include "bout/build_config.hxx" #include "iterative_parallel_tri.hxx" + +#if not BOUT_USE_METRIC_3D + #include "globals.hxx" #include @@ -249,7 +253,7 @@ FieldPerp LaplaceIPT::solve(const FieldPerp& b, const FieldPerp& x0) { xs = localmesh->xstart; // First interior point xe = localmesh->xend; // Last interior point - const BoutReal kwaveFactor = 2.0 * PI / coords->zlength(); + const BoutReal kwaveFactor = 2.0 * PI / getUniform(coords->zlength()); // Setting the width of the boundary. // NOTE: The default is a width of 2 guard cells @@ -1450,3 +1454,5 @@ void LaplaceIPT::Level::synchronize_reduced_field(const LaplaceIPT& l, l.nmode, MPI_DOUBLE_COMPLEX, proc_out, 1, comm, MPI_STATUS_IGNORE); } } + +#endif // BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx index 3c3bac73e5..f457761f87 100644 --- a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx +++ b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx @@ -29,8 +29,19 @@ class LaplaceIPT; #ifndef __IPT_H__ #define __IPT_H__ +#include "bout/build_config.hxx" +#include "invert_laplace.hxx" + +#if BOUT_USE_METRIC_3D + +namespace{ +RegisterUnavailableLaplace registerlaplaceipt(LAPLACE_IPT, + "BOUT++ was configured with 3D metrics"); +} + +#else + #include -#include #include #include @@ -233,4 +244,6 @@ private: } }; +#endif // BOUT_USE_METRIC_3D + #endif // __IPT_H__ From 2566caedd95fc6e6de40ae18489214f25133fc62 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 5 Jan 2021 15:34:28 +0000 Subject: [PATCH 239/293] Add note about breaking changes with dz/zlength --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21671f2e9d..4d745386b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,12 @@ - The `LaplaceShoot` Laplacian implementation was removed. There are very few cases, if any, where this implementation actually works. [\#2177](https://github.com/boutproject/BOUT-dev/pull/2177) +- `dz` is now a `Field2D`, and `Coordinates::zlength()` also returns a + `Field2D`. In most cases, wrapping these in a call to `getUniform` + in order to get a `BoutReal` will do the correct thing. If checks + are enabled, `getUniform` will throw an exception if its argument is + not uniform (that is, that all values are identical). + [\#2025](https://github.com/boutproject/BOUT-dev/pull/2025) ## [v4.3.2](https://github.com/boutproject/BOUT-dev/tree/v4.3.2) (2020-10-19) From 7318f32d82152740a08fd37cff8786817e071cc7 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 5 Jan 2021 16:01:33 +0000 Subject: [PATCH 240/293] Fix some issues with zoidberg/field.py - different parameter names from overridden method - missing `self` argument - unused imports - missing brackets in function call - mutable values as default arguments - commented out exception - condense string addition into a single format call --- tools/pylib/zoidberg/field.py | 83 +++++++++++++++++------------------ 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 2a935bf4ee..7e51227ef3 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -191,7 +191,7 @@ def field_direction(self, pos, ycoord, flatten=False): if np.amin(np.abs(By)) < 1e-8: # Very small By print(x,z,ycoord, By) - # raise ValueError("Small By") + raise ValueError("Small By ({}) at (x={}, y={}, z={})".format(By, x, ycoord, z)) R_By = Rmaj / By # Rate of change of x location [m] with y angle [radians] @@ -312,7 +312,7 @@ def Rfunc(self, x, z, phi): return np.full(x.shape, self.Rmaj) try: - from sympy import Symbol, atan2, cos, sin, log, pi, sqrt, lambdify, Piecewise, Sum, gamma, And, factorial, symbols, Add, symarray, diff + from sympy import Symbol, atan2, cos, sin, log, pi, sqrt, lambdify, Piecewise, Sum, gamma, And, factorial, diff class StraightStellarator(MagneticField): """A "rotating ellipse" stellarator without curvature @@ -543,18 +543,18 @@ def __init__(self, A, R_0=1.0, B_0=1.0): self.Byf = lambdify((self.R, self.phi, self.Z), By, "numpy") self.Bzf = lambdify((self.R, self.phi, self.Z), Bz, "numpy") - def Bxfunc(self, x, z, y): + def Bxfunc(self, x, z, phi): - return self.Bxf(x, y, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + return self.Bxf(x, phi, z)/self.Byf(self.R_0, 0, 0)*self.B_0 - def Byfunc(self, x, z, y): + def Byfunc(self, x, z, phi): - return self.Byf(x, y, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + return self.Byf(x, phi, z)/self.Byf(self.R_0, 0, 0)*self.B_0 - def Bzfunc(self, x, z, y): + def Bzfunc(self, x, z, phi): - return self.Bzf(x, y, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + return self.Bzf(x, phi, z)/self.Byf(self.R_0, 0, 0)*self.B_0 def Sfunc(self, x, z, y): """ @@ -570,7 +570,7 @@ def Sfunc(self, x, z, y): """ return self.Sf(x,y,z) - def Rfunc(self, x, z, y): + def Rfunc(self, x, z, phi): """ Parameters ---------- @@ -1250,8 +1250,8 @@ def pressure(self, x, z, phi): return self.p_spl(psinorm) class W7X_vacuum(MagneticField): - def __init__(self,nx=128,ny=32,nz=128,x_range=[4.05,6.55],z_range=[-1.35,1,35], phimax=2.*np.pi, configuration=0, plot_poincare=False,include_plasma_field=False, wout_file='wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc'): - from scipy.interpolate import griddata, RegularGridInterpolator + def __init__(self,nx=128,ny=32,nz=128,x_range=(4.05,6.55),z_range=(-1.35,1,35), phimax=2.*np.pi, configuration=0, plot_poincare=False,include_plasma_field=False, wout_file='wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc'): + from scipy.interpolate import RegularGridInterpolator import numpy as np ## create 1D arrays of cylindrical coordinates r = np.linspace(x_range[0],x_range[-1],nx) @@ -1315,23 +1315,28 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): ny = phi.shape[1] nz = z.shape[2] - ### create (standardized) file name for saving/loading magnetic field. - fname = "B.w7x."+str(nx)+"."+str(ny)+"."+str(nz)\ - +"."+"{:.2f}".format(r[0,0,0]) +"-"+"{:.2f}".format(r[-1,0,0])\ - +"."+"{:.2f}".format(phi[0,0,0])+"-"+"{:.2f}".format(phi[0,-1,0])\ - +"."+"{:.2f}".format(z[0,0,0]) +"-"+"{:.2f}".format(z[0,0,-1])+".dat" + # create (standardized) file name for saving/loading magnetic field. + fname = "B.w7x.{}.{}.{}.{:.2f}-{:.2f}.{:.2f}-{:.2f}.{:.2f}-{:.2f}.dat".format( + nx, + ny, + nz, + r[0, 0, 0], + r[-1, 0, 0], + phi[0, 0, 0], + phi[0, -1, 0], + z[0, 0, 0], + z[0, 0, -1], + ) if(os.path.isfile(fname)): if sys.version_info >= (3, 0): print ("Saved field found, loading from: ", fname) - f = open(fname, "rb") - Br, Bphi, Bz = pickle.load(f) - f.close + with open(fname, "rb") as f: + Br, Bphi, Bz = pickle.load(f) else: print ("Saved field found, loading from: ", fname) - f = open(fname, 'r') - Br, Bphi, Bz = pickle.load(f) ## error here means you pickled with v3+ re-do. - f.close + with open(fname, 'r') as f: + Br, Bphi, Bz = pickle.load(f) ## error here means you pickled with v3+ re-do. else: print ("No saved field found -- (re)calculating (must be on IPP network for this to work...)") print ("Calculating field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) @@ -1416,28 +1421,26 @@ def plasma_field(r, phi, z, wout_file='wout.nc'): import os.path import sys import pickle - import matplotlib.pyplot as plt - from boututils.datafile import DataFile cl = Client('http://esb.ipp-hgw.mpg.de:8280/services/Extender?wsdl') - # print (os.path.isfile(wout_file)) - # if not (os.path.isfile(wout_file)): - #vmecURL = 'http://svvmec1.ipp-hgw.mpg.de:8080/vmecrest/v1/run/test42/wout.nc' vmecURL = "http://svvmec1.ipp-hgw.mpg.de:8080/vmecrest/v1/w7x_ref_1/wout.nc" - # else: - # f = DataFile(wout_file) - # wout = f - # f.close() nx = r.shape[0] ny = phi.shape[1] nz = z.shape[2] - ### create (standardized) file name for saving/loading magnetic field. - fname = "B.w7x_plasma_field."+str(nx)+"."+str(ny)+"."+str(nz)\ - +"."+"{:.2f}".format(r[0,0,0]) +"-"+"{:.2f}".format(r[-1,0,0])\ - +"."+"{:.2f}".format(phi[0,0,0])+"-"+"{:.2f}".format(phi[0,-1,0])\ - +"."+"{:.2f}".format(z[0,0,0]) +"-"+"{:.2f}".format(z[0,0,-1])+".dat" + # create (standardized) file name for saving/loading magnetic field. + fname = "B.w7x_plasma_field.{}.{}.{}.{:.2f}-{:.2f}.{:.2f}-{:.2f}.{:.2f}-{:.2f}.dat".format( + nx, + ny, + nz, + r[0, 0, 0], + r[-1, 0, 0], + phi[0, 0, 0], + phi[0, -1, 0], + z[0, 0, 0], + z[0, 0, -1], + ) if(os.path.isfile(fname)): if sys.version_info >= (3, 0): @@ -1487,10 +1490,6 @@ def plasma_field(r, phi, z, wout_file='wout.nc'): def magnetic_axis(self, phi_axis=0,configuration=0): from osa import Client - import os.path - import sys - import pickle - import matplotlib.pyplot as plt tracer = Client('http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl') @@ -1530,7 +1529,7 @@ def Rfunc(self, x, z, phi): return x class W7X_VMEC(MagneticField): - def __init__(self,nx=512,ny=32,nz=512,x_range=[4.05,6.55],z_range=[-1.35,1,35], phi_range=[0,2*np.pi], vmec_id='w7x_ref_171'): + def __init__(self,nx=512,ny=32,nz=512,x_range=(4.05,6.55),z_range=(-1.35,1,35), phi_range=(0,2*np.pi), vmec_id='w7x_ref_171'): from scipy.interpolate import RegularGridInterpolator self.nx = nx self.ny = ny @@ -1557,7 +1556,7 @@ def __init__(self,nx=512,ny=32,nz=512,x_range=[4.05,6.55],z_range=[-1.35,1,35], self.bz_interp = RegularGridInterpolator(points, Bz_vmec, bounds_error=False, fill_value=0.0) self.bphi_interp = RegularGridInterpolator(points, By_vmec, bounds_error=False, fill_value=1.0) - def field_values(r,phi,z, vmec_id='w7x_ref_171'): + def field_values(self, r,phi,z, vmec_id='w7x_ref_171'): from osa import Client vmec = Client('http://esb:8280/services/vmec_v5?wsdl') From b952e9681c156fffd544163959c9f065753823dc Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 5 Jan 2021 16:30:15 +0000 Subject: [PATCH 241/293] Simplify some pickle reading/writing in zoidberg --- tools/pylib/zoidberg/field.py | 51 +++++++++++++---------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 7e51227ef3..ff288d9100 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -1,6 +1,8 @@ from builtins import object import numpy as np +import sys + try: from . import boundary @@ -8,6 +10,14 @@ import boundary +if sys.version_info >= (3, 0): + pickle_read_mode = "rb" + pickle_write_mode = "wb" +else: + pickle_read_mode = "r" + pickle_write_mode = "w" + + class MagneticField(object): """Represents a magnetic field in either Cartesian or cylindrical geometry @@ -1305,7 +1315,6 @@ def __init__(self,nx=128,ny=32,nz=128,x_range=(4.05,6.55),z_range=(-1.35,1,35), def field_values(r, phi, z, configuration=0, plot_poincare=False): from osa import Client import os.path - import sys import pickle import matplotlib.pyplot as plt @@ -1329,14 +1338,10 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): ) if(os.path.isfile(fname)): - if sys.version_info >= (3, 0): - print ("Saved field found, loading from: ", fname) - with open(fname, "rb") as f: - Br, Bphi, Bz = pickle.load(f) - else: - print ("Saved field found, loading from: ", fname) - with open(fname, 'r') as f: - Br, Bphi, Bz = pickle.load(f) ## error here means you pickled with v3+ re-do. + print ("Saved field found, loading from: ", fname) + with open(fname, pickle_read_mode) as f: + Br, Bphi, Bz = pickle.load(f) + else: print ("No saved field found -- (re)calculating (must be on IPP network for this to work...)") print ("Calculating field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) @@ -1367,14 +1372,8 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): Bphi = -Bx*np.sin(phi) + By*np.cos(phi) ## Save so we don't have to do this every time. - if sys.version_info >= (3, 0): - f = open(fname, "wb") + with open(fname, pickle_write_mode) as f: pickle.dump([Br,Bphi,Bz],f) - f.close() - else: - f = open(fname, 'w') - pickle.dump([Br,Bphi,Bz],f) - f.close() if(plot_poincare): ## Poincare plot as done on the web services @@ -1419,7 +1418,6 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): def plasma_field(r, phi, z, wout_file='wout.nc'): from osa import Client import os.path - import sys import pickle cl = Client('http://esb.ipp-hgw.mpg.de:8280/services/Extender?wsdl') @@ -1443,16 +1441,9 @@ def plasma_field(r, phi, z, wout_file='wout.nc'): ) if(os.path.isfile(fname)): - if sys.version_info >= (3, 0): - print ("Saved field found, loading from: ", fname) - f = open(fname, "rb") + print ("Saved field found, loading from: ", fname) + with open(fname, pickle_read_mode) as f: Br, Bphi, Bz = pickle.load(f) - f.close - else: - print ("Saved field found, loading from: ", fname) - f = open(fname, 'r') - Br, Bphi, Bz = pickle.load(f) ## error here means you pickled with v3+ re-do. - f.close else: print ("No saved plasma field found -- (re)calculating (must be on IPP network for this to work...)") print ("Calculating plasma field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) @@ -1477,14 +1468,8 @@ def plasma_field(r, phi, z, wout_file='wout.nc'): Bz = np.ndarray.reshape(np.asarray(plasmafield.x3), (nx,ny,nz)) ## Save so we don't have to do this every time. - if sys.version_info >= (3, 0): - f = open(fname, "wb") - pickle.dump([Br,Bphi,Bz],f) - f.close() - else: - f = open(fname, 'w') + with open(fname, pickle_write_mode) as f: pickle.dump([Br,Bphi,Bz],f) - f.close() return Br, Bphi, Bz From b20883540b25a3605ea6df88b8d765f264991f64 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 5 Jan 2021 16:35:41 +0000 Subject: [PATCH 242/293] Turn a couple of zoidberg comments into docstrings --- tools/pylib/zoidberg/field.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index ff288d9100..789e527c40 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -1304,15 +1304,16 @@ def __init__(self,nx=128,ny=32,nz=128,x_range=(4.05,6.55),z_range=(-1.35,1,35), # return points, br_interp, bphi_interp, bz_interp - ################## Vacuum field service ######################## - # This uses the webservices field line tracer to get # - # the vacuum magnetic field given 3d arrrays for R, phi, and Z # - # http://webservices.ipp-hgw.mpg.de/docs/fieldlinetracer.html # - # Only works on IPP network # - # Contact brendan.shanahan@ipp.mpg.de for questions # - ################################################################ - def field_values(r, phi, z, configuration=0, plot_poincare=False): + """This uses the webservices field line tracer to get the vacuum + magnetic field given 3d arrrays for R, phi, and Z. Only works + on IPP network + + http://webservices.ipp-hgw.mpg.de/docs/fieldlinetracer.html + + Contact brendan.shanahan@ipp.mpg.de for questions + + """ from osa import Client import os.path import pickle @@ -1405,17 +1406,16 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): return Br, Bphi, Bz + def plasma_field(r, phi, z, wout_file='wout.nc'): + """This uses EXTENDER via the IPP webservices to get the magnetic + field from the plasma given 3d arrrays for R, phi, and Z. Only + works on IPP network - ################## Plasma field service ######################## - # This uses EXTENDER via the webservices to get # - # the magnetic field from the plasma given 3d arrrays # - # for R, phi, and Z # - # http://webservices.ipp-hgw.mpg.de/docs/extender.html # - # Only works on IPP network # - # Contact brendan.shanahan@ipp.mpg.de for questions # - ################################################################ + http://webservices.ipp-hgw.mpg.de/docs/extender.html - def plasma_field(r, phi, z, wout_file='wout.nc'): + Contact brendan.shanahan@ipp.mpg.de for questions + + """ from osa import Client import os.path import pickle From 89488e20985a8b3d87bc4e1618d69ddcade16f9f Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 5 Jan 2021 16:37:50 +0000 Subject: [PATCH 243/293] Apply black formatting to zoidberg/field.py --- tools/pylib/zoidberg/field.py | 1007 ++++++++++++++++++++------------- 1 file changed, 623 insertions(+), 384 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 789e527c40..28735cc01f 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -316,13 +316,29 @@ def Byfunc(self, x, z, phi): return np.full(x.shape, self.By) def Bzfunc(self, x, z, phi): - return self.Bz + (x - self.xcentre)*self.Bzprime + return self.Bz + (x - self.xcentre) * self.Bzprime def Rfunc(self, x, z, phi): return np.full(x.shape, self.Rmaj) + try: - from sympy import Symbol, atan2, cos, sin, log, pi, sqrt, lambdify, Piecewise, Sum, gamma, And, factorial, diff + from sympy import ( + Symbol, + atan2, + cos, + sin, + log, + pi, + sqrt, + lambdify, + Piecewise, + Sum, + gamma, + And, + factorial, + diff, + ) class StraightStellarator(MagneticField): """A "rotating ellipse" stellarator without curvature @@ -361,32 +377,52 @@ def coil(self, xcentre, zcentre, radius, angle, iota, I): (x, z) - x, z coordinates of coils along phi """ - return (xcentre + radius * cos(angle + iota * self.phi), - zcentre + radius * sin(angle + iota * self.phi), I) - - def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, - I_coil=0.05, smooth=False, smooth_args={}): + return ( + xcentre + radius * cos(angle + iota * self.phi), + zcentre + radius * sin(angle + iota * self.phi), + I, + ) + + def __init__( + self, + xcentre=0.0, + zcentre=0.0, + radius=0.8, + yperiod=np.pi, + I_coil=0.05, + smooth=False, + smooth_args={}, + ): xcentre = float(xcentre) zcentre = float(zcentre) radius = float(radius) yperiod = float(yperiod) - iota = 2.*np.pi / yperiod + iota = 2.0 * np.pi / yperiod - self.x = Symbol('x') - self.z = Symbol('z') - self.y = Symbol('y') - self.r = Symbol('r') - self.r = (self.x**2 + self.z**2)**(0.5) - self.phi = Symbol('phi') + self.x = Symbol("x") + self.z = Symbol("z") + self.y = Symbol("y") + self.r = Symbol("r") + self.r = (self.x ** 2 + self.z ** 2) ** (0.5) + self.phi = Symbol("phi") self.xcentre = xcentre self.zcentre = zcentre self.radius = radius # Four coils equally spaced, alternating direction for current - self.coil_list = [self.coil(xcentre, zcentre, radius, n*pi, iota, ((-1)**np.mod(i,2))*I_coil) - for i, n in enumerate(np.arange(4)/2.)] + self.coil_list = [ + self.coil( + xcentre, + zcentre, + radius, + n * pi, + iota, + ((-1) ** np.mod(i, 2)) * I_coil, + ) + for i, n in enumerate(np.arange(4) / 2.0) + ] A = 0.0 Bx = 0.0 @@ -394,18 +430,18 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, for c in self.coil_list: xc, zc, Ic = c - rc = (xc**2 + zc**2)**(0.5) - r2 = (self.x - xc)**2 + (self.z - zc)**2 - theta = atan2(self.z - zc, self.x - xc) # Angle relative to coil + rc = (xc ** 2 + zc ** 2) ** (0.5) + r2 = (self.x - xc) ** 2 + (self.z - zc) ** 2 + theta = atan2(self.z - zc, self.x - xc) # Angle relative to coil A -= Ic * 0.1 * log(r2) - B = Ic * 0.2/sqrt(r2) + B = Ic * 0.2 / sqrt(r2) Bx += B * sin(theta) Bz -= B * cos(theta) - self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") + self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") @@ -445,33 +481,54 @@ def coil(self, xcentre, zcentre, radius, angle, iota, I): (x, z) - x, z coordinates of coils along phi """ - return (xcentre + radius * cos(angle + iota * self.phi), - zcentre + radius * sin(angle + iota * self.phi), I) - - def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, - I_coil=0.05, Btor=1.0, smooth=False, smooth_args={}): + return ( + xcentre + radius * cos(angle + iota * self.phi), + zcentre + radius * sin(angle + iota * self.phi), + I, + ) + + def __init__( + self, + xcentre=0.0, + zcentre=0.0, + radius=0.8, + yperiod=np.pi, + I_coil=0.05, + Btor=1.0, + smooth=False, + smooth_args={}, + ): xcentre = float(xcentre) zcentre = float(zcentre) radius = float(radius) yperiod = float(yperiod) Btor = float(Btor) - iota = 2.*np.pi / yperiod + iota = 2.0 * np.pi / yperiod - self.x = Symbol('x') - self.z = Symbol('z') - self.y = Symbol('y') - self.r = Symbol('r') - self.r = (self.x**2 + self.z**2)**(0.5) - self.phi = Symbol('phi') + self.x = Symbol("x") + self.z = Symbol("z") + self.y = Symbol("y") + self.r = Symbol("r") + self.r = (self.x ** 2 + self.z ** 2) ** (0.5) + self.phi = Symbol("phi") self.xcentre = xcentre self.zcentre = zcentre self.radius = radius # Four coils equally spaced, alternating direction for current - self.coil_list = [self.coil(xcentre, zcentre, radius, n*pi, iota, ((-1)**np.mod(i,2))*I_coil) - for i, n in enumerate(np.arange(4)/2.)] + self.coil_list = [ + self.coil( + xcentre, + zcentre, + radius, + n * pi, + iota, + ((-1) ** np.mod(i, 2)) * I_coil, + ) + for i, n in enumerate(np.arange(4) / 2.0) + ] A = 0.0 Bx = 0.0 @@ -479,19 +536,19 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, for c in self.coil_list: xc, zc, Ic = c - rc = (xc**2 + zc**2)**(0.5) - r2 = (self.x - xc)**2 + (self.z - zc)**2 - theta = atan2(self.z - zc, self.x - xc) # Angle relative to coil + rc = (xc ** 2 + zc ** 2) ** (0.5) + r2 = (self.x - xc) ** 2 + (self.z - zc) ** 2 + theta = atan2(self.z - zc, self.x - xc) # Angle relative to coil A -= Ic * 0.1 * log(r2) - B = Ic * 0.2/sqrt(r2) + B = Ic * 0.2 / sqrt(r2) Bx += B * sin(theta) Bz -= B * cos(theta) - By = Btor/self.x - self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") + By = Btor / self.x + self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") @@ -499,9 +556,9 @@ def __init__(self, xcentre=0.0, zcentre=0.0, radius=0.8, yperiod=np.pi, def Rfunc(self, x, z, phi): return np.full(x.shape, x) - + class DommaschkPotentials(MagneticField): - """A magnetic field generator using the Dommaschk potentials. + """A magnetic field generator using the Dommaschk potentials. Parameters ---------- A: Coefficient matrix for the torodial and polidial harmonics. Form: (m,l,(a,b,c,d)) @@ -512,39 +569,47 @@ class DommaschkPotentials(MagneticField): ----------------- Bxfunc/Byfunc/Bzfunc(x,z,y): Returns magnetic field in radial/torodial/z-direction Sfunc(x,z,y): Returns approximate magnetic surface invariant for Dommaschk potentials. Use this to visualize flux surfaces - + """ - def __init__(self, A, R_0=1.0, B_0=1.0): self.R_0 = R_0 self.B_0 = B_0 - - - self.R = Symbol('R') - self.phi = Symbol('phi') - self.Z = Symbol('Z') + self.R = Symbol("R") + self.phi = Symbol("phi") + self.Z = Symbol("Z") - self.m = Symbol('m') - self.l = Symbol('l') - self.n = Symbol('n') - self.k = Symbol('k') + self.m = Symbol("m") + self.l = Symbol("l") + self.n = Symbol("n") + self.k = Symbol("k") self.A = A - - self.P = self.U(self.A).doit().subs([(self.R, self.R/self.R_0), (self.Z, self.Z/R_0)]) - self.P_hat = self.U_hat(self.A).doit().subs([(self.R, self.R/self.R_0), (self.Z, self.Z/R_0)]) - - S = (0.5*(log(self.R/self.R_0)**2 + (self.Z/R_0)**2) - self.R/self.R_0 * (log(self.R/self.R_0)*self.R_0*diff(self.P_hat, self.R) + self.Z*self.R/self.R_0*diff(self.P_hat, self.Z)))#.subs([(self.R, self.R/self.R_0), (self.Z, self.Z)]) - - - Bx = R_0*diff(self.P, self.R) - By = R_0/self.R * diff(self.P, self.phi) + self.P = ( + self.U(self.A) + .doit() + .subs([(self.R, self.R / self.R_0), (self.Z, self.Z / R_0)]) + ) + self.P_hat = ( + self.U_hat(self.A) + .doit() + .subs([(self.R, self.R / self.R_0), (self.Z, self.Z / R_0)]) + ) + + S = 0.5 * ( + log(self.R / self.R_0) ** 2 + (self.Z / R_0) ** 2 + ) - self.R / self.R_0 * ( + log(self.R / self.R_0) * self.R_0 * diff(self.P_hat, self.R) + + self.Z * self.R / self.R_0 * diff(self.P_hat, self.Z) + ) # .subs([(self.R, self.R/self.R_0), (self.Z, self.Z)]) + + Bx = R_0 * diff(self.P, self.R) + By = R_0 / self.R * diff(self.P, self.phi) Bz = diff(self.P, self.Z) self.Sf = lambdify((self.R, self.phi, self.Z), S, "numpy") @@ -554,17 +619,16 @@ def __init__(self, A, R_0=1.0, B_0=1.0): self.Bzf = lambdify((self.R, self.phi, self.Z), Bz, "numpy") def Bxfunc(self, x, z, phi): - - return self.Bxf(x, phi, z)/self.Byf(self.R_0, 0, 0)*self.B_0 - - def Byfunc(self, x, z, phi): + return self.Bxf(x, phi, z) / self.Byf(self.R_0, 0, 0) * self.B_0 - return self.Byf(x, phi, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + def Byfunc(self, x, z, phi): + + return self.Byf(x, phi, z) / self.Byf(self.R_0, 0, 0) * self.B_0 def Bzfunc(self, x, z, phi): - return self.Bzf(x, phi, z)/self.Byf(self.R_0, 0, 0)*self.B_0 + return self.Bzf(x, phi, z) / self.Byf(self.R_0, 0, 0) * self.B_0 def Sfunc(self, x, z, y): """ @@ -578,7 +642,7 @@ def Sfunc(self, x, z, y): ------- Approximate magnetic surface invariant S at location (x,z,y). This is from the original Dommaschk paper. Use to visualize flux surfaces """ - return self.Sf(x,y,z) + return self.Sf(x, y, z) def Rfunc(self, x, z, phi): """ @@ -595,8 +659,6 @@ def Rfunc(self, x, z, phi): return x - - def CD(self, m, k): """ Parameters @@ -609,29 +671,59 @@ def CD(self, m, k): Sympy function CD_mk (R) (Dirichlet boudary conditions) """ - n = Symbol('n') - b = Symbol('b') - i = Symbol('i') - - alpha = Piecewise(((((-1)**n)/(gamma(b + n + 1) * gamma(n + 1) * 2**(2 * n + b) )), n >= 0), (0, True)) - alpha_st = Piecewise((alpha * (2*n + b), n >= 0), (0, True)) - - - beta = Piecewise(((gamma(b - n))/(gamma(n + 1) * 2**(2*n - b + 1)), And(n >= 0, n < b)), (0, True)) - beta_st = Piecewise((beta * (2*n - b), And(n >= 0, n < b)), (0, True)) - - - delta = Piecewise((alpha/2 * Sum(1/i + 1/(b + i), (i, 1, n+1)), n > 0), (0, True)) + n = Symbol("n") + b = Symbol("b") + i = Symbol("i") + + alpha = Piecewise( + ( + ( + ((-1) ** n) + / (gamma(b + n + 1) * gamma(n + 1) * 2 ** (2 * n + b)) + ), + n >= 0, + ), + (0, True), + ) + alpha_st = Piecewise((alpha * (2 * n + b), n >= 0), (0, True)) + + beta = Piecewise( + ( + (gamma(b - n)) / (gamma(n + 1) * 2 ** (2 * n - b + 1)), + And(n >= 0, n < b), + ), + (0, True), + ) + beta_st = Piecewise((beta * (2 * n - b), And(n >= 0, n < b)), (0, True)) + + delta = Piecewise( + (alpha / 2 * Sum(1 / i + 1 / (b + i), (i, 1, n + 1)), n > 0), (0, True) + ) delta_st = Piecewise((delta * (2 * n + b), n > 0), (0, True)) - j = Symbol('j') - - CD = Sum(-( alpha.subs([(n, j), (b,m)]) * ( alpha_st.subs([(n, k - m - j), (b, m)]) * log(self.R) + delta_st.subs([(n, k - m - j), (b, m)]) - alpha.subs([(n, k - m - j), (b, m)]) ) - delta.subs([(n, j), (b,m)]) * alpha_st.subs([(n, k - m - j), (b, m)]) + alpha.subs([(n, j), (b,m)]) * beta_st.subs([(n, k - j), (b, m)])) * self.R**(2*j + m)\ - + beta.subs([(n, j), (b, m)]) * alpha_st.subs([(n, k - j), (b, m)]) * self.R**(2*j - m), (j, 0, k)) + j = Symbol("j") + + CD = Sum( + -( + alpha.subs([(n, j), (b, m)]) + * ( + alpha_st.subs([(n, k - m - j), (b, m)]) * log(self.R) + + delta_st.subs([(n, k - m - j), (b, m)]) + - alpha.subs([(n, k - m - j), (b, m)]) + ) + - delta.subs([(n, j), (b, m)]) + * alpha_st.subs([(n, k - m - j), (b, m)]) + + alpha.subs([(n, j), (b, m)]) * beta_st.subs([(n, k - j), (b, m)]) + ) + * self.R ** (2 * j + m) + + beta.subs([(n, j), (b, m)]) + * alpha_st.subs([(n, k - j), (b, m)]) + * self.R ** (2 * j - m), + (j, 0, k), + ) return CD - def CN(self, m, k): """ Parameters @@ -644,33 +736,58 @@ def CN(self, m, k): Sympy function CN_mk (R) (Neumann boundary conditions) """ - - n = Symbol('n') - b = Symbol('b') - i = Symbol('i') - - - alpha = Piecewise(((((-1)**n)/(gamma(b + n + 1) * gamma(n + 1) * 2**(2 * n + b) )), n >= 0), (0, True)) - alpha_st = Piecewise((alpha * (2*n + b), n >= 0), (0, True)) - - - beta = Piecewise(((gamma(b - n))/(gamma(n + 1) * 2**(2*n - b + 1)), And(n >= 0, n < b)), (0, True)) - beta_st = Piecewise((beta * (2*n - b), And(n >= 0, n < b)), (0, True)) - - - delta = Piecewise((alpha/2 * Sum(1/i + 1/(b + i), (i, 1, n+1)), n > 0), (0, True)) + n = Symbol("n") + b = Symbol("b") + i = Symbol("i") + + alpha = Piecewise( + ( + ( + ((-1) ** n) + / (gamma(b + n + 1) * gamma(n + 1) * 2 ** (2 * n + b)) + ), + n >= 0, + ), + (0, True), + ) + alpha_st = Piecewise((alpha * (2 * n + b), n >= 0), (0, True)) + + beta = Piecewise( + ( + (gamma(b - n)) / (gamma(n + 1) * 2 ** (2 * n - b + 1)), + And(n >= 0, n < b), + ), + (0, True), + ) + beta_st = Piecewise((beta * (2 * n - b), And(n >= 0, n < b)), (0, True)) + + delta = Piecewise( + (alpha / 2 * Sum(1 / i + 1 / (b + i), (i, 1, n + 1)), n > 0), (0, True) + ) delta_st = Piecewise((delta * (2 * n + b), n > 0), (0, True)) - j = Symbol('j') - - CN = Sum(( alpha.subs([(n, j), (b,m)]) * ( alpha.subs( [(n, k - m - j), (b, m)] ) * log(self.R) + delta.subs([(n, k - m - j), (b, m)])) - delta.subs([(n, j), (b,m)]) * alpha.subs( [(n, k - m - j), (b, m)] ) + alpha.subs([(n, j), (b,m)]) * beta.subs([(n, k - j), (b, m)]) ) * self.R**( 2*j + m )\ - - beta.subs([(n, j), (b,m)]) * alpha.subs([(n, k-j),(b, m)]) * self.R**(2*j - m), (j, 0, k)) - - + j = Symbol("j") + + CN = Sum( + ( + alpha.subs([(n, j), (b, m)]) + * ( + alpha.subs([(n, k - m - j), (b, m)]) * log(self.R) + + delta.subs([(n, k - m - j), (b, m)]) + ) + - delta.subs([(n, j), (b, m)]) + * alpha.subs([(n, k - m - j), (b, m)]) + + alpha.subs([(n, j), (b, m)]) * beta.subs([(n, k - j), (b, m)]) + ) + * self.R ** (2 * j + m) + - beta.subs([(n, j), (b, m)]) + * alpha.subs([(n, k - j), (b, m)]) + * self.R ** (2 * j - m), + (j, 0, k), + ) return CN - def D(self, m, n): """ Parameters @@ -682,21 +799,17 @@ def D(self, m, n): -------- Sympy function D_mn (R, Z) (Dirichlet boundary conditions) """ - - i = Symbol('i') + + i = Symbol("i") D = log(1) - k_arr = np.arange(0,int(n/2)+1,1) + k_arr = np.arange(0, int(n / 2) + 1, 1) CD_f = self.CD(m, i) - for k in k_arr: - D += ((self.Z**(n - 2*k))/factorial(n-2*k)*CD_f.subs(i,k)) - + D += (self.Z ** (n - 2 * k)) / factorial(n - 2 * k) * CD_f.subs(i, k) return D - - def N(self, m, n): """ Parameters @@ -709,15 +822,14 @@ def N(self, m, n): Sympy function N_mn (R, Z) (Neumann boundary conditions) """ - i = Symbol('i') + i = Symbol("i") N = log(1) - k_arr = np.arange(0, int(n/2)+1, 1) + k_arr = np.arange(0, int(n / 2) + 1, 1) CN_f = self.CN(m, i) for k in k_arr: - N += ((self.Z**(n - 2*k))/factorial(n-2*k)*CN_f.subs(i,k)) - - return N + N += (self.Z ** (n - 2 * k)) / factorial(n - 2 * k) * CN_f.subs(i, k) + return N def V(self, m, l, a, b, c, d): """ @@ -732,29 +844,31 @@ def V(self, m, l, a, b, c, d): Sympy function V_ml """ - V = ( a*cos(m*self.phi) + b*sin(m*self.phi) ) * self.D(m, l) + ( c*cos(m*self.phi) + d*sin(m*self.phi) ) * self.N(m, l-1) + V = (a * cos(m * self.phi) + b * sin(m * self.phi)) * self.D(m, l) + ( + c * cos(m * self.phi) + d * sin(m * self.phi) + ) * self.N(m, l - 1) return V - - def U(self, A): """ Parameters ---------- A: Coefficient matrix for the torodial and polidial harmonics. Form: (m,l,(a,b,c,d)) - + Returns ----------------- U: Superposition of all modes given in A - + """ U = self.phi for i in range(A.shape[0]): - for j in range(A.shape[1]): - if A[i,j,0] or A[i,j,1] or A[i,j,2] or A[i,j,3] != 0: + for j in range(A.shape[1]): + if A[i, j, 0] or A[i, j, 1] or A[i, j, 2] or A[i, j, 3] != 0: - U += self.V(i, j, A[i,j,0], A[i,j,1], A[i,j,2], A[i,j,3]) + U += self.V( + i, j, A[i, j, 0], A[i, j, 1], A[i, j, 2], A[i, j, 3] + ) return U @@ -771,8 +885,15 @@ def V_hat(self, m, l, a, b, c, d): Sympy function V_hat_ml; Similar to V; needed for calculation of magnetic surface invariant S """ - V = ( a*cos(m*(self.phi-np.pi/(2*m))) + b*sin(m*(self.phi-np.pi/(2*m)) ) ) * self.D(m, l) + ( c*cos(m*(self.phi-np.pi/(2*m))) + d*sin(m*(self.phi-np.pi/(2*m)) ) ) * self.N(m, l-1) - + V = ( + a * cos(m * (self.phi - np.pi / (2 * m))) + + b * sin(m * (self.phi - np.pi / (2 * m))) + ) * self.D(m, l) + ( + c * cos(m * (self.phi - np.pi / (2 * m))) + + d * sin(m * (self.phi - np.pi / (2 * m))) + ) * self.N( + m, l - 1 + ) return V @@ -787,44 +908,47 @@ def U_hat(self, A): U: Superposition of all modes given in A """ - + U = log(1) for i in range(A.shape[0]): - for j in range(A.shape[1]): - if A[i,j,0] or A[i,j,1] or A[i,j,2] or A[i,j,3] != 0: - U += self.V_hat(i, j, A[i,j,0], A[i,j,1], A[i,j,2], A[i,j,3]) * Piecewise((self.phi, i==0), (1/i, i>0)) + for j in range(A.shape[1]): + if A[i, j, 0] or A[i, j, 1] or A[i, j, 2] or A[i, j, 3] != 0: + U += self.V_hat( + i, j, A[i, j, 0], A[i, j, 1], A[i, j, 2], A[i, j, 3] + ) * Piecewise((self.phi, i == 0), (1 / i, i > 0)) return U + class Screwpinch(MagneticField): + def __init__( + self, xcentre=1.5, zcentre=0.0, shear=0, yperiod=2 * np.pi, Btor=1.0 + ): + self.x = Symbol("x") + self.z = Symbol("z") + self.y = Symbol("y") + self.r = Symbol("r") + self.r = ((self.x - xcentre) ** 2 + (self.z - zcentre) ** 2) ** (0.5) + self.phi = Symbol("phi") - - class Screwpinch(MagneticField): - - def __init__(self, xcentre=1.5, zcentre=0.0, shear = 0, yperiod=2*np.pi, Btor=1.0): - self.x = Symbol('x') - self.z = Symbol('z') - self.y = Symbol('y') - self.r = Symbol('r') - self.r = ((self.x-xcentre)**2 + (self.z-zcentre)**2)**(0.5) - - self.phi = Symbol('phi') - alpha = shear self.theta = atan2(self.z - zcentre, self.x - xcentre) - A = alpha*self.r**2 - Bx = -alpha*self.r*self.r*sin(self.theta) - Bz = alpha*self.r*self.r*cos(self.theta) - By = Btor/self.x - - self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") + A = alpha * self.r ** 2 + Bx = -alpha * self.r * self.r * sin(self.theta) + Bz = alpha * self.r * self.r * cos(self.theta) + By = Btor / self.x + + self.Afunc = lambdify((self.x, self.z, self.phi), A, "numpy") self.Bxfunc = lambdify((self.x, self.z, self.phi), Bx, "numpy") self.Bzfunc = lambdify((self.x, self.z, self.phi), Bz, "numpy") self.Byfunc = lambdify((self.x, self.z, self.phi), By, "numpy") + def Rfunc(self, x, z, phi): return np.full(x.shape, x) - + + except ImportError: + class StraightStellarator(MagneticField): """ Invalid StraightStellarator, since no Sympy module. @@ -833,8 +957,11 @@ class StraightStellarator(MagneticField): be missed or ignored, this raises an exception if StraightStellarator is ever used. """ + def __init__(self, *args, **kwargs): - raise ImportError("No Sympy module: Can't generate StraightStellarator fields") + raise ImportError( + "No Sympy module: Can't generate StraightStellarator fields" + ) class RotatingEllipse(MagneticField): """ @@ -843,6 +970,7 @@ class RotatingEllipse(MagneticField): be missed or ignored, this raises an exception if StraightStellarator is ever used. """ + def __init__(self, *args, **kwargs): raise ImportError("No Sympy module: Can't generate RotatingEllipse fields") @@ -853,9 +981,11 @@ class Screwpinch(MagneticField): be missed or ignored, this raises an exception if StraightStellarator is ever used. """ + def __init__(self, *args, **kwargs): raise ImportError("No Sympy module: Can't generate screwpinch fields") - + + class VMEC(MagneticField): """A numerical magnetic field from a VMEC equilibrium file @@ -876,109 +1006,107 @@ class VMEC(MagneticField): def __rolling_average(self, field): result = np.zeros_like(field) - result[:,0] = field[:,1] - 0.5*field[:,2] - result[:,2:-2] = 0.5 * (field[:,2:-2] + field[:,3:-1]) - result[:,-1] = 2*field[:,-2] - field[:,-3] + result[:, 0] = field[:, 1] - 0.5 * field[:, 2] + result[:, 2:-2] = 0.5 * (field[:, 2:-2] + field[:, 3:-1]) + result[:, -1] = 2 * field[:, -2] - field[:, -3] return result def cfunct(self, field): - """VMEC DCT - """ + """VMEC DCT""" ns = field.shape[0] lt = self.theta.size lz = self.zeta.size # Create mode x angle arrays - mt = self.xm[:,np.newaxis]*self.theta - nz = self.xn[:,np.newaxis]*self.zeta + mt = self.xm[:, np.newaxis] * self.theta + nz = self.xn[:, np.newaxis] * self.zeta # Create Trig Arrays cosmt = np.cos(mt) sinmt = np.sin(mt) cosnz = np.cos(nz) sinnz = np.sin(nz) # Calculate the transform - f = np.zeros((ns,lt,lz)) + f = np.zeros((ns, lt, lz)) for k, field_slice in enumerate(field): - rmn = np.repeat(field_slice[:,np.newaxis], lt, axis=1) - a = rmn*cosmt + rmn = np.repeat(field_slice[:, np.newaxis], lt, axis=1) + a = rmn * cosmt b = np.dot(a.T, cosnz) # print("a: {}, b: {}".format(a.shape, b.shape)) - c = rmn*sinmt + c = rmn * sinmt d = np.dot(c.T, sinnz) # print("c: {}, d: {}".format(c.shape, d.shape)) - f[k,:,:] = b - d + f[k, :, :] = b - d return f def sfunct(self, field): - """VMEC DST - """ + """VMEC DST""" ns = field.shape[0] lt = self.theta.size lz = self.zeta.size # Create mode x angle arrays - mt = self.xm[:,np.newaxis]*self.theta - nz = self.xn[:,np.newaxis]*self.zeta + mt = self.xm[:, np.newaxis] * self.theta + nz = self.xn[:, np.newaxis] * self.zeta # Create Trig Arrays cosmt = np.cos(mt) sinmt = np.sin(mt) cosnz = np.cos(nz) sinnz = np.sin(nz) # Calculate the transform - f = np.zeros((ns,lt,lz)) + f = np.zeros((ns, lt, lz)) for k, field_slice in enumerate(field): - rmn = np.repeat(field_slice[:,np.newaxis], lt, axis=1) - a = rmn*sinmt + rmn = np.repeat(field_slice[:, np.newaxis], lt, axis=1) + a = rmn * sinmt b = np.dot(a.T, cosnz) - c = rmn*cosmt + c = rmn * cosmt d = np.dot(c.T, sinnz) - f[k,:,:] = b + d + f[k, :, :] = b + d return f def read_vmec_file(self, vmec_file, ntheta=None, nzeta=None): - """Read a VMEC equilibrium file - """ + """Read a VMEC equilibrium file""" from boututils.datafile import DataFile + # Read necessary stuff with DataFile(vmec_file, write=False) as f: - self.xm = f['xm'].T - self.xn = f['xn'].T - ns = int(f['ns']) - xm_big = np.repeat(self.xm[:,np.newaxis], ns, axis=1) - xn_big = np.repeat(self.xn[:,np.newaxis], ns, axis=1) + self.xm = f["xm"].T + self.xn = f["xn"].T + ns = int(f["ns"]) + xm_big = np.repeat(self.xm[:, np.newaxis], ns, axis=1) + xn_big = np.repeat(self.xn[:, np.newaxis], ns, axis=1) # s and c seem to swap meanings here... - rumns = -f['rmnc'].T*xm_big - rvmns = -f['rmnc'].T*xn_big - zumnc = f['zmns'].T*xm_big - zvmnc = f['zmns'].T*xn_big + rumns = -f["rmnc"].T * xm_big + rvmns = -f["rmnc"].T * xn_big + zumnc = f["zmns"].T * xm_big + zvmnc = f["zmns"].T * xn_big try: - iasym = f['iasym'] + iasym = f["iasym"] except KeyError: iasym = 0 if iasym: - rumnc = -f['rmns'].T*xm_big - rvmnc = -f['rmns'].T*xn_big - zumns = f['zmnc'].T*xm_big - zvmns = f['zmnc'].T*xn_big + rumnc = -f["rmns"].T * xm_big + rvmnc = -f["rmns"].T * xn_big + zumns = f["zmnc"].T * xm_big + zvmns = f["zmnc"].T * xn_big - bsupumnc = self.__rolling_average(f['bsupumnc'].T).T - bsupvmnc = self.__rolling_average(f['bsupvmnc'].T).T + bsupumnc = self.__rolling_average(f["bsupumnc"].T).T + bsupvmnc = self.__rolling_average(f["bsupvmnc"].T).T if ntheta is None: - self.ntheta = int(f['mpol']) + self.ntheta = int(f["mpol"]) else: self.ntheta = ntheta if nzeta is None: - self.nzeta = int(f['ntor']) + 1 + self.nzeta = int(f["ntor"]) + 1 else: self.nzeta = nzeta - self.theta = np.linspace(0, 2*np.pi, self.ntheta) - self.zeta = np.linspace(0, 2*np.pi, self.nzeta) + self.theta = np.linspace(0, 2 * np.pi, self.ntheta) + self.zeta = np.linspace(0, 2 * np.pi, self.nzeta) # R, Z on (s, theta, zeta) - self.r_stz = self.cfunct(f['rmnc']) - self.z_stz = self.sfunct(f['zmns']) + self.r_stz = self.cfunct(f["rmnc"]) + self.z_stz = self.sfunct(f["zmns"]) bu = self.cfunct(bsupumnc) bv = self.cfunct(bsupvmnc) @@ -988,17 +1116,17 @@ def read_vmec_file(self, vmec_file, ntheta=None, nzeta=None): dzdu = self.cfunct(zumnc.T) dzdv = self.cfunct(zvmnc.T) if iasym: - self.r_stz = self.r_stz + self.sfunct(f['rmnc']) + self.r_stz = self.r_stz + self.sfunct(f["rmnc"]) drdu = drdu + self.cfunct(rumnc.T) drdv = drdv + self.cfunct(rvmnc.T) - self.z_stz = self.z_stz + self.cfunct(f['zmnc']) + self.z_stz = self.z_stz + self.cfunct(f["zmnc"]) dzdu = dzdu + self.sfunct(zumns.T) dzdv = dzdv + self.sfunct(zvmns.T) # Convert to bR, bZ, bphi - self.br = bu*drdu + bv*drdv - self.bphi = self.r_stz*bv - self.bz = bu*dzdu + bv*dzdv + self.br = bu * drdu + bv * drdv + self.bphi = self.r_stz * bv + self.bz = bu * dzdu + bv * dzdv def __init__(self, vmec_file, ntheta=None, nzeta=None, nr=32, nz=32): # Only needed here @@ -1012,40 +1140,63 @@ def __init__(self, vmec_file, ntheta=None, nzeta=None, nr=32, nz=32): # Make a new rectangular grid in (R,Z) self.r_1D = np.linspace(self.r_stz.min(), self.r_stz.max(), nr) self.z_1D = np.linspace(self.z_stz.min(), self.z_stz.max(), nz) - self.R_2D, self.Z_2D = np.meshgrid(self.r_1D, self.z_1D, indexing='ij') + self.R_2D, self.Z_2D = np.meshgrid(self.r_1D, self.z_1D, indexing="ij") # First, interpolate the magnetic field components onto (R,Z) - self.br_rz = np.zeros( (nr, nz, self.nzeta) ) - self.bz_rz = np.zeros( (nr, nz, self.nzeta) ) - self.bphi_rz = np.zeros( (nr, nz, self.nzeta) ) + self.br_rz = np.zeros((nr, nz, self.nzeta)) + self.bz_rz = np.zeros((nr, nz, self.nzeta)) + self.bphi_rz = np.zeros((nr, nz, self.nzeta)) # No need to interpolate in zeta, so do this one slice at a time - for k, (br, bz, bphi, r, z) in enumerate(zip(self.br.T, self.bz.T, self.bphi.T, self.r_stz.T, self.z_stz.T)): - points = np.column_stack( (r.flatten(), z.flatten()) ) - self.br_rz[...,k] = griddata(points, br.flatten(), (self.R_2D, self.Z_2D), - method='linear', fill_value=0.0) - self.bz_rz[...,k] = griddata(points, bz.flatten(), (self.R_2D, self.Z_2D), - method='linear', fill_value=0.0) - self.bphi_rz[...,k] = griddata(points, bphi.flatten(), (self.R_2D, self.Z_2D), - method='linear', fill_value=1.0) + for k, (br, bz, bphi, r, z) in enumerate( + zip(self.br.T, self.bz.T, self.bphi.T, self.r_stz.T, self.z_stz.T) + ): + points = np.column_stack((r.flatten(), z.flatten())) + self.br_rz[..., k] = griddata( + points, + br.flatten(), + (self.R_2D, self.Z_2D), + method="linear", + fill_value=0.0, + ) + self.bz_rz[..., k] = griddata( + points, + bz.flatten(), + (self.R_2D, self.Z_2D), + method="linear", + fill_value=0.0, + ) + self.bphi_rz[..., k] = griddata( + points, + bphi.flatten(), + (self.R_2D, self.Z_2D), + method="linear", + fill_value=1.0, + ) # Now we have a regular grid in (R,Z,phi) (as zeta==phi), so # we can get an interpolation function in 3D - points = ( self.r_1D, self.z_1D, self.zeta ) + points = (self.r_1D, self.z_1D, self.zeta) - self.br_interp = RegularGridInterpolator(points, self.br_rz, bounds_error=False, fill_value=0.0) - self.bz_interp = RegularGridInterpolator(points, self.bz_rz, bounds_error=False, fill_value=0.0) - self.bphi_interp = RegularGridInterpolator(points, self.bphi_rz, bounds_error=False, fill_value=1.0) + self.br_interp = RegularGridInterpolator( + points, self.br_rz, bounds_error=False, fill_value=0.0 + ) + self.bz_interp = RegularGridInterpolator( + points, self.bz_rz, bounds_error=False, fill_value=0.0 + ) + self.bphi_interp = RegularGridInterpolator( + points, self.bphi_rz, bounds_error=False, fill_value=1.0 + ) def Bxfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) return self.br_interp((x, z, phi)) def Bzfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) return self.bz_interp((x, z, phi)) def Byfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) return self.bphi_interp((x, z, phi)) def Rfunc(self, x, z, phi): @@ -1071,9 +1222,9 @@ class SmoothedMagneticField(MagneticField): Number of grid points in x over which the magnetic field is smoothed """ + def __init__(self, field, grid, xboundary=None, zboundary=None): - """ - """ + """""" self.field = field self.grid = grid @@ -1082,12 +1233,12 @@ def __init__(self, field, grid, xboundary=None, zboundary=None): def Bxfunc(self, x, z, phi): # Get closest y (phi) grid index - ind = np.argmin(np.abs( phi - self.grid.ycoords)) + ind = np.argmin(np.abs(phi - self.grid.ycoords)) if phi < self.grid.ycoords[ind]: ind -= 1 # phi now between ind and ind+1 grid_d, y_d = self.grid.getPoloidalGrid(ind) - grid_u, y_u = self.grid.getPoloidalGrid(ind+1) + grid_u, y_u = self.grid.getPoloidalGrid(ind + 1) # Get x,z indices from poloidal grids x_d, z_d = grid_d.findIndex(x, z) @@ -1116,29 +1267,29 @@ def smooth_field_line(self, xa, za): z_top = (za - self.zt_inner) / (self.zt_inner - self.zt_outer) + 1 z_bottom = (za - self.zb_inner) / (self.zb_inner - self.zb_outer) + 1 - if (xa < self.xl_inner): - if (za < self.zb_inner): + if xa < self.xl_inner: + if za < self.zb_inner: P = np.min([x_left, z_bottom]) - elif (za >= self.zt_inner): + elif za >= self.zt_inner: P = np.min([x_left, z_top]) else: P = x_left - elif (xa >= self.xr_inner): - if (za < self.zb_inner): + elif xa >= self.xr_inner: + if za < self.zb_inner: P = np.min([x_right, z_bottom]) - elif (za >= self.zt_inner): + elif za >= self.zt_inner: P = np.min([x_right, z_top]) else: P = x_right - elif (za < self.zb_inner): + elif za < self.zb_inner: P = z_bottom - elif (za > self.zt_inner): + elif za > self.zt_inner: P = z_top else: - P=1. - if (P<0.): - P=0. + P = 1.0 + if P < 0.0: + P = 0.0 return P @@ -1163,39 +1314,40 @@ def __init__(self, gfile): g.openFile(gfile) # Get the range of major radius - self.rmin = g.get('rleft') - self.rmax = g.get('rdim') + self.rmin + self.rmin = g.get("rleft") + self.rmax = g.get("rdim") + self.rmin # Range of height - self.zmin = g.get('zmid') - 0.5*g.get('zdim') - self.zmax = g.get('zmid') + 0.5*g.get('zdim') + self.zmin = g.get("zmid") - 0.5 * g.get("zdim") + self.zmax = g.get("zmid") + 0.5 * g.get("zdim") print("Major radius: {0} -> {1} m".format(self.rmin, self.rmax)) print("Height: {0} -> {1} m".format(self.zmin, self.zmax)) # Poloidal flux - self.psi = np.transpose(g.get('psirz')) + self.psi = np.transpose(g.get("psirz")) nr, nz = self.psi.shape # Normalising factors: psi on axis and boundary - self.psi_axis = g.get('simag') - self.psi_bndry = g.get('sibry') + self.psi_axis = g.get("simag") + self.psi_bndry = g.get("sibry") # Current flux function f = R * Bt - self.fpol = g.get('fpol') + self.fpol = g.get("fpol") # Pressure [Pascals] - self.p = g.get('pres') + self.p = g.get("pres") self.r = np.linspace(self.rmin, self.rmax, nr) self.z = np.linspace(self.zmin, self.zmax, nz) # Create a 2D spline interpolation for psi from scipy import interpolate + self.psi_func = interpolate.RectBivariateSpline(self.r, self.z, self.psi) # Add to the attributes so that it can be written to file - self.attributes["psi"] = lambda x,z,phi : self.psi_func(x,z,grid=False) + self.attributes["psi"] = lambda x, z, phi: self.psi_func(x, z, grid=False) # Create a normalised psi array @@ -1205,16 +1357,18 @@ def __init__(self, gfile): # eg. around coils or in the private flux region # Create a boundary - rb = g.get('rbbbs') - zb = g.get('zbbbs') + rb = g.get("rbbbs") + zb = g.get("zbbbs") core_bndry = boundary.PolygonBoundaryXZ(rb, zb) # Get the points outside the boundary - rxz, zxz = np.meshgrid(self.r, self.z, indexing='ij') + rxz, zxz = np.meshgrid(self.r, self.z, indexing="ij") outside = core_bndry.outside(rxz, 0.0, zxz) self.psinorm[outside] = 1.0 - self.psinorm_func = interpolate.RectBivariateSpline(self.r, self.z, self.psinorm) + self.psinorm_func = interpolate.RectBivariateSpline( + self.r, self.z, self.psinorm + ) # Spline for interpolation of f = R*Bt psinorm = np.linspace(0.0, 1.0, nr) @@ -1225,25 +1379,25 @@ def __init__(self, gfile): self.p_spl = interpolate.InterpolatedUnivariateSpline(psinorm, self.p, ext=3) # Set boundary - rlim = g.get('rlim') - zlim = g.get('zlim') + rlim = g.get("rlim") + zlim = g.get("zlim") if len(rlim) > 0: # Create a boundary in X-Z with a polygon representation - self.boundary = boundary.PolygonBoundaryXZ(rlim,zlim) + self.boundary = boundary.PolygonBoundaryXZ(rlim, zlim) def Bxfunc(self, x, z, phi): - return -self.psi_func(x,z,dy=1,grid=False)/x + return -self.psi_func(x, z, dy=1, grid=False) / x def Bzfunc(self, x, z, phi): - return self.psi_func(x,z,dx=1,grid=False)/x + return self.psi_func(x, z, dx=1, grid=False) / x def Byfunc(self, x, z, phi): # Interpolate to get flux surface normalised psi - psinorm = self.psinorm_func(x,z, grid=False) + psinorm = self.psinorm_func(x, z, grid=False) # Interpolate fpol array at values of normalised psi if hasattr(psinorm, "shape"): - return np.reshape(self.f_spl(np.ravel(psinorm)),psinorm.shape) / x + return np.reshape(self.f_spl(np.ravel(psinorm)), psinorm.shape) / x return self.f_spl(psinorm) / x # f = R*Bt @@ -1252,56 +1406,80 @@ def Rfunc(self, x, z, phi): def pressure(self, x, z, phi): # Interpolate to get flux surface normalised psi - psinorm = self.psinorm_func(x,z, grid=False) + psinorm = self.psinorm_func(x, z, grid=False) if hasattr(psinorm, "shape"): - return np.reshape(self.p_spl(np.ravel(psinorm)),psinorm.shape) + return np.reshape(self.p_spl(np.ravel(psinorm)), psinorm.shape) return self.p_spl(psinorm) + class W7X_vacuum(MagneticField): - def __init__(self,nx=128,ny=32,nz=128,x_range=(4.05,6.55),z_range=(-1.35,1,35), phimax=2.*np.pi, configuration=0, plot_poincare=False,include_plasma_field=False, wout_file='wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc'): + def __init__( + self, + nx=128, + ny=32, + nz=128, + x_range=(4.05, 6.55), + z_range=(-1.35, 1, 35), + phimax=2.0 * np.pi, + configuration=0, + plot_poincare=False, + include_plasma_field=False, + wout_file="wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc", + ): from scipy.interpolate import RegularGridInterpolator import numpy as np + ## create 1D arrays of cylindrical coordinates - r = np.linspace(x_range[0],x_range[-1],nx) - phi = np.linspace(0,phimax,ny) - z = np.linspace(z_range[0],z_range[-1],nz) + r = np.linspace(x_range[0], x_range[-1], nx) + phi = np.linspace(0, phimax, ny) + z = np.linspace(z_range[0], z_range[-1], nz) ## make those 1D arrays 3D - rarray,yarray,zarray = np.meshgrid(r,phi,z,indexing='ij') - + rarray, yarray, zarray = np.meshgrid(r, phi, z, indexing="ij") + ## call vacuum field values - b_vac = W7X_vacuum.field_values(rarray,yarray,zarray,configuration,plot_poincare) + b_vac = W7X_vacuum.field_values( + rarray, yarray, zarray, configuration, plot_poincare + ) Bx_vac = b_vac[0] By_vac = b_vac[1] Bz_vac = b_vac[2] - if(include_plasma_field): - b_plasma = W7X_vacuum.plasma_field(rarray,yarray,zarray,wout_file=wout_file) + if include_plasma_field: + b_plasma = W7X_vacuum.plasma_field( + rarray, yarray, zarray, wout_file=wout_file + ) Bx_plasma = b_plasma[0] By_plasma = b_plasma[1] - Bz_plasma = b_plasma[2] + Bz_plasma = b_plasma[2] else: Bx_plasma = 0 By_plasma = 0 Bz_plasma = 0 - + Bx = Bx_vac + Bx_plasma By = By_vac + By_plasma Bz = Bz_vac + Bz_plasma - + # Now we have a field and regular grid in (R,Z,phi) so # we can get an interpolation function in 3D - points = (r,phi,z) - - self.br_interp = RegularGridInterpolator(points, Bx, bounds_error=False, fill_value=0.0) - self.bz_interp = RegularGridInterpolator(points, Bz, bounds_error=False, fill_value=0.0) - self.bphi_interp = RegularGridInterpolator(points, By, bounds_error=False, fill_value=1.0) + points = (r, phi, z) + + self.br_interp = RegularGridInterpolator( + points, Bx, bounds_error=False, fill_value=0.0 + ) + self.bz_interp = RegularGridInterpolator( + points, Bz, bounds_error=False, fill_value=0.0 + ) + self.bphi_interp = RegularGridInterpolator( + points, By, bounds_error=False, fill_value=1.0 + ) # if you want non-interpolated, 3D arrays, make this your return function: # return Bx,By,Bz - + # return points, br_interp, bphi_interp, bz_interp def field_values(r, phi, z, configuration=0, plot_poincare=False): @@ -1319,12 +1497,12 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): import pickle import matplotlib.pyplot as plt - tracer = Client('http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl') + tracer = Client("http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl") nx = r.shape[0] ny = phi.shape[1] nz = z.shape[2] - + # create (standardized) file name for saving/loading magnetic field. fname = "B.w7x.{}.{}.{}.{:.2f}-{:.2f}.{:.2f}-{:.2f}.{:.2f}-{:.2f}.dat".format( nx, @@ -1338,61 +1516,76 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): z[0, 0, -1], ) - if(os.path.isfile(fname)): - print ("Saved field found, loading from: ", fname) + if os.path.isfile(fname): + print("Saved field found, loading from: ", fname) with open(fname, pickle_read_mode) as f: Br, Bphi, Bz = pickle.load(f) else: - print ("No saved field found -- (re)calculating (must be on IPP network for this to work...)") - print ("Calculating field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) + print( + "No saved field found -- (re)calculating (must be on IPP network for this to work...)" + ) + print( + "Calculating field for Wendelstein 7-X; nx = ", + nx, + " ny = ", + ny, + " nz = ", + nz, + ) ## Create configuration objects config = tracer.types.MagneticConfig() config.configIds = configuration - Br = np.zeros((nx,ny,nz)) - Bphi = np.ones((nx,ny,nz)) - Bz = np.zeros((nx,ny,nz)) + Br = np.zeros((nx, ny, nz)) + Bphi = np.ones((nx, ny, nz)) + Bz = np.zeros((nx, ny, nz)) pos = tracer.types.Points3D() - pos.x1 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.cos(phi)) #x in Cartesian (real-space) - pos.x2 = np.ndarray.flatten(np.ones((nx,ny,nz))*r*np.sin(phi)) #y in Cartesian (real-space) - pos.x3 = np.ndarray.flatten(z) #z in Cartesian (real-space) + pos.x1 = np.ndarray.flatten( + np.ones((nx, ny, nz)) * r * np.cos(phi) + ) # x in Cartesian (real-space) + pos.x2 = np.ndarray.flatten( + np.ones((nx, ny, nz)) * r * np.sin(phi) + ) # y in Cartesian (real-space) + pos.x3 = np.ndarray.flatten(z) # z in Cartesian (real-space) ## Call tracer service res = tracer.service.magneticField(pos, config) ## Reshape to 3d array - Bx = np.ndarray.reshape(np.asarray(res.field.x1),(nx,ny,nz)) - By = np.ndarray.reshape(np.asarray(res.field.x2),(nx,ny,nz)) - Bz = np.ndarray.reshape(np.asarray(res.field.x3), (nx,ny,nz)) + Bx = np.ndarray.reshape(np.asarray(res.field.x1), (nx, ny, nz)) + By = np.ndarray.reshape(np.asarray(res.field.x2), (nx, ny, nz)) + Bz = np.ndarray.reshape(np.asarray(res.field.x3), (nx, ny, nz)) ## Convert to cylindrical coordinates - Br = Bx*np.cos(phi) + By*np.sin(phi) - Bphi = -Bx*np.sin(phi) + By*np.cos(phi) - + Br = Bx * np.cos(phi) + By * np.sin(phi) + Bphi = -Bx * np.sin(phi) + By * np.cos(phi) + ## Save so we don't have to do this every time. with open(fname, pickle_write_mode) as f: - pickle.dump([Br,Bphi,Bz],f) - - if(plot_poincare): + pickle.dump([Br, Bphi, Bz], f) + + if plot_poincare: ## Poincare plot as done on the web services ## Independent of the previously-made field. - - print( "Making poincare plot (only works on IPP network)...") + + print("Making poincare plot (only works on IPP network)...") ## Create configuration objects config = tracer.types.MagneticConfig() config.configIds = configuration pos = tracer.types.Points3D() - + pos.x1 = np.linspace(5.6, 6.2, 80) pos.x2 = np.zeros(80) pos.x3 = np.zeros(80) - + poincare = tracer.types.PoincareInPhiPlane() poincare.numPoints = 200 - poincare.phi0 = [0.] ## This is where the poincare plane is (bean=0, triangle = pi/5.) + poincare.phi0 = [ + 0.0 + ] ## This is where the poincare plane is (bean=0, triangle = pi/5.) task = tracer.types.Task() task.step = 0.2 @@ -1401,12 +1594,14 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): res = tracer.service.trace(pos, config, task, None, None) for i in range(0, len(res.surfs)): - plt.scatter(res.surfs[i].points.x1, res.surfs[i].points.x3, color="black", s=0.1) + plt.scatter( + res.surfs[i].points.x1, res.surfs[i].points.x3, color="black", s=0.1 + ) plt.show() - - return Br, Bphi, Bz - def plasma_field(r, phi, z, wout_file='wout.nc'): + return Br, Bphi, Bz + + def plasma_field(r, phi, z, wout_file="wout.nc"): """This uses EXTENDER via the IPP webservices to get the magnetic field from the plasma given 3d arrrays for R, phi, and Z. Only works on IPP network @@ -1419,8 +1614,8 @@ def plasma_field(r, phi, z, wout_file='wout.nc'): from osa import Client import os.path import pickle - - cl = Client('http://esb.ipp-hgw.mpg.de:8280/services/Extender?wsdl') + + cl = Client("http://esb.ipp-hgw.mpg.de:8280/services/Extender?wsdl") vmecURL = "http://svvmec1.ipp-hgw.mpg.de:8080/vmecrest/v1/w7x_ref_1/wout.nc" nx = r.shape[0] @@ -1440,142 +1635,186 @@ def plasma_field(r, phi, z, wout_file='wout.nc'): z[0, 0, -1], ) - if(os.path.isfile(fname)): - print ("Saved field found, loading from: ", fname) + if os.path.isfile(fname): + print("Saved field found, loading from: ", fname) with open(fname, pickle_read_mode) as f: Br, Bphi, Bz = pickle.load(f) else: - print ("No saved plasma field found -- (re)calculating (must be on IPP network for this to work...)") - print ("Calculating plasma field for Wendelstein 7-X; nx = ",nx," ny = ",ny," nz = ", nz ) - print ("This part takes AGES... estimate: ",nx*ny*nz/52380., " minutes.") + print( + "No saved plasma field found -- (re)calculating (must be on IPP network for this to work...)" + ) + print( + "Calculating plasma field for Wendelstein 7-X; nx = ", + nx, + " ny = ", + ny, + " nz = ", + nz, + ) + print( + "This part takes AGES... estimate: ", + nx * ny * nz / 52380.0, + " minutes.", + ) points = cl.types.Points3D() ## Extender uses cylindrical coordinates, no need to convert, just flatten. - points.x1 = np.ndarray.flatten(r) #x in Cylindrical - points.x2 = np.ndarray.flatten(phi) #y in Cylindrical - points.x3 = np.ndarray.flatten(z) #z in Cylindrical + points.x1 = np.ndarray.flatten(r) # x in Cylindrical + points.x2 = np.ndarray.flatten(phi) # y in Cylindrical + points.x3 = np.ndarray.flatten(z) # z in Cylindrical ## call EXTENDER on web services # if not (os.path.isfile(wout_file)): plasmafield = cl.service.getPlasmaField(None, vmecURL, points, None) # else: # plasmafield = cl.service.getPlasmaField(wout, None, points, None) - + ## Reshape to 3d array - Br = np.ndarray.reshape(np.asarray(plasmafield.x1),(nx,ny,nz)) - Bphi = np.ndarray.reshape(np.asarray(plasmafield.x2),(nx,ny,nz)) - Bz = np.ndarray.reshape(np.asarray(plasmafield.x3), (nx,ny,nz)) - + Br = np.ndarray.reshape(np.asarray(plasmafield.x1), (nx, ny, nz)) + Bphi = np.ndarray.reshape(np.asarray(plasmafield.x2), (nx, ny, nz)) + Bz = np.ndarray.reshape(np.asarray(plasmafield.x3), (nx, ny, nz)) + ## Save so we don't have to do this every time. with open(fname, pickle_write_mode) as f: - pickle.dump([Br,Bphi,Bz],f) - - return Br, Bphi, Bz - - def magnetic_axis(self, phi_axis=0,configuration=0): + pickle.dump([Br, Bphi, Bz], f) + + return Br, Bphi, Bz + + def magnetic_axis(self, phi_axis=0, configuration=0): from osa import Client - - tracer = Client('http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl') - + + tracer = Client("http://esb.ipp-hgw.mpg.de:8280/services/FieldLineProxy?wsdl") + config = tracer.types.MagneticConfig() config.configIds = configuration settings = tracer.types.AxisSettings() res = tracer.service.findAxis(0.05, config, settings) - - magnetic_axis_x = np.asarray(res.axis.vertices.x1)# (m) - magnetic_axis_y = np.asarray(res.axis.vertices.x2)# (m) -- REAL SPACE from an arbitrary start point - magnetic_axis_z = np.asarray(res.axis.vertices.x3)# (m) - magnetic_axis_rmaj = np.sqrt(magnetic_axis_x**2 + magnetic_axis_y**2 + magnetic_axis_z**2) - magnetic_axis_r = np.sqrt(np.asarray(magnetic_axis_x)**2 + np.asarray(magnetic_axis_y**2)) - magnetic_axis_phi = np.arctan(magnetic_axis_y/magnetic_axis_x) + magnetic_axis_x = np.asarray(res.axis.vertices.x1) # (m) + magnetic_axis_y = np.asarray( + res.axis.vertices.x2 + ) # (m) -- REAL SPACE from an arbitrary start point + magnetic_axis_z = np.asarray(res.axis.vertices.x3) # (m) + magnetic_axis_rmaj = np.sqrt( + magnetic_axis_x ** 2 + magnetic_axis_y ** 2 + magnetic_axis_z ** 2 + ) - index = np.where((magnetic_axis_phi >= 0.97*phi_axis ) & (magnetic_axis_phi <= 1.03*phi_axis) ) + magnetic_axis_r = np.sqrt( + np.asarray(magnetic_axis_x) ** 2 + np.asarray(magnetic_axis_y ** 2) + ) + magnetic_axis_phi = np.arctan(magnetic_axis_y / magnetic_axis_x) + + index = np.where( + (magnetic_axis_phi >= 0.97 * phi_axis) + & (magnetic_axis_phi <= 1.03 * phi_axis) + ) index = index[0] - return np.asarray([magnetic_axis_r[index],magnetic_axis_z[index]])[:,0] + return np.asarray([magnetic_axis_r[index], magnetic_axis_z[index]])[:, 0] def Bxfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) - return self.br_interp((x,phi,z)) + phi = np.mod(phi, 2.0 * np.pi) + return self.br_interp((x, phi, z)) def Bzfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) - return self.bz_interp((x,phi,z)) + phi = np.mod(phi, 2.0 * np.pi) + return self.bz_interp((x, phi, z)) def Byfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) # Interpolate to get flux surface normalised psi - return self.bphi_interp((x,phi,z)) - + return self.bphi_interp((x, phi, z)) + def Rfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) return x + class W7X_VMEC(MagneticField): - def __init__(self,nx=512,ny=32,nz=512,x_range=(4.05,6.55),z_range=(-1.35,1,35), phi_range=(0,2*np.pi), vmec_id='w7x_ref_171'): + def __init__( + self, + nx=512, + ny=32, + nz=512, + x_range=(4.05, 6.55), + z_range=(-1.35, 1, 35), + phi_range=(0, 2 * np.pi), + vmec_id="w7x_ref_171", + ): from scipy.interpolate import RegularGridInterpolator + self.nx = nx self.ny = ny self.nz = nz ## create 1D arrays of cylindrical coordinates r = np.linspace(x_range[0], x_range[-1], nx) - phi = np.linspace(phi_range[0], phi_range[-1],ny) + phi = np.linspace(phi_range[0], phi_range[-1], ny) z = np.linspace(z_range[0], z_range[-1], nz) ## make those 1D arrays 3D - rarray,yarray,zarray = np.meshgrid(r,phi,z,indexing='ij') - + rarray, yarray, zarray = np.meshgrid(r, phi, z, indexing="ij") + ## call vacuum field values - b_vmec = self.field_values(rarray,yarray,zarray,vmec_id) + b_vmec = self.field_values(rarray, yarray, zarray, vmec_id) Bx_vmec = b_vmec[0] By_vmec = b_vmec[1] Bz_vmec = b_vmec[2] # Now we have a field and regular grid in (R,Z,phi) so # we can get an interpolation function in 3D - points = (r,phi,z) - - self.br_interp = RegularGridInterpolator(points, Bx_vmec, bounds_error=False, fill_value=0.0) - self.bz_interp = RegularGridInterpolator(points, Bz_vmec, bounds_error=False, fill_value=0.0) - self.bphi_interp = RegularGridInterpolator(points, By_vmec, bounds_error=False, fill_value=1.0) + points = (r, phi, z) - def field_values(self, r,phi,z, vmec_id='w7x_ref_171'): + self.br_interp = RegularGridInterpolator( + points, Bx_vmec, bounds_error=False, fill_value=0.0 + ) + self.bz_interp = RegularGridInterpolator( + points, Bz_vmec, bounds_error=False, fill_value=0.0 + ) + self.bphi_interp = RegularGridInterpolator( + points, By_vmec, bounds_error=False, fill_value=1.0 + ) + + def field_values(self, r, phi, z, vmec_id="w7x_ref_171"): from osa import Client - vmec = Client('http://esb:8280/services/vmec_v5?wsdl') + + vmec = Client("http://esb:8280/services/vmec_v5?wsdl") pos = vmec.types.Points3D() - pos.x1 = np.ndarray.flatten(np.ones((self.nx,self.ny,self.nz))*r*np.cos(phi)) #x in Cartesian (real-space) - pos.x2 = np.ndarray.flatten(np.ones((self.nx,self.ny,self.nz))*r*np.sin(phi)) #y in Cartesian (real-space) - pos.x3 = np.ndarray.flatten(z) #z in Cartesian (real-space) + pos.x1 = np.ndarray.flatten( + np.ones((self.nx, self.ny, self.nz)) * r * np.cos(phi) + ) # x in Cartesian (real-space) + pos.x2 = np.ndarray.flatten( + np.ones((self.nx, self.ny, self.nz)) * r * np.sin(phi) + ) # y in Cartesian (real-space) + pos.x3 = np.ndarray.flatten(z) # z in Cartesian (real-space) b = vmec.service.magneticField(str(vmec_id), pos) ## Reshape to 3d array - Bx = np.ndarray.reshape(np.asarray(b.field.x1),(self.nx,self.ny,self.nz)) - By = np.ndarray.reshape(np.asarray(b.field.x2),(self.nx,self.ny,self.nz)) - Bz = np.ndarray.reshape(np.asarray(b.field.x3), (self.nx,self.ny,self.nz)) - + Bx = np.ndarray.reshape(np.asarray(b.field.x1), (self.nx, self.ny, self.nz)) + By = np.ndarray.reshape(np.asarray(b.field.x2), (self.nx, self.ny, self.nz)) + Bz = np.ndarray.reshape(np.asarray(b.field.x3), (self.nx, self.ny, self.nz)) + ## Convert to cylindrical coordinates - Br = Bx*np.cos(phi) + By*np.sin(phi) - Bphi = -Bx*np.sin(phi) + By*np.cos(phi) + Br = Bx * np.cos(phi) + By * np.sin(phi) + Bphi = -Bx * np.sin(phi) + By * np.cos(phi) return Br, Bphi, Bz def Bxfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) - return self.br_interp((x,phi,z)) + phi = np.mod(phi, 2.0 * np.pi) + return self.br_interp((x, phi, z)) def Bzfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) - return self.bz_interp((x,phi,z)) + phi = np.mod(phi, 2.0 * np.pi) + return self.bz_interp((x, phi, z)) def Byfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) # Interpolate to get flux surface normalised psi - return self.bphi_interp((x,phi,z)) - + return self.bphi_interp((x, phi, z)) + def Rfunc(self, x, z, phi): - phi = np.mod(phi, 2.*np.pi) + phi = np.mod(phi, 2.0 * np.pi) return x From 849c498211a8c8cd7f5daf71c4e1212006f1d25d Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Wed, 6 Jan 2021 10:33:57 +0000 Subject: [PATCH 244/293] Throw in Vol_Integral if using 3D metrics --- src/physics/smoothing.cxx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/physics/smoothing.cxx b/src/physics/smoothing.cxx index 2a53eaedc3..465cedcce6 100644 --- a/src/physics/smoothing.cxx +++ b/src/physics/smoothing.cxx @@ -32,6 +32,8 @@ #include +#include "bout/build_config.hxx" + #include #include #include @@ -320,12 +322,11 @@ BoutReal Average_XY(const Field2D &var) { return Vol_Glb; } -BoutReal Average_XY(const Field3D&) { - AUTO_TRACE(); - throw BoutException("Average_XY(Field3D) not yet implemented."); -} - BoutReal Vol_Integral(const Field2D &var) { +#if BOUT_USE_METRIC_3D + AUTO_TRACE(); + throw BoutException("Vol_Intregral currently incompatible with 3D metrics"); +#else Mesh *mesh = var.getMesh(); BoutReal Int_Glb; Coordinates *metric = var.getCoordinates(); @@ -338,6 +339,7 @@ BoutReal Vol_Integral(const Field2D &var) { * (mesh->GlobalNy-mesh->numberOfYBoundaries()*2*mesh->ystart)) * PI * 2.; return Int_Glb; +#endif } const Field3D smoothXY(const Field3D &f) { From af4f5cce84422893df5c0d632ce767e62b2edc20 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 14:58:30 +0000 Subject: [PATCH 245/293] Partial revert of ca8c533, unused Regions --- src/mesh/mesh.cxx | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index 33c88654fb..c53fe8d930 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -541,13 +541,6 @@ void Mesh::createDefaultRegions(){ (getRegion3D("RGN_NOBNDRY") + getRegion3D("RGN_XGUARDS") + getRegion3D("RGN_YGUARDS") + getRegion3D("RGN_ZGUARDS")).unique()); - addRegion3D("RGN_UPPER_Y_THIN", - Region(xstart, xend, yend + 1, yend + 1, 0, LocalNz - 1, LocalNy, - LocalNz, maxregionblocksize)); - addRegion3D("RGN_LOWER_Y_THIN", - Region(xstart, xend, ystart + 1, ystart + 1, 0, LocalNz - 1, LocalNy, - LocalNz, maxregionblocksize)); - //2D regions addRegion2D("RGN_ALL", Region(0, LocalNx - 1, 0, LocalNy - 1, 0, 0, LocalNy, 1, maxregionblocksize)); @@ -576,11 +569,6 @@ void Mesh::createDefaultRegions(){ (getRegion2D("RGN_NOBNDRY") + getRegion2D("RGN_XGUARDS") + getRegion2D("RGN_YGUARDS") + getRegion2D("RGN_ZGUARDS")).unique()); - addRegion2D("RGN_UPPER_Y_THIN", Region(xstart, xend, yend + 1, yend + 1, 0, -1, - LocalNy, 1, maxregionblocksize)); - addRegion2D("RGN_LOWER_Y_THIN", Region(xstart, xend, ystart + 1, ystart + 1, 0, - -1, LocalNy, 1, maxregionblocksize)); - // Perp regions addRegionPerp("RGN_ALL", Region(0, LocalNx - 1, 0, 0, 0, LocalNz - 1, 1, LocalNz, maxregionblocksize)); From 1e8d09f24298493c06f4b9898a0b965c506d1e52 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 15:12:17 +0000 Subject: [PATCH 246/293] Delete some commented out code in laplacexz-petsc --- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index 1db03ff84e..91a229620a 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -467,8 +467,6 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { } { // x+1/2, z-1/2 - // J = 0.5*(coords->J(x,y,z) + coords->J(x+1,y,z)); - // g13 = 0.5*(coords->gxz(x,y,z) + coords->gxz(x+1,y,z)); const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); const BoutReal val = @@ -550,28 +548,6 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { } } - ///////////// OLDER CODE ///////////////// - // Note that because metrics are constant in Z many terms cancel - - // // Wrap around z-1 and z+1 indices - // // int zminus = (z - 1 + (localmesh->LocalNz)) % (localmesh->LocalNz); - // // int zplus = (z + 1) % (localmesh->LocalNz); - - // // Metrics on z+1/2 boundary - // Acoef = 0.5*(A(x,y,z) + A(x,y,z+1)); - - // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); - // zp = val; - // c -= val; - - // // Metrics on z-1/2 boundary - // Acoef = 0.5*(A(x,y,z) + A(x,y,z-1)); - - // val = Acoef * coords->gzz(x,y,z) / (coords->dz(x,y,z)*coords->dz(x,y,z)); - // zm = val; - // c -= val; - ////////////////////////////////////////// - // B term c += B(x,y,z); From 7f5051a22203bec09f8d5265436a78b41040e9a0 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 15:28:15 +0000 Subject: [PATCH 247/293] Apply clang-format to 3D metric branch --- include/bout/coordinates.hxx | 40 ++++----- include/bout/paralleltransform.hxx | 4 +- include/derivs.hxx | 86 +++++++++---------- include/difops.hxx | 73 +++++++--------- include/vector2d.hxx | 5 +- src/field/vecops.cxx | 26 +++--- src/fileio/impls/netcdf/nc_format.cxx | 4 +- src/fileio/impls/netcdf4/ncxx4.cxx | 1 - .../laplace/impls/cyclic/cyclic_laplace.cxx | 2 +- .../laplace/impls/cyclic/cyclic_laplace.hxx | 4 +- .../iterative_parallel_tri.cxx | 2 +- .../iterative_parallel_tri.hxx | 4 +- .../impls/multigrid/multigrid_laplace.cxx | 2 +- .../impls/multigrid/multigrid_laplace.hxx | 2 +- .../laplace/impls/serial_band/serial_band.cxx | 12 +-- .../laplace/impls/serial_band/serial_band.hxx | 2 +- src/invert/laplace/invert_laplace.cxx | 1 - .../impls/cyclic/laplacexz-cyclic.cxx | 2 +- src/invert/parderiv/impls/cyclic/cyclic.cxx | 10 +-- src/invert/parderiv/impls/cyclic/cyclic.hxx | 5 +- src/mesh/boundary_standard.cxx | 51 +++++------ src/mesh/coordinates.cxx | 60 +++++++------ src/mesh/difops.cxx | 34 ++++---- src/mesh/fv_ops.cxx | 85 +++++++++--------- src/mesh/mesh.cxx | 4 +- src/mesh/parallel/fci.cxx | 7 +- src/mesh/parallel/fci.hxx | 20 +++-- src/solver/solver.cxx | 2 +- src/sys/derivs.cxx | 68 ++++++--------- .../test-laplacexz/test-laplacexz.cxx | 6 +- tests/unit/field/test_field_factory.cxx | 6 +- tests/unit/mesh/data/test_gridfromoptions.cxx | 15 ++-- 32 files changed, 311 insertions(+), 334 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 9c285ac60a..c61a5dd7d6 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -138,9 +138,7 @@ public: /// Return if the metrics are 3D // needs to be static for old gcc - static constexpr bool is3D() { - return bout::build::use_metric_3d; - } + static constexpr bool is3D() { return bout::build::use_metric_3d; } /////////////////////////////////////////////////////////// // Parallel transforms @@ -196,18 +194,18 @@ public: #endif FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, FieldMetric, Field2D); FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, FieldMetric, Field2D); FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, FieldMetric, Field2D); Field3D DDX(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, @@ -224,7 +222,7 @@ public: /// Gradient along magnetic field b.Grad(f) FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); + const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Grad_par, FieldMetric, Field2D); Field3D Grad_par(const Field3D& var, CELL_LOC outloc = CELL_DEFAULT, @@ -233,12 +231,11 @@ public: /// Advection along magnetic field V*b.Grad(f) FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); - [[deprecated( - "Please use Coordinates::Vpar_Grad_par(const Field2D& v, " - "const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " - "const std::string& method = \"DEFAULT\") instead")]] inline FieldMetric + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); + [[deprecated("Please use Coordinates::Vpar_Grad_par(const Field2D& v, " + "const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, " + "const std::string& method = \"DEFAULT\") instead")]] inline FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } @@ -255,7 +252,7 @@ public: /// Divergence along magnetic field Div(b*f) = B.Grad(f/B) FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); + const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Div_par, FieldMetric, Field2D); Field3D Div_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, @@ -264,7 +261,7 @@ public: // Second derivative along magnetic field FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); + const std::string& method = "DEFAULT"); GRAD_FUNC_REGION_ENUM_TO_STRING(Grad2_par2, FieldMetric, Field2D); Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, @@ -277,8 +274,7 @@ public: // Perpendicular Laplacian operator, using only X-Z derivatives // NOTE: This might be better bundled with the Laplacian inversion code // since it makes use of the same coefficients and FFT routines - FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - bool useFFT = true); + FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); @@ -289,8 +285,8 @@ public: // Full Laplacian operator on scalar field FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_conditions = "free_o3", - const std::string& dfdy_dy_region = ""); + const std::string& dfdy_boundary_conditions = "free_o3", + const std::string& dfdy_dy_region = ""); Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_conditions = "free_o3", const std::string& dfdy_dy_region = ""); diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index e206f06e9f..2aaa038ead 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -79,11 +79,11 @@ public: /// Field2D are axisymmetric, so transformation to or from field-aligned coordinates is /// a null operation. - virtual const Field2D toFieldAligned(const Field2D &f, + virtual const Field2D toFieldAligned(const Field2D& f, const std::string& UNUSED(region) = "RGN_ALL") { return f; } - virtual const Field2D fromFieldAligned(const Field2D &f, + virtual const Field2D fromFieldAligned(const Field2D& f, const std::string& UNUSED(region) = "RGN_ALL") { return f; } diff --git a/include/derivs.hxx b/include/derivs.hxx index 95939b5c09..0b77834499 100644 --- a/include/derivs.hxx +++ b/include/derivs.hxx @@ -107,8 +107,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDX, Field2D, Coordinates::FieldMetric) /// Calculate first partial derivative in Y @@ -140,8 +140,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric DDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDY, Field2D, Coordinates::FieldMetric) /// Calculate first partial derivative in Z @@ -173,8 +173,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric DDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(DDZ, Field2D, Coordinates::FieldMetric) /// Calculate first partial derivative in Z @@ -240,8 +240,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D2DX2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DX2, Field2D, Coordinates::FieldMetric) /// Calculate second partial derivative in Y @@ -273,8 +273,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D2DY2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DY2, Field2D, Coordinates::FieldMetric) /// Calculate second partial derivative in Z @@ -306,8 +306,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D2DZ2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DZ2, Field2D, Coordinates::FieldMetric) ////////// FOURTH DERIVATIVES ////////// @@ -341,8 +341,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D4DX4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D4DX4, Field2D, Coordinates::FieldMetric) /// Calculate forth partial derivative in Y @@ -374,8 +374,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D4DY4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D4DY4, Field2D, Coordinates::FieldMetric) /// Calculate forth partial derivative in Z @@ -407,8 +407,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D4DZ4, Field2D, Coordinates::FieldMetric) /// For terms of form v * grad(f) @@ -442,9 +442,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Field3D, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDX, Coordinates::FieldMetric, Field2D, Field2D) /// For terms of form v * grad(f) @@ -478,9 +478,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Field3D, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric VDDY(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDY, Coordinates::FieldMetric, Field2D, Field2D) /// For terms of form v * grad(f) @@ -514,9 +514,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Field3D, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric VDDZ(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::FieldMetric, Field2D, Field2D) /// For terms of form v * grad(f) @@ -533,9 +533,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::FieldMetric, Field2D, Field /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric VDDZ(const Field3D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(VDDZ, Coordinates::FieldMetric, Field3D, Field2D) /// for terms of form div(v * f) @@ -569,9 +569,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Field3D, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDX, Coordinates::FieldMetric, Field2D, Field2D) /// for terms of form div(v * f) @@ -605,9 +605,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Field3D, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric FDDY(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDY, Coordinates::FieldMetric, Field2D, Field2D) /// for terms of form div(v * f) @@ -641,9 +641,9 @@ VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Field3D, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric FDDZ(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); VDERIV_FUNC_REGION_ENUM_TO_STRING(FDDZ, Coordinates::FieldMetric, Field2D, Field2D) /// Calculate mixed partial derivative in x and y @@ -765,8 +765,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D2DXDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DXDZ, Field2D, Coordinates::FieldMetric) /// Calculate mixed partial derivative in y and z @@ -798,8 +798,8 @@ DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field3D, Field3D) /// @param[in] region What region is expected to be calculated /// If not given, defaults to RGN_NOBNDRY Coordinates::FieldMetric D2DYDZ(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); + const std::string& method = "DEFAULT", + const std::string& region = "RGN_NOBNDRY"); DERIV_FUNC_REGION_ENUM_TO_STRING(D2DYDZ, Field2D, Coordinates::FieldMetric) #undef DERIV_FUNC_REGION_ENUM_TO_STRING diff --git a/include/difops.hxx b/include/difops.hxx index 73eb5b7631..5644793c09 100644 --- a/include/difops.hxx +++ b/include/difops.hxx @@ -53,19 +53,18 @@ * enabled) * @param[in] method The method to use. The default is set in the options. */ -Coordinates::FieldMetric Grad_par(const Field2D& var, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); DEPRECATED(Coordinates::FieldMetric Grad_par(const Field2D& var, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); inline Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc, - DIFF_METHOD method) { + DIFF_METHOD method) { return Grad_par(var, outloc, toString(method)); } DEPRECATED(inline Coordinates::FieldMetric Grad_par(const Field2D& var, - DIFF_METHOD method, - CELL_LOC outloc)) { + DIFF_METHOD method, + CELL_LOC outloc)) { return Grad_par(var, outloc, toString(method)); } @@ -109,14 +108,13 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f); * */ Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, - const Field2D& f, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); + CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); +DEPRECATED(Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, + const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); inline Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc, DIFF_METHOD method) { + CELL_LOC outloc, DIFF_METHOD method) { return Vpar_Grad_par(v, f, outloc, toString(method)); } DEPRECATED(inline Coordinates::FieldMetric Vpar_Grad_par( @@ -151,17 +149,15 @@ DEPRECATED(inline Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, * */ Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); -DEPRECATED(Coordinates::FieldMetric Div_par(const Field2D& f, - const std::string& method, - CELL_LOC outloc = CELL_DEFAULT)); + const std::string& method = "DEFAULT"); +DEPRECATED(Coordinates::FieldMetric Div_par(const Field2D& f, const std::string& method, + CELL_LOC outloc = CELL_DEFAULT)); inline Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { + DIFF_METHOD method) { return Div_par(f, outloc, toString(method)); } -DEPRECATED(inline Coordinates::FieldMetric Div_par(const Field2D& f, - DIFF_METHOD method, - CELL_LOC outloc)) { +DEPRECATED(inline Coordinates::FieldMetric Div_par(const Field2D& f, DIFF_METHOD method, + CELL_LOC outloc)) { return Div_par(f, outloc, toString(method)); } @@ -211,11 +207,10 @@ DEPRECATED(inline Field3D Div_par_flux(const Field3D& v, const Field3D& f, * @param[in] f The field to be differentiated * @param[in] outloc The cell location of the result */ -Coordinates::FieldMetric Grad2_par2(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT"); +Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& method = "DEFAULT"); inline Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc, - DIFF_METHOD method) { + DIFF_METHOD method) { return Grad2_par2(f, outloc, toString(method)); } @@ -304,10 +299,10 @@ Div_par_CtoL(const Field2D& var) { * @param[in] f The field whose gradient drives a flux */ Coordinates::FieldMetric Div_par_K_Grad_par(BoutReal kY, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); + CELL_LOC outloc = CELL_DEFAULT); Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); Coordinates::FieldMetric Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); + CELL_LOC outloc = CELL_DEFAULT); Field3D Div_par_K_Grad_par(const Field2D& kY, const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Div_par_K_Grad_par(const Field3D& kY, const Field2D& f, @@ -325,7 +320,7 @@ Field3D Div_par_K_Grad_par(const Field3D& kY, const Field3D& f, * For the full perpendicular Laplacian, use Laplace_perp */ Coordinates::FieldMetric Delp2(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - bool useFFT = true); + bool useFFT = true); Field3D Delp2(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc = CELL_DEFAULT, bool useFFT = true); @@ -346,17 +341,15 @@ Field3D Laplace_perp(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, * Parallel Laplacian operator * */ -Coordinates::FieldMetric Laplace_par(const Field2D& f, - CELL_LOC outloc = CELL_DEFAULT); +Coordinates::FieldMetric Laplace_par(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT); Field3D Laplace_par(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT); /*! * Full Laplacian operator (par + perp) */ -Coordinates::FieldMetric -Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& dfdy_boundary_condition = "free_o3", - const std::string& dfdy_region = ""); +Coordinates::FieldMetric Laplace(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, + const std::string& dfdy_boundary_condition = "free_o3", + const std::string& dfdy_region = ""); Field3D Laplace(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, const std::string& dfdy_boundary_condition = "free_o3", const std::string& dfdy_region = ""); @@ -371,7 +364,7 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f); * */ Coordinates::FieldMetric b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, - CELL_LOC outloc = CELL_DEFAULT); + CELL_LOC outloc = CELL_DEFAULT); /*! * Terms of form @@ -424,9 +417,9 @@ constexpr BRACKET_METHOD BRACKET_ARAKAWA_OLD = BRACKET_METHOD::arakawa_old; * */ Coordinates::FieldMetric bracket(const Field2D& f, const Field2D& g, - BRACKET_METHOD method = BRACKET_STD, - CELL_LOC outloc = CELL_DEFAULT, - Solver* solver = nullptr); + BRACKET_METHOD method = BRACKET_STD, + CELL_LOC outloc = CELL_DEFAULT, + Solver* solver = nullptr); Field3D bracket(const Field2D& f, const Field3D& g, BRACKET_METHOD method = BRACKET_STD, CELL_LOC outloc = CELL_DEFAULT, Solver* solver = nullptr); Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method = BRACKET_STD, diff --git a/include/vector2d.hxx b/include/vector2d.hxx index f6751247bd..9722c0709e 100644 --- a/include/vector2d.hxx +++ b/include/vector2d.hxx @@ -128,8 +128,7 @@ public: const Vector2D operator/(const Field2D &rhs) const; ///< Divides all components by \p rhs const Vector3D operator/(const Field3D &rhs) const; ///< Divides all components by \p rhs - const Coordinates::FieldMetric - operator*(const Vector2D& rhs) const; ///< Dot product + const Coordinates::FieldMetric operator*(const Vector2D& rhs) const; ///< Dot product const Field3D operator*(const Vector3D &rhs) const; ///< Dot product /*! @@ -182,7 +181,7 @@ const Vector3D cross(const Vector2D & lhs, const Vector3D &rhs); * |v| = sqrt( v dot v ) */ const Coordinates::FieldMetric abs(const Vector2D& v, - const std::string& region = "RGN_ALL"); + const std::string& region = "RGN_ALL"); [[deprecated( "Please use Vector2D abs(const Vector2D& f, " "const std::string& region = \"RGN_ALL\") instead")]] inline const Coordinates:: diff --git a/src/field/vecops.cxx b/src/field/vecops.cxx index 978fba84f5..71091500fc 100644 --- a/src/field/vecops.cxx +++ b/src/field/vecops.cxx @@ -67,7 +67,7 @@ Vector2D Grad(const Field2D& f, CELL_LOC outloc, const std::string& method) { return result; } -Vector3D Grad(const Field3D &f, CELL_LOC outloc, const std::string& method) { +Vector3D Grad(const Field3D& f, CELL_LOC outloc, const std::string& method) { TRACE("Grad( Field3D )"); SCOREP0(); CELL_LOC outloc_x, outloc_y, outloc_z; @@ -96,7 +96,7 @@ Vector3D Grad(const Field3D &f, CELL_LOC outloc, const std::string& method) { return result; } -Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc, const std::string& method) { +Vector3D Grad_perp(const Field3D& f, CELL_LOC outloc, const std::string& method) { TRACE("Grad_perp( Field3D )"); SCOREP0(); ASSERT1(outloc == CELL_DEFAULT || outloc == f.getLocation()); @@ -118,7 +118,7 @@ Vector3D Grad_perp(const Field3D &f, CELL_LOC outloc, const std::string& method) return result; } -Vector2D Grad_perp(const Field2D &f, CELL_LOC outloc, const std::string& method) { +Vector2D Grad_perp(const Field2D& f, CELL_LOC outloc, const std::string& method) { AUTO_TRACE(); SCOREP0(); ASSERT1(outloc == CELL_DEFAULT || outloc == f.getLocation()); @@ -189,7 +189,7 @@ Field3D Div(const Vector3D& v, CELL_LOC outloc, const std::string& method) { auto vcnJy = vcn.y.getCoordinates()->J * vcn.y; if (v.y.hasParallelSlices()) { - // If v.y has parallel slices then we are using ShiftedMetric (with + // If v.y has parallel slices then we are using ShiftedMetric (with // mesh:calcParallelSlices_on_communicate=true) or FCI, so we should calculate // parallel slices for vcnJy in order to calculate the parallel derivative DDY vcnJy.calcParallelSlices(); @@ -263,7 +263,7 @@ Field3D Div(const Vector3D& v, const Field3D& f, CELL_LOC outloc, * Curl operators **************************************************************************/ -Vector2D Curl(const Vector2D &v) { +Vector2D Curl(const Vector2D& v) { TRACE("Curl( Vector2D )"); @@ -291,7 +291,7 @@ Vector2D Curl(const Vector2D &v) { return result; } -Vector3D Curl(const Vector3D &v) { +Vector3D Curl(const Vector3D& v) { TRACE("Curl( Vector3D )"); SCOREP0(); ASSERT1(v.getLocation() != CELL_VSHIFT); @@ -333,7 +333,7 @@ Coordinates::FieldMetric V_dot_Grad(const Vector2D& v, const Field2D& f) { return VDDX(vcn.x, f) + VDDY(vcn.y, f) + VDDZ(vcn.z, f); } -Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { +Field3D V_dot_Grad(const Vector2D& v, const Field3D& f) { TRACE("V_dot_Grad( Vector2D , Field3D )"); SCOREP0(); @@ -344,7 +344,7 @@ Field3D V_dot_Grad(const Vector2D &v, const Field3D &f) { return VDDX(vcn.x, f) + VDDY(vcn.y, f) + VDDZ(vcn.z, f); } -Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { +Field3D V_dot_Grad(const Vector3D& v, const Field2D& f) { TRACE("V_dot_Grad( Vector3D , Field2D )"); SCOREP0(); @@ -355,7 +355,7 @@ Field3D V_dot_Grad(const Vector3D &v, const Field2D &f) { return VDDX(vcn.x, f) + VDDY(vcn.y, f) + VDDZ(vcn.z, f); } -Field3D V_dot_Grad(const Vector3D &v, const Field3D &f) { +Field3D V_dot_Grad(const Vector3D& v, const Field3D& f) { TRACE("V_dot_Grad( Vector3D , Field3D )"); SCOREP0(); @@ -440,15 +440,15 @@ R V_dot_Grad(const T &v, const F &a) { } // Implement vector-vector operation in terms of templated routine above -Vector2D V_dot_Grad(const Vector2D &v, const Vector2D &a) { +Vector2D V_dot_Grad(const Vector2D& v, const Vector2D& a) { return V_dot_Grad(v, a); } -Vector3D V_dot_Grad(const Vector2D &v, const Vector3D &a) { +Vector3D V_dot_Grad(const Vector2D& v, const Vector3D& a) { return V_dot_Grad(v, a); } -Vector3D V_dot_Grad(const Vector3D &v, const Vector2D &a) { +Vector3D V_dot_Grad(const Vector3D& v, const Vector2D& a) { return V_dot_Grad(v, a); } -Vector3D V_dot_Grad(const Vector3D &v, const Vector3D &a) { +Vector3D V_dot_Grad(const Vector3D& v, const Vector3D& a) { return V_dot_Grad(v, a); } diff --git a/src/fileio/impls/netcdf/nc_format.cxx b/src/fileio/impls/netcdf/nc_format.cxx index a9ebb520a0..89d136703b 100644 --- a/src/fileio/impls/netcdf/nc_format.cxx +++ b/src/fileio/impls/netcdf/nc_format.cxx @@ -28,10 +28,10 @@ #include #include -#include #include "bout/build_config.hxx" -#include +#include #include +#include using std::string; using std::vector; diff --git a/src/fileio/impls/netcdf4/ncxx4.cxx b/src/fileio/impls/netcdf4/ncxx4.cxx index 5d6c0cd901..85c2acdef2 100644 --- a/src/fileio/impls/netcdf4/ncxx4.cxx +++ b/src/fileio/impls/netcdf4/ncxx4.cxx @@ -1417,4 +1417,3 @@ std::vector Ncxx4::getRecDimVec(int nd) { } #endif // BOUT_HAS_NETCDF - diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx index 2df2e70953..3ebc2ad221 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.cxx @@ -33,8 +33,8 @@ * */ -#include "bout/build_config.hxx" #include "cyclic_laplace.hxx" +#include "bout/build_config.hxx" #if not BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx b/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx index 1a718d4918..d8c2a1abe3 100644 --- a/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx +++ b/src/invert/laplace/impls/cyclic/cyclic_laplace.hxx @@ -31,12 +31,12 @@ class LaplaceCyclic; #ifndef __LAP_CYCLIC_H__ #define __LAP_CYCLIC_H__ -#include "bout/build_config.hxx" #include "invert_laplace.hxx" +#include "bout/build_config.hxx" #if BOUT_USE_METRIC_3D -namespace{ +namespace { RegisterUnavailableLaplace registerlaplacecycle(LAPLACE_CYCLIC, "BOUT++ was configured with 3D metrics"); } diff --git a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx index 36b2064c2d..29a6bcb5cf 100644 --- a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx +++ b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.cxx @@ -24,8 +24,8 @@ * **************************************************************************/ -#include "bout/build_config.hxx" #include "iterative_parallel_tri.hxx" +#include "bout/build_config.hxx" #if not BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx index f457761f87..062daa575a 100644 --- a/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx +++ b/src/invert/laplace/impls/iterative_parallel_tri/iterative_parallel_tri.hxx @@ -29,12 +29,12 @@ class LaplaceIPT; #ifndef __IPT_H__ #define __IPT_H__ -#include "bout/build_config.hxx" #include "invert_laplace.hxx" +#include "bout/build_config.hxx" #if BOUT_USE_METRIC_3D -namespace{ +namespace { RegisterUnavailableLaplace registerlaplaceipt(LAPLACE_IPT, "BOUT++ was configured with 3D metrics"); } diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx index dc6fd4ec4b..03926fa1c6 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.cxx @@ -27,8 +27,8 @@ * **************************************************************************/ -#include "bout/build_config.hxx" #include "multigrid_laplace.hxx" +#include "bout/build_config.hxx" #if not BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx b/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx index 0d5ac653f8..aa2b675082 100644 --- a/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx +++ b/src/invert/laplace/impls/multigrid/multigrid_laplace.hxx @@ -31,8 +31,8 @@ #ifndef __MULTIGRID_LAPLACE_H__ #define __MULTIGRID_LAPLACE_H__ -#include "bout/build_config.hxx" #include "invert_laplace.hxx" +#include "bout/build_config.hxx" #if BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/impls/serial_band/serial_band.cxx b/src/invert/laplace/impls/serial_band/serial_band.cxx index bbeb202d99..66ccc15ecb 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.cxx +++ b/src/invert/laplace/impls/serial_band/serial_band.cxx @@ -24,19 +24,19 @@ * **************************************************************************/ -#include "bout/build_config.hxx" #include "serial_band.hxx" +#include "bout/build_config.hxx" #if not BOUT_USE_METRIC_3D -#include +#include #include -#include -#include +#include #include +#include +#include #include -#include -#include +#include #include diff --git a/src/invert/laplace/impls/serial_band/serial_band.hxx b/src/invert/laplace/impls/serial_band/serial_band.hxx index aeea2d172e..a856a0566f 100644 --- a/src/invert/laplace/impls/serial_band/serial_band.hxx +++ b/src/invert/laplace/impls/serial_band/serial_band.hxx @@ -29,8 +29,8 @@ class LaplaceSerialBand; #ifndef __SERIAL_BAND_H__ #define __SERIAL_BAND_H__ -#include "bout/build_config.hxx" #include "invert_laplace.hxx" +#include "bout/build_config.hxx" #if BOUT_USE_METRIC_3D diff --git a/src/invert/laplace/invert_laplace.cxx b/src/invert/laplace/invert_laplace.cxx index 4a60401f91..5b3eb2fcc5 100644 --- a/src/invert/laplace/invert_laplace.cxx +++ b/src/invert/laplace/invert_laplace.cxx @@ -746,7 +746,6 @@ void Laplacian::tridagMatrix(dcomplex *avec, dcomplex *bvec, dcomplex *cvec, } #endif - /********************************************************************************** * LEGACY INTERFACE * diff --git a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx index 6bb3e90e67..e8c925fcf2 100644 --- a/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx +++ b/src/invert/laplacexz/impls/cyclic/laplacexz-cyclic.cxx @@ -1,5 +1,5 @@ -#include "bout/build_config.hxx" #include "laplacexz-cyclic.hxx" +#include "bout/build_config.hxx" #if not BOUT_USE_METRIC_3D diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index db16930210..f3e9237ad4 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -35,8 +35,8 @@ * ************************************************************************/ -#include "bout/build_config.hxx" #include "cyclic.hxx" +#include "bout/build_config.hxx" #if not BOUT_USE_METRIC_3D @@ -183,15 +183,15 @@ const Field3D InvertParCR::solve(const Field3D &f) { bout::globals::mpi->MPI_Comm_rank(surf.communicator(), &rank); bout::globals::mpi->MPI_Comm_size(surf.communicator(), &np); - if(rank == 0) { - for(int k=0; kLocalNy - 2 * localmesh->ystart - 1) *= phase; diff --git a/src/invert/parderiv/impls/cyclic/cyclic.hxx b/src/invert/parderiv/impls/cyclic/cyclic.hxx index f1fa8c7021..d7db822adb 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.hxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.hxx @@ -42,13 +42,14 @@ #ifndef __INV_PAR_CR_H__ #define __INV_PAR_CR_H__ -#include "bout/build_config.hxx" #include "invert_parderiv.hxx" +#include "bout/build_config.hxx" #if BOUT_USE_METRIC_3D namespace { -RegisterUnavailableInvertPar registerinvertparcyclic{PARDERIVCYCLIC, "BOUT++ was configured with 3D metrics"}; +RegisterUnavailableInvertPar registerinvertparcyclic{ + PARDERIVCYCLIC, "BOUT++ was configured with 3D metrics"}; } #else diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index d3e49f9775..098885847b 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1887,8 +1887,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2126,9 +2126,9 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y, zk) + bndry->by * metric->dy(bndry->x, bndry->y, zk); #else - BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) - + bndry->by * metric->dy(bndry->x, bndry->y); - for (int zk = 0; zk < mesh->LocalNz; zk++) { + BoutReal delta = bndry->bx * metric->dx(bndry->x, bndry->y) + + bndry->by * metric->dy(bndry->x, bndry->y); + for (int zk = 0; zk < mesh->LocalNz; zk++) { #endif if (fg) { val = fg->generate(Context(bndry, zk, loc, t, mesh)); @@ -2223,8 +2223,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2328,8 +2328,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { // cell } #else - throw BoutException("void BoundaryNeumann_4thOrder::apply(Field2D& f) not " - "implemented with 3D metrics"); + throw BoutException("void BoundaryNeumann_4thOrder::apply(Field2D& f) not " + "implemented with 3D metrics"); #endif } @@ -2397,8 +2397,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { * sqrt(metric->g_22(bndry->x, bndry->y) / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2549,8 +2549,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2610,8 +2610,9 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " - "ZeroLaplace case."); + throw BoutException( + "Applying boundary to Field3D not compatible with 3D metrics in " + "ZeroLaplace case."); #endif } @@ -2652,8 +2653,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException( + "Applying boundary to Field2D not compatible with 3D metrics in all cases."); #endif } @@ -2710,8 +2711,9 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " - "ZeroLaplace2 case."); + throw BoutException( + "Applying boundary to Field3D not compatible with 3D metrics in " + "ZeroLaplace2 case."); #endif } @@ -2812,7 +2814,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { for (int jz = 1; jz <= ncz / 2; jz++) { BoutReal kwave = jz * 2.0 * PI / getUniform(metric->zlength()); // wavenumber in [rad^-1] - c0[jz] *= exp(coef * kwave); // The decaying solution only + c0[jz] *= exp(coef * kwave); // The decaying solution only // Add the particular solution c2[jz] = c0[jz] - c1[jz] / (metric->g33(x - bx, y) * kwave * kwave); } @@ -2825,8 +2827,9 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException("Applying boundary to Field3D not compatible with 3D metrics in " - "ConstLaplace case."); + throw BoutException( + "Applying boundary to Field3D not compatible with 3D metrics in " + "ConstLaplace case."); #endif } @@ -2937,8 +2940,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Vector3D not compatible with 3D metrics in DivCurl."); + throw BoutException( + "Applying boundary to Vector3D not compatible with 3D metrics in DivCurl."); #endif } diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 450ac9b13e..1c9309a3c1 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -315,7 +315,7 @@ int getAtLoc(Mesh* mesh, Coordinates::FieldMetric& var, const std::string& name, const std::string& suffix, CELL_LOC location, BoutReal default_value = 0.) { checkStaggeredGet(mesh, name, suffix); - int result = mesh->get(var, name+suffix, default_value, false, location); + int result = mesh->get(var, name + suffix, default_value, false, location); return result; } @@ -326,7 +326,8 @@ int getAtLocAndFillGuards(Mesh* mesh, Coordinates::FieldMetric& var, bool extrapolate_y, bool no_extra_interpolate, ParallelTransform* pt) { auto ret = getAtLoc(mesh, var, name, suffix, location, default_value); - var = interpolateAndExtrapolate(var, location, extrapolate_x, extrapolate_y, no_extra_interpolate, pt); + var = interpolateAndExtrapolate(var, location, extrapolate_x, extrapolate_y, + no_extra_interpolate, pt); return ret; } @@ -342,8 +343,8 @@ std::string getLocationSuffix(CELL_LOC location) { return "_ylow"; } case CELL_ZLOW: { - // in 2D metric, same as CELL_CENTRE - return bout::build::use_metric_3d ? "_zlow" : ""; + // in 2D metric, same as CELL_CENTRE + return bout::build::use_metric_3d ? "_zlow" : ""; } default: { throw BoutException("Incorrect location passed to " @@ -745,8 +746,8 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, dz = interpolateAndExtrapolate(dz, location, extrapolate_x, extrapolate_y, false, transform.get()); - getAtLocAndFillGuards(mesh, dx, "dx", suffix, location, 1.0, extrapolate_x, extrapolate_y, false, - transform.get()); + getAtLocAndFillGuards(mesh, dx, "dx", suffix, location, 1.0, extrapolate_x, + extrapolate_y, false, transform.get()); if (mesh->periodicX) { communicate(dx); @@ -1226,7 +1227,7 @@ int Coordinates::geometry(bool recalculate_staggered, bool extrapolate_x = not localmesh->sourceHasXBoundaryGuards(); bool extrapolate_y = not localmesh->sourceHasYBoundaryGuards(); - if (localmesh->get(d2x, "d2x"+suffix, 0.0, false, location)) { + if (localmesh->get(d2x, "d2x" + suffix, 0.0, false, location)) { output_warn.write( "\tWARNING: differencing quantity 'd2x' not found. Calculating from dx\n"); d1_dx = bout::derivatives::index::DDX(1. / dx); // d/di(1/dx) @@ -1243,7 +1244,7 @@ int Coordinates::geometry(bool recalculate_staggered, d1_dx = -d2x / (dx * dx); } - if (localmesh->get(d2y, "d2y"+suffix, 0.0, false, location)) { + if (localmesh->get(d2y, "d2y" + suffix, 0.0, false, location)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) @@ -1537,9 +1538,9 @@ void Coordinates::setParallelTransform(Options* options) { if (localmesh->sourceHasVar("dx"+suffix)) { // Grid file has variables at this location, so should be able to read checkStaggeredGet(localmesh, "zShift", suffix); - if (localmesh->get(zShift, "zShift"+suffix, 0.0, false, location)) { + if (localmesh->get(zShift, "zShift" + suffix, 0.0, false, location)) { // No zShift variable. Try qinty in BOUT grid files - if (localmesh->get(zShift, "qinty"+suffix, 0.0, false, location)) { + if (localmesh->get(zShift, "qinty" + suffix, 0.0, false, location)) { // Failed to find either variable, cannot use ShiftedMetric throw BoutException("Could not read zShift"+suffix+" from grid file"); } @@ -1598,8 +1599,8 @@ void Coordinates::setParallelTransform(Options* options) { *******************************************************************************/ Coordinates::FieldMetric Coordinates::DDX(const Field2D& f, CELL_LOC loc, - const std::string& method, - const std::string& region) { + const std::string& method, + const std::string& region) { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDX(f, loc, method, region) / dx; } @@ -1618,8 +1619,8 @@ Field3D Coordinates::DDX(const Field3D& f, CELL_LOC outloc, const std::string& m }; Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, - const std::string& method, - const std::string& region) { + const std::string& method, + const std::string& region) { ASSERT1(location == loc || loc == CELL_DEFAULT); return bout::derivatives::index::DDY(f, loc, method, region) / dy; } @@ -1630,8 +1631,8 @@ Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& m }; Coordinates::FieldMetric Coordinates::DDZ(const Field2D& f, CELL_LOC loc, - const std::string& UNUSED(method), - const std::string& UNUSED(region)) { + const std::string& UNUSED(method), + const std::string& UNUSED(region)) { ASSERT1(location == loc || loc == CELL_DEFAULT); ASSERT1(f.getMesh() == localmesh); if (loc == CELL_DEFAULT) { @@ -1648,8 +1649,8 @@ Field3D Coordinates::DDZ(const Field3D& f, CELL_LOC outloc, const std::string& m // Parallel gradient Coordinates::FieldMetric Coordinates::Grad_par(const Field2D& var, - MAYBE_UNUSED(CELL_LOC outloc), - const std::string& UNUSED(method)) { + MAYBE_UNUSED(CELL_LOC outloc), + const std::string& UNUSED(method)) { TRACE("Coordinates::Grad_par( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == var.getLocation())); @@ -1669,10 +1670,9 @@ Field3D Coordinates::Grad_par(const Field3D& var, CELL_LOC outloc, // Vpar_Grad_par // vparallel times the parallel derivative along unperturbed B-field -Coordinates::FieldMetric -Coordinates::Vpar_Grad_par(const Field2D& v, const Field2D& f, - MAYBE_UNUSED(CELL_LOC outloc), - const std::string& UNUSED(method)) { +Coordinates::FieldMetric Coordinates::Vpar_Grad_par(const Field2D& v, const Field2D& f, + MAYBE_UNUSED(CELL_LOC outloc), + const std::string& UNUSED(method)) { ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); return VDDY(v, f) / sqrt(g_22); } @@ -1687,7 +1687,7 @@ Field3D Coordinates::Vpar_Grad_par(const Field3D& v, const Field3D& f, CELL_LOC // Parallel divergence Coordinates::FieldMetric Coordinates::Div_par(const Field2D& f, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { TRACE("Coordinates::Div_par( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1728,7 +1728,7 @@ Field3D Coordinates::Div_par(const Field3D& f, CELL_LOC outloc, // Note: For parallel Laplacian use Laplace_par Coordinates::FieldMetric Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { TRACE("Coordinates::Grad2_par2( Field2D )"); ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); @@ -1769,7 +1769,7 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, #include // Delp2 uses same coefficients as inversion code Coordinates::FieldMetric Coordinates::Delp2(const Field2D& f, CELL_LOC outloc, - bool UNUSED(useFFT)) { + bool UNUSED(useFFT)) { TRACE("Coordinates::Delp2( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); @@ -1903,8 +1903,7 @@ FieldPerp Coordinates::Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { return result; } -Coordinates::FieldMetric Coordinates::Laplace_par(const Field2D& f, - CELL_LOC outloc) { +Coordinates::FieldMetric Coordinates::Laplace_par(const Field2D& f, CELL_LOC outloc) { ASSERT1(location == outloc || outloc == CELL_DEFAULT); return D2DY2(f, outloc) / g_22 + DDY(J / g_22, outloc) * DDY(f, outloc) / J; } @@ -1916,10 +1915,9 @@ Field3D Coordinates::Laplace_par(const Field3D& f, CELL_LOC outloc) { // Full Laplacian operator on scalar field -Coordinates::FieldMetric -Coordinates::Laplace(const Field2D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_conditions, - const std::string& dfdy_dy_region) { +Coordinates::FieldMetric Coordinates::Laplace(const Field2D& f, CELL_LOC outloc, + const std::string& dfdy_boundary_conditions, + const std::string& dfdy_dy_region) { TRACE("Coordinates::Laplace( Field2D )"); ASSERT1(location == outloc || outloc == CELL_DEFAULT); diff --git a/src/mesh/difops.cxx b/src/mesh/difops.cxx index 578629d34e..2fa2e36a81 100644 --- a/src/mesh/difops.cxx +++ b/src/mesh/difops.cxx @@ -48,12 +48,12 @@ *******************************************************************************/ Coordinates::FieldMetric Grad_par(const Field2D& var, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } Coordinates::FieldMetric Grad_par(const Field2D& var, const std::string& method, - CELL_LOC outloc) { + CELL_LOC outloc) { return var.getCoordinates(outloc)->Grad_par(var, outloc, method); } @@ -191,12 +191,12 @@ Field3D Grad_parP(const Field3D& apar, const Field3D& f) { *******************************************************************************/ Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - CELL_LOC outloc, const std::string& method) { + CELL_LOC outloc, const std::string& method) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } Coordinates::FieldMetric Vpar_Grad_par(const Field2D& v, const Field2D& f, - const std::string& method, CELL_LOC outloc) { + const std::string& method, CELL_LOC outloc) { return f.getCoordinates(outloc)->Vpar_Grad_par(v, f, outloc, method); } @@ -215,12 +215,12 @@ Field3D Vpar_Grad_par(const Field3D& v, const Field3D& f, const std::string& met * parallel divergence operator B \partial_{||} (F/B) *******************************************************************************/ Coordinates::FieldMetric Div_par(const Field2D& f, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } Coordinates::FieldMetric Div_par(const Field2D& f, const std::string& method, - CELL_LOC outloc) { + CELL_LOC outloc) { return f.getCoordinates(outloc)->Div_par(f, outloc, method); } @@ -309,7 +309,7 @@ Field3D Div_par_flux(const Field3D& v, const Field3D& f, const std::string& meth *******************************************************************************/ Coordinates::FieldMetric Grad2_par2(const Field2D& f, CELL_LOC outloc, - const std::string& method) { + const std::string& method) { return f.getCoordinates(outloc)->Grad2_par2(f, outloc, method); } @@ -323,7 +323,7 @@ Field3D Grad2_par2(const Field3D& f, CELL_LOC outloc, const std::string& method) *******************************************************************************/ Coordinates::FieldMetric Div_par_K_Grad_par(BoutReal kY, const Field2D& f, - CELL_LOC outloc) { + CELL_LOC outloc) { return kY*Grad2_par2(f, outloc); } @@ -332,7 +332,7 @@ Field3D Div_par_K_Grad_par(BoutReal kY, const Field3D& f, CELL_LOC outloc) { } Coordinates::FieldMetric Div_par_K_Grad_par(const Field2D& kY, const Field2D& f, - CELL_LOC outloc) { + CELL_LOC outloc) { if (outloc == CELL_DEFAULT) outloc = f.getLocation(); return interp_to(kY, outloc)*Grad2_par2(f, outloc) + Div_par(kY, outloc)*Grad_par(f, outloc); } @@ -377,8 +377,8 @@ FieldPerp Delp2(const FieldPerp& f, CELL_LOC outloc, bool useFFT) { *******************************************************************************/ Coordinates::FieldMetric Laplace_perp(const Field2D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { return Laplace(f, outloc, dfdy_boundary_condition, dfdy_region) - Laplace_par(f, outloc); } @@ -412,8 +412,8 @@ Field3D Laplace_par(const Field3D& f, CELL_LOC outloc) { *******************************************************************************/ Coordinates::FieldMetric Laplace(const Field2D& f, CELL_LOC outloc, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { return f.getCoordinates(outloc)->Laplace(f, outloc, dfdy_boundary_condition, dfdy_region); } @@ -441,7 +441,7 @@ Field2D Laplace_perpXY(const Field2D& A, const Field2D& f) { *******************************************************************************/ Coordinates::FieldMetric b0xGrad_dot_Grad(const Field2D& phi, const Field2D& A, - CELL_LOC outloc) { + CELL_LOC outloc) { TRACE("b0xGrad_dot_Grad( Field2D , Field2D )"); @@ -589,8 +589,8 @@ Field3D b0xGrad_dot_Grad(const Field3D& phi, const Field3D& A, CELL_LOC outloc) *******************************************************************************/ Coordinates::FieldMetric bracket(const Field2D& f, const Field2D& g, - BRACKET_METHOD method, CELL_LOC outloc, - Solver* UNUSED(solver)) { + BRACKET_METHOD method, CELL_LOC outloc, + Solver* UNUSED(solver)) { TRACE("bracket(Field2D, Field2D)"); ASSERT1_FIELDS_COMPATIBLE(f, g); @@ -622,7 +622,7 @@ Field3D bracket(const Field3D& f, const Field2D& g, BRACKET_METHOD method, } ASSERT1(outloc == g.getLocation()); - MAYBE_UNUSED(Mesh *mesh) = f.getMesh(); + MAYBE_UNUSED(Mesh * mesh) = f.getMesh(); Field3D result{emptyFrom(f).setLocation(outloc)}; diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 3ebaa26595..28193bcb39 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -32,10 +32,10 @@ namespace FV { xe -= 1; */ - for(int i=xs;i<=xe;i++) - for(int j=mesh->ystart;j<=mesh->yend;j++) { - for(int k=0;kLocalNz;k++) { - // Calculate flux from i to i+1 + for (int i = xs; i <= xe; i++) { + for (int j = mesh->ystart; j <= mesh->yend; j++) { + for (int k = 0; k < mesh->LocalNz; k++) { + // Calculate flux from i to i+1 BoutReal fout = 0.5 * (a(i, j, k) + a(i + 1, j, k)) * (coord->J(i, j, k) * coord->g11(i, j, k) @@ -47,7 +47,7 @@ namespace FV { result(i + 1, j, k) -= fout / (coord->dx(i + 1, j, k) * coord->J(i + 1, j, k)); } } - + } // Y and Z fluxes require Y derivatives @@ -55,7 +55,6 @@ namespace FV { Field3D fup(mesh), fdown(mesh); Field3D aup(mesh), adown(mesh); - Field3D g23up(mesh), g23down(mesh); Field3D g_23up(mesh), g_23down(mesh); Field3D Jup(mesh), Jdown(mesh); @@ -63,7 +62,6 @@ namespace FV { Field3D dzup(mesh), dzdown(mesh); Field3D Bxyup(mesh), Bxydown(mesh); - // Values on this y slice (centre). // This is needed because toFieldAligned may modify the field Field3D fc = f; @@ -76,12 +74,11 @@ namespace FV { Field3D dzc = coord->dz; Field3D Bxyc = coord->Bxy; - // Result of the Y and Z fluxes Field3D yzresult(mesh); yzresult.allocate(); - if (f.hasParallelSlices() && a.hasParallelSlices() ) { + if (f.hasParallelSlices() && a.hasParallelSlices()) { // Both inputs have yup and ydown fup = f.yup(); @@ -95,7 +92,7 @@ namespace FV { fup = fdown = fc = toFieldAligned(f); aup = adown = ac = toFieldAligned(a); - + yzresult.setDirectionY(YDirectionType::Aligned); } @@ -103,18 +100,18 @@ namespace FV { // 3D Metric, need yup/ydown fields. // Requires previous communication of metrics // -- should insert communication here? - if (!coord->g23.hasParallelSlices() || !coord->g_23.hasParallelSlices() || - !coord->dy.hasParallelSlices() || !coord->dz.hasParallelSlices() || - !coord->Bxy.hasParallelSlices() || !coord->J.hasParallelSlices() ) { - throw BoutException("metrics have no yup/down: Maybe communicate in init?"); + if (!coord->g23.hasParallelSlices() || !coord->g_23.hasParallelSlices() + || !coord->dy.hasParallelSlices() || !coord->dz.hasParallelSlices() + || !coord->Bxy.hasParallelSlices() || !coord->J.hasParallelSlices()) { + throw BoutException("metrics have no yup/down: Maybe communicate in init?"); } - + g23up = coord->g23.yup(); g23down = coord->g23.ydown(); g_23up = coord->g_23.yup(); g_23down = coord->g_23.ydown(); - + Jup = coord->J.yup(); Jdown = coord->J.ydown(); @@ -126,7 +123,7 @@ namespace FV { Bxyup = coord->Bxy.yup(); Bxydown = coord->Bxy.ydown(); - + } else { // No 3D metrics // Need to shift to/from field aligned coordinates @@ -136,7 +133,6 @@ namespace FV { dyup = dydown = dyc = toFieldAligned(coord->dy); dzup = dzdown = dzc = toFieldAligned(coord->dz); Bxyup = Bxydown = Bxyc = toFieldAligned(coord->Bxy); - } // Y flux @@ -151,22 +147,21 @@ namespace FV { BoutReal coef = 0.5 * (g_23c(i, j, k) / SQ(Jc(i, j, k) * Bxyc(i, j, k)) - + g_23up(i, j + 1, k) - / SQ(Jup(i, j + 1, k) * Bxyup(i, j + 1, k))); + + g_23up(i, j + 1, k) / SQ(Jup(i, j + 1, k) * Bxyup(i, j + 1, k))); // Calculate Z derivative at y boundary BoutReal dfdz = 0.5 * (fc(i, j, kp) - fc(i, j, km) + fup(i, j + 1, kp) - fup(i, j + 1, km)) - / (dzc(i, j, k) + dzup(i, j+1, k)); + / (dzc(i, j, k) + dzup(i, j + 1, k)); // Y derivative - BoutReal dfdy = 2. * (fup(i, j + 1, k) - fc(i, j, k)) - / (dyup(i, j + 1, k) + dyc(i, j, k)); + BoutReal dfdy = + 2. * (fup(i, j + 1, k) - fc(i, j, k)) / (dyup(i, j + 1, k) + dyc(i, j, k)); - BoutReal fout = 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) - * (Jc(i, j, k) * g23c(i, j, k) - + Jup(i, j + 1, k) * g23up(i, j + 1, k)) - * (dfdz - coef * dfdy); + BoutReal fout = + 0.25 * (ac(i, j, k) + aup(i, j + 1, k)) + * (Jc(i, j, k) * g23c(i, j, k) + Jup(i, j + 1, k) * g23up(i, j + 1, k)) + * (dfdz - coef * dfdy); yzresult(i, j, k) = fout / (dyc(i, j, k) * Jc(i, j, k)); @@ -174,15 +169,15 @@ namespace FV { dfdz = 0.5 * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) - / (dzc(i, j, k) + dzdown(i, j-1, k)); + / (dzc(i, j, k) + dzdown(i, j - 1, k)); dfdy = 2. * (fc(i, j, k) - fdown(i, j - 1, k)) / (dyc(i, j, k) + dydown(i, j - 1, k)); - fout = 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) - * (Jc(i, j, k) * g23c(i, j, k) - + Jdown(i, j - 1, k) * g23down(i, j - 1, k)) - * (dfdz - coef * dfdy); + fout = + 0.25 * (ac(i, j, k) + adown(i, j - 1, k)) + * (Jc(i, j, k) * g23c(i, j, k) + Jdown(i, j - 1, k) * g23down(i, j - 1, k)) + * (dfdz - coef * dfdy); yzresult(i, j, k) -= fout / (dyc(i, j, k) * Jc(i, j, k)); } @@ -200,19 +195,19 @@ namespace FV { // Coefficient in front of df/dy term BoutReal coef = g_23c(i, j, k) - / (dyup(i, j + 1, k) + 2. * dyc(i, j, k) - + dydown(i, j - 1, k)) + / (dyup(i, j + 1, k) + 2. * dyc(i, j, k) + dydown(i, j - 1, k)) / SQ(Jc(i, j, k) * Bxyc(i, j, k)); - BoutReal fout = 0.25 * (ac(i, j, k) + ac(i, j, kp)) * - (Jc(i, j, k) * coord->g33(i, j, k) + Jc(i, j, kp) * coord->g33(i, j, kp)) - * ( // df/dz - (fc(i, j, kp) - fc(i, j, k)) / dzc(i, j, k) - // - g_yz * df/dy / SQ(J*B) - - coef - * (fup(i, j + 1, k) + fup(i, j + 1, kp) - - fdown(i, j - 1, k) - fdown(i, j - 1, kp))); - + BoutReal fout = + 0.25 * (ac(i, j, k) + ac(i, j, kp)) + * (Jc(i, j, k) * coord->g33(i, j, k) + Jc(i, j, kp) * coord->g33(i, j, kp)) + * ( // df/dz + (fc(i, j, kp) - fc(i, j, k)) / dzc(i, j, k) + // - g_yz * df/dy / SQ(J*B) + - coef + * (fup(i, j + 1, k) + fup(i, j + 1, kp) - fdown(i, j - 1, k) + - fdown(i, j - 1, kp))); + yzresult(i, j, k) += fout / (Jc(i, j, k) * dzc(i, j, k)); yzresult(i, j, kp) -= fout / (Jc(i, j, kp) * dzc(i, j, kp)); } @@ -394,8 +389,8 @@ namespace FV { const BoutReal d3fdx3 = (f(i, j + 2, k) - 3. * f(i, j + 1, k) + 3. * f(i, j, k) - f(i, j - 1, k)); - result(i,j, k) += d3fdx3 * factor_rc; - result(i,j+1,k) -= d3fdx3 * factor_rp; + result(i,j, k) += d3fdx3 * factor_rc; + result(i, j + 1, k) -= d3fdx3 * factor_rp; } } else { // At a domain boundary diff --git a/src/mesh/mesh.cxx b/src/mesh/mesh.cxx index c53fe8d930..ce4ed39c4b 100644 --- a/src/mesh/mesh.cxx +++ b/src/mesh/mesh.cxx @@ -139,8 +139,8 @@ int Mesh::get(bool &bval, const std::string &name, bool def) { return !success; } -int Mesh::get(Field2D &var, const std::string &name, BoutReal def, - bool communicate, CELL_LOC location) { +int Mesh::get(Field2D& var, const std::string& name, BoutReal def, bool communicate, + CELL_LOC location) { TRACE("Loading 2D field: Mesh::get(Field2D, {:s})", name); if (source == nullptr or !source->get(this, var, name, def, location)) { diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 6bd5f9b669..75ee217a98 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -47,8 +47,9 @@ #include -FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* inner_boundary, - BoundaryRegionPar* outer_boundary, bool zperiodic) +FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, + BoundaryRegionPar* inner_boundary, BoundaryRegionPar* outer_boundary, + bool zperiodic) : map_mesh(mesh), offset(offset_), boundary_mask(map_mesh), corner_boundary_mask(map_mesh) { @@ -269,7 +270,7 @@ FCIMap::FCIMap(Mesh& mesh, Options& options, int offset_, BoundaryRegionPar* inn z), // sqrt( SQ(dR) + SQ(dZ) ), // Distance to intersection PI // Right-angle intersection ); - } else if (xt_prime(x, y, z) >= map_mesh.xend+1) { + } else if (xt_prime(x, y, z) >= map_mesh.xend + 1) { // Hit an outer boundary // Set to false to not skip this point boundary_mask(x, y, z) = false; diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index 1c3666e7eb..7cba209579 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -45,7 +45,7 @@ class FCIMap { public: FCIMap() = delete; FCIMap(Mesh& mesh, Options& options, int offset, BoundaryRegionPar* inner_boundary, - BoundaryRegionPar* outer_boundary, bool zperiodic); + BoundaryRegionPar* outer_boundary, bool zperiodic); // The mesh this map was created on Mesh& map_mesh; @@ -77,10 +77,14 @@ public: // check the coordinate system used for the grid data source FCITransform::checkInputGrid(); - auto forward_boundary_xin = new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD_XIN, +1, &mesh); - auto backward_boundary_xin = new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD_XIN, -1, &mesh); - auto forward_boundary_xout = new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD_XOUT, +1, &mesh); - auto backward_boundary_xout = new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD_XOUT, -1, &mesh); + auto forward_boundary_xin = + new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD_XIN, +1, &mesh); + auto backward_boundary_xin = + new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD_XIN, -1, &mesh); + auto forward_boundary_xout = + new BoundaryRegionPar("FCI_forward", BNDRY_PAR_FWD_XOUT, +1, &mesh); + auto backward_boundary_xout = + new BoundaryRegionPar("FCI_backward", BNDRY_PAR_BKWD_XOUT, -1, &mesh); // Add the boundary region to the mesh's vector of parallel boundaries mesh.addBoundaryPar(forward_boundary_xin); @@ -90,8 +94,10 @@ public: field_line_maps.reserve(mesh.ystart * 2); for (int offset = 1; offset < mesh.ystart + 1; ++offset) { - field_line_maps.emplace_back(mesh, options, offset, forward_boundary_xin, forward_boundary_xout, zperiodic); - field_line_maps.emplace_back(mesh, options, -offset, backward_boundary_xin, backward_boundary_xout, zperiodic); + field_line_maps.emplace_back(mesh, options, offset, forward_boundary_xin, + forward_boundary_xout, zperiodic); + field_line_maps.emplace_back(mesh, options, -offset, backward_boundary_xin, + backward_boundary_xout, zperiodic); } } diff --git a/src/solver/solver.cxx b/src/solver/solver.cxx index 19f4506191..0dcafd8ae1 100644 --- a/src/solver/solver.cxx +++ b/src/solver/solver.cxx @@ -719,7 +719,7 @@ int Solver::call_monitors(BoutReal simtime, int iter, int NOUT) { throw BoutException(_("Monitor signalled to quit (return code {})"), ret); } } - } catch (const BoutException &e) { + } catch (const BoutException& e) { for (const auto& it : monitors) { it->cleanup(); } diff --git a/src/sys/derivs.cxx b/src/sys/derivs.cxx index 8871de14c1..f7d301476e 100644 --- a/src/sys/derivs.cxx +++ b/src/sys/derivs.cxx @@ -63,8 +63,8 @@ Field3D DDX(const Field3D& f, CELL_LOC outloc, const std::string& method, return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } -Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { +Coordinates::FieldMetric DDX(const Field2D& f, CELL_LOC outloc, const std::string& method, + const std::string& region) { return f.getCoordinates(outloc)->DDX(f, outloc, method, region); } @@ -76,8 +76,8 @@ Field3D DDY(const Field3D &f, CELL_LOC outloc, const std::string &method, / f.getCoordinates(outloc)->dy; } -Coordinates::FieldMetric DDY(const Field2D& f, CELL_LOC outloc, - const std::string& method, const std::string& region) { +Coordinates::FieldMetric DDY(const Field2D& f, CELL_LOC outloc, const std::string& method, + const std::string& region) { return f.getCoordinates(outloc)->DDY(f, outloc, method, region); } @@ -90,8 +90,8 @@ Field3D DDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric DDZ(const Field2D& f, CELL_LOC UNUSED(outloc), - const std::string& UNUSED(method), - const std::string& UNUSED(region)) { + const std::string& UNUSED(method), + const std::string& UNUSED(region)) { auto tmp = Field2D(0., f.getMesh()); tmp.setLocation(f.getLocation()); return tmp; @@ -168,8 +168,7 @@ Field3D D2DX2(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D2DX2(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { Coordinates *coords = f.getCoordinates(outloc); auto result = @@ -206,8 +205,7 @@ Field3D D2DY2(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D2DY2(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { Coordinates *coords = f.getCoordinates(outloc); auto result = @@ -230,8 +228,7 @@ Field3D D2DZ2(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D2DZ2(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::D2DZ2(f, outloc, method, region) / SQ(f.getCoordinates(outloc)->dz); } @@ -247,8 +244,7 @@ Field3D D4DX4(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D4DX4(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::D4DX4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dx)); } @@ -260,8 +256,7 @@ Field3D D4DY4(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D4DY4(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::D4DY4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dy)); } @@ -273,8 +268,7 @@ Field3D D4DZ4(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::D4DZ4(f, outloc, method, region) / SQ(SQ(f.getCoordinates(outloc)->dz)); } @@ -291,10 +285,9 @@ Coordinates::FieldMetric D4DZ4(const Field2D& f, CELL_LOC outloc, * ** Communicates and applies boundary in X. */ Coordinates::FieldMetric D2DXDY(const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region, - const std::string& dfdy_boundary_condition, - const std::string& dfdy_region) { + const std::string& method, const std::string& region, + const std::string& dfdy_boundary_condition, + const std::string& dfdy_region) { std::string dy_region = dfdy_region.empty() ? region : dfdy_region; // If staggering in x, take y-derivative at f's location. @@ -336,8 +329,8 @@ Field3D D2DXDY(const Field3D& f, CELL_LOC outloc, const std::string& method, } Coordinates::FieldMetric D2DXDZ(const Field2D& f, CELL_LOC outloc, - MAYBE_UNUSED(const std::string& method), - MAYBE_UNUSED(const std::string& region)) { + MAYBE_UNUSED(const std::string& method), + MAYBE_UNUSED(const std::string& region)) { #if BOUT_USE_METRIC_3D Field3D tmp{f}; return D2DXDZ(tmp, outloc, method, region); @@ -361,8 +354,8 @@ Field3D D2DXDZ(const Field3D &f, CELL_LOC outloc, const std::string &method, } Coordinates::FieldMetric D2DYDZ(const Field2D& f, CELL_LOC outloc, - MAYBE_UNUSED(const std::string& method), - MAYBE_UNUSED(const std::string& region)) { + MAYBE_UNUSED(const std::string& method), + MAYBE_UNUSED(const std::string& region)) { #if BOUT_USE_METRIC_3D Field3D tmp{f}; return D2DYDZ(tmp, outloc, method, region); @@ -393,8 +386,7 @@ Field3D D2DYDZ(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(const std::string /// Special case where both arguments are 2D. Coordinates::FieldMetric VDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::VDDX(v, f, outloc, method, region) / f.getCoordinates(outloc)->dx; } @@ -410,8 +402,7 @@ Field3D VDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str // special case where both are 2D Coordinates::FieldMetric VDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::VDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; } @@ -427,17 +418,15 @@ Field3D VDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str // special case where both are 2D Coordinates::FieldMetric VDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::VDDZ(v, f, outloc, method, region) / f.getCoordinates(outloc)->dz; } // Note that this is zero because no compression is included Coordinates::FieldMetric VDDZ(MAYBE_UNUSED(const Field3D& v), const Field2D& f, - CELL_LOC outloc, - MAYBE_UNUSED(const std::string& method), - MAYBE_UNUSED(const std::string& region)) { + CELL_LOC outloc, MAYBE_UNUSED(const std::string& method), + MAYBE_UNUSED(const std::string& region)) { #if BOUT_USE_METRIC_3D Field3D tmp{f}; return bout::derivatives::index::VDDZ(v, tmp, outloc, method, region) @@ -461,8 +450,7 @@ Field3D VDDZ(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str * Flux conserving schemes *******************************************************************************/ Coordinates::FieldMetric FDDX(const Field2D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::FDDX(v, f, outloc, method, region) / f.getCoordinates(outloc)->dx; } @@ -476,8 +464,7 @@ Field3D FDDX(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ///////////////////////////////////////////////////////////////////////// Coordinates::FieldMetric FDDY(const Field2D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::FDDY(v, f, outloc, method, region) / f.getCoordinates(outloc)->dy; } @@ -491,8 +478,7 @@ Field3D FDDY(const Field3D &v, const Field3D &f, CELL_LOC outloc, const std::str ///////////////////////////////////////////////////////////////////////// Coordinates::FieldMetric FDDZ(const Field2D& v, const Field2D& f, CELL_LOC outloc, - const std::string& method, - const std::string& region) { + const std::string& method, const std::string& region) { return bout::derivatives::index::FDDZ(v, f, outloc, method, region) / f.getCoordinates(outloc)->dz; } diff --git a/tests/integrated/test-laplacexz/test-laplacexz.cxx b/tests/integrated/test-laplacexz/test-laplacexz.cxx index 2fb237af8f..8ecf77cced 100644 --- a/tests/integrated/test-laplacexz/test-laplacexz.cxx +++ b/tests/integrated/test-laplacexz/test-laplacexz.cxx @@ -43,7 +43,8 @@ int main(int argc, char** argv) { output.write("First solve\n"); - Field3D rhs = FieldFactory::get()->create3D("rhs", Options::getRoot(), bout::globals::mesh); + Field3D rhs = + FieldFactory::get()->create3D("rhs", Options::getRoot(), bout::globals::mesh); Field3D x = inv->solve(rhs, 0.0); SAVE_ONCE2(rhs, x); @@ -52,7 +53,8 @@ int main(int argc, char** argv) { inv->setCoefs(Field3D(2.0),Field3D(0.1)); - Field3D rhs2 = FieldFactory::get()->create3D("rhs", Options::getRoot(), bout::globals::mesh); + Field3D rhs2 = + FieldFactory::get()->create3D("rhs", Options::getRoot(), bout::globals::mesh); Field3D x2 = inv->solve(rhs2, 0.0); SAVE_ONCE2(rhs2, x2); diff --git a/tests/unit/field/test_field_factory.cxx b/tests/unit/field/test_field_factory.cxx index 3bef98307a..560a3f1177 100644 --- a/tests/unit/field/test_field_factory.cxx +++ b/tests/unit/field/test_field_factory.cxx @@ -575,9 +575,9 @@ TYPED_TEST(FieldFactoryCreationTest, CreateOnMesh) { localmesh.createDefaultRegions(); localmesh.setCoordinates(std::make_shared( &localmesh, Field2D{1.0}, Field2D{1.0}, BoutReal{1.0}, Field2D{1.0}, Field2D{0.0}, - Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, - Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0})); + Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, + Field2D{1.0}, Field2D{1.0}, Field2D{1.0}, Field2D{0.0}, Field2D{0.0}, Field2D{0.0}, + Field2D{0.0}, Field2D{0.0})); // No call to Coordinates::geometry() needed here localmesh.getCoordinates()->setParallelTransform( diff --git a/tests/unit/mesh/data/test_gridfromoptions.cxx b/tests/unit/mesh/data/test_gridfromoptions.cxx index 823a0559b5..53cd35eeae 100644 --- a/tests/unit/mesh/data/test_gridfromoptions.cxx +++ b/tests/unit/mesh/data/test_gridfromoptions.cxx @@ -64,9 +64,9 @@ class GridFromOptionsTest : public ::testing::Test { &mesh_from_options); expected_metric = #if BOUT_USE_METRIC_3D - expected_3d; + expected_3d; #else - expected_2d; + expected_2d; #endif } @@ -377,12 +377,11 @@ TEST_F(GridFromOptionsTest, CoordinatesXlowInterp) { auto coords = mesh_from_options.getCoordinates(CELL_XLOW); - Coordinates::FieldMetric expected_xlow = - makeField( - [](Coordinates::FieldMetric::ind_type& index) { - return index.x() - 0.5 + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; - }, - &mesh_from_options); + Coordinates::FieldMetric expected_xlow = makeField( + [](Coordinates::FieldMetric::ind_type& index) { + return index.x() - 0.5 + (TWOPI * index.y()) + (TWOPI * index.z() / nz) + 3; + }, + &mesh_from_options); mesh_from_options.communicate(expected_xlow); From f7ce2e416f84040a3ec3aed4cdea7a63b1d29a1f Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 16:00:06 +0000 Subject: [PATCH 248/293] Remove declaration of deleted methods The implementations were removed in #2179, missed the declarations --- include/bout/coordinates.hxx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index c61a5dd7d6..5478bf19f7 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -306,22 +306,6 @@ private: /// Set the parallel (y) transform from the options file. /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); - - /// Alternative implementation for `fromFieldAligned` that can be - /// called before the `Coordinates` constructor is finished - Field3D maybeFromFieldAligned(const Field3D& f, const std::string& region = "RGN_ALL"); - - Field2D maybeFromFieldAligned(const Field2D& f, - const std::string& UNUSED(region) = "RGN_ALL"); - - /// A wrapper for index:DDY derivative that is able to tranform - /// fields before the constructor is finished. - FieldMetric indexDDY(const Field2D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); - Field3D indexDDY(const Field3D& f, CELL_LOC outloc = CELL_DEFAULT, - const std::string& method = "DEFAULT", - const std::string& region = "RGN_NOBNDRY"); }; /* From d40ecb020e6cffc4c3766ca0f5384225597af35c Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 16:01:27 +0000 Subject: [PATCH 249/293] Remove Coordinates::is3D Unused in codebase, and equivalent to bout::build::use_metric_3d --- include/bout/coordinates.hxx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 5478bf19f7..516460d71f 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -136,10 +136,6 @@ public: int calcContravariant(const std::string& region = "RGN_ALL"); int jacobian(); ///< Calculate J and Bxy - /// Return if the metrics are 3D - // needs to be static for old gcc - static constexpr bool is3D() { return bout::build::use_metric_3d; } - /////////////////////////////////////////////////////////// // Parallel transforms /////////////////////////////////////////////////////////// From d6e4ec07bd391198917a1f0a3c72e50709a59f90 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 16:44:10 +0000 Subject: [PATCH 250/293] Add some explanatory comments --- src/mesh/coordinates.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 1c9309a3c1..408d8ee110 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -41,6 +41,8 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, bool extr // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); + // Use sendY()/sendX() and wait() instead of communicate() to ensure we don't + // try to calculate parallel slices as Coordinates are not constructed yet. auto h = localmesh->sendY(result); localmesh->wait(h); h = localmesh->sendX(result); @@ -157,8 +159,12 @@ Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, Field3D f = f_; ParallelTransform* pt_f; if (f.getCoordinates() == nullptr) { + // if input f is member of the Coordinates we are currently constructing, it will not + // have Coordinates and needs to use the passed-in ParallelTransform pt_f = pt_; } else { + // if input f is from Coordinates at a different location, it will have its own + // Coordinates, and we should use its ParallelTransform pt_f = &f.getCoordinates()->getParallelTransform(); } if (f.getDirectionY() != YDirectionType::Standard) { @@ -189,6 +195,8 @@ Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); + // Use sendY()/sendX() and wait() instead of communicate() to ensure we don't + // try to calculate parallel slices as Coordinates are not constructed yet. auto h = localmesh->sendY(result); localmesh->wait(h); h = localmesh->sendX(result); From cfb263a463cbd926dd80394e3936bcef03f732a5 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 17:02:08 +0000 Subject: [PATCH 251/293] Use existing free-function communicate instead of inline code --- src/mesh/coordinates.cxx | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 408d8ee110..df1910adb5 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -22,6 +22,17 @@ // use anonymous namespace so this utility function is not available outside this file namespace { +template +// Use sendY()/sendX() and wait() instead of Mesh::communicate() to ensure we +// don't try to calculate parallel slices as Coordinates are not constructed yet +void communicate(T& t, Ts&... ts) { + FieldGroup g(t, ts...); + auto h = t.getMesh()->sendY(g); + t.getMesh()->wait(h); + h = t.getMesh()->sendX(g); + t.getMesh()->wait(h); +} + /// Interpolate a Field2D to a new CELL_LOC with interp_to. /// Communicates to set internal guard cells. /// Boundary guard cells are set by extrapolating from the grid, like @@ -41,12 +52,7 @@ Field2D interpolateAndExtrapolate(const Field2D& f, CELL_LOC location, bool extr // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); - // Use sendY()/sendX() and wait() instead of communicate() to ensure we don't - // try to calculate parallel slices as Coordinates are not constructed yet. - auto h = localmesh->sendY(result); - localmesh->wait(h); - h = localmesh->sendX(result); - localmesh->wait(h); + communicate(result); // Extrapolate into boundaries (if requested) so that differential geometry // terms can be interpolated if necessary @@ -195,12 +201,7 @@ Field3D interpolateAndExtrapolate(const Field3D& f_, CELL_LOC location, // communicate f. We will sort out result's boundary guard cells below, but // not f's so we don't want to change f. result.allocate(); - // Use sendY()/sendX() and wait() instead of communicate() to ensure we don't - // try to calculate parallel slices as Coordinates are not constructed yet. - auto h = localmesh->sendY(result); - localmesh->wait(h); - h = localmesh->sendX(result); - localmesh->wait(h); + communicate(result); // Extrapolate into boundaries (if requested) so that differential geometry // terms can be interpolated if necessary @@ -360,17 +361,6 @@ std::string getLocationSuffix(CELL_LOC location) { } } } - -template -void communicate(T& t, Ts&... ts) { - FieldGroup g(t, ts...); - // emulate full communicate - auto h = t.getMesh()->sendY(g); - t.getMesh()->wait(h); - h = t.getMesh()->sendX(g); - t.getMesh()->wait(h); -} - } // anonymous namespace Coordinates::Coordinates(Mesh* mesh, FieldMetric dx, FieldMetric dy, FieldMetric dz, From 10f5b98ef5a8d599c12b5fc66d6d0dbd10f3f1e5 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 17:04:22 +0000 Subject: [PATCH 252/293] Remove superfluous semi-colon --- src/invert/parderiv/impls/cyclic/cyclic.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index f3e9237ad4..24f7b8076c 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -239,6 +239,6 @@ const Field3D InvertParCR::solve(const Field3D &f) { } return fromFieldAligned(result, "RGN_NOBNDRY"); -}; +} #endif // BOUT_USE_METRIC_3D From 1657c842dfb8d3ade19ea93883ff7c62471ce0ee Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Thu, 7 Jan 2021 17:05:41 +0000 Subject: [PATCH 253/293] Make local variable const --- src/invert/parderiv/impls/cyclic/cyclic.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/invert/parderiv/impls/cyclic/cyclic.cxx b/src/invert/parderiv/impls/cyclic/cyclic.cxx index 24f7b8076c..3b27fee955 100644 --- a/src/invert/parderiv/impls/cyclic/cyclic.cxx +++ b/src/invert/parderiv/impls/cyclic/cyclic.cxx @@ -107,7 +107,7 @@ const Field3D InvertParCR::solve(const Field3D &f) { auto b = Matrix(nsys, size); auto c = Matrix(nsys, size); - auto zlength = getUniform(coord->zlength()); + const auto zlength = getUniform(coord->zlength()); // Loop over flux-surfaces for (surf.first(); !surf.isDone(); surf.next()) { int x = surf.xpos; From c59c86a8ece41fff68de3253499d6aefcc159115 Mon Sep 17 00:00:00 2001 From: Ben Dudson Date: Fri, 8 Jan 2021 12:41:12 +0000 Subject: [PATCH 254/293] Correct Laplacexz petsc implementation of g13 terms Off-diagonal terms for non-orthogonal meshes. Now includes ASCII art to explain what each term is doing. --- .../laplacexz/impls/petsc/laplacexz-petsc.cxx | 235 +++++++++++------- 1 file changed, 141 insertions(+), 94 deletions(-) diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index 91a229620a..24b62fe5d9 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -391,8 +391,9 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { for(int x=localmesh->xstart; x <= localmesh->xend; x++) { for(int z=0; z < localmesh->LocalNz; z++) { // stencil entries - PetscScalar c, xm, xp, zm, zp, xpzp, xpzm, xmzp, xmzm; - PetscScalar zpxp, zpxm, zmxp, zmxm; + PetscScalar c, xm, xp, zm, zp; + // Diagonal entries + PetscScalar xpzp{0.0}, xpzm{0.0}, xmzp{0.0}, xmzm{0.0}; // XX component { @@ -450,109 +451,154 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { } // XZ components - + // (1/J) d/dx ( A * J * g13 d/dz ) { - // x+1/2, z+1/2 - // TODOL Should they have a z dependency? + // + // x+1/2 + // + // --o------x-- + // | | z + // | c -> flux ^ + // | | | + // --o------x-- -> x + // + // Taking derivative in z (between corners marked x) + // so metrics at (x+1/2,z) + + // Metrics const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x + 1, y, z)); const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x + 1, y, z)); - const BoutReal fourdz = 2 * (coords->dz(x, y, z) + coords->dz(x + 1, y, zplus)); - { - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zplus)); - - const BoutReal val = - Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); - xpzp = val; - c -= val; - } - { - // x+1/2, z-1/2 - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); - - const BoutReal val = - -Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); - xpzm = val; - c -= val; - } + const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x + 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x + 1, y, z)); + + const BoutReal val = + Acoef * J * g13 / (coords->J(x, y, z) * dz * coords->dx(x, y, z)); + + // This val coefficient is multiplied by the (x+1/2,z+1/2) corner + // and (x+1/2,z-1/2) corner + + // (x+1/2,z+1/2) + //xp += 0.25 * val; Note cancels + xpzp += 0.25 * val; + zp += 0.25 * val; + //c += 0.25 * val; Note cancels + + // (x+1/2,z-1/2) + //xp -= 0.25 * val; Note cancels + xpzm -= 0.25 * val; + zm -= 0.25 * val; + //c -= 0.25 * val; Note cancels } { - // x-1/2, z+1/2 + // + // x-1/2 + // + // --x------o-- + // | | z + // flux -> c | ^ + // | | | + // --x------o-- -> x + // + // Taking derivative in z (between corners marked x) + // so metrics at (x-1/2,z) + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x - 1, y, z)); const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x - 1, y, z)); - const BoutReal fourdz = 2 * (coords->dz(x, y, z) + coords->dz(x - 1, y, z)); - { - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zplus)); - - const BoutReal val = - -Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); - xmzp = val; - c -= val; - } - { - // x-1/2, z-1/2 - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); - - const BoutReal val = - Acoef * J * g13 / (coords->J(x, y, z) * fourdz * coords->dx(x, y, z)); - xmzm = val; - c -= val; - } + const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x - 1, y, z)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x - 1, y, z)); + + const BoutReal val = + -Acoef * J * g13 / (coords->J(x, y, z) * dz * coords->dx(x, y, z)); + + // (x+1/2,z+1/2) + xpzp += 0.25 * val; + zp += 0.25 * val; + + // (x+1/2,z-1/2) + xpzm -= 0.25 * val; + zm -= 0.25 * val; } + // ZX components + // (1/J) d/dz ( A * J * g13 d/dx ) { - // ZX components - // z+1/2, x+1/2 + // z+1/2 + // + // flux + // ^ + // --x---|--x-- + // | | z + // | c | ^ + // | | | + // --o------o-- -> x + // + // Taking derivative in x (between corners marked x) + // so metrics at (x,z+1/2) + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x, y, zplus)); const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x, y, zplus)); - const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x, y, zplus)); + const BoutReal dx = 0.5 * (coords->dx(x, y, z) + coords->dx(x, y, zplus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zplus)); - { - const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x + 1, y, z)); - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x + 1, y, z)); - - const BoutReal val = Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); - zpxp = val; - c -= val; - } - { - // z+1/2, x-1/2 - const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x - 1, y, z)); - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x - 1, y, z)); - - const BoutReal val = -Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); - zpxm = val; - c -= val; - } + const BoutReal val = + Acoef * J * g13 / (coords->J(x, y, z) * dx * coords->dz(x, y, z)); + + // (x+1/2,z+1/2) + //zp += 0.25 * val; Note cancels + xpzp += 0.25 * val; + xp += 0.25 * val; + //c += 0.25 * val; Note cancels + + // (x-1/2,z+1/2) + //zp -= 0.25 * val; Note cancels + //c -= 0.25 * val; Note cancels + xm -= 0.25 * val; + xmzp -= 0.25 * val; } { - // z-1/2, x+1/2 + // z-1/2 + // + // --o------o-- + // | | z + // | c | ^ + // | ^ | | + // --x---|--x-- -> x + // flux + // + // Taking derivative in x (between corners marked x) + // so metrics at (x,z-1/2) + const BoutReal J = 0.5 * (coords->J(x, y, z) + coords->J(x, y, zminus)); const BoutReal g13 = 0.5 * (coords->g13(x, y, z) + coords->g13(x, y, zminus)); - const BoutReal dz = 0.5 * (coords->dz(x, y, z) + coords->dz(x, y, zminus)); - { - const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x + 1, y, z)); - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x + 1, y, z)); - - const BoutReal val = -Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); - zmxp = val; - c -= val; - } - { - // z-1/2, x-1/2 - const BoutReal dx = 2.0 * (coords->dx(x, y, z) + coords->dx(x - 1, y, z)); - const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x - 1, y, z)); - - const BoutReal val = Acoef * J * g13 / (coords->J(x, y, z) * dx * dz); - zmxm = val; - c -= val; - } + const BoutReal dx = 0.5 * (coords->dx(x, y, z) + coords->dx(x, y, zminus)); + const BoutReal Acoef = 0.5 * (A(x, y, z) + A(x, y, zminus)); + + const BoutReal val = + -Acoef * J * g13 / (coords->J(x, y, z) * dx * coords->dz(x, y, z)); + + // (x+1/2,z-1/2) + xpzm += 0.25 * val; + xp += 0.25 * val; + + // (x-1/2,z+1/2) + xm -= 0.25 * val; + xmzm -= 0.25 * val; } // B term c += B(x,y,z); ///////////////////////////////////////////////// - // Now have a 5-point stencil for the Laplacian + // Now have a 9-point stencil for the Laplacian + // + // o------o------o------o + // | xmzp | zp | xpzp | + // o------o------o------o + // | xm | c | xp | + // o------o------o------o + // | xmzm | zm | xpzm | + // o------o------o------o + // // Set the centre (diagonal) MatSetValues(it.MatA, 1, &row, 1, &row, &c, INSERT_VALUES); @@ -570,15 +616,16 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { if(z == localmesh->LocalNz-1) { col -= localmesh->LocalNz; // Wrap around } + MatSetValues(it.MatA, 1, &row, 1, &col, &zp, INSERT_VALUES); - int xzcol = col + (localmesh->LocalNz); // X+1 - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xpzp, INSERT_VALUES); - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zpxp, INSERT_VALUES); + // X + 1, Z + 1 + const int xpzp_col = col + localmesh->LocalNz; + MatSetValues(it.MatA, 1, &row, 1, &xpzp_col, &xpzp, INSERT_VALUES); - xzcol = col - (localmesh->LocalNz); // X-1 - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xmzp, INSERT_VALUES); - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zpxm, INSERT_VALUES); + // X - 1, Z + 1 + const int xmzp_col = col - localmesh->LocalNz; + MatSetValues(it.MatA, 1, &row, 1, &xmzp_col, &xmzp, INSERT_VALUES); // Z - 1 col = row - 1; @@ -587,13 +634,13 @@ void LaplaceXZpetsc::setCoefs(const Field3D &Ain, const Field3D &Bin) { } MatSetValues(it.MatA, 1, &row, 1, &col, &zm, INSERT_VALUES); - xzcol = col + (localmesh->LocalNz); // X+1 - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xpzm, INSERT_VALUES); - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zmxp, INSERT_VALUES); + // X + 1, Z - 1 + const int xpzm_col = col + localmesh->LocalNz; + MatSetValues(it.MatA, 1, &row, 1, &xpzm_col, &xpzm, INSERT_VALUES); - xzcol = col - (localmesh->LocalNz); // X-1 - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &xmzm, INSERT_VALUES); - MatSetValues(it.MatA, 1, &row, 1, &xzcol, &zmxm, INSERT_VALUES); + // X - 1, Z - 1 + const int xmzm_col = col - localmesh->LocalNz; + MatSetValues(it.MatA, 1, &row, 1, &xmzm_col, &xmzm, INSERT_VALUES); row++; } From 08d7771d966939e34068e6662c28f87a2c01ee44 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 8 Jan 2021 16:31:05 +0000 Subject: [PATCH 255/293] Write some documentation for 3D metrics --- CHANGELOG.md | 11 ++- manual/sphinx/index.rst | 1 + manual/sphinx/user_docs/new_in_v5.rst | 117 ++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 manual/sphinx/user_docs/new_in_v5.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index e9d45bcff0..817ed83ea0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,15 +43,20 @@ - The `LaplaceShoot` Laplacian implementation was removed. There are very few cases, if any, where this implementation actually works. [\#2177](https://github.com/boutproject/BOUT-dev/pull/2177) +- `PhysicsModel` expects the options `datadir` and `dump_format` to + have been set; this is only a problem if you don't call + `BoutInitialise`. [\#2062](https://github.com/boutproject/BOUT-dev/pull/2062) - `dz` is now a `Field2D`, and `Coordinates::zlength()` also returns a `Field2D`. In most cases, wrapping these in a call to `getUniform` in order to get a `BoutReal` will do the correct thing. If checks are enabled, `getUniform` will throw an exception if its argument is not uniform (that is, that all values are identical). [\#2025](https://github.com/boutproject/BOUT-dev/pull/2025) -- `PhysicsModel` expects the options `datadir` and `dump_format` to - have been set; this is only a problem if you don't call - `BoutInitialise`. [\#2062](https://github.com/boutproject/BOUT-dev/pull/2062) +- The parallel boundaries `BNDRY_PAR_FWD` and `BNDRY_PAR_BKWD` have + been expanded to distinguish between the inner and outer boundaries + in x; the enums have been replaced with `BNDRY_PAR_*_XIN`, and + `BNDRY_PAR_*_XOUT` for both `FWD` and + `BKWD`. [\#2025](https://github.com/boutproject/BOUT-dev/pull/2025) ## [v4.3.2](https://github.com/boutproject/BOUT-dev/tree/v4.3.2) (2020-10-19) diff --git a/manual/sphinx/index.rst b/manual/sphinx/index.rst index 2460b30025..79402cef63 100644 --- a/manual/sphinx/index.rst +++ b/manual/sphinx/index.rst @@ -28,6 +28,7 @@ The documentation is divided into the following sections: user_docs/installing user_docs/advanced_install user_docs/running_bout + user_docs/new_in_v5 .. toctree:: :maxdepth: 2 diff --git a/manual/sphinx/user_docs/new_in_v5.rst b/manual/sphinx/user_docs/new_in_v5.rst new file mode 100644 index 0000000000..8a1f5b0128 --- /dev/null +++ b/manual/sphinx/user_docs/new_in_v5.rst @@ -0,0 +1,117 @@ +.. _sec-newv5: + +============================= + New Features in BOUT++ v5.0 +============================= + +BOUT++ v5.0 is a new major release, adding tons of new features, improving +existing code, as well as removing some old and deprecated things. There are +some breaking changes which will require modifications to your physics model, +but for the vast majority we have provided tooling to automate this as much as +possible. + + +3D Metrics +========== + +Up until now, BOUT++ has been limited to varying the metric components only in +the XY plane. This release now introduces 3D metrics as a compile-time option, +allow simulations of devices such as stellarators. + +To enable 3D metrics, build BOUT++ like: + +.. code-block:: console + + ./configure --enable-metric-3D + +or, with CMake: + +.. code-block:: console + + cmake . -B build -DBOUT_ENABLE_METRIC_3D=ON + +Changes +------- + +Types +~~~~~ + +Adding 3D metrics to BOUT++ has been a substantial effort, requiring many +changes to a significant amount of the source code. The main change is that the +metric components, ``g11``, ``g22``, and so on, as well as the grid spacing, +``dx``, ``dy``, ``dz``, have changed from `Field2D` to +`Coordinates::FieldMetric`: a type alias for either `Field3D` or `Field2D` +depending on if BOUT++ was built with or without 3D metrics respectively. + +.. note:: + `Coordinates::dz` has also changed to be `Field2D` even without 3D + metrics. This is a breaking change, in that it may be necessary to change + user code in order to keep working. If you don't use 3D metrics, wrapping the + use of ``dz``, and similarly `Coordinates::zlength()`, in a call to + `getUniform` will return a ``BoutReal``. + + +The use of `Coordinates::FieldMetric` has been followed through the rest of the +code base. If a metric component enters an expression that previously contained +only `Field2D` and `BoutReal` types, the result is now a +`Coordinates::FieldMetric`. This means that functions that previously both took +and returned a `Field2D` now return a `Coordinates::FieldMetric` (we could have +chosen to make the return type ``auto`` instead and rely on the compiler to +deduce the correct type, but we have chosen to make the dependence on the metric +dimensionality more explicit). + +Because almost any operation on a vector involves the metric, the individual +components of `Vector2D` are now also of type +`Coordinates::FieldMetric`. Realistically, the use of `Vector2D` in a model +making use of 3D metrics is probably ill-advised. + +Indexing +~~~~~~~~ + +3D metrics also requires changes in how fields are indexed. In `BOUT_FOR` loops, +generally no changes are required, as they already do The Right Thing. In other +cases, simply changing, for example, ``dx(x, y)`` to ``dx(x, y, z)`` is +sufficient: in the 2D metric case, the third index is accepted and discarded. + +Many methods and operators have been upgraded to deal with 3D metrics. For +example, the `LaplaceXZpetsc` implementation has been modified to deal with +non-zero ``g_{xz}`` terms. + +FIXME WHEN COORDINATES REFACTORED +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order to simplify a lot of code, the call to `Coordinates::geometry`, which +calculates the connection coefficients `Coordinates::G1_11` and so on, has been +moved out of the `Coordinates` constructor. This is because computing the +coefficients involves derivatives which requires `Coordinates` and causes all +sorts of headaches and shims. As most users do not call the constructor +themselves anyway, this change should not be much of an issue. + + +Incompatibilities +----------------- + +Many features of BOUT++ have been written assuming an axisymmetric coordinate +system. Once 3D metrics are enabled, this is no longer (necessarily) true which +breaks several features. For instance, many of the Laplacian inversion solvers +use intrinsically 2D methods, and so are not available when using 3D +metrics. Most of these features are runtime options, and therefore will throw an +exception if you try to use them. To get a list of available Laplacian solvers, +for example, you can pass the ``--list-laplacians`` flag to a compiled BOUT++ +executable, which will print all the Laplacian solvers, noting which are +unavailable and why. + +Several boundary conditions are also incompatible with 3D metrics, unfortunately +at the time of writing there is no easy way to list those that are. Several of +these, such as ``zerolaplace`` have no alternative implementations, so this may +mean it is not possible to run a given model with 3D metrics. + +There are a few tests that don't work with 3D metrics, mostly because they rely +on one of the above incompatible methods or operators. + +There is a preprocessor macro, ``BOUT_USE_METRIC_3D``, and a ``constexpr bool``, +`bout::build::use_metric_3d`, which can be used to guard code that doesn't +compile or work with 3D metrics, or perhaps needs to be handled differently. + +Caution should be exercised with FFT-based methods. Technically, FFTs do work +with 3D metrics, but will not give the correct answer with non-constant ``dz``. From a5d147f76dc2e65c0ee370da661f55fb53f969a1 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 8 Jan 2021 17:14:15 +0000 Subject: [PATCH 256/293] Make boundary condition exception messages more explicit --- src/mesh/boundary_standard.cxx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index 098885847b..88a5dd5799 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -1600,8 +1600,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field2D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException("Applying boundary condition 'neumann_4thorder' to Field2D not " + "compatible with 3D metrics in all cases."); #endif } @@ -1887,8 +1887,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException("Applying boundary condition 'neumann' to Field2D " + "not compatible with 3D metrics in all cases."); #endif } @@ -2223,8 +2223,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException("Applying boundary condition 'neumann_O4' to Field2D not " + "compatible with 3D metrics in all cases."); #endif } @@ -2397,8 +2397,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { * sqrt(metric->g_22(bndry->x, bndry->y) / metric->g_22(bndry->x - bndry->bx, bndry->y - bndry->by)); #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException("Applying boundary condition 'neumannpar' to Field2D not " + "compatible with 3D metrics in all cases."); #endif } @@ -2549,8 +2549,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException("Applying boundary condition 'zerolaplace' to Field2D not " + "compatible with 3D metrics in all cases."); #endif } @@ -2653,8 +2653,8 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { } while (!bndry->isDone()); } #else - throw BoutException( - "Applying boundary to Field2D not compatible with 3D metrics in all cases."); + throw BoutException("Applying boundary condition 'zerolaplace2' to Field2D not " + "compatible with 3D metrics in all cases."); #endif } From b6d3420c6877911ee0e9e5d154cc2725d47a31a9 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 8 Jan 2021 17:27:31 +0000 Subject: [PATCH 257/293] Delete an extraneous interpolation of ShiftTorsion in Coordinates --- src/mesh/coordinates.cxx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index df1910adb5..6321d61a6e 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1017,9 +1017,6 @@ Coordinates::Coordinates(Mesh* mesh, Options* options, const CELL_LOC loc, true, true, false, transform.get()); } } - - ShiftTorsion = - interpolateAndNeumann(coords_in->ShiftTorsion, location, transform.get()); } void Coordinates::outputVars(Datafile& file) { From 10b2adf0313e90d16619a10f0e064fafefa47445 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 8 Jan 2021 17:31:22 +0000 Subject: [PATCH 258/293] Remove a couple of unhelpful comments --- src/mesh/coordinates.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 6321d61a6e..33190df9a1 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1260,7 +1260,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2z, "d2z" + suffix, 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); - d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) + d1_dz = bout::derivatives::index::DDZ(1. / dz); communicate(d1_dz); d1_dz = interpolateAndExtrapolate(d1_dz, location, true, true, true, transform.get()); @@ -1310,7 +1310,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2z, "d2z", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2z' not found. Calculating from dz\n"); - d1_dz = bout::derivatives::index::DDZ(1. / dz); // d/di(1/dy) + d1_dz = bout::derivatives::index::DDZ(1. / dz); communicate(d1_dz); d1_dz = From 819aed53c819b1f752786578e15c89b20b474a34 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 8 Jan 2021 17:31:29 +0000 Subject: [PATCH 259/293] Revert `MAYBE_UNUSED` attribute on Delp2 useFFT argument --- 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 33190df9a1..1ae50a648f 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1773,7 +1773,7 @@ Coordinates::FieldMetric Coordinates::Delp2(const Field2D& f, CELL_LOC outloc, return result; } -Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, MAYBE_UNUSED(bool useFFT)) { +Field3D Coordinates::Delp2(const Field3D& f, CELL_LOC outloc, bool useFFT) { TRACE("Coordinates::Delp2( Field3D )"); if (outloc == CELL_DEFAULT) { From 13c5af3ea84065b27138deb65c29d569ae0d1574 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Fri, 8 Jan 2021 17:33:28 +0000 Subject: [PATCH 260/293] Partially revert 4c06a94 Mesh::communicate is needed for parallel slices --- src/mesh/coordinates.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 1ae50a648f..38796c33ce 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1728,7 +1728,8 @@ Coordinates::FieldMetric Coordinates::Grad2_par2(const Field2D& f, CELL_LOC outl ASSERT1(location == outloc || (outloc == CELL_DEFAULT && location == f.getLocation())); auto invSg = 1.0 / sqrt(g_22); - communicate(invSg); + // Communicate to get parallel slices + localmesh->communicate(invSg); auto result = DDY(invSg, outloc, method) * DDY(f, outloc, method) * invSg + D2DY2(f, outloc, method) / g_22; @@ -1744,7 +1745,8 @@ Field3D Coordinates::Grad2_par2(const Field3D& f, CELL_LOC outloc, ASSERT1(location == outloc); auto invSg = 1.0 / sqrt(g_22); - communicate(invSg); + // Communicate to get parallel slices + localmesh->communicate(invSg); auto sg = DDY(invSg, outloc, method) * invSg; Field3D result = ::DDY(f, outloc, method); From d391e1b7c5c3b0c9c513c9c64ee0d41f6db7e5c0 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 11 Jan 2021 16:09:03 +0000 Subject: [PATCH 261/293] Fix previous merge for inner/outer parallel boundaries --- src/mesh/parallel/fci.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index f61576b27a..7eb93d661a 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -170,7 +170,7 @@ FCIMap::FCIMap(Mesh& mesh, const Field2D& dy, Options& options, int offset_, } } - if (xt_prime[i] >= 0.0) { + if ((xt_prime[i] >= 0.0) or (xt_prime[i] <= map_mesh.xend)) { // Not a boundary continue; } @@ -232,6 +232,10 @@ FCIMap::FCIMap(Mesh& mesh, const Field2D& dy, Options& options, int offset_, // Invert 2x2 matrix to get change in index const BoutReal dx = (dZ_dz * dR - dR_dz * dZ) / det; const BoutReal dz = (dR_dx * dZ - dZ_dx * dR) / det; + + // Negative xt_prime means we've hit the inner boundary, otherwise + // the outer boundary + auto* boundary = (xt_prime[i] < 0.0) ? inner_boundary : outer_boundary; boundary->add_point(x, y, z, x + dx, y + 0.5 * offset, z + dz, // Intersection point in local index space 0.5 * dy[i], // Distance to intersection From c99ac24c4999698938482fd61263b6e751da2ea2 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 11 Jan 2021 16:10:10 +0000 Subject: [PATCH 262/293] Revert use of abs(xt_prime) in FCI Part of wider, not yet implemented, parallel boundaries changes --- src/mesh/parallel/fci.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 7eb93d661a..78b4286ee3 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -244,7 +244,6 @@ FCIMap::FCIMap(Mesh& mesh, const Field2D& dy, Options& options, int offset_, } interp->setMask(boundary_mask); - interp->calcWeights(abs(xt_prime), zt_prime); } Field3D FCIMap::integrate(Field3D &f) const { From 502bc4d29bb879cba273bb6b8b2ad108374bbd37 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 11 Jan 2021 17:41:01 +0000 Subject: [PATCH 263/293] Change Field2D -> FieldMetric in FCI --- src/mesh/parallel/fci.cxx | 6 +++--- src/mesh/parallel/fci.hxx | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 78b4286ee3..fd985c91b9 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -47,9 +47,9 @@ #include -FCIMap::FCIMap(Mesh& mesh, const Field2D& dy, Options& options, int offset_, - BoundaryRegionPar* inner_boundary, BoundaryRegionPar* outer_boundary, - bool zperiodic) +FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& dy, Options& options, + int offset_, BoundaryRegionPar* inner_boundary, + BoundaryRegionPar* outer_boundary, bool zperiodic) : map_mesh(mesh), offset(offset_), boundary_mask(map_mesh), corner_boundary_mask(map_mesh) { diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index 8fc7de880c..b7f3045c32 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -44,7 +44,7 @@ class FCIMap { public: FCIMap() = delete; - FCIMap(Mesh& mesh, const Field2D& dy, Options& options, int offset, + FCIMap(Mesh& mesh, const Coordinates::FieldMetric& dy, Options& options, int offset, BoundaryRegionPar* inner_boundary, BoundaryRegionPar* outer_boundary, bool zperiodic); @@ -72,7 +72,8 @@ public: class FCITransform : public ParallelTransform { public: FCITransform() = delete; - FCITransform(Mesh& mesh, const Field2D& dy, bool zperiodic = true, Options* opt = nullptr) + FCITransform(Mesh& mesh, const Coordinates::FieldMetric& dy, bool zperiodic = true, + Options* opt = nullptr) : ParallelTransform(mesh, opt) { // check the coordinate system used for the grid data source From 8ee7727d5e9f9a0bcbd405c3c5fbead408aa444b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Mon, 11 Jan 2021 17:42:18 +0000 Subject: [PATCH 264/293] Disable crashing clang-tidy check clang-analyzer-optin.mpi.MPI-Checker crashes --- .github/workflows/clang-tidy-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 7fdcd203fb..bc9d6c445e 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -50,5 +50,5 @@ jobs: with: build_dir: build apt_packages: "libfftw3-dev,libnetcdf-c++4-dev,libhdf5-mpi-dev,libopenmpi-dev,petsc-dev,slepc-dev,liblapack-dev,libparpack2-dev,libsundials-dev" - clang_tidy_checks: '-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers' + clang_tidy_checks: '-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-clang-analyzer-optin.mpi*' From 97e369ed7dd5751ed501abb37cab609b71c82e8b Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 12 Jan 2021 10:38:31 +0000 Subject: [PATCH 265/293] Remove unused imports from laplacexz runtest --- tests/integrated/test-laplacexz/runtest | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index f1b8151e57..fe040fb6bd 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -9,18 +9,13 @@ # Run the test, compare results against the benchmark # -from __future__ import print_function -try: - from builtins import str -except: - pass tol = 1e-10 # Absolute tolerance -from boututils.run_wrapper import shell, shell_safe, launch_safe, getmpirun, build_and_log +from boututils.run_wrapper import shell, launch_safe, getmpirun, build_and_log from boutdata.collect import collect import numpy as np -from sys import stdout, exit +from sys import exit MPIRUN = getmpirun() From 9e9fc1df2a6c070950f2820d1fdc5a430649a063 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 12 Jan 2021 10:39:05 +0000 Subject: [PATCH 266/293] Apply black formatting to laplacexz runtest --- tests/integrated/test-laplacexz/runtest | 75 ++++++++++++------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/tests/integrated/test-laplacexz/runtest b/tests/integrated/test-laplacexz/runtest index fe040fb6bd..e9e91fabe8 100755 --- a/tests/integrated/test-laplacexz/runtest +++ b/tests/integrated/test-laplacexz/runtest @@ -1,22 +1,21 @@ #!/usr/bin/env python3 -#requires: not metric_3d -#requires: petsc +# requires: not metric_3d +# requires: petsc # travis doesn't have superlu_dist -#requires: not travis +# requires: not travis -# +# # Run the test, compare results against the benchmark # - -tol = 1e-10 # Absolute tolerance - from boututils.run_wrapper import shell, launch_safe, getmpirun, build_and_log from boutdata.collect import collect import numpy as np from sys import exit +tol = 1e-10 # Absolute tolerance + MPIRUN = getmpirun() build_and_log("LaplaceXZ test") @@ -24,36 +23,36 @@ build_and_log("LaplaceXZ test") print("Running LaplaceXZ test") success = True -for nproc in [1,2,4]: - nxpe = nproc - - cmd = "./test-laplacexz nxpe=" + str(nxpe) - - shell("rm data/BOUT.dmp.*.nc") - - print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) - s, out = launch_safe(cmd, runcmd=MPIRUN, nproc=nproc, mthread=1, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) - - # Collect output data - f = collect('f', path="data", info=False) - f2 = collect('f2', path="data", info=False) - stdout.write(" Checking tolerance... ") - # Compare benchmark and output - if np.shape(f) != np.shape(f2): - print("Fail, wrong shape") - success = False - diff = np.max(np.abs(f2) - f) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - else: - print("Pass") +for nproc in [1, 2, 4]: + nxpe = nproc + + cmd = "./test-laplacexz nxpe=" + str(nxpe) + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) + s, out = launch_safe(cmd, runcmd=MPIRUN, nproc=nproc, mthread=1, pipe=True) + with open("run.log." + str(nproc), "w") as f: + f.write(out) + + # Collect output data + f = collect("f", path="data", info=False) + f2 = collect("f2", path="data", info=False) + print(" Checking tolerance... ") + # Compare benchmark and output + if np.shape(f) != np.shape(f2): + print("Fail, wrong shape") + success = False + diff = np.max(np.abs(f2 - f)) + if diff > tol: + print("Fail, maximum difference = " + str(diff)) + success = False + else: + print("Pass") if success: - print(" => LaplaceXZ inversion test passed") - exit(0) -else: - print(" => LaplaceXZ test failed") - exit(1) + print(" => LaplaceXZ inversion test passed") + exit(0) + +print(" => LaplaceXZ test failed") +exit(1) From 94f1098784e431c6f0960c9d26918f90b445dc90 Mon Sep 17 00:00:00 2001 From: bshanahan Date: Tue, 12 Jan 2021 15:46:33 +0100 Subject: [PATCH 267/293] Give slightly more helpful error messages in fci.hxx when transforming to/fromFieldAligned --- src/mesh/parallel/fci.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index b7f3045c32..d32179a4e8 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -115,10 +115,10 @@ public: } const Field3D fromFieldAligned(const Field3D &UNUSED(f), const std::string& UNUSED(region) = "RGN_ALL") override { - throw BoutException("FCI method cannot transform into field aligned grid"); + throw BoutException("FCI method cannot transform from field aligned grid"); } const FieldPerp fromFieldAligned(const FieldPerp &UNUSED(f), const std::string& UNUSED(region) = "RGN_ALL") override { - throw BoutException("FCI method cannot transform into field aligned grid"); + throw BoutException("FCI method cannot transform from field aligned grid"); } bool canToFromFieldAligned() override { return false; } From d71321c1cede4a46a1b67d2b54bbc46b80619108 Mon Sep 17 00:00:00 2001 From: bshanahan Date: Wed, 13 Jan 2021 10:49:57 +0100 Subject: [PATCH 268/293] Initialize zt_prime_corner consistent with zt_prime --- src/mesh/parallel/fci.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index fd985c91b9..89aa426636 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -116,7 +116,7 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& dy, Options& options, // Cell corners Field3D xt_prime_corner{emptyFrom(xt_prime)}; - Field3D zt_prime_corner{emptyFrom(xt_prime)}; + Field3D zt_prime_corner{emptyFrom(zt_prime)}; BOUT_FOR(i, xt_prime_corner.getRegion("RGN_NOBNDRY")) { // Point interpolated from (x+1/2, z+1/2) From 792936ae4e92beb98233256a64d15a328ca24c65 Mon Sep 17 00:00:00 2001 From: bshanahan Date: Wed, 13 Jan 2021 11:21:49 +0100 Subject: [PATCH 269/293] remove stale comment in fv_ops.cxx --- src/mesh/fv_ops.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 28193bcb39..118b8139db 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -185,7 +185,6 @@ namespace FV { } // Z flux - // Easier since all metrics constant in Z for (int i = mesh->xstart; i <= mesh->xend; i++) { for (int j = mesh->ystart; j <= mesh->yend; j++) { From 3dfebb0d1f076d90a5466d475786770ab62e53a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 21 Jan 2021 16:04:18 +0100 Subject: [PATCH 270/293] In the case of 3D FCI we need to take care to not call index::DDY without ensuring that parallel slices are present. This partially reverts 5a77878a0e40b6bbb077e6d1bcbf912dba865ce0 --- include/bout/coordinates.hxx | 3 +++ src/mesh/coordinates.cxx | 41 ++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index 516460d71f..ee49f8c5f9 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -302,6 +302,9 @@ private: /// Set the parallel (y) transform from the options file. /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); +#if BOUT_USE_METRIC_3D + Field3D maybeFromFieldAligned(const Field3D&, const std::string&); +#endif }; /* diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index 5fa18360fc..ad76b26ad4 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1242,7 +1242,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2y, "d2y" + suffix, 0.0, false, location)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) + d1_dy = DDY(1. / dy); // d/di(1/dy) communicate(d1_dy); d1_dy = @@ -1294,7 +1294,7 @@ int Coordinates::geometry(bool recalculate_staggered, if (localmesh->get(d2y, "d2y", 0.0, false)) { output_warn.write( "\tWARNING: differencing quantity 'd2y' not found. Calculating from dy\n"); - d1_dy = bout::derivatives::index::DDY(1. / dy); // d/di(1/dy) + d1_dy = DDY(1. / dy); // d/di(1/dy) communicate(d1_dy); d1_dy = @@ -1617,11 +1617,34 @@ Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, const std::string& method, const std::string& region) { ASSERT1(location == loc || loc == CELL_DEFAULT); +#if BOUT_USE_METRIC_3D + if (!f.hasParallelSlices()) { + const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); + const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + Field3D result = bout::derivatives::index::DDY(f_aligned, loc, method, region); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result); + } +#endif return bout::derivatives::index::DDY(f, loc, method, region) / dy; } Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { +#if BOUT_USE_METRIC_3D + if (!f.hasParallelSlices()) { + const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); + Field3D f_aligned; + if (transform->canToFromFieldAligned()) { + f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; + } else { + Field3D f_parallel = f; + transform->calcParallelSlices(f_parallel); + return bout::derivatives::index::DDY(f_parallel, outloc, method, region); + } + Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); + return (is_unaligned ? maybeFromFieldAligned(result, region) : result); + } +#endif return bout::derivatives::index::DDY(f, outloc, method, region) / dy; }; @@ -2006,3 +2029,17 @@ Field2D Coordinates::Laplace_perpXY(MAYBE_UNUSED(const Field2D& A), throw BoutException("Coordinates::Laplace_perpXY for 3D metric not implemented"); #endif } + +#if BOUT_USE_METRIC_3D +Field3D Coordinates::maybeFromFieldAligned(const Field3D& f, const std::string& region) { + ASSERT1(location == f.getLocation()); + ASSERT1(localmesh == f.getMesh()); + if (f.getDirectionY() == YDirectionType::Standard) { + return f; + } + if (this->getParallelTransform().canToFromFieldAligned()) { + return this->getParallelTransform().fromFieldAligned(f, region); + } + return copy(f).setDirectionY(YDirectionType::Standard); +} +#endif From 294bc1481d573d5533e275eb7d893c830f6f6612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 22 Jan 2021 09:51:54 +0100 Subject: [PATCH 271/293] Only keep special case for 3D+FCI --- include/bout/coordinates.hxx | 3 --- src/mesh/coordinates.cxx | 38 ++++-------------------------------- 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/include/bout/coordinates.hxx b/include/bout/coordinates.hxx index ee49f8c5f9..516460d71f 100644 --- a/include/bout/coordinates.hxx +++ b/include/bout/coordinates.hxx @@ -302,9 +302,6 @@ private: /// Set the parallel (y) transform from the options file. /// Used in the constructor to create the transform object. void setParallelTransform(Options* options); -#if BOUT_USE_METRIC_3D - Field3D maybeFromFieldAligned(const Field3D&, const std::string&); -#endif }; /* diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index ad76b26ad4..892fa18f6d 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1617,32 +1617,16 @@ Coordinates::FieldMetric Coordinates::DDY(const Field2D& f, CELL_LOC loc, const std::string& method, const std::string& region) { ASSERT1(location == loc || loc == CELL_DEFAULT); -#if BOUT_USE_METRIC_3D - if (!f.hasParallelSlices()) { - const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - const Field3D f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; - Field3D result = bout::derivatives::index::DDY(f_aligned, loc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result); - } -#endif return bout::derivatives::index::DDY(f, loc, method, region) / dy; } Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& method, const std::string& region) { #if BOUT_USE_METRIC_3D - if (!f.hasParallelSlices()) { - const bool is_unaligned = (f.getDirectionY() == YDirectionType::Standard); - Field3D f_aligned; - if (transform->canToFromFieldAligned()) { - f_aligned = is_unaligned ? transform->toFieldAligned(f, "RGN_NOX") : f; - } else { - Field3D f_parallel = f; - transform->calcParallelSlices(f_parallel); - return bout::derivatives::index::DDY(f_parallel, outloc, method, region); - } - Field3D result = bout::derivatives::index::DDY(f_aligned, outloc, method, region); - return (is_unaligned ? maybeFromFieldAligned(result, region) : result); + if (! f.hasParallelSlices() and ! transform->canToFromFieldAligned()) { + Field3D f_parallel = f; + transform->calcParallelSlices(f_parallel); + return bout::derivatives::index::DDY(f_parallel, outloc, method, region); } #endif return bout::derivatives::index::DDY(f, outloc, method, region) / dy; @@ -2029,17 +2013,3 @@ Field2D Coordinates::Laplace_perpXY(MAYBE_UNUSED(const Field2D& A), throw BoutException("Coordinates::Laplace_perpXY for 3D metric not implemented"); #endif } - -#if BOUT_USE_METRIC_3D -Field3D Coordinates::maybeFromFieldAligned(const Field3D& f, const std::string& region) { - ASSERT1(location == f.getLocation()); - ASSERT1(localmesh == f.getMesh()); - if (f.getDirectionY() == YDirectionType::Standard) { - return f; - } - if (this->getParallelTransform().canToFromFieldAligned()) { - return this->getParallelTransform().fromFieldAligned(f, region); - } - return copy(f).setDirectionY(YDirectionType::Standard); -} -#endif From 51ee19c477a979d3a2a6ca2968dad9cdf8efaee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 9 Feb 2021 08:41:04 +0100 Subject: [PATCH 272/293] Chunk download osa isn't using numpy, so arrays are huge in memory. Chunking the download hugely helps reducing memory usage. --- tools/pylib/zoidberg/field.py | 46 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 28735cc01f..ecac0343f3 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -17,6 +17,8 @@ pickle_read_mode = "r" pickle_write_mode = "w" +from .progress import update_progress + class MagneticField(object): """Represents a magnetic field in either Cartesian or cylindrical @@ -1538,26 +1540,44 @@ def field_values(r, phi, z, configuration=0, plot_poincare=False): config = tracer.types.MagneticConfig() config.configIds = configuration - Br = np.zeros((nx, ny, nz)) - Bphi = np.ones((nx, ny, nz)) - Bz = np.zeros((nx, ny, nz)) + tot = nx * ny * nz + + Bx = np.zeros(tot) + By = np.zeros(tot) + Bz = np.zeros(tot) pos = tracer.types.Points3D() - pos.x1 = np.ndarray.flatten( + x1 = np.ndarray.flatten( np.ones((nx, ny, nz)) * r * np.cos(phi) ) # x in Cartesian (real-space) - pos.x2 = np.ndarray.flatten( + x2 = np.ndarray.flatten( np.ones((nx, ny, nz)) * r * np.sin(phi) ) # y in Cartesian (real-space) - pos.x3 = np.ndarray.flatten(z) # z in Cartesian (real-space) - - ## Call tracer service - res = tracer.service.magneticField(pos, config) - + x3 = np.ndarray.flatten(z) # z in Cartesian (real-space) + chunk = 100000 + if tot > chunk * 2: + update_progress(0) + for i in range(0, tot, chunk): + end = i + chunk + end = min(end, tot) + slc = slice(i, end) + pos.x1 = x1[slc] + pos.x2 = x2[slc] + pos.x3 = x3[slc] + + ## Call tracer service + res = tracer.service.magneticField(pos, config) + + Bx[slc] = res.field.x1 + By[slc] = res.field.x2 + Bz[slc] = res.field.x3 + + if tot > chunk * 2: + update_progress((i + 1) / tot) ## Reshape to 3d array - Bx = np.ndarray.reshape(np.asarray(res.field.x1), (nx, ny, nz)) - By = np.ndarray.reshape(np.asarray(res.field.x2), (nx, ny, nz)) - Bz = np.ndarray.reshape(np.asarray(res.field.x3), (nx, ny, nz)) + Bx = Bx.reshape((nx, ny, nz)) + By = By.reshape((nx, ny, nz)) + Bz = Bz.reshape((nx, ny, nz)) ## Convert to cylindrical coordinates Br = Bx * np.cos(phi) + By * np.sin(phi) From 0a59fbf6a7c5bd4097dedcb9d5141c985f55c52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 9 Feb 2021 08:41:39 +0100 Subject: [PATCH 273/293] Add some ducumentation --- tools/pylib/zoidberg/field.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index ecac0343f3..47875017a2 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -1430,6 +1430,17 @@ def __init__( include_plasma_field=False, wout_file="wout_w7x.0972_0926_0880_0852_+0000_+0000.01.00jh.nc", ): + """ + Get the field for W7X from the webservices. + + Parameters + ---------- + configuration : int + The id's are listed here: + http://webservices.ipp-hgw.mpg.de/docs/fieldlinetracer.html#MagneticConfig + While the description are at: + http://svvmec1.ipp-hgw.mpg.de:8080/vmecrest/v1/Coil_currents_1_AA_T_0011.pdf + """ from scipy.interpolate import RegularGridInterpolator import numpy as np From 66a642df9c17f75a206f38d29e6b7aee2f4040bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 9 Feb 2021 08:49:48 +0100 Subject: [PATCH 274/293] Fix progress bar * total count was off * local count was off * move to end and add plus one to ensure we always end with 100% Previously it was sometimes 99.99%, which is confusing if it crashes afterwards. * float is not needed, we are using python3, division defaults to true_div --- tools/pylib/zoidberg/zoidberg.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index d12e807c11..f1f8c3392b 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -111,15 +111,14 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): parallel_slices.append(ParallelSlice(offset, *fields)) # Total size of the progress bar - total_work = float((len(parallel_slices) - 1) * (ny-1)) + total_work = len(parallel_slices) * ny # TODO: if axisymmetric, don't loop, do one slice and copy # TODO: restart tracing for adjacent offsets + if (not quiet) and (ny > 1): + update_progress(0, **kwargs) for slice_index, parallel_slice in enumerate(parallel_slices): for j in range(ny): - if (not quiet) and (ny > 1): - update_progress(float(slice_index * j) / total_work, **kwargs) - # Get this poloidal grid pol, ycoord = grid.getPoloidalGrid(j) @@ -152,6 +151,9 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): parallel_slice.xt_prime[:, j, :] = xind parallel_slice.zt_prime[:, j, :] = zind + if (not quiet) and (ny > 1): + update_progress((slice_index * ny + j + 1) / total_work, **kwargs) + return maps From 1ae9d86eb75c11de633a900197657d51b3a73c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 9 Feb 2021 08:51:24 +0100 Subject: [PATCH 275/293] Add underrelaxation * This seems to help with numerical convergence. --- tools/pylib/zoidberg/poloidal_grid.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/pylib/zoidberg/poloidal_grid.py b/tools/pylib/zoidberg/poloidal_grid.py index 72b10aba3e..bc21a6c675 100644 --- a/tools/pylib/zoidberg/poloidal_grid.py +++ b/tools/pylib/zoidberg/poloidal_grid.py @@ -383,7 +383,10 @@ def findIndex(self, R, Z, tol=1e-10, show=False): if show and plotting_available: plt.plot(self.R, self.Z, '.') plt.plot(R, Z, 'x') - + + cnt = 0 + underrelax = 1 + print() while True: # Use Newton iteration to find the index # dR, dZ are the distance away from the desired point @@ -395,8 +398,18 @@ def findIndex(self, R, Z, tol=1e-10, show=False): # Check if close enough # Note: only check the points which are not in the boundary - if np.amax(mask*(dR**2 + dZ**2)) < tol: + val = np.amax(mask*(dR**2 + dZ**2)) + if val < tol: break + cnt += 1 + if cnt == 10: + underrelax = 1.5 + if cnt == 100: + underrelax = 2 + if cnt == 1000: + underrelax = 2.5 + if cnt == 10000: + underrelax = 3 # Calculate derivatives dRdx, dZdx = self.getCoordinate(xind, zind, dx=1) @@ -412,8 +425,9 @@ def findIndex(self, R, Z, tol=1e-10, show=False): # (y) (-dZ/dx dR/dx ) (dZ) / (dR/dx*dZ/dy - dR/dy*dZ/dx) determinant = dRdx*dZdz - dRdz*dZdx - xind -= mask * ((dZdz*dR - dRdz*dZ) / determinant) - zind -= mask * ((dRdx*dZ - dZdx*dR) / determinant) + xind -= mask * ((dZdz*dR - dRdz*dZ) / determinant / underrelax) + zind -= mask * ((dRdx*dZ - dZdx*dR) / determinant / underrelax) + # Re-check for boundary in_boundary = xind < 0.5 From 7915e1ac673db7956155e7581d12f05186d5687d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 9 Feb 2021 08:53:59 +0100 Subject: [PATCH 276/293] black --- tools/pylib/zoidberg/__init__.py | 10 +- tools/pylib/zoidberg/boundary.py | 22 +- tools/pylib/zoidberg/field.py | 60 ++- tools/pylib/zoidberg/fieldtracer.py | 164 +++---- tools/pylib/zoidberg/grid.py | 126 +++--- tools/pylib/zoidberg/plot.py | 235 ++++++---- tools/pylib/zoidberg/poloidal_grid.py | 488 +++++++++++---------- tools/pylib/zoidberg/progress.py | 35 +- tools/pylib/zoidberg/rzline.py | 234 +++++----- tools/pylib/zoidberg/test_field.py | 16 +- tools/pylib/zoidberg/test_fieldtracer.py | 79 ++-- tools/pylib/zoidberg/test_grid.py | 19 +- tools/pylib/zoidberg/test_poloidal_grid.py | 30 +- tools/pylib/zoidberg/test_rzline.py | 55 ++- tools/pylib/zoidberg/test_zoidberg.py | 16 +- tools/pylib/zoidberg/zoidberg.py | 201 +++++---- 16 files changed, 1015 insertions(+), 775 deletions(-) diff --git a/tools/pylib/zoidberg/__init__.py b/tools/pylib/zoidberg/__init__.py index f6830c78ff..48ed10027f 100644 --- a/tools/pylib/zoidberg/__init__.py +++ b/tools/pylib/zoidberg/__init__.py @@ -11,4 +11,12 @@ from .zoidberg import make_maps, write_maps -__all__ = ["field", "fieldtracer", "grid", "make_maps", "plot", "write_maps", "zoidberg"] +__all__ = [ + "field", + "fieldtracer", + "grid", + "make_maps", + "plot", + "write_maps", + "zoidberg", +] diff --git a/tools/pylib/zoidberg/boundary.py b/tools/pylib/zoidberg/boundary.py index bafb5dc10c..3c478a588e 100644 --- a/tools/pylib/zoidberg/boundary.py +++ b/tools/pylib/zoidberg/boundary.py @@ -6,9 +6,8 @@ class NoBoundary(object): - """No boundary, so no points outside + """No boundary, so no points outside""" - """ def outside(self, x, y, z): """Returns True if the point is outside the boundary @@ -57,8 +56,10 @@ def outside(self, x, y, z): """ - return np.logical_or( np.logical_or( x < self.xmin, x > self.xmax), - np.logical_or( z < self.zmin, z > self.zmax)) + return np.logical_or( + np.logical_or(x < self.xmin, x > self.xmax), + np.logical_or(z < self.zmin, z > self.zmax), + ) class PolygonBoundaryXZ(object): @@ -74,7 +75,7 @@ def __init__(self, xarr, zarr): """ # Find a point outside the polygon - self.zout = np.amax(zarr) + 1.0 # Somewhere outside the polygon + self.zout = np.amax(zarr) + 1.0 # Somewhere outside the polygon self.xarr = xarr self.zarr = zarr @@ -115,12 +116,12 @@ def outside(self, x, y, z): # changes True->False->True i.e. XOR nsegments = len(self.xarr) - for i in range(nsegments): # Loop over all segments + for i in range(nsegments): # Loop over all segments xp_0 = self.xarr[i] zp_0 = self.zarr[i] - ip = (i + 1) % nsegments # Next point + ip = (i + 1) % nsegments # Next point xp_1 = self.xarr[ip] zp_1 = self.zarr[ip] @@ -131,10 +132,11 @@ def outside(self, x, y, z): b = (x_0 - xp_0) / (xp_1 - xp_0) - a = (zp_0 - z_0 + b * (zp_1 - zp_0))/(z_1 - z_0) + a = (zp_0 - z_0 + b * (zp_1 - zp_0)) / (z_1 - z_0) - intersect = np.logical_and( np.logical_and( b >= 0.0, b <= 1.0), - np.logical_and( a >= 0.0, a <= 1.0)) + intersect = np.logical_and( + np.logical_and(b >= 0.0, b <= 1.0), np.logical_and(a >= 0.0, a <= 1.0) + ) # intersect is now true for those points which intersect this line segment outside = np.logical_xor(outside, intersect) diff --git a/tools/pylib/zoidberg/field.py b/tools/pylib/zoidberg/field.py index 47875017a2..2ec358a4e9 100644 --- a/tools/pylib/zoidberg/field.py +++ b/tools/pylib/zoidberg/field.py @@ -54,7 +54,7 @@ class MagneticField(object): """ - boundary = boundary.NoBoundary() # An optional Boundary object + boundary = boundary.NoBoundary() # An optional Boundary object attributes = {} def Bxfunc(self, x, z, phi): @@ -157,7 +157,11 @@ def Bmag(self, x, z, phi): The magnitude of the magnetic field """ - return np.sqrt( self.Bxfunc(x,z,phi)**2 + self.Byfunc(x,z,phi)**2 + self.Bzfunc(x,z,phi)**2 ) + return np.sqrt( + self.Bxfunc(x, z, phi) ** 2 + + self.Byfunc(x, z, phi) ** 2 + + self.Bzfunc(x, z, phi) ** 2 + ) def field_direction(self, pos, ycoord, flatten=False): """Calculate the direction of the magnetic field @@ -189,34 +193,36 @@ def field_direction(self, pos, ycoord, flatten=False): if flatten: position = pos.reshape((-1, 2)) - x = position[:,0] - z = position[:,1] + x = position[:, 0] + z = position[:, 1] else: - x,z = pos + x, z = pos - By = self.Byfunc(x,z,ycoord) - Rmaj = self.Rfunc(x,z,ycoord) # Major radius. None if Cartesian + By = self.Byfunc(x, z, ycoord) + Rmaj = self.Rfunc(x, z, ycoord) # Major radius. None if Cartesian if Rmaj is not None: # In cylindrical coordinates if np.amin(np.abs(By)) < 1e-8: # Very small By - print(x,z,ycoord, By) - raise ValueError("Small By ({}) at (x={}, y={}, z={})".format(By, x, ycoord, z)) + print(x, z, ycoord, By) + raise ValueError( + "Small By ({}) at (x={}, y={}, z={})".format(By, x, ycoord, z) + ) R_By = Rmaj / By # Rate of change of x location [m] with y angle [radians] - dxdphi = R_By * self.Bxfunc(x,z,ycoord) + dxdphi = R_By * self.Bxfunc(x, z, ycoord) # Rate of change of z location [m] with y angle [radians] - dzdphi = R_By * self.Bzfunc(x,z,ycoord) + dzdphi = R_By * self.Bzfunc(x, z, ycoord) else: # In Cartesian coordinates # Rate of change of x location [m] with y angle [radians] - dxdphi = self.Bxfunc(x,z,ycoord) / By + dxdphi = self.Bxfunc(x, z, ycoord) / By # Rate of change of z location [m] with y angle [radians] - dzdphi = self.Bzfunc(x,z,ycoord) / By + dzdphi = self.Bzfunc(x, z, ycoord) / By if flatten: result = np.column_stack((dxdphi, dzdphi)).flatten() @@ -245,6 +251,7 @@ class Slab(MagneticField): Rate of change of Bz with x """ + def __init__(self, By=1.0, Bz=0.1, xcentre=0.0, Bzprime=1.0): By = float(By) @@ -264,7 +271,7 @@ def Byfunc(self, x, z, phi): return np.full(x.shape, self.By) def Bzfunc(self, x, z, phi): - return self.Bz + (x - self.xcentre)*self.Bzprime + return self.Bz + (x - self.xcentre) * self.Bzprime class CurvedSlab(MagneticField): @@ -291,6 +298,7 @@ class CurvedSlab(MagneticField): Major radius of the slab """ + def __init__(self, By=1.0, Bz=0.1, xcentre=0.0, Bzprime=1.0, Rmaj=1.0): By = float(By) @@ -306,10 +314,10 @@ def __init__(self, By=1.0, Bz=0.1, xcentre=0.0, Bzprime=1.0, Rmaj=1.0): self.Rmaj = Rmaj # Set poloidal magnetic field - #Bpx = self.Bp + (self.grid.xarray-self.grid.Lx/2.) * self.Bpprime - #self.Bpxy = np.resize(Bpx, (self.grid.nz, self.grid.ny, self.grid.nx)) - #self.Bpxy = np.transpose(self.Bpxy, (2,1,0)) - #self.Bxy = np.sqrt(self.Bpxy**2 + self.Bt**2) + # Bpx = self.Bp + (self.grid.xarray-self.grid.Lx/2.) * self.Bpprime + # self.Bpxy = np.resize(Bpx, (self.grid.nz, self.grid.ny, self.grid.nx)) + # self.Bpxy = np.transpose(self.Bpxy, (2,1,0)) + # self.Bxy = np.sqrt(self.Bpxy**2 + self.Bt**2) def Bxfunc(self, x, z, phi): return np.zeros(x.shape) @@ -1480,9 +1488,19 @@ def __init__( # we can get an interpolation function in 3D points = (r, phi, z) - self.br_interp = RegularGridInterpolator( - points, Bx, bounds_error=False, fill_value=0.0 - ) + try: + self.br_interp = RegularGridInterpolator( + points, Bx, bounds_error=False, fill_value=0.0 + ) + except: + print([i.shape for i in points], Bx.shape) + import matplotlib.pyplot as plt + + for i in points: + plt.plot(i) + plt.show() + raise + self.bz_interp = RegularGridInterpolator( points, Bz, bounds_error=False, fill_value=0.0 ) diff --git a/tools/pylib/zoidberg/fieldtracer.py b/tools/pylib/zoidberg/fieldtracer.py index 54cedc4309..e6dc1ce741 100644 --- a/tools/pylib/zoidberg/fieldtracer.py +++ b/tools/pylib/zoidberg/fieldtracer.py @@ -71,7 +71,9 @@ def follow_field_lines(self, x_values, z_values, y_values, rtol=None): elif z_values.size == 1: z_values = np.zeros(x_values.shape) + z_values else: - raise ValueError("x_values and z_values must be the same size, or one must be a scalar") + raise ValueError( + "x_values and z_values must be the same size, or one must be a scalar" + ) array_shape = x_values.shape @@ -87,8 +89,9 @@ def follow_field_lines(self, x_values, z_values, y_values, rtol=None): if len(x_values) < 1000: position = np.column_stack((x_values, z_values)).flatten() - result = odeint(self.field_direction, position, y_values, args=(True,), - rtol=rtol) + result = odeint( + self.field_direction, position, y_values, args=(True,), rtol=rtol + ) else: # Split into smaller pieces @@ -100,16 +103,16 @@ def follow_field_lines(self, x_values, z_values, y_values, rtol=None): z_values = np.array_split(z_values, nchunks) # Combine x,z into flattened position arrays - chunks = [ np.column_stack((x, z)).flatten() for x,z in zip(x_values, z_values) ] + chunks = [ + np.column_stack((x, z)).flatten() for x, z in zip(x_values, z_values) + ] # Process in chunks. Note: multiprocessing has trouble with closures # so fails in Python 2. Python 3 may work - results = [odeint(self.field_direction, - chunk, - y_values, - args=(True,), - rtol=rtol) - for chunk in chunks] + results = [ + odeint(self.field_direction, chunk, y_values, args=(True,), rtol=rtol) + for chunk in chunks + ] # Concatenate results into a single array result = np.concatenate(results, axis=1) @@ -141,6 +144,7 @@ class FieldTracerReversible(object): Number of sub-steps between outputs """ + def __init__(self, field, rtol=1e-8, eps=1e-5, nsteps=20): self.field_direction = field.field_direction @@ -148,7 +152,9 @@ def __init__(self, field, rtol=1e-8, eps=1e-5, nsteps=20): self.eps = float(eps) self.nsteps = int(nsteps) - def follow_field_lines(self, x_values, z_values, y_values, rtol=None, eps=None, nsteps=None): + def follow_field_lines( + self, x_values, z_values, y_values, rtol=None, eps=None, nsteps=None + ): """Uses field_direction to follow the magnetic field from every grid (x,z) point at toroidal angle y through a change in toroidal angle dy @@ -192,7 +198,7 @@ def follow_field_lines(self, x_values, z_values, y_values, rtol=None, eps=None, # Check settings, use defaults if not given if rtol is None: - rtol = self.rtol # Value set in __init__ + rtol = self.rtol # Value set in __init__ rtol = float(rtol) if eps is None: eps = self.eps @@ -205,7 +211,7 @@ def follow_field_lines(self, x_values, z_values, y_values, rtol=None, eps=None, x_values = np.atleast_1d(x_values) y_values = np.atleast_1d(y_values) z_values = np.atleast_1d(z_values) - + if len(y_values) < 2: raise ValueError("There must be at least two elements in y_values") if len(y_values.shape) > 1: @@ -218,90 +224,93 @@ def follow_field_lines(self, x_values, z_values, y_values, rtol=None, eps=None, elif z_values.size == 1: z_values = np.zeros(x_values.shape) + z_values else: - raise ValueError("x_values and z_values must be the same size, or one must be a scalar") + raise ValueError( + "x_values and z_values must be the same size, or one must be a scalar" + ) array_shape = x_values.shape - - result = np.zeros((len(y_values),)+ array_shape + (2,)) + + result = np.zeros((len(y_values),) + array_shape + (2,)) # Starting position x_pos = x_values z_pos = z_values y_pos = y_values[0] - - result[0,...,0] = x_pos - result[0,...,1] = z_pos - + + result[0, ..., 0] = x_pos + result[0, ..., 1] = z_pos + for yindex, y_next in enumerate(y_values[1:]): - yindex += 1 # Since we chopped off the first y_value - + yindex += 1 # Since we chopped off the first y_value + # Split into sub-steps dy = (y_next - y_pos) / float(nsteps) for step in range(nsteps): # Evaluate gradient at current position - dxdy, dzdy = self.field_direction( (x_pos, z_pos), y_pos ) - + dxdy, dzdy = self.field_direction((x_pos, z_pos), y_pos) + # Half-step values - x_half = x_pos + 0.5*dxdy*dy - z_half = z_pos + 0.5*dzdy*dy - + x_half = x_pos + 0.5 * dxdy * dy + z_half = z_pos + 0.5 * dzdy * dy + # Now need to find the roots of a nonlinear equation # # f = 0.5*(dpos/dy)(pos_next)*dy - (pos_next - pos_half) = 0 - # - + # + # Use Euler method to get starting guess - x_pos += dxdy*dy - z_pos += dzdy*dy + x_pos += dxdy * dy + z_pos += dzdy * dy y_pos += dy - + while True: - dxdy, dzdy = self.field_direction( (x_pos, z_pos), y_pos ) - + dxdy, dzdy = self.field_direction((x_pos, z_pos), y_pos) + # Calculate derivatives (Jacobian matrix) by finite difference - dxdy_xe, dzdy_xe = self.field_direction( (x_pos+eps, z_pos), y_pos ) - dxdy_x = (dxdy_xe - dxdy)/eps - dzdy_x = (dzdy_xe - dzdy)/eps - - dxdy_ze, dzdy_ze = self.field_direction( (x_pos, z_pos+eps), y_pos ) - dxdy_z = (dxdy_ze - dxdy)/eps - dzdy_z = (dzdy_ze - dzdy)/eps - + dxdy_xe, dzdy_xe = self.field_direction((x_pos + eps, z_pos), y_pos) + dxdy_x = (dxdy_xe - dxdy) / eps + dzdy_x = (dzdy_xe - dzdy) / eps + + dxdy_ze, dzdy_ze = self.field_direction((x_pos, z_pos + eps), y_pos) + dxdy_z = (dxdy_ze - dxdy) / eps + dzdy_z = (dzdy_ze - dzdy) / eps + # The function we are trying to find the roots of: - fx = 0.5*dxdy*dy - x_pos + x_half - fz = 0.5*dzdy*dy - z_pos + z_half - + fx = 0.5 * dxdy * dy - x_pos + x_half + fz = 0.5 * dzdy * dy - z_pos + z_half + # Now have a linear system to solve # # (x_pos) -= ( dfx/dx dfx/dz )^-1 (fx) # (z_pos) ( dfz/dx dfz/dz ) (fz) - - dfxdx = 0.5*dxdy_x*dy - 1.0 - dfxdz = 0.5*dxdy_z*dy - dfzdx = 0.5*dzdy_x*dy - dfzdz = 0.5*dzdy_z*dy - 1.0 - - determinant = dfxdx*dfzdz - dfxdz*dfzdx + + dfxdx = 0.5 * dxdy_x * dy - 1.0 + dfxdz = 0.5 * dxdy_z * dy + dfzdx = 0.5 * dzdy_x * dy + dfzdz = 0.5 * dzdy_z * dy - 1.0 + + determinant = dfxdx * dfzdz - dfxdz * dfzdx # Note: If determinant is too small then dt should be reduced - + dx = (dfzdz * fx - dfxdz * fz) / determinant dz = (dfxdx * fz - dfzdx * fx) / determinant - + x_pos -= dx z_pos -= dz # Check for convergence within tolerance - if np.amax(dx**2 + dz**2) < rtol: + if np.amax(dx ** 2 + dz ** 2) < rtol: break # Finished Newton iteration, taken step to (x_pos,y_pos,z_pos) # Finished sub-steps, reached y_pos = y_next - result[yindex,...,0] = x_pos - result[yindex,...,1] = z_pos - + result[yindex, ..., 0] = x_pos + result[yindex, ..., 1] = z_pos + return result -def trace_poincare(magnetic_field, xpos, zpos, yperiod, nplot=3, - y_slices=None, revs=20, nover=20): +def trace_poincare( + magnetic_field, xpos, zpos, yperiod, nplot=3, y_slices=None, revs=20, nover=20 +): """Trace a Poincare graph of the field lines Does no plotting, see :py:func:`zoidberg.plot.plot_poincare` @@ -339,13 +348,16 @@ def trace_poincare(magnetic_field, xpos, zpos, yperiod, nplot=3, if nplot is None and y_slices is None: raise ValueError("nplot and y_slices cannot both be None") - + if y_slices is not None: y_slices = np.asfarray(y_slices) - + if np.amin(y_slices) < 0.0 or np.amax(y_slices) > yperiod: - raise ValueError("y_slices must all be between 0.0 and yperiod ({yperiod})" - .format(yperiod=yperiod)) + raise ValueError( + "y_slices must all be between 0.0 and yperiod ({yperiod})".format( + yperiod=yperiod + ) + ) # Make sure y_slices is monotonically increasing y_slices.sort() # If y_slices is given, then nplot is the number of slices @@ -356,18 +368,20 @@ def trace_poincare(magnetic_field, xpos, zpos, yperiod, nplot=3, y_slices = np.linspace(0, yperiod, nplot, endpoint=False) # Extend the domain from [0,yperiod] to [0,revs*yperiod] - - revs = int(revs) + + revs = int(revs) y_values = y_slices[:] for n in np.arange(1, revs): - y_values = np.append(y_values, n*yperiod + y_values[:nplot]) - - nover = int(nover) # Over-sample - y_values_over = np.zeros( ( nplot * revs * nover - (nover-1)) ) + y_values = np.append(y_values, n * yperiod + y_values[:nplot]) + + nover = int(nover) # Over-sample + y_values_over = np.zeros((nplot * revs * nover - (nover - 1))) y_values_over[::nover] = y_values - for i in range(1,nover): - y_values_over[i::nover] = (float(i)/float(nover))*y_values[1:] + (float(nover-i)/float(nover))*y_values[:-1] - + for i in range(1, nover): + y_values_over[i::nover] = (float(i) / float(nover)) * y_values[1:] + ( + float(nover - i) / float(nover) + ) * y_values[:-1] + # Starting location xpos = np.asfarray(xpos) zpos = np.asfarray(zpos) @@ -375,9 +389,9 @@ def trace_poincare(magnetic_field, xpos, zpos, yperiod, nplot=3, field_tracer = FieldTracer(magnetic_field) result = field_tracer.follow_field_lines(xpos, zpos, y_values_over) - result = result[::nover,...] # Remove unneeded points + result = result[::nover, ...] # Remove unneeded points # Reshape data. Loops fastest over planes (nplot) - result = np.reshape(result, (revs, nplot)+result.shape[1:]) + result = np.reshape(result, (revs, nplot) + result.shape[1:]) return result, y_slices diff --git a/tools/pylib/zoidberg/grid.py b/tools/pylib/zoidberg/grid.py index 8ca964517b..33948c1c31 100644 --- a/tools/pylib/zoidberg/grid.py +++ b/tools/pylib/zoidberg/grid.py @@ -59,14 +59,18 @@ def __init__(self, poloidal_grids, ycoords, Ly, yperiodic=False, name="fci_grid" self.ycoords = np.asfarray(ycoords) self.Ly = Ly self.yperiodic = yperiodic - + # Define the shape of the grid self.shape = (nx, len(ycoords), nz) - + def __repr__(self): - return "Grid({0}, {1}:{2}:{3}, yperiodic={4})".format(self.poloidal_grids, - np.amin(self.ycoords), np.amax(self.ycoords), self.ycoords.size, - self.yperiodic) + return "Grid({0}, {1}:{2}:{3}, yperiodic={4})".format( + self.poloidal_grids, + np.amin(self.ycoords), + np.amax(self.ycoords), + self.ycoords.size, + self.yperiodic, + ) def numberOfPoloidalGrids(self): """Returns the number of poloidal grids i.e. number of points in Y @@ -98,7 +102,7 @@ def getPoloidalGrid(self, yindex): """ yindex = int(yindex) - + ny = self.ycoords.size if (yindex >= 0) and (yindex < ny): @@ -107,28 +111,28 @@ def getPoloidalGrid(self, yindex): # Only one grid return self.poloidal_grids, self.ycoords[yindex] return self.poloidal_grids[yindex], self.ycoords[yindex] - + # Out of range - + if self.yperiodic: # Periodic domain # Map index into domain - y_remap = np.remainder(yindex, ny) # 0 <= yremap < ny + y_remap = np.remainder(yindex, ny) # 0 <= yremap < ny # Get number of periods around the domain. Note this can be negative - nperiods = np.floor( float(yindex) / float(ny) ) + nperiods = np.floor(float(yindex) / float(ny)) + + ycoord = self.ycoords[y_remap] + nperiods * self.Ly - ycoord = self.ycoords[y_remap] + nperiods*self.Ly - if self._ngrids == 1: return self.poloidal_grids, ycoord return self.poloidal_grids[y_remap], ycoord - + # Not periodic - + if yindex < 0: - return None, 0.0 # Hit the lower end in Y + return None, 0.0 # Hit the lower end in Y return None, self.Ly # Hit the upper end in Y def metric(self): @@ -146,58 +150,67 @@ def metric(self): # Gather dx,dz and x-z metrics from poloidal slices dx = np.zeros(self.shape) dz = np.zeros(self.shape) - + gxx = np.zeros(self.shape) gxz = np.zeros(self.shape) gzz = np.zeros(self.shape) - + g_xx = np.zeros(self.shape) g_xz = np.zeros(self.shape) g_zz = np.zeros(self.shape) - + # Separate grids for each slice for y in range(self.shape[1]): pol_metric = self.getPoloidalGrid(y)[0].metric() - dx[:,y,:] = pol_metric["dx"] - dz[:,y,:] = pol_metric["dz"] - - gxx[:,y,:] = pol_metric["gxx"] - gxz[:,y,:] = pol_metric["gxz"] - gzz[:,y,:] = pol_metric["gzz"] - - g_xx[:,y,:] = pol_metric["g_xx"] - g_xz[:,y,:] = pol_metric["g_xz"] - g_zz[:,y,:] = pol_metric["g_zz"] - + dx[:, y, :] = pol_metric["dx"] + dz[:, y, :] = pol_metric["dz"] + + gxx[:, y, :] = pol_metric["gxx"] + gxz[:, y, :] = pol_metric["gxz"] + gzz[:, y, :] = pol_metric["gzz"] + + g_xx[:, y, :] = pol_metric["g_xx"] + g_xz[:, y, :] = pol_metric["g_xz"] + g_zz[:, y, :] = pol_metric["g_zz"] + # Calculate the gradient of the y coordinate w.r.t index # To avoid edge effects, repeat array three times then take the middle - ycoords = np.concatenate( (self.ycoords - self.Ly, self.ycoords, self.ycoords + self.Ly) ) + ycoords = np.concatenate( + (self.ycoords - self.Ly, self.ycoords, self.ycoords + self.Ly) + ) ny = self.ycoords.size if ny == 1: dy = np.array([self.Ly]) else: - dy = np.gradient(ycoords[ny:(2*ny)]) - + dy = np.gradient(ycoords[ny : (2 * ny)]) + dy3d = np.zeros(self.shape) for i in range(self.shape[1]): - dy3d[:,i,:] = dy[i] + dy3d[:, i, :] = dy[i] # Note: These y metrics are for Cartesian coordinates # If in cylindrical coordinates then these should be different g_yy = np.ones(self.shape) gyy = np.ones(self.shape) - return {"dx":dx, "dy":dy3d, "dz": dz, - "gyy": gyy, "g_yy":g_yy, - "gxx": gxx, "g_xx":g_xx, - "gxz": gxz, "g_xz":g_xz, - "gzz": gzz, "g_zz":g_zz} - - -def rectangular_grid(nx, ny, nz, - Lx=1.0, Ly=10., Lz=1.0, - xcentre=0.0, zcentre=0.0, - yperiodic=False): + return { + "dx": dx, + "dy": dy3d, + "dz": dz, + "gyy": gyy, + "g_yy": g_yy, + "gxx": gxx, + "g_xx": g_xx, + "gxz": gxz, + "g_xz": g_xz, + "gzz": gzz, + "g_zz": g_zz, + } + + +def rectangular_grid( + nx, ny, nz, Lx=1.0, Ly=10.0, Lz=1.0, xcentre=0.0, zcentre=0.0, yperiodic=False +): """Create a rectangular grid in (x,y,z) Here y is along the magnetic field (typically toroidal angle), and @@ -222,27 +235,22 @@ def rectangular_grid(nx, ny, nz, # In this simple case we only need one RectangularPoloidalGrid # to represent all poloidal planes - - poloidal_grid = RectangularPoloidalGrid(nx, nz, Lx, Lz, - xcentre, - zcentre) + + poloidal_grid = RectangularPoloidalGrid(nx, nz, Lx, Lz, xcentre, zcentre) if yperiodic: ycoords = np.linspace(0.0, Ly, ny, endpoint=False) else: # Doesn't include the end points - ycoords = (np.arange(ny) + 0.5)*Ly/float(ny) - - return Grid( poloidal_grid, - ycoords, - Ly, - yperiodic=yperiodic ) - - + ycoords = (np.arange(ny) + 0.5) * Ly / float(ny) + + return Grid(poloidal_grid, ycoords, Ly, yperiodic=yperiodic) + + if __name__ == "__main__": - - grid = rectangular_grid(10,10,10) + + grid = rectangular_grid(10, 10, 10) p = grid.getPoloidalGrid(-2) - + print(grid) diff --git a/tools/pylib/zoidberg/plot.py b/tools/pylib/zoidberg/plot.py index 8fdcfc687d..58b0c24a60 100644 --- a/tools/pylib/zoidberg/plot.py +++ b/tools/pylib/zoidberg/plot.py @@ -7,14 +7,24 @@ try: import matplotlib.animation as anim import matplotlib.pyplot as plt + plotting_available = True except ImportError: warnings.warn("Couldn't import matplotlib, plotting not available.") plotting_available = False -def plot_poincare(magnetic_field, xpos, zpos, yperiod, nplot=3, y_slices=None, revs=40, nover=20, - interactive=False): +def plot_poincare( + magnetic_field, + xpos, + zpos, + yperiod, + nplot=3, + y_slices=None, + revs=40, + nover=20, + interactive=False, +): """Plot a Poincare graph of the field lines. Parameters @@ -48,40 +58,47 @@ def plot_poincare(magnetic_field, xpos, zpos, yperiod, nplot=3, y_slices=None, r return # Get Poincare plot - result, y_slices = fieldtracer.trace_poincare(magnetic_field, xpos, zpos, yperiod, - nplot=nplot, y_slices=y_slices, revs=revs, - nover=nover) + result, y_slices = fieldtracer.trace_poincare( + magnetic_field, + xpos, + zpos, + yperiod, + nplot=nplot, + y_slices=y_slices, + revs=revs, + nover=nover, + ) nplot = len(y_slices) - + ####################################################### # Plotting colours = ["k", "b", "r", "g", "c", "m"] if nplot > len(colours): - colours += colours * np.floor(nplot/len(colours)) - - fig, ax = plt.subplots(1,1) - + colours += colours * np.floor(nplot / len(colours)) + + fig, ax = plt.subplots(1, 1) + for index in range(nplot): - r = result[:,index,..., 0] - z = result[:,index,..., 1] + r = result[:, index, ..., 0] + z = result[:, index, ..., 1] style = { - 'marker' : '.', - 'color' : colours[index], - 'linestyle' : 'None', - } + "marker": ".", + "color": colours[index], + "linestyle": "None", + } ax.plot(r, z, **style) ax.set_xlabel("Radius [m]", fontsize=20) ax.set_ylabel("Height [m]", fontsize=20) - ax.tick_params(axis='both', labelsize=15) - + ax.tick_params(axis="both", labelsize=15) + for phi, colour in zip(y_slices, colours): - ax.plot([], [], color=colour, label=r'$Y = {0:.2f}$'.format(phi)) + ax.plot([], [], color=colour, label=r"$Y = {0:.2f}$".format(phi)) ax.legend() - overplot, = ax.plot([], [], 'ok') + (overplot,) = ax.plot([], [], "ok") def onclick(event): # Check if user clicked inside the plot @@ -97,12 +114,12 @@ def onclick(event): # Right mouse if event.button == 3: x_, z_ = overplot.get_data() - x_ = np.append(x_, result[:,0]) - z_ = np.append(z_, result[:,1]) + x_ = np.append(x_, result[:, 0]) + z_ = np.append(z_, result[:, 1]) # Left mouse else: - x_ = result[:,0] - z_ = result[:,1] + x_ = result[:, 0] + z_ = result[:, 1] overplot.set_data(x_, z_) ax.relim() @@ -111,13 +128,13 @@ def onclick(event): if interactive: field_tracer = fieldtracer.FieldTracer(magnetic_field) - - revs = int(revs) + + revs = int(revs) y_values = y_slices[:] for n in np.arange(1, revs): - y_values = np.append(y_values, n*yperiod + y_values[:nplot]) - - fig.canvas.mpl_connect('button_press_event', onclick) + y_values = np.append(y_values, n * yperiod + y_values[:nplot]) + + fig.canvas.mpl_connect("button_press_event", onclick) plt.show() return fig, ax @@ -153,8 +170,8 @@ def plot_3d_field_line(magnetic_field, xpos, zpos, yperiod, cycles=20, y_res=50) yperiod = float(yperiod) # Go round toroidally cycles times - phivals_hires = np.linspace(0, cycles*yperiod, num=y_res*cycles, endpoint=False) - + phivals_hires = np.linspace(0, cycles * yperiod, num=y_res * cycles, endpoint=False) + xpos = np.asfarray(xpos) zpos = np.asfarray(zpos) @@ -165,14 +182,18 @@ def plot_3d_field_line(magnetic_field, xpos, zpos, yperiod, cycles=20, y_res=50) phivals_hires_mod = np.remainder(phivals_hires, yperiod) # There are cycles sets of field lines y_res points long each # and we also need to transpose for reasons - phivals_hires_mod = phivals_hires_mod.reshape( (cycles, y_res) ).T + phivals_hires_mod = phivals_hires_mod.reshape((cycles, y_res)).T # Same for the result, but only swap first and second indices - result_hires_mod = result_hires.reshape( (cycles,y_res,2) ).transpose(1,0,2) + result_hires_mod = result_hires.reshape((cycles, y_res, 2)).transpose(1, 0, 2) fig = plt.figure() - ax = fig.gca(projection='3d') + ax = fig.gca(projection="3d") for n in range(cycles): - ax.plot(result_hires_mod[:,n,0], result_hires_mod[:,n,1], phivals_hires_mod[:,n]) + ax.plot( + result_hires_mod[:, n, 0], + result_hires_mod[:, n, 1], + phivals_hires_mod[:, n], + ) plt.show() @@ -205,25 +226,28 @@ def plot_streamlines(grid, magnetic_field, y_slice=0, width=None, **kwargs): warnings.warning("matplotlib not available, unable to plot") return - fig, ax = plt.subplots(1,1) + fig, ax = plt.subplots(1, 1) full_slice = np.s_[:, y_slice, :] if width is not None: # Get the B field magnitude in the poloidal plane - bxz_mag = np.sqrt(magnetic_field.b_mag**2 - magnetic_field.by**2) - linewidth = width*(bxz_mag[full_slice] / bxz_mag.max()).T + bxz_mag = np.sqrt(magnetic_field.b_mag ** 2 - magnetic_field.by ** 2) + linewidth = width * (bxz_mag[full_slice] / bxz_mag.max()).T else: linewidth = 1 - ax.streamplot(grid.xarray, grid.zarray, - magnetic_field.bx[full_slice].T, - magnetic_field.bz[full_slice].T, - linewidth=linewidth, - **kwargs) + ax.streamplot( + grid.xarray, + grid.zarray, + magnetic_field.bx[full_slice].T, + magnetic_field.bz[full_slice].T, + linewidth=linewidth, + **kwargs + ) ax.set_xlabel("Radius [m]", fontsize=20) ax.set_ylabel("Height [m]", fontsize=20) - ax.tick_params(axis='both', labelsize=15) + ax.tick_params(axis="both", labelsize=15) plt.show() @@ -260,16 +284,19 @@ def __init__(self, X, Y, U, V): self.frames = U.shape[0] - self.fig, self.ax = plt.subplots(1,1) - self.quiv_plot = self.ax.quiver(X, Y, U[0,...].T, V[0,...].T, pivot='mid', angles='xy') + self.fig, self.ax = plt.subplots(1, 1) + self.quiv_plot = self.ax.quiver( + X, Y, U[0, ...].T, V[0, ...].T, pivot="mid", angles="xy" + ) def __update_quiver(self, num): - self.quiv_plot.set_UVC(self.U[num,...].T, self.V[num,...].T) - return self.quiv_plot, + self.quiv_plot.set_UVC(self.U[num, ...].T, self.V[num, ...].T) + return (self.quiv_plot,) def animate(self): - self.animation = anim.FuncAnimation(self.fig, self.__update_quiver, frames=self.frames, - interval=100, blit=False) + self.animation = anim.FuncAnimation( + self.fig, self.__update_quiver, frames=self.frames, interval=100, blit=False + ) plt.show() plt.draw() @@ -296,33 +323,52 @@ def plot_forward_map(grid, maps, yslice=0): if not plotting_available: warnings.warning("matplotlib not available, unable to plot") return - + nx, ny, nz = grid.shape - + pol, ycoord = grid.getPoloidalGrid(yslice) - pol_next, ycoord_next = grid.getPoloidalGrid(yslice+1) - + pol_next, ycoord_next = grid.getPoloidalGrid(yslice + 1) + # Plot the points on yslice+1 as 'bx' # Note: ravel used here only so multiple labels are not created - plt.plot(np.ravel(pol_next.R), np.ravel(pol_next.Z), 'bx', label="Grid points on slice {0}".format(yslice+1)) - + plt.plot( + np.ravel(pol_next.R), + np.ravel(pol_next.Z), + "bx", + label="Grid points on slice {0}".format(yslice + 1), + ) + # Plot the forward map from yslice to yslice+1 as red 'o' - forward_R = maps['forward_R'][:,yslice,:] - forward_Z = maps['forward_Z'][:,yslice,:] - plt.plot(np.ravel(forward_R), np.ravel(forward_Z), 'ro', label="Forward map from slice {0}".format(yslice)) - + forward_R = maps["forward_R"][:, yslice, :] + forward_Z = maps["forward_Z"][:, yslice, :] + plt.plot( + np.ravel(forward_R), + np.ravel(forward_Z), + "ro", + label="Forward map from slice {0}".format(yslice), + ) + # Mark the points which hit the inner boundary # These are marked with a negative x index - in_boundary = maps['forward_xt_prime'][:,yslice,:] < 0.0 - plt.plot( np.ravel(forward_R[ in_boundary ]), np.ravel(forward_Z[ in_boundary ]), 'ko', label="Inner boundary points") - + in_boundary = maps["forward_xt_prime"][:, yslice, :] < 0.0 + plt.plot( + np.ravel(forward_R[in_boundary]), + np.ravel(forward_Z[in_boundary]), + "ko", + label="Inner boundary points", + ) + # Outer boundary marked with x index nx - out_boundary = maps['forward_xt_prime'][:,yslice,:] > nx-0.5 - plt.plot( np.ravel(forward_R[ out_boundary ]), np.ravel(forward_Z[ out_boundary ]), 'bo', label="Outer boundary points") - - + out_boundary = maps["forward_xt_prime"][:, yslice, :] > nx - 0.5 + plt.plot( + np.ravel(forward_R[out_boundary]), + np.ravel(forward_Z[out_boundary]), + "bo", + label="Outer boundary points", + ) + plt.legend() - + plt.show() @@ -350,29 +396,48 @@ def plot_backward_map(grid, maps, yslice=0): return nx, ny, nz = grid.shape - + pol, ycoord = grid.getPoloidalGrid(yslice) - pol_last, ycoord_last = grid.getPoloidalGrid(yslice-1) - + pol_last, ycoord_last = grid.getPoloidalGrid(yslice - 1) + # Plot the points on yslice-1 as 'bx' # Note: ravel used here only so multiple labels are not created - plt.plot(np.ravel(pol_last.R), np.ravel(pol_last.Z), 'bx', label="Grid points on slice {0}".format(yslice-1)) - + plt.plot( + np.ravel(pol_last.R), + np.ravel(pol_last.Z), + "bx", + label="Grid points on slice {0}".format(yslice - 1), + ) + # Plot the backward map from yslice to yslice-1 as red 'o' - backward_R = maps['backward_R'][:,yslice,:] - backward_Z = maps['backward_Z'][:,yslice,:] - plt.plot(np.ravel(backward_R), np.ravel(backward_Z), 'ro', label="Backward map from slice {0}".format(yslice)) - + backward_R = maps["backward_R"][:, yslice, :] + backward_Z = maps["backward_Z"][:, yslice, :] + plt.plot( + np.ravel(backward_R), + np.ravel(backward_Z), + "ro", + label="Backward map from slice {0}".format(yslice), + ) + # Mark the points which hit the inner boundary # These are marked with a negative x index - in_boundary = maps['backward_xt_prime'][:,yslice,:] < 0.0 - plt.plot( np.ravel(backward_R[ in_boundary ]), np.ravel(backward_Z[ in_boundary ]), 'ko', label="Inner boundary points") - + in_boundary = maps["backward_xt_prime"][:, yslice, :] < 0.0 + plt.plot( + np.ravel(backward_R[in_boundary]), + np.ravel(backward_Z[in_boundary]), + "ko", + label="Inner boundary points", + ) + # Outer boundary marked with x index nx - out_boundary = maps['backward_xt_prime'][:,yslice,:] > nx-0.5 - plt.plot( np.ravel(backward_R[ out_boundary ]), np.ravel(backward_Z[ out_boundary ]), 'bo', label="Outer boundary points") - - + out_boundary = maps["backward_xt_prime"][:, yslice, :] > nx - 0.5 + plt.plot( + np.ravel(backward_R[out_boundary]), + np.ravel(backward_Z[out_boundary]), + "bo", + label="Outer boundary points", + ) + plt.legend() - + plt.show() diff --git a/tools/pylib/zoidberg/poloidal_grid.py b/tools/pylib/zoidberg/poloidal_grid.py index bc21a6c675..5616cc86cd 100644 --- a/tools/pylib/zoidberg/poloidal_grid.py +++ b/tools/pylib/zoidberg/poloidal_grid.py @@ -27,6 +27,7 @@ try: import matplotlib.pyplot as plt + plotting_available = True except ImportError: warnings.warn("Couldn't import matplotlib, plotting not available.") @@ -79,14 +80,14 @@ def plot(self, axis=None, show=True): if axis is None: fig = plt.figure() - axis = fig.add_subplot(1,1,1) + axis = fig.add_subplot(1, 1, 1) - axis.plot(self.R, self.Z, 'k-') - axis.plot(self.R.T, self.Z.T, 'k-') + axis.plot(self.R, self.Z, "k-") + axis.plot(self.R.T, self.Z.T, "k-") if show: plt.show() - + return axis @@ -131,25 +132,29 @@ def __init__(self, nx, nz, Lx, Lz, Rcentre=0.0, Zcentre=0.0, MXG=2): self.Lx = Lx self.Lz = Lz - + self.Rcentre = Rcentre self.Zcentre = Zcentre - + # Some useful derived quantities # Note: index at the middle of the domain is (nx - 1)/2 # e.g. nx=5 : 0 1 | 2 | 3 4 - self.dR = self.Lx/(self.nx-2*MXG) - self.dZ = self.Lz/self.nz - self.Rmin = self.Rcentre - self.dR * (self.nx-1.0)/2.0 - self.Zmin = self.Zcentre - self.dZ * (self.nz-1.0)/2.0 + self.dR = self.Lx / (self.nx - 2 * MXG) + self.dZ = self.Lz / self.nz + self.Rmin = self.Rcentre - self.dR * (self.nx - 1.0) / 2.0 + self.Zmin = self.Zcentre - self.dZ * (self.nz - 1.0) / 2.0 # Generate 2D arrays # Using getCoordinate to ensure consistency - xind, zind = np.meshgrid(np.arange(nx), np.arange(nz), indexing='ij') + xind, zind = np.meshgrid(np.arange(nx), np.arange(nz), indexing="ij") self.R, self.Z = self.getCoordinate(xind, zind) - + def __repr__(self): - return "RectangularPoloidalGrid({0},{1},{2},{3},Rcentre={4},Zcentre={5})".format(self.nx, self.nz, self.Lx, self.Lz, self.Rcentre, self.Zcentre) + return ( + "RectangularPoloidalGrid({0},{1},{2},{3},Rcentre={4},Zcentre={5})".format( + self.nx, self.nz, self.Lx, self.Lz, self.Rcentre, self.Zcentre + ) + ) def getCoordinate(self, xind, zind, dx=0, dz=0): """Get coordinates (R,Z) at given (xind,zind) index @@ -177,17 +182,17 @@ def getCoordinate(self, xind, zind, dx=0, dz=0): # Make sure dx and dz are integers dx = int(dx) dz = int(dz) - + assert xind.shape == zind.shape assert dx >= 0 assert dz >= 0 - + shape = xind.shape - + if dx + dz > 2: # Second derivatives and mixed derivatives all zero return np.zeros(shape), np.zeros(shape) - + if dx == 1: # dR/dx, dZ/dx return np.full(shape, self.dR), np.zeros(shape) @@ -195,7 +200,7 @@ def getCoordinate(self, xind, zind, dx=0, dz=0): # dR/dz, dZ/dz return np.zeros(shape), np.full(shape, self.dZ) # Return (R,Z) location - return self.Rmin + xind*self.dR, self.Zmin + zind*self.dZ + return self.Rmin + xind * self.dR, self.Zmin + zind * self.dZ def findIndex(self, R, Z): """Finds the (x,z) index corresponding to the given (R,Z) coordinate @@ -215,17 +220,17 @@ def findIndex(self, R, Z): # Make sure inputs are NumPy arrays R = np.asfarray(R) Z = np.asfarray(Z) - + # Check that they have the same shape assert R.shape == Z.shape - xind = (R - self.Rmin)/self.dR - zind = (Z - self.Zmin)/self.dZ + xind = (R - self.Rmin) / self.dR + zind = (Z - self.Zmin) / self.dZ # Note: These indices may be outside the domain, # but this is handled in BOUT++, and useful for periodic # domains. - + return xind, zind def metric(self): @@ -241,10 +246,16 @@ def metric(self): - **gxx, gxz, gzz**: Covariant components - **g_xx, g_xz, g_zz**: Contravariant components """ - return {"dx": self.dR, "dz": self.dZ, # Grid spacing - "gxx": 1.0, "g_xx": 1.0, - "gxz": 0.0, "g_xz": 0.0, - "gzz": 1.0, "g_zz": 1.0} + return { + "dx": self.dR, + "dz": self.dZ, # Grid spacing + "gxx": 1.0, + "g_xx": 1.0, + "gxz": 0.0, + "g_xz": 0.0, + "gzz": 1.0, + "g_zz": 1.0, + } class StructuredPoloidalGrid(PoloidalGrid): @@ -268,33 +279,34 @@ class StructuredPoloidalGrid(PoloidalGrid): modified afterwards """ + def __init__(self, R, Z): - + assert R.shape == Z.shape - + self.R = R self.Z = Z - + # Create a KDTree for quick lookup of nearest points n = R.size - data = np.concatenate( (R.reshape((n,1)), Z.reshape((n,1)) ), axis=1) + data = np.concatenate((R.reshape((n, 1)), Z.reshape((n, 1))), axis=1) self.tree = KDTree(data) - + # Create splines for quick interpolation of coordinates - nx,nz = R.shape + nx, nz = R.shape self.nx = nx self.nz = nz - + xinds = np.arange(nx) - zinds = np.arange(nz+1) + zinds = np.arange(nz + 1) # Repeat the final point in y since periodic in y - R_ext = np.concatenate((R, np.reshape(R[:,0], (nx, 1))), axis=1) - Z_ext = np.concatenate((Z, np.reshape(Z[:,0], (nx, 1))), axis=1) - + R_ext = np.concatenate((R, np.reshape(R[:, 0], (nx, 1))), axis=1) + Z_ext = np.concatenate((Z, np.reshape(Z[:, 0], (nx, 1))), axis=1) + self._spl_r = RectBivariateSpline(xinds, zinds, R_ext) self._spl_z = RectBivariateSpline(xinds, zinds, Z_ext) - + def __repr__(self): return "StructuredPoloidalGrid()" @@ -317,18 +329,18 @@ def getCoordinate(self, xind, zind, dx=0, dz=0): indices if dx,dz != 0 """ - nx,nz = self.R.shape - if (np.amin(xind) < 0) or (np.amax(xind) > nx-1): + nx, nz = self.R.shape + if (np.amin(xind) < 0) or (np.amax(xind) > nx - 1): raise ValueError("x index out of range") - + # Periodic in y zind = np.remainder(zind, nz) - + R = self._spl_r(xind, zind, dx=dx, dy=dz, grid=False) Z = self._spl_z(xind, zind, dx=dx, dy=dz, grid=False) - - return R,Z - + + return R, Z + def findIndex(self, R, Z, tol=1e-10, show=False): """Finds the (x, z) index corresponding to the given (R, Z) coordinate @@ -349,40 +361,41 @@ def findIndex(self, R, Z, tol=1e-10, show=False): # Make sure inputs are NumPy arrays R = np.asfarray(R) Z = np.asfarray(Z) - + # Check that they have the same shape assert R.shape == Z.shape - + input_shape = R.shape # So output has same shape as input - + # Get distance and index into flattened data # Note ind can be an integer, or an array of ints # with the same number of elements as the input (R,Z) arrays n = R.size - position = np.concatenate( (R.reshape((n,1)), Z.reshape((n,1))), axis=1) - + position = np.concatenate((R.reshape((n, 1)), Z.reshape((n, 1))), axis=1) + R = R.reshape((n,)) Z = Z.reshape((n,)) - + dists, ind = self.tree.query(position) - + # Calculate (x,y) index - nx,nz = self.R.shape + nx, nz = self.R.shape xind = np.floor_divide(ind, nz) - zind = ind - xind*nz - + zind = ind - xind * nz + # Convert indices to float xind = np.asfarray(xind) zind = np.asfarray(zind) - + # Create a mask for the positions mask = np.ones(xind.shape) - mask[ np.logical_or((xind < 0.5), (xind > (nx-1.5))) ] = 0.0 # Set to zero if near the boundary - - + mask[ + np.logical_or((xind < 0.5), (xind > (nx - 1.5))) + ] = 0.0 # Set to zero if near the boundary + if show and plotting_available: - plt.plot(self.R, self.Z, '.') - plt.plot(R, Z, 'x') + plt.plot(self.R, self.Z, ".") + plt.plot(R, Z, "x") cnt = 0 underrelax = 1 @@ -390,15 +403,15 @@ def findIndex(self, R, Z, tol=1e-10, show=False): while True: # Use Newton iteration to find the index # dR, dZ are the distance away from the desired point - Rpos,Zpos = self.getCoordinate(xind, zind) + Rpos, Zpos = self.getCoordinate(xind, zind) if show and plotting_available: - plt.plot(Rpos, Zpos, 'o') + plt.plot(Rpos, Zpos, "o") dR = Rpos - R dZ = Zpos - Z - + # Check if close enough # Note: only check the points which are not in the boundary - val = np.amax(mask*(dR**2 + dZ**2)) + val = np.amax(mask * (dR ** 2 + dZ ** 2)) if val < tol: break cnt += 1 @@ -410,42 +423,41 @@ def findIndex(self, R, Z, tol=1e-10, show=False): underrelax = 2.5 if cnt == 10000: underrelax = 3 - + # Calculate derivatives dRdx, dZdx = self.getCoordinate(xind, zind, dx=1) dRdz, dZdz = self.getCoordinate(xind, zind, dz=1) - + # Invert 2x2 matrix to get change in coordinates # - # (x) -= ( dR/dx dR/dz )^-1 (dR) - # (y) ( dZ/dx dZ/dz ) (dz) + # (x) -= ( dR/dx dR/dz )^-1 (dR) + # (y) ( dZ/dx dZ/dz ) (dz) # # - # (x) -= ( dZ/dz -dR/dz ) (dR) + # (x) -= ( dZ/dz -dR/dz ) (dR) # (y) (-dZ/dx dR/dx ) (dZ) / (dR/dx*dZ/dy - dR/dy*dZ/dx) - determinant = dRdx*dZdz - dRdz*dZdx - - xind -= mask * ((dZdz*dR - dRdz*dZ) / determinant / underrelax) - zind -= mask * ((dRdx*dZ - dZdx*dR) / determinant / underrelax) + determinant = dRdx * dZdz - dRdz * dZdx + + xind -= mask * ((dZdz * dR - dRdz * dZ) / determinant / underrelax) + zind -= mask * ((dRdx * dZ - dZdx * dR) / determinant / underrelax) - # Re-check for boundary in_boundary = xind < 0.5 - mask[ in_boundary ] = 0.0 # Set to zero if near the boundary - xind[ in_boundary ] = 0.0 - out_boundary = xind > (nx-1.5) - mask[ out_boundary ] = 0.0 # Set to zero if near the boundary - xind[ out_boundary ] = nx-1 + mask[in_boundary] = 0.0 # Set to zero if near the boundary + xind[in_boundary] = 0.0 + out_boundary = xind > (nx - 1.5) + mask[out_boundary] = 0.0 # Set to zero if near the boundary + xind[out_boundary] = nx - 1 if show and plotting_available: plt.show() - + # Set xind to -1 if in the inner boundary, nx if in outer boundary in_boundary = xind < 0.5 - xind[ in_boundary ] = -1 - out_boundary = xind > (nx-1.5) - xind[ out_boundary ] = nx - + xind[in_boundary] = -1 + out_boundary = xind > (nx - 1.5) + xind[out_boundary] = nx + return xind.reshape(input_shape), zind.reshape(input_shape) def metric(self): @@ -461,12 +473,12 @@ def metric(self): """ - dx = 1.0 / float(self.nx-1) # x from 0 to 1 - dz = 2.*np.pi / float(self.nz) # z from 0 to 2pi - + dx = 1.0 / float(self.nx - 1) # x from 0 to 1 + dz = 2.0 * np.pi / float(self.nz) # z from 0 to 2pi + # Get arrays of indices - xind, zind = np.meshgrid(np.arange(self.nx), np.arange(self.nz), indexing='ij') - + xind, zind = np.meshgrid(np.arange(self.nx), np.arange(self.nz), indexing="ij") + # Calculate the gradient along each coordinate dRdx, dZdx = self.getCoordinate(xind, zind, dx=1) dRdx /= dx @@ -474,24 +486,30 @@ def metric(self): dRdz, dZdz = self.getCoordinate(xind, zind, dz=1) dRdz /= dz dZdz /= dz - - g_xx = dRdx**2 + dZdx**2 - g_xz = dRdx*dRdz + dZdx*dZdz - g_zz = dRdz**2 + dZdz**2 - + + g_xx = dRdx ** 2 + dZdx ** 2 + g_xz = dRdx * dRdz + dZdx * dZdz + g_zz = dRdz ** 2 + dZdz ** 2 + # Calculate metric by inverting # ( gxx gxz ) = ( g_xx g_xz )^-1 # ( gxz gzz ) ( g_xz g_zz ) - - determinant = g_xx*g_zz - g_xz**2 + + determinant = g_xx * g_zz - g_xz ** 2 gxx = g_zz / determinant gzz = g_xx / determinant gxz = -g_xz / determinant - - return {"dx": dx, "dz": dz, # Grid spacing - "gxx": gxx, "g_xx": g_xx, - "gxz": gxz, "g_xz": g_xz, - "gzz": gzz, "g_zz": g_zz} + + return { + "dx": dx, + "dz": dz, # Grid spacing + "gxx": gxx, + "g_xx": g_xx, + "gxz": gxz, + "g_xz": g_xz, + "gzz": gzz, + "g_zz": g_zz, + } def grid_annulus(inner, outer, nx, nz, show=True, return_coords=False): @@ -524,17 +542,17 @@ def grid_annulus(inner, outer, nx, nz, show=True, return_coords=False): assert nx >= 2 assert nz > 1 - + R = zeros((nx, nz)) Z = zeros((nx, nz)) - + # Generate angle values, which should now be equally spaced # in distance along inner and outer boundaries - thetavals = linspace(0, 2*pi, nz, endpoint=False) - + thetavals = linspace(0, 2 * pi, nz, endpoint=False) + # Radial coordinate xvals = linspace(0, 1.0, nx, endpoint=True) - + innerR = inner.Rvalue(thetavals) innerZ = inner.Zvalue(thetavals) @@ -542,24 +560,34 @@ def grid_annulus(inner, outer, nx, nz, show=True, return_coords=False): outerZ = outer.Zvalue(thetavals) for i, x in enumerate(xvals): # Get the R and Z coordinates of this line - R[i,:] = x*outerR + (1.-x)*innerR - Z[i,:] = x*outerZ + (1.-x)*innerZ - + R[i, :] = x * outerR + (1.0 - x) * innerR + Z[i, :] = x * outerZ + (1.0 - x) * innerZ + if show and plotting_available: - plt.plot(inner.R, inner.Z, '-o') - plt.plot(outer.R, outer.Z, '-o') - - plt.plot(R, Z, 'x') - + plt.plot(inner.R, inner.Z, "-o") + plt.plot(outer.R, outer.Z, "-o") + + plt.plot(R, Z, "x") + plt.show() if return_coords: return R, Z - return StructuredPoloidalGrid(R,Z) - - -def grid_elliptic(inner, outer, nx, nz, show=False, tol=1e-10, align=True, - restrict_size=20, restrict_factor=2, return_coords=False): + return StructuredPoloidalGrid(R, Z) + + +def grid_elliptic( + inner, + outer, + nx, + nz, + show=False, + tol=1e-10, + align=True, + restrict_size=20, + restrict_factor=2, + return_coords=False, +): """Create a structured grid between inner and outer boundaries using elliptic method @@ -627,14 +655,14 @@ def grid_elliptic(inner, outer, nx, nz, show=False, tol=1e-10, align=True, https://en.wikipedia.org/wiki/Principles_of_grid_generation """ - + assert nx >= 2 assert nz > 1 - - # Generate angle values (y coordinate), + + # Generate angle values (y coordinate), # which should now be equally spaced # in distance along inner and outer boundaries - thetavals = linspace(0, 2*pi, nz, endpoint=False) + thetavals = linspace(0, 2 * pi, nz, endpoint=False) # Radial coordinate xvals = linspace(0, 1.0, nx, endpoint=True) @@ -643,168 +671,184 @@ def grid_elliptic(inner, outer, nx, nz, show=False, tol=1e-10, align=True, # Align inner and outer boundaries # Easiest way is to roll both boundaries # so that index 0 is on the outboard midplane - - ind = np.argmax( inner.R ) - inner = rzline.RZline( np.roll(inner.R, -ind), np.roll(inner.Z, -ind) ) - ind = np.argmax( outer.R ) - outer = rzline.RZline( np.roll(outer.R, -ind), np.roll(outer.Z, -ind) ) - + + ind = np.argmax(inner.R) + inner = rzline.RZline(np.roll(inner.R, -ind), np.roll(inner.Z, -ind)) + ind = np.argmax(outer.R) + outer = rzline.RZline(np.roll(outer.R, -ind), np.roll(outer.Z, -ind)) + if (nx > restrict_size) or (nz > restrict_size): # Create a coarse grid first to get a starting guess # Only restrict the dimensions which exceed restrict_size # Note that this might result in multiple levels of resolution - + nx_r = nx if nx > restrict_size: nx_r = int(nx / restrict_factor) - + nz_r = nz if nz > restrict_size: nz_r = int(nz / restrict_factor) # Create the coarse mesh - R_r, Z_r = grid_elliptic(inner, outer, nx_r, nz_r, align=False, - tol=tol, restrict_size=restrict_size, restrict_factor=restrict_factor, return_coords=True) + R_r, Z_r = grid_elliptic( + inner, + outer, + nx_r, + nz_r, + align=False, + tol=tol, + restrict_size=restrict_size, + restrict_factor=restrict_factor, + return_coords=True, + ) # Note: Lower case x,z are indices - z_r = linspace(0, 2*pi, nz_r+1, endpoint=True) # Add on the final point duplicating the first + z_r = linspace( + 0, 2 * pi, nz_r + 1, endpoint=True + ) # Add on the final point duplicating the first x_r = linspace(0, 1.0, nx_r, endpoint=True) - + # Note: Upper case R,Z are real-space locations - R_r = np.concatenate((R_r, np.reshape(R_r[:,0], (nx_r, 1))), axis=1) - Z_r = np.concatenate((Z_r, np.reshape(Z_r[:,0], (nx_r, 1))), axis=1) - + R_r = np.concatenate((R_r, np.reshape(R_r[:, 0], (nx_r, 1))), axis=1) + Z_r = np.concatenate((Z_r, np.reshape(Z_r[:, 0], (nx_r, 1))), axis=1) + # Now interpolate spl = RectBivariateSpline(x_r, z_r, R_r) R = spl(xvals, thetavals, grid=True) spl = RectBivariateSpline(x_r, z_r, Z_r) Z = spl(xvals, thetavals, grid=True) - + # Make sure that the inner and outer boundaries are on the # inner and outer RZline, not interpolated - R[0,:] = inner.Rvalue(thetavals) - Z[0,:] = inner.Zvalue(thetavals) - - R[-1,:] = outer.Rvalue(thetavals) - Z[-1,:] = outer.Zvalue(thetavals) - + R[0, :] = inner.Rvalue(thetavals) + Z[0, :] = inner.Zvalue(thetavals) + + R[-1, :] = outer.Rvalue(thetavals) + Z[-1, :] = outer.Zvalue(thetavals) + else: # Interpolate coordinates of inner and outer boundary Rinner = inner.Rvalue(thetavals) Zinner = inner.Zvalue(thetavals) - + Router = outer.Rvalue(thetavals) Zouter = outer.Zvalue(thetavals) - + # Interpolate in x between inner and outer # to get starting guess for a grid R = zeros((nx, nz)) Z = zeros((nx, nz)) for i in range(nx): - R[i,:] = xvals[i]*Router + (1.-xvals[i])*Rinner - Z[i,:] = xvals[i]*Zouter + (1.-xvals[i])*Zinner - + R[i, :] = xvals[i] * Router + (1.0 - xvals[i]) * Rinner + Z[i, :] = xvals[i] * Zouter + (1.0 - xvals[i]) * Zinner + dx = xvals[1] - xvals[0] dz = thetavals[1] - thetavals[0] if show and plotting_available: # Markers on original points on inner and outer boundaries - plt.plot(inner.R, inner.Z, '-o') - plt.plot(outer.R, outer.Z, '-o') - + plt.plot(inner.R, inner.Z, "-o") + plt.plot(outer.R, outer.Z, "-o") + # Black lines through inner and outer boundaries - r,z = inner.position(np.linspace(0,2*np.pi, 100)) - plt.plot(r,z, 'k') - r,z = outer.position(np.linspace(0,2*np.pi, 100)) - plt.plot(r,z, 'k') + r, z = inner.position(np.linspace(0, 2 * np.pi, 100)) + plt.plot(r, z, "k") + r, z = outer.position(np.linspace(0, 2 * np.pi, 100)) + plt.plot(r, z, "k") # Red dots to mark the inner and outer boundaries - plt.plot(R[0,:], Z[0,:], 'ro') - plt.plot(R[-1,:], Z[-1,:], 'ro') - + plt.plot(R[0, :], Z[0, :], "ro") + plt.plot(R[-1, :], Z[-1, :], "ro") + # Start solver loop while True: # Calculate coefficients, which exclude boundary points # Note that the domain is periodic in y so roll arrays - - R_xm = R[:-2,:] # R(x-1,z) - R_xp = R[2:, :] # R(x+1,z) - R_zm = np.roll(R, 1, axis=1) # R(x, z-1) - R_zp = np.roll(R,-1, axis=1) # R(x, z+1) - R_xmzm = R_zm[:-2,:] # R(x-1, z-1) - R_xpzm = R_zm[2:,:] # R(x+1, z-1) - R_xmzp = R_zp[:-2,:] # R(x-1, z+1) - R_xpzp = R_zp[2:,:] # R(x+1, z+1) - R_zm = R_zm[1:-1,:] # Now chop off x boundaries - R_zp = R_zp[1:-1,:] # This is done to minimise number of rolls - - Z_xm = Z[:-2,:] + + R_xm = R[:-2, :] # R(x-1,z) + R_xp = R[2:, :] # R(x+1,z) + R_zm = np.roll(R, 1, axis=1) # R(x, z-1) + R_zp = np.roll(R, -1, axis=1) # R(x, z+1) + R_xmzm = R_zm[:-2, :] # R(x-1, z-1) + R_xpzm = R_zm[2:, :] # R(x+1, z-1) + R_xmzp = R_zp[:-2, :] # R(x-1, z+1) + R_xpzp = R_zp[2:, :] # R(x+1, z+1) + R_zm = R_zm[1:-1, :] # Now chop off x boundaries + R_zp = R_zp[1:-1, :] # This is done to minimise number of rolls + + Z_xm = Z[:-2, :] Z_xp = Z[2:, :] Z_zm = np.roll(Z, 1, axis=1) - Z_zp = np.roll(Z,-1, axis=1) - Z_xmzm = Z_zm[:-2,:] - Z_xpzm = Z_zm[2:,:] - Z_xmzp = Z_zp[:-2,:] - Z_xpzp = Z_zp[2:,:] - Z_zm = Z_zm[1:-1,:] - Z_zp = Z_zp[1:-1,:] - - dRdz = (R_zp - R_zm)/(2.*dz) - dRdx = (R_xp - R_xm)/(2.*dx) - - dZdz = (Z_zp - Z_zm)/(2.*dz) - dZdx = (Z_xp - Z_xm)/(2.*dx) - - a = dRdz**2 + dZdz**2 - b = dRdz*dRdx + dZdx*dZdz - c = dRdx**2 + dZdx**2 - + Z_zp = np.roll(Z, -1, axis=1) + Z_xmzm = Z_zm[:-2, :] + Z_xpzm = Z_zm[2:, :] + Z_xmzp = Z_zp[:-2, :] + Z_xpzp = Z_zp[2:, :] + Z_zm = Z_zm[1:-1, :] + Z_zp = Z_zp[1:-1, :] + + dRdz = (R_zp - R_zm) / (2.0 * dz) + dRdx = (R_xp - R_xm) / (2.0 * dx) + + dZdz = (Z_zp - Z_zm) / (2.0 * dz) + dZdx = (Z_xp - Z_xm) / (2.0 * dx) + + a = dRdz ** 2 + dZdz ** 2 + b = dRdz * dRdx + dZdx * dZdz + c = dRdx ** 2 + dZdx ** 2 + # Now solve a*R_xx - 2*b*R_xz + c*R_zz = 0 # For now using Jacobi update - - a_dx2 = a/dx**2 - b_dxdz = b/(2.*dx*dz) - c_dz2 = c/dz**2 - inv_diag = 1./(2*a/dx**2 + 2*c/dz**2) - + + a_dx2 = a / dx ** 2 + b_dxdz = b / (2.0 * dx * dz) + c_dz2 = c / dz ** 2 + inv_diag = 1.0 / (2 * a / dx ** 2 + 2 * c / dz ** 2) + Rold = R.copy() Zold = Z.copy() - - R[1:-1,:] = ( a_dx2*(R_xm + R_xp) - b_dxdz*(R_xpzp - R_xmzp - R_xpzm + R_xmzm) + c_dz2*(R_zm + R_zp) ) * inv_diag - - Z[1:-1,:] = ( a_dx2*(Z_xm + Z_xp) - b_dxdz*(Z_xpzp - Z_xmzp - Z_xpzm + Z_xmzm) + c_dz2*(Z_zm + Z_zp) ) * inv_diag - - - maxchange_sq = np.amax((R-Rold)**2 + (Z-Zold)**2) - + + R[1:-1, :] = ( + a_dx2 * (R_xm + R_xp) + - b_dxdz * (R_xpzp - R_xmzp - R_xpzm + R_xmzm) + + c_dz2 * (R_zm + R_zp) + ) * inv_diag + + Z[1:-1, :] = ( + a_dx2 * (Z_xm + Z_xp) + - b_dxdz * (Z_xpzp - Z_xmzp - Z_xpzm + Z_xmzm) + + c_dz2 * (Z_zm + Z_zp) + ) * inv_diag + + maxchange_sq = np.amax((R - Rold) ** 2 + (Z - Zold) ** 2) + if maxchange_sq < tol: break if show and plotting_available: - plt.plot(R,Z) + plt.plot(R, Z) plt.plot(np.transpose(R), np.transpose(Z)) plt.show() - + if return_coords: return R, Z - return StructuredPoloidalGrid(R,Z) + return StructuredPoloidalGrid(R, Z) + if __name__ == "__main__": - + import rzline - - #inner = circle(R0=1.5, r=1.0, n=100) - #outer = circle(R0=1.0, r=2.0, n=100) + + # inner = circle(R0=1.5, r=1.0, n=100) + # outer = circle(R0=1.0, r=2.0, n=100) inner = rzline.shaped_line(R0=3.0, a=0.5, elong=1.0, triang=0.0, indent=1.0, n=50) outer = rzline.shaped_line(R0=2.8, a=1.5, elong=1.0, triang=0.0, indent=0.2, n=50) - #outer = shaped_line(R0=3.0, a=1.0, elong=1.0, triang=0.0, indent=1.0, n=50) - + # outer = shaped_line(R0=3.0, a=1.0, elong=1.0, triang=0.0, indent=1.0, n=50) + grid = grid_elliptic(inner, outer, 100, 100, show=True) - - #grid.findIndex(2.0, 1.5) - x,z = grid.findIndex([2.0,1.9], [1.5,2.0]) - print(x,z) - - - + + # grid.findIndex(2.0, 1.5) + x, z = grid.findIndex([2.0, 1.9], [1.5, 2.0]) + print(x, z) diff --git a/tools/pylib/zoidberg/progress.py b/tools/pylib/zoidberg/progress.py index db484ac83d..93927ec16b 100644 --- a/tools/pylib/zoidberg/progress.py +++ b/tools/pylib/zoidberg/progress.py @@ -4,6 +4,7 @@ from sys import stdout + def update_progress(progress, barLength=10, ascii=False, **kwargs): """Displays or updates a console progress bar @@ -24,9 +25,9 @@ def update_progress(progress, barLength=10, ascii=False, **kwargs): """ if ascii: - cursor = '#' + cursor = "#" else: - cursor = u'█' + cursor = u"█" status = "" if isinstance(progress, int): @@ -40,13 +41,14 @@ def update_progress(progress, barLength=10, ascii=False, **kwargs): if progress >= 1: progress = 1 status = "Done...\r\n" - block = int(round(barLength*progress)) + block = int(round(barLength * progress)) text = u"\rPercent: [{prog:-<{len}}] {perc:6.2f}% {stat}".format( - len=barLength, prog=cursor*block, perc=progress*100, stat=status) + len=barLength, prog=cursor * block, perc=progress * 100, stat=status + ) # Secret undocumented feature - if 'zoidberg' in kwargs: - if kwargs['zoidberg']: + if "zoidberg" in kwargs: + if kwargs["zoidberg"]: if barLength < 40: barLength = 40 if ascii: @@ -56,21 +58,26 @@ def update_progress(progress, barLength=10, ascii=False, **kwargs): face = u" (°,,,°) " ink = u"█" - open_claw = "(\/)" + open_claw = "(\/)" closed_claw = "(|)" - if int(progress*barLength) % 2: - left_claw = open_claw + if int(progress * barLength) % 2: + left_claw = open_claw right_claw = closed_claw else: - left_claw = closed_claw + left_claw = closed_claw right_claw = open_claw - zb = left_claw+face+right_claw - zb_middle = int(len(zb)/2) - start = int(round((barLength-zb_middle)*progress)) + zb = left_claw + face + right_claw + zb_middle = int(len(zb) / 2) + start = int(round((barLength - zb_middle) * progress)) text = u"\rProgress: [{start}{zb}{rest}] {perc:6.2f}% {stat}".format( - start=ink*start, zb=zb, perc=progress*100, rest='-'*(barLength-start-zb_middle), stat=status) + start=ink * start, + zb=zb, + perc=progress * 100, + rest="-" * (barLength - start - zb_middle), + stat=status, + ) stdout.write(text) stdout.flush() diff --git a/tools/pylib/zoidberg/rzline.py b/tools/pylib/zoidberg/rzline.py index 0585d0b028..665d326188 100644 --- a/tools/pylib/zoidberg/rzline.py +++ b/tools/pylib/zoidberg/rzline.py @@ -13,6 +13,7 @@ try: import matplotlib.pyplot as plt + plotting_available = True except ImportError: warnings.warn("Couldn't import matplotlib, plotting not available.") @@ -51,10 +52,11 @@ class RZline: theta angle goes anticlockwise in the R-Z plane """ + def __init__(self, r, z, anticlockwise=True): r = np.asfarray(r) z = np.asfarray(z) - + # Check the sizes of the variables n = len(r) assert len(z) == n @@ -63,23 +65,23 @@ def __init__(self, r, z, anticlockwise=True): if anticlockwise: # Ensure that the line is going anticlockwise (positive theta) - mid_ind = np.argmax(r) # Outboard midplane index - if z[(mid_ind+1)%n] < z[mid_ind]: + mid_ind = np.argmax(r) # Outboard midplane index + if z[(mid_ind + 1) % n] < z[mid_ind]: # Line going down at outboard midplane. Need to reverse - r = r[::-1] #r = np.flip(r) - z = z[::-1] #z = np.flip(z) - + r = r[::-1] # r = np.flip(r) + z = z[::-1] # z = np.flip(z) + self.R = r self.Z = z - + # Define an angle variable - self.theta = linspace(0,2*pi,n, endpoint=False) - + self.theta = linspace(0, 2 * pi, n, endpoint=False) + # Create a spline representation # Note that the last point needs to be passed but is not used - self._rspl = splrep(append(self.theta,2*pi), append(r,r[0]), per=True) - self._zspl = splrep(append(self.theta,2*pi), append(z,z[0]), per=True) - + self._rspl = splrep(append(self.theta, 2 * pi), append(r, r[0]), per=True) + self._zspl = splrep(append(self.theta, 2 * pi), append(z, z[0]), per=True) + def Rvalue(self, theta=None, deriv=0): """Calculate the value of R at given theta locations @@ -99,8 +101,8 @@ def Rvalue(self, theta=None, deriv=0): if theta is None: theta = self.theta else: - theta = np.remainder(theta, 2*np.pi) - + theta = np.remainder(theta, 2 * np.pi) + return splev(theta, self._rspl, der=deriv) def Zvalue(self, theta=None, deriv=0): @@ -122,7 +124,7 @@ def Zvalue(self, theta=None, deriv=0): if theta is None: theta = self.theta else: - theta = np.remainder(theta, 2*np.pi) + theta = np.remainder(theta, 2 * np.pi) return splev(theta, self._zspl, der=deriv) def position(self, theta=None): @@ -160,12 +162,14 @@ def positionPolygon(self, theta=None): if theta is None: return self.R, self.Z n = len(self.R) - theta = np.remainder(theta, 2.*pi) - dtheta = 2.*np.pi/n - ind = np.trunc(theta/dtheta ) + theta = np.remainder(theta, 2.0 * pi) + dtheta = 2.0 * np.pi / n + ind = np.trunc(theta / dtheta) rem = np.remainder(theta, dtheta) - indp = (ind+1) % n - return (rem*self.R[indp] + (1.-rem)*self.R[ind]), (rem*self.Z[indp] + (1.-rem)*self.Z[ind]) + indp = (ind + 1) % n + return (rem * self.R[indp] + (1.0 - rem) * self.R[ind]), ( + rem * self.Z[indp] + (1.0 - rem) * self.Z[ind] + ) def distance(self, sample=20): """Integrates the distance along the line. @@ -185,11 +189,15 @@ def distance(self, sample=20): sample = int(sample) assert sample >= 1 - thetavals = np.linspace(0.0, 2.*np.pi, sample*len(self.theta) + 1, endpoint=True) - + thetavals = np.linspace( + 0.0, 2.0 * np.pi, sample * len(self.theta) + 1, endpoint=True + ) + # variation of length with angle dl/dtheta - dldtheta = sqrt(self.Rvalue(thetavals, deriv=1)**2 + self.Zvalue(thetavals, deriv=1)**2) - + dldtheta = sqrt( + self.Rvalue(thetavals, deriv=1) ** 2 + self.Zvalue(thetavals, deriv=1) ** 2 + ) + # Integrate cumulatively, then take only the values at the grid points (including end) return cumtrapz(dldtheta, thetavals, initial=0.0)[::sample] @@ -209,18 +217,20 @@ def equallySpaced(self, n=None): """ if n is None: n = len(self.theta) - + # Distance along the line dist = self.distance() - + # Positions where points are desired positions = linspace(dist[0], dist[-1], n, endpoint=False) - + # Find which theta value these correspond to - thetavals = interp1d(dist, append(self.theta, 2.*pi), copy=False, assume_sorted=True) + thetavals = interp1d( + dist, append(self.theta, 2.0 * pi), copy=False, assume_sorted=True + ) new_theta = thetavals(positions) - - return RZline( self.Rvalue(new_theta), self.Zvalue(new_theta) ) + + return RZline(self.Rvalue(new_theta), self.Zvalue(new_theta)) def closestPoint(self, R, Z, niter=3, subdivide=20): """Find the closest point on the curve to the given (R,Z) point @@ -240,22 +250,24 @@ def closestPoint(self, R, Z, niter=3, subdivide=20): """ # First find the closest control point - ind = argmin((self.R - R)**2 + (self.Z - Z)**2) + ind = argmin((self.R - R) ** 2 + (self.Z - Z) ** 2) theta0 = self.theta[ind] dtheta = self.theta[1] - self.theta[0] - + # Iteratively refine and find new minimum for i in range(niter): # Create a new set of points between point (ind +/- 1) # By using dtheta, wrapping around [0,2pi] is handled - thetas = np.linspace(theta0 - dtheta, theta0 + dtheta, subdivide, endpoint=False) + thetas = np.linspace( + theta0 - dtheta, theta0 + dtheta, subdivide, endpoint=False + ) Rpos, Zpos = self.positionPolygon(thetas) - - ind = argmin((Rpos - R)**2 + (Zpos - Z)**2) + + ind = argmin((Rpos - R) ** 2 + (Zpos - Z) ** 2) theta0 = thetas[ind] dtheta = thetas[1] - thetas[0] - - return np.remainder(theta0, 2*np.pi) + + return np.remainder(theta0, 2 * np.pi) def plot(self, axis=None, show=True): """Plot the RZline, either on the given axis or a new figure @@ -281,12 +293,12 @@ def plot(self, axis=None, show=True): if axis is None: fig = plt.figure() - axis = fig.add_subplot(1,1,1) + axis = fig.add_subplot(1, 1, 1) + + theta = np.linspace(0, 2 * np.pi, 100, endpoint=True) + axis.plot(self.Rvalue(theta), self.Zvalue(theta), "k-") + axis.plot(self.R, self.Z, "ro") - theta = np.linspace(0,2*np.pi, 100, endpoint=True) - axis.plot(self.Rvalue(theta), self.Zvalue(theta), 'k-') - axis.plot(self.R, self.Z, 'ro') - if show: plt.show() @@ -312,9 +324,9 @@ def circle(R0=1.0, r=0.5, n=20): """ # Define an angle coordinate - theta = linspace(0,2*pi,n, endpoint=False) - - return RZline( R0 + r*cos(theta), r*sin(theta) ) + theta = linspace(0, 2 * pi, n, endpoint=False) + + return RZline(R0 + r * cos(theta), r * sin(theta)) def shaped_line(R0=3.0, a=1.0, elong=0.0, triang=0.0, indent=0.0, n=20): @@ -340,9 +352,11 @@ def shaped_line(R0=3.0, a=1.0, elong=0.0, triang=0.0, indent=0.0, n=20): An `RZline` matching the given parameterisation """ - theta = linspace(0,2*pi,n, endpoint=False) - return RZline( R0 - indent + (a + indent*cos(theta))*cos(theta + triang*sin(theta)), - (1.+elong)*a*sin(theta) ) + theta = linspace(0, 2 * pi, n, endpoint=False) + return RZline( + R0 - indent + (a + indent * cos(theta)) * cos(theta + triang * sin(theta)), + (1.0 + elong) * a * sin(theta), + ) def line_from_points_poly(rarray, zarray, show=False): @@ -373,43 +387,48 @@ def line_from_points_poly(rarray, zarray, show=False): npoints = rarray.size rvals = rarray.copy() - zvals = zarray.copy() - + zvals = zarray.copy() + # Take the first three points to make a triangle if show and plotting_available: plt.figure() - plt.plot(rarray, zarray, 'x') - plt.plot(np.append(rvals[:3], rvals[0]), np.append(zvals[:3], zvals[0])) # Starting triangle + plt.plot(rarray, zarray, "x") + plt.plot( + np.append(rvals[:3], rvals[0]), np.append(zvals[:3], zvals[0]) + ) # Starting triangle for i in range(3, npoints): line = RZline(rvals[:i], zvals[:i]) - - angle = np.linspace(0,2*pi,100) - r,z = line.position(angle) - + + angle = np.linspace(0, 2 * pi, 100) + r, z = line.position(angle) + # Next point to add - #plt.plot(rarray[i], zarray[i], 'o') - + # plt.plot(rarray[i], zarray[i], 'o') + # Find the closest point on the line - theta = line.closestPoint(rarray[i],zarray[i]) + theta = line.closestPoint(rarray[i], zarray[i]) rl, zl = line.position(theta) - - ind = np.floor(float(i)*theta / (2.*np.pi)) - + + ind = np.floor(float(i) * theta / (2.0 * np.pi)) + # Insert after this index - - if ind != i-1: + + if ind != i - 1: # If not the last point, then need to shift other points along - rvals[ind+2:i+1] = rvals[ind+1:i] - zvals[ind+2:i+1] = zvals[ind+1:i] - rvals[ind+1] = rarray[i] - zvals[ind+1] = zarray[i] - + rvals[ind + 2 : i + 1] = rvals[ind + 1 : i] + zvals[ind + 2 : i + 1] = zvals[ind + 1 : i] + rvals[ind + 1] = rarray[i] + zvals[ind + 1] = zarray[i] + if show and plotting_available: - plt.plot([rarray[i], rl], [zarray[i],zl]) - plt.plot(np.append(rvals[:(i+1)], rvals[0]), np.append(zvals[:(i+1)], zvals[0])) # New line + plt.plot([rarray[i], rl], [zarray[i], zl]) + plt.plot( + np.append(rvals[: (i + 1)], rvals[0]), + np.append(zvals[: (i + 1)], zvals[0]), + ) # New line if show and plotting_available: plt.show() @@ -439,7 +458,7 @@ def line_from_points(rarray, zarray, show=False): zarray = np.asfarray(zarray) assert rarray.size == zarray.size - + # We can get different answers depending on which point # we start the line on. # Therefore start the line from every point in turn, @@ -447,90 +466,91 @@ def line_from_points(rarray, zarray, show=False): best_line = None # The best line found so far best_dist = 0.0 # Distance around best line - + for start_ind in range(rarray.size): - + # Create an array of remaining points # Make copies since we edit the array later rarr = np.roll(rarray, start_ind).copy() zarr = np.roll(zarray, start_ind).copy() - + # Create new lists for the result rvals = [rarr[0]] zvals = [zarr[0]] - + rarr = rarr[1:] zarr = zarr[1:] while rarr.size > 1: # Find the index in array closest to last point - ind = np.argmin( (rvals[-1] - rarr)**2 + (zvals[-1] - zarr)**2 ) + ind = np.argmin((rvals[-1] - rarr) ** 2 + (zvals[-1] - zarr) ** 2) rvals.append(rarr[ind]) zvals.append(zarr[ind]) # Shift arrays - rarr[ind:-1] = rarr[(ind+1):] - zarr[ind:-1] = zarr[(ind+1):] + rarr[ind:-1] = rarr[(ind + 1) :] + zarr[ind:-1] = zarr[(ind + 1) :] # Chop off last point rarr = rarr[:-1] zarr = zarr[:-1] - + # One left, add to the end rvals.append(rarr[0]) zvals.append(zarr[0]) new_line = RZline(rvals, zvals) - new_dist = new_line.distance()[-1] # Total distance - - if (best_line is None) or ( new_dist < best_dist ): + new_dist = new_line.distance()[-1] # Total distance + + if (best_line is None) or (new_dist < best_dist): # Either if we haven't got a line, or found # a better line best_line = new_line best_dist = new_dist - - return best_line - + + return best_line + + if __name__ == "__main__": import field - import fieldtracer + import fieldtracer import poloidal_grid ############################################################################# # Define the magnetic field - + # Length in y after which the coils return to their starting (R,Z) locations - yperiod = 10. - - magnetic_field = field.StraightStellarator(I_coil=0.3, radius = 1.0, yperiod = yperiod) + yperiod = 10.0 + + magnetic_field = field.StraightStellarator(I_coil=0.3, radius=1.0, yperiod=yperiod) ############################################################################# # Create the inner flux surface, starting at a point at phi=0 # To do this we need to define the y locations of the poloidal points # where we will construct grids - + start_r = 0.2 start_z = 0.0 - + nslices = 8 # Number of poloidal slices ycoords = np.linspace(0, yperiod, nslices) npoints = 20 # Points per poloidal slice - + # Create a field line tracer tracer = fieldtracer.FieldTracer(magnetic_field) - + # Extend the y coordinates so the tracer loops npoints times around yperiod ycoords_all = ycoords - for i in range(1,npoints): - ycoords_all = np.append(ycoords_all, ycoords + i*yperiod) - + for i in range(1, npoints): + ycoords_all = np.append(ycoords_all, ycoords + i * yperiod) + coord = tracer.follow_field_lines(start_r, start_z, ycoords_all, rtol=1e-12) inner_lines = [] for i in range(nslices): - r = coord[i::nslices,0] - z = coord[i::nslices,1] - line = line_from_points(r,z) + r = coord[i::nslices, 0] + z = coord[i::nslices, 1] + line = line_from_points(r, z) # Re-map the points so they're approximately uniform in distance along the surface # Note that this results in some motion of the line line = line.equallySpaced() @@ -540,15 +560,17 @@ def line_from_points(rarray, zarray, show=False): ############################################################################# # Generate a fixed circle for the outer boundary - + outer_line = circle(R0=0.0, r=0.8) ############################################################################# # Now have inner and outer boundaries for each poloidal slice # Generate a grid on each poloidal slice using the elliptic grid generator - + nx = 20 ny = 20 - - pol_slices = [ poloidal_grid.grid_elliptic(inner_line, outer_line, nx,ny, show=True) for inner_line in inner_lines ] - + + pol_slices = [ + poloidal_grid.grid_elliptic(inner_line, outer_line, nx, ny, show=True) + for inner_line in inner_lines + ] diff --git a/tools/pylib/zoidberg/test_field.py b/tools/pylib/zoidberg/test_field.py index bac69ab5eb..1c9cef384f 100644 --- a/tools/pylib/zoidberg/test_field.py +++ b/tools/pylib/zoidberg/test_field.py @@ -1,7 +1,7 @@ - import numpy as np from .field import Slab, CurvedSlab + def test_slab(): # Slab with no shear (Bzprime = 0) slab = Slab(By=0.5, Bz=0.2, Bzprime=0.0) @@ -10,18 +10,19 @@ def test_slab(): x = np.arange(10) z = x - Bx = slab.Bxfunc(x,z,0.0) + Bx = slab.Bxfunc(x, z, 0.0) assert Bx.shape == x.shape assert np.allclose(Bx, 0.0) - By = slab.Byfunc(x,z,0.0) + By = slab.Byfunc(x, z, 0.0) assert By.shape == x.shape assert np.allclose(By, 0.5) - Bz = slab.Bzfunc(x,z,0.0) + Bz = slab.Bzfunc(x, z, 0.0) assert Bz.shape == x.shape assert np.allclose(Bz, 0.2) + def test_curved_slab(): # Slab with no shear (Bzprime = 0) slab = CurvedSlab(By=0.5, Bz=0.2, Bzprime=0.0) @@ -30,15 +31,14 @@ def test_curved_slab(): x = np.arange(10) z = x - Bx = slab.Bxfunc(x,z,0.0) + Bx = slab.Bxfunc(x, z, 0.0) assert Bx.shape == x.shape assert np.allclose(Bx, 0.0) - By = slab.Byfunc(x,z,0.0) + By = slab.Byfunc(x, z, 0.0) assert By.shape == x.shape assert np.allclose(By, 0.5) - Bz = slab.Bzfunc(x,z,0.0) + Bz = slab.Bzfunc(x, z, 0.0) assert Bz.shape == x.shape assert np.allclose(Bz, 0.2) - diff --git a/tools/pylib/zoidberg/test_fieldtracer.py b/tools/pylib/zoidberg/test_fieldtracer.py index 8cdac5fdf0..619fac5ff3 100644 --- a/tools/pylib/zoidberg/test_fieldtracer.py +++ b/tools/pylib/zoidberg/test_fieldtracer.py @@ -3,54 +3,57 @@ from . import fieldtracer from . import field + def test_slab(): - mag_field = field.Slab(By=0.5, Bz=0.1, Bzprime = 0.0) - + mag_field = field.Slab(By=0.5, Bz=0.1, Bzprime=0.0) + tracer = fieldtracer.FieldTracer(mag_field) - coords = tracer.follow_field_lines( 0.2, 0.3, [1.5, 2.5] ) - - assert coords.shape == (2,1,2) - assert np.allclose(coords[:,0,0], 0.2) # X coordinate - - assert np.allclose(coords[0,0,1], 0.3) - assert np.allclose(coords[1,0,1], 0.3 + 0.1/0.5) # Z coordinate + coords = tracer.follow_field_lines(0.2, 0.3, [1.5, 2.5]) + + assert coords.shape == (2, 1, 2) + assert np.allclose(coords[:, 0, 0], 0.2) # X coordinate + + assert np.allclose(coords[0, 0, 1], 0.3) + assert np.allclose(coords[1, 0, 1], 0.3 + 0.1 / 0.5) # Z coordinate - coords = tracer.follow_field_lines( [0.2,0.3,0.4], 0.5, [1.0,2.5] ) + coords = tracer.follow_field_lines([0.2, 0.3, 0.4], 0.5, [1.0, 2.5]) + + assert coords.shape == (2, 3, 2) + assert np.allclose(coords[:, 0, 0], 0.2) + assert np.allclose(coords[:, 1, 0], 0.3) + assert np.allclose(coords[:, 2, 0], 0.4) + assert np.allclose(coords[1, :, 1], 0.5 + 1.5 * 0.1 / 0.5) # Z coord - assert coords.shape == (2,3,2) - assert np.allclose(coords[:,0,0], 0.2) - assert np.allclose(coords[:,1,0], 0.3) - assert np.allclose(coords[:,2,0], 0.4) - assert np.allclose(coords[1,:,1], 0.5 + 1.5*0.1/0.5) # Z coord def test_FieldTracerReversible_slab(): - mag_field = field.Slab(By=0.5, Bz=0.1, Bzprime = 0.0) - + mag_field = field.Slab(By=0.5, Bz=0.1, Bzprime=0.0) + tracer = fieldtracer.FieldTracerReversible(mag_field) - coords = tracer.follow_field_lines( 0.2, 0.3, [1.5, 2.5] ) - - assert coords.shape == (2,1,2) - assert np.allclose(coords[:,0,0], 0.2) # X coordinate - - assert np.allclose(coords[0,0,1], 0.3) - assert np.allclose(coords[1,0,1], 0.3 + 0.1/0.5) # Z coordinate - - coords = tracer.follow_field_lines( [0.2,0.3,0.4], 0.5, [1.0,2.5] ) - - assert coords.shape == (2,3,2) - assert np.allclose(coords[:,0,0], 0.2) - assert np.allclose(coords[:,1,0], 0.3) - assert np.allclose(coords[:,2,0], 0.4) - assert np.allclose(coords[1,:,1], 0.5 + 1.5*0.1/0.5) # Z coord - + coords = tracer.follow_field_lines(0.2, 0.3, [1.5, 2.5]) + + assert coords.shape == (2, 1, 2) + assert np.allclose(coords[:, 0, 0], 0.2) # X coordinate + + assert np.allclose(coords[0, 0, 1], 0.3) + assert np.allclose(coords[1, 0, 1], 0.3 + 0.1 / 0.5) # Z coordinate + + coords = tracer.follow_field_lines([0.2, 0.3, 0.4], 0.5, [1.0, 2.5]) + + assert coords.shape == (2, 3, 2) + assert np.allclose(coords[:, 0, 0], 0.2) + assert np.allclose(coords[:, 1, 0], 0.3) + assert np.allclose(coords[:, 2, 0], 0.4) + assert np.allclose(coords[1, :, 1], 0.5 + 1.5 * 0.1 / 0.5) # Z coord + + def test_poincare(): - mag_field = field.Slab(By=0.5, Bz=0.1, Bzprime = 0.0) - - result, y_slices = fieldtracer.trace_poincare(mag_field, 0.0, 0.0, 1.0, - nplot=3, revs=5,nover=1) + mag_field = field.Slab(By=0.5, Bz=0.1, Bzprime=0.0) + + result, y_slices = fieldtracer.trace_poincare( + mag_field, 0.0, 0.0, 1.0, nplot=3, revs=5, nover=1 + ) assert y_slices.size == 3 assert result.shape == (5, y_slices.size, 1, 2) - diff --git a/tools/pylib/zoidberg/test_grid.py b/tools/pylib/zoidberg/test_grid.py index 7e408f27f9..df19fa13a4 100644 --- a/tools/pylib/zoidberg/test_grid.py +++ b/tools/pylib/zoidberg/test_grid.py @@ -1,14 +1,14 @@ - from .grid import rectangular_grid import numpy as np + def test_getPoloidalGrid(): # Create a simple non-periodic grid - grid = rectangular_grid(10,10,10, yperiodic=False) + grid = rectangular_grid(10, 10, 10, yperiodic=False) # Check number of y points assert grid.numberOfPoloidalGrids() == 10 - + # Try to get points outside the domain p, y = grid.getPoloidalGrid(-1) assert p == None @@ -16,25 +16,26 @@ def test_getPoloidalGrid(): p, y = grid.getPoloidalGrid(10) assert p == None - assert np.allclose(y, 10.) + assert np.allclose(y, 10.0) # Check values of y at the start and end of the domain p, y = grid.getPoloidalGrid(0) - assert np.allclose(y, 0.5) + assert np.allclose(y, 0.5) p, y = grid.getPoloidalGrid(9) - assert np.allclose(y, 9.5) + assert np.allclose(y, 9.5) + def test_getPoloidalGrid_periodic(): # Create a periodic grid - grid = rectangular_grid(10,10,10, yperiodic=True) + grid = rectangular_grid(10, 10, 10, yperiodic=True) assert grid.numberOfPoloidalGrids() == 10 - p_last, y_last = grid.getPoloidalGrid(9) # Last in domain + p_last, y_last = grid.getPoloidalGrid(9) # Last in domain assert p_last is not None - + p, y = grid.getPoloidalGrid(-1) assert p is p_last diff --git a/tools/pylib/zoidberg/test_poloidal_grid.py b/tools/pylib/zoidberg/test_poloidal_grid.py index 755880a6f9..39ffc4c900 100644 --- a/tools/pylib/zoidberg/test_poloidal_grid.py +++ b/tools/pylib/zoidberg/test_poloidal_grid.py @@ -1,9 +1,9 @@ - import numpy as np from . import rzline from . import poloidal_grid + def test_out_of_domain(): # Create inner and outer boundaries inner = rzline.circle(R0=0.0, r=1.0, n=20) @@ -13,23 +13,23 @@ def test_out_of_domain(): # Test a point in domain - x,y = grid.findIndex(1.0, 1.0) - r,z = grid.getCoordinate(x,y) + x, y = grid.findIndex(1.0, 1.0) + r, z = grid.getCoordinate(x, y) assert np.allclose(r, 1.0) and np.allclose(z, 1.0) # Should get original R,Z # Test out of domain - x,y = grid.findIndex(2.5,0) - assert np.allclose(x, 10) # Should mark out of domain at outer x - - x,y = grid.findIndex(0.5,0.2) - assert np.allclose(x, -1) # Should mark out of domain at inner x - + x, y = grid.findIndex(2.5, 0) + assert np.allclose(x, 10) # Should mark out of domain at outer x + + x, y = grid.findIndex(0.5, 0.2) + assert np.allclose(x, -1) # Should mark out of domain at inner x + # Test a mix of values inside and outside domain - - x,y = grid.findIndex([2.5, 1.0], [0.0, 0.5]) - - assert np.allclose(x[0], 10) # First one out of domain - - r,z = grid.getCoordinate(x[1],y[1]) + + x, y = grid.findIndex([2.5, 1.0], [0.0, 0.5]) + + assert np.allclose(x[0], 10) # First one out of domain + + r, z = grid.getCoordinate(x[1], y[1]) assert np.allclose(r, 1.0) and np.allclose(z, 0.5) # Second point in domain diff --git a/tools/pylib/zoidberg/test_rzline.py b/tools/pylib/zoidberg/test_rzline.py index 9fc47dae57..687758f014 100644 --- a/tools/pylib/zoidberg/test_rzline.py +++ b/tools/pylib/zoidberg/test_rzline.py @@ -2,65 +2,72 @@ import numpy as np + def test_circular_boundaries(): inner = rzline.circle(R0=1.0, r=1.0, n=20) outer = rzline.circle(R0=1.0, r=2.0, n=20) - + assert np.amax(inner.R) <= 2.0 assert np.amin(inner.R) >= 0.0 - - + + def test_distance(): # Check the RZline.distance() function - + n = 50 inner = rzline.circle(R0=1.0, r=1.0, n=n) outer = rzline.circle(R0=1.0, r=2.0, n=n) - + dist = inner.distance() # Check size of the array - assert len(dist) == n+1 - + assert len(dist) == n + 1 + # Check start and end values assert np.allclose(dist[0], 0.0) - assert np.allclose(dist[-1], 2.*np.pi) - + assert np.allclose(dist[-1], 2.0 * np.pi) + # Check that dist is monotonically increasing - assert np.all(np.greater(dist[1:] - dist[:-1], 0.0)) - + assert np.all(np.greater(dist[1:] - dist[:-1], 0.0)) + dist_outer = outer.distance() - assert np.allclose(dist_outer[-1], 4.*np.pi) - + assert np.allclose(dist_outer[-1], 4.0 * np.pi) + + def test_order_by_distance(): # Check the RZline.equallySpaced function inner = rzline.circle(R0=1.0, r=1.0, n=20) outer = rzline.circle(R0=1.0, r=2.0, n=20) - + new_inner = inner.equallySpaced(n=10) - + assert len(new_inner.R) == 10 - + + def test_line_from_points(): # Create a shaped periodic line - original = rzline.shaped_line(R0=3.0, a=1.0, elong=1.0, triang=0.4, indent=1.0, n=20) - + original = rzline.shaped_line( + R0=3.0, a=1.0, elong=1.0, triang=0.4, indent=1.0, n=20 + ) + # Permute points from numpy import random - random.seed(1235) # Fix seed so same every time + + random.seed(1235) # Fix seed so same every time indx = random.permutation(original.R.size) - + R = original.R[indx] Z = original.Z[indx] - + reconstructed = rzline.line_from_points(R, Z) # Reconstructed should now be a rotated version of original match = False for i in range(len(R)): - if np.allclose(original.R, np.roll(reconstructed.R, i)) and np.allclose(original.Z, np.roll(reconstructed.Z, i)): + if np.allclose(original.R, np.roll(reconstructed.R, i)) and np.allclose( + original.Z, np.roll(reconstructed.Z, i) + ): match = True break - + assert match - diff --git a/tools/pylib/zoidberg/test_zoidberg.py b/tools/pylib/zoidberg/test_zoidberg.py index 45c1626381..a4382e3381 100644 --- a/tools/pylib/zoidberg/test_zoidberg.py +++ b/tools/pylib/zoidberg/test_zoidberg.py @@ -22,7 +22,9 @@ def test_make_maps_slab(): # Since this is a straight magnetic field in a simple rectangle, # all the maps should be the same, and should be the identity - identity_map_x, identity_map_z = np.meshgrid(np.arange(nx), np.arange(nz), indexing='ij') + identity_map_x, identity_map_z = np.meshgrid( + np.arange(nx), np.arange(nz), indexing="ij" + ) # Check that maps has the required forward and backward index variables offsets = chain(range(1, nslice + 1), range(-1, -(nslice + 1), -1)) @@ -37,7 +39,9 @@ def test_make_maps_slab(): assert maps[var].shape == (nx, ny, nz) # The first/last abs(offset) points are not valid, so ignore those - interior_range = range(ny-abs(offset)) if offset > 0 else range(abs(offset), ny) + interior_range = ( + range(ny - abs(offset)) if offset > 0 else range(abs(offset), ny) + ) # Those invalid points should be set to -1 end_slice = slice(-1, -(offset + 1), -1) if offset > 0 else slice(0, -offset) identity_map = identity_map_x if "x" in var else identity_map_z @@ -55,12 +59,12 @@ def test_make_maps_straight_stellarator(): nz = 7 # Create magnetic field - magnetic_field = field.StraightStellarator(radius = np.sqrt(2.0)) + magnetic_field = field.StraightStellarator(radius=np.sqrt(2.0)) # Create a rectangular grid in (x,y,z) - rectangle = grid.rectangular_grid(nx,ny,nz, - Lx = 1.0, Lz = 1.0, Ly = 10.0, - yperiodic = True) + rectangle = grid.rectangular_grid( + nx, ny, nz, Lx=1.0, Lz=1.0, Ly=10.0, yperiodic=True + ) # Here both the field and and grid are centred at (x,z) = (0,0) # and the rectangular grid here fits entirely within the coils diff --git a/tools/pylib/zoidberg/zoidberg.py b/tools/pylib/zoidberg/zoidberg.py index f1f8c3392b..21dcae8696 100644 --- a/tools/pylib/zoidberg/zoidberg.py +++ b/tools/pylib/zoidberg/zoidberg.py @@ -31,7 +31,7 @@ def parallel_slice_field_name(field, offset): Parallel slice offset """ - prefix = 'forward' if offset > 0 else 'backward' + prefix = "forward" if offset > 0 else "backward" suffix = "_{}".format(abs(offset)) if abs(offset) > 1 else "" return "{}_{}{}".format(prefix, field, suffix) @@ -87,20 +87,24 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): # The field line maps and coordinates, etc. maps = { - 'R': R, - 'Z': Z, + "R": R, + "Z": Z, } # A helper data structure that groups the various field line maps along with the offset - ParallelSlice = namedtuple('ParallelSlice', ['offset', 'R', 'Z', 'xt_prime', 'zt_prime']) + ParallelSlice = namedtuple( + "ParallelSlice", ["offset", "R", "Z", "xt_prime", "zt_prime"] + ) # A list of the above data structures for each offset we want parallel_slices = [] # Loop over offsets {1, ... nslice, -1, ... -nslice} for offset in chain(range(1, nslice + 1), range(-1, -(nslice + 1), -1)): # Unique names of the field line maps for this offset - field_names = [parallel_slice_field_name(field, offset) - for field in ['R', 'Z', 'xt_prime', 'zt_prime']] + field_names = [ + parallel_slice_field_name(field, offset) + for field in ["R", "Z", "xt_prime", "zt_prime"] + ] # Initialise the field arrays -- puts them straight into the result dict for field in field_names: @@ -111,7 +115,7 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): parallel_slices.append(ParallelSlice(offset, *fields)) # Total size of the progress bar - total_work = len(parallel_slices) * ny + total_work = len(parallel_slices) * ny # TODO: if axisymmetric, don't loop, do one slice and copy # TODO: restart tracing for adjacent offsets @@ -126,7 +130,9 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): pol_slice, y_slice = grid.getPoloidalGrid(j + parallel_slice.offset) # We only want the end point, as [0,...] is the initial position - coord = field_tracer.follow_field_lines(pol.R, pol.Z, [ycoord, y_slice], rtol=rtol)[1, ...] + coord = field_tracer.follow_field_lines( + pol.R, pol.Z, [ycoord, y_slice], rtol=rtol + )[1, ...] # Store the coordinates in real space parallel_slice.R[:, j, :] = coord[:, :, 0] @@ -157,9 +163,16 @@ def make_maps(grid, magnetic_field, nslice=1, quiet=False, **kwargs): return maps -def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', - new_names=False, metric2d=True, format="NETCDF3_64BIT", - quiet=False): +def write_maps( + grid, + magnetic_field, + maps, + gridfile="fci.grid.nc", + new_names=False, + metric2d=True, + format="NETCDF3_64BIT", + quiet=False, +): """Write FCI maps to BOUT++ grid file Parameters @@ -203,8 +216,8 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', for yindex in range(grid.numberOfPoloidalGrids()): pol_grid, ypos = grid.getPoloidalGrid(yindex) Rmaj[:, yindex, :] = magnetic_field.Rfunc(pol_grid.R, pol_grid.Z, ypos) - metric["gyy"] = 1./Rmaj**2 - metric["g_yy"] = Rmaj**2 + metric["gyy"] = 1.0 / Rmaj ** 2 + metric["g_yy"] = Rmaj ** 2 # Get magnetic field and pressure Bmag = np.zeros(grid.shape) @@ -214,12 +227,16 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', Bmag[:, yindex, :] = magnetic_field.Bmag(pol_grid.R, pol_grid.Z, ypos) pressure[:, yindex, :] = magnetic_field.pressure(pol_grid.R, pol_grid.Z, ypos) - metric["g_yy"][:, yindex, :] = (metric["g_yy"][:, yindex, :] - * (Bmag[:, yindex, :] - / magnetic_field.Byfunc(pol_grid.R, pol_grid.Z, ypos))**2) - metric["gyy"][:, yindex, :] = (metric["gyy"][:, yindex, :] - * (magnetic_field.Byfunc(pol_grid.R, pol_grid.Z, ypos) - / Bmag[:, yindex, :])**2) + metric["g_yy"][:, yindex, :] = ( + metric["g_yy"][:, yindex, :] + * (Bmag[:, yindex, :] / magnetic_field.Byfunc(pol_grid.R, pol_grid.Z, ypos)) + ** 2 + ) + metric["gyy"][:, yindex, :] = ( + metric["gyy"][:, yindex, :] + * (magnetic_field.Byfunc(pol_grid.R, pol_grid.Z, ypos) / Bmag[:, yindex, :]) + ** 2 + ) # Get attributes from magnetic field (e.g. psi) attributes = {} @@ -227,7 +244,9 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', attribute = np.zeros(grid.shape) for yindex in range(grid.numberOfPoloidalGrids()): pol_grid, ypos = grid.getPoloidalGrid(yindex) - attribute[:, yindex, :] = magnetic_field.attributes[name](pol_grid.R, pol_grid.Z, ypos) + attribute[:, yindex, :] = magnetic_field.attributes[name]( + pol_grid.R, pol_grid.Z, ypos + ) attributes[name] = attribute # Metric is now 3D @@ -249,9 +268,8 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', metric["Rxy"] = maps["R"] metric["Bxy"] = Bmag - with bdata.DataFile(gridfile, write=True, create=True, format=format) as f: - ixseps = nx+1 + ixseps = nx + 1 f.write("nx", nx) f.write("ny", ny) f.write("nz", nz) @@ -272,14 +290,16 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', # Translate between output variable names and metric names # Map from new to old names. Anything not in this dict # is output unchanged - name_changes = {"g_yy": "g_22", - "gyy": "g22", - "gxx": "g11", - "gxz": "g13", - "gzz": "g33", - "g_xx": "g_11", - "g_xz": "g_13", - "g_zz": "g_33"} + name_changes = { + "g_yy": "g_22", + "gyy": "g22", + "gxx": "g11", + "gxz": "g13", + "gzz": "g33", + "g_xx": "g_11", + "g_xz": "g_13", + "g_zz": "g_33", + } for key in metric: name = key if name in name_changes: @@ -301,8 +321,9 @@ def write_maps(grid, magnetic_field, maps, gridfile='fci.grid.nc', f.write(key, maps[key]) -def write_Bfield_to_vtk(grid, magnetic_field, scale=5, - vtkfile="fci_zoidberg", psi=True): +def write_Bfield_to_vtk( + grid, magnetic_field, scale=5, vtkfile="fci_zoidberg", psi=True +): """Write the magnetic field to a VTK file Parameters @@ -323,19 +344,21 @@ def write_Bfield_to_vtk(grid, magnetic_field, scale=5, path - Full path to vtkfile """ - point_data = {'B' : (magnetic_field.bx*scale, - magnetic_field.by, - magnetic_field.bz*scale)} + point_data = { + "B": (magnetic_field.bx * scale, magnetic_field.by, magnetic_field.bz * scale) + } if psi: psi = make_surfaces(grid, magnetic_field) - point_data['psi'] = psi + point_data["psi"] = psi - path = gridToVTK(vtkfile, - grid.xarray*scale, - grid.yarray, - grid.zarray*scale, - pointData=point_data) + path = gridToVTK( + vtkfile, + grid.xarray * scale, + grid.yarray, + grid.zarray * scale, + pointData=point_data, + ) return path @@ -346,28 +369,30 @@ def fci_to_vtk(infile, outfile, scale=5): return with bdata.DataFile(infile, write=False, create=False) as f: - dx = f.read('dx') - dy = f.read('dy') + dx = f.read("dx") + dy = f.read("dy") - bx = f.read('bx') + bx = f.read("bx") by = np.ones(bx.shape) - bz = f.read('bz') + bz = f.read("bz") if bx is None: - xt_prime = f.read('forward_xt_prime') - zt_prime = f.read('forward_zt_prime') + xt_prime = f.read("forward_xt_prime") + zt_prime = f.read("forward_zt_prime") array_indices = indices(xt_prime.shape) - bx = xt_prime - array_indices[0,...] + bx = xt_prime - array_indices[0, ...] by = by * dy - bz = zt_prime - array_indices[2,...] + bz = zt_prime - array_indices[2, ...] nx, ny, nz = bx.shape - dz = nx*dx / nz + dz = nx * dx / nz - x = np.linspace(0, nx*dx, nx) - y = np.linspace(0, ny*dy, ny, endpoint=False) - z = np.linspace(0, nz*dz, nz, endpoint=False) + x = np.linspace(0, nx * dx, nx) + y = np.linspace(0, ny * dy, ny, endpoint=False) + z = np.linspace(0, nz * dz, nz, endpoint=False) - gridToVTK(outfile, x*scale, y, z*scale, pointData={'B' : (bx*scale, by, bz*scale)}) + gridToVTK( + outfile, x * scale, y, z * scale, pointData={"B": (bx * scale, by, bz * scale)} + ) def make_surfaces(grid, magnetic_field, nsurfaces=10, revs=100): @@ -394,14 +419,13 @@ def make_surfaces(grid, magnetic_field, nsurfaces=10, revs=100): from scipy.interpolate import griddata # initial x, z points in surface - xpos = grid.xcentre + np.linspace(0, 0.5*np.max(grid.xarray), - nsurfaces) + xpos = grid.xcentre + np.linspace(0, 0.5 * np.max(grid.xarray), nsurfaces) zpos = grid.zcentre phi_values = grid.yarray[:] # Extend the domain from [0,grid.Ly] to [0,revs*grid.Ly] for n in np.arange(1, revs): - phi_values = np.append(phi_values, n*grid.Ly + phi_values[:grid.ny]) + phi_values = np.append(phi_values, n * grid.Ly + phi_values[: grid.ny]) # Get field line tracer and trace out surfaces tracer = fieldtracer.FieldTracer(magnetic_field) @@ -413,16 +437,22 @@ def make_surfaces(grid, magnetic_field, nsurfaces=10, revs=100): # Arbitarily number the surfaces from 0 to 1 psi_points = np.zeros((revs, grid.ny, nsurfaces)) for surf in range(nsurfaces): - psi_points[:,:,surf] = float(surf)/float(nsurfaces-1) + psi_points[:, :, surf] = float(surf) / float(nsurfaces - 1) - x_2d, z_2d = np.meshgrid(grid.xarray, grid.zarray, indexing='ij') + x_2d, z_2d = np.meshgrid(grid.xarray, grid.zarray, indexing="ij") psi = np.zeros_like(grid.x_3d) for y_slice in range(grid.ny): - points_2d = np.column_stack((points[:,y_slice,:,0].flatten(), - points[:,y_slice,:,1].flatten())) - psi[:,y_slice,:] = griddata(points_2d, psi_points[:,y_slice,:].flatten(), - (x_2d, z_2d), method='linear', fill_value=1) + points_2d = np.column_stack( + (points[:, y_slice, :, 0].flatten(), points[:, y_slice, :, 1].flatten()) + ) + psi[:, y_slice, :] = griddata( + points_2d, + psi_points[:, y_slice, :].flatten(), + (x_2d, z_2d), + method="linear", + fill_value=1, + ) return psi @@ -465,16 +495,19 @@ def upscale(field, maps, upscale_factor=4, quiet=True): try: field = field.reshape(xt_prime.T.shape).T except ValueError: - raise ValueError("Field, {}, must be same shape as grid, {}" - .format(field.shape, xt_prime.shape)) + raise ValueError( + "Field, {}, must be same shape as grid, {}".format( + field.shape, xt_prime.shape + ) + ) # Get the shape of the grid nx, ny, nz = xt_prime.shape index_coords = np.mgrid[0:nx, 0:ny, 0:nz] # We use the forward maps, so get the y-index of the *next* y-slice - yup_3d = index_coords[1,...] + 1 - yup_3d[:,-1,:] = 0 + yup_3d = index_coords[1, ...] + 1 + yup_3d[:, -1, :] = 0 # Index space coordinates of the field line end points end_points = np.array([xt_prime, yup_3d, zt_prime]) @@ -487,17 +520,19 @@ def upscale(field, maps, upscale_factor=4, quiet=True): field_aligned = np.array([field, field_prime]) # x, z coords at start/end of field line - x_start_end = np.array([index_coords[0,...], xt_prime]) - z_start_end = np.array([index_coords[2,...], zt_prime]) + x_start_end = np.array([index_coords[0, ...], xt_prime]) + z_start_end = np.array([index_coords[2, ...], zt_prime]) # Parametric points along the field line midpoints = np.linspace(0, 1, upscale_factor, endpoint=False) # Need to make this 4D as well - new_points = np.tile(midpoints[:,np.newaxis,np.newaxis,np.newaxis], [nx, ny, nz]) + new_points = np.tile(midpoints[:, np.newaxis, np.newaxis, np.newaxis], [nx, ny, nz]) # Index space coordinates of our upscaled field - index_4d = np.mgrid[0:upscale_factor,0:nx,0:ny,0:nz] - hires_points = np.array([new_points, index_4d[1,...], index_4d[2,...], index_4d[3,...]]) + index_4d = np.mgrid[0:upscale_factor, 0:nx, 0:ny, 0:nz] + hires_points = np.array( + [new_points, index_4d[1, ...], index_4d[2, ...], index_4d[3, ...]] + ) # Upscale the field hires_field = map_coordinates(field_aligned, hires_points) @@ -510,7 +545,7 @@ def twizzle(array): """Transpose and reshape the output of map_coordinates to be 3D """ - return array.transpose((1, 2, 0, 3)).reshape((nx, upscale_factor*ny, nz)) + return array.transpose((1, 2, 0, 3)).reshape((nx, upscale_factor * ny, nz)) # Rearrange arrays to be 3D hires_field = twizzle(hires_field) @@ -518,22 +553,24 @@ def twizzle(array): hires_z = twizzle(hires_z) # Interpolate from field line sections onto grid - hires_grid_field = np.zeros( (nx, upscale_factor*ny, nz) ) - hires_index_coords = np.mgrid[0:nx, 0:ny:1./upscale_factor, 0:nz] - grid_points = (hires_index_coords[0,:,0,:], hires_index_coords[2,:,0,:]) + hires_grid_field = np.zeros((nx, upscale_factor * ny, nz)) + hires_index_coords = np.mgrid[0:nx, 0 : ny : 1.0 / upscale_factor, 0:nz] + grid_points = (hires_index_coords[0, :, 0, :], hires_index_coords[2, :, 0, :]) def y_first(array): - """Put the middle index first - """ + """Put the middle index first""" return array.transpose((0, 2, 1)) # The hires data is unstructed only in (x,z), interpolate onto # (x,z) grid for each y-slice individually - for k, (x_points, z_points, f_slice) in enumerate(zip(y_first(hires_x).T, y_first(hires_z).T, y_first(hires_field).T)): + for k, (x_points, z_points, f_slice) in enumerate( + zip(y_first(hires_x).T, y_first(hires_z).T, y_first(hires_field).T) + ): points = np.column_stack((x_points.flat, z_points.flat)) - hires_grid_field[:,k,:] = griddata(points, f_slice.flat, grid_points, - method='linear', fill_value=0.0) + hires_grid_field[:, k, :] = griddata( + points, f_slice.flat, grid_points, method="linear", fill_value=0.0 + ) if not quiet: - update_progress(float(k)/float(ny-1)) + update_progress(float(k) / float(ny - 1)) return hires_grid_field From 0356fe8326b6d7767625a5def024155b3ba6cc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 9 Feb 2021 09:11:18 +0100 Subject: [PATCH 277/293] Make it more obvious that default is 2D grid --- manual/sphinx/user_docs/input_grids.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manual/sphinx/user_docs/input_grids.rst b/manual/sphinx/user_docs/input_grids.rst index 26ff5f0f68..d4fdbcbab3 100644 --- a/manual/sphinx/user_docs/input_grids.rst +++ b/manual/sphinx/user_docs/input_grids.rst @@ -377,7 +377,7 @@ the magnetic field is followed along the Y coordinate from each 2D grid to where it either intersects the forward and backward grid, or hits a boundary. -The simplest code which creates an output file is:: +A simple code which creates an output file is:: import zoidberg @@ -387,8 +387,8 @@ The simplest code which creates an output file is:: grid = zoidberg.grid.rectangular_grid(10,10,10) # Follow magnetic fields from each point maps = zoidberg.make_maps(grid, field) - # Write everything to file - zoidberg.write_maps(grid, field, maps, gridfile="grid.fci.nc") + # Write everything to file - with default option for gridfile and metric2d + zoidberg.write_maps(grid, field, maps, gridfile="grid.fci.nc", metric2d=True) As in the above code, creating an output file consists of the following steps: From 41296c13ef11955ab419530b18b0b539845dabcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 16 Feb 2021 11:37:46 +0100 Subject: [PATCH 278/293] Ensure dz is const in tests Ensure that if the code is copied to other use cases, it still is giving the correct result - or fails properly. --- tests/MMS/diffusion/diffusion.cxx | 6 ++++-- tests/MMS/wave-1d/wave.cxx | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/MMS/diffusion/diffusion.cxx b/tests/MMS/diffusion/diffusion.cxx index 205a9c1b4c..6113570446 100644 --- a/tests/MMS/diffusion/diffusion.cxx +++ b/tests/MMS/diffusion/diffusion.cxx @@ -81,13 +81,14 @@ int Diffusion::init(bool UNUSED(restarting)) { // Tell BOUT++ to solve N SOLVE_FOR(N); + BoutReal dz = getUniform(coord->dz); //Set initial condition to MS at t = 0. for (int xi = mesh->xstart; xi < mesh->xend +1; xi++){ for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ for (int zk = 0; zk < mesh->LocalNz; zk++) { output.write("Initial condition at {:d},{:d},{:d}\n", xi, yj, zk); N(xi, yj, zk) = MS(0., mesh->GlobalX(xi) * Lx, mesh->GlobalY(yj) * Ly, - coord->dz(xi, yj, zk) * zk); + dz * zk); } } } @@ -146,12 +147,13 @@ void solution(Field3D &f, BoutReal t, BoutReal UNUSED(D)) { int by = (mesh->LocalNy - (mesh->yend - mesh->ystart + 1)) / 2; BoutReal x,y,z; + BoutReal dz = getUniform(coord->dz); for (int xi = mesh->xstart - bx; xi < mesh->xend + bx + 1; xi++){ for (int yj = mesh->ystart - by; yj < mesh->yend + by + 1; yj++){ x = mesh->GlobalX(xi); y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - z = coord->dz(xi, yj, zk) * zk; + z = dz * zk; output.write("Solution at {:d},{:d},{:d}\n", xi, yj, zk); f(xi, yj, zk) = MS(t,x,y,z); } diff --git a/tests/MMS/wave-1d/wave.cxx b/tests/MMS/wave-1d/wave.cxx index 6518dc56d6..b2280929fb 100644 --- a/tests/MMS/wave-1d/wave.cxx +++ b/tests/MMS/wave-1d/wave.cxx @@ -73,27 +73,25 @@ class Wave1D : public PhysicsModel { SOLVE_FOR(f, g); // Set initial condition to MS at t = 0. + BoutReal dz = getUniform(coord->dz); if (mesh->StaggerGrids) { for (int xi = mesh->xstart; xi < mesh->xend + 1; xi++) { - for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++){ - for (int zk = 0; zk < mesh->LocalNz; zk++) { - f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), - coord->dz(xi, yj, zk) * zk); + for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++) { + for (int zk = 0; zk < mesh->LocalNz; zk++) { + f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), dz * zk); g(xi, yj, zk) = MS_g(0., 0.5 * (mesh->GlobalX(xi) + mesh->GlobalX(xi - 1)), - mesh->GlobalY(yj), coord->dz(xi, yj, zk) * zk); + mesh->GlobalY(yj), dz * zk); output.write("{:d}: {:e}\n", xi, g(xi, yj, zk)); } - } + } } } else { for (int xi = mesh->xstart; xi < mesh->xend + 1; xi++) { for (int yj = mesh->ystart; yj < mesh->yend + 1; yj++) { for (int zk = 0; zk < mesh->LocalNz; zk++) { - f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), - coord->dz(xi, yj, zk) * zk); - g(xi, yj, zk) = MS_g(0., mesh->GlobalX(xi), mesh->GlobalY(yj), - coord->dz(xi, yj, zk) * zk); + f(xi, yj, zk) = MS_f(0., mesh->GlobalX(xi), mesh->GlobalY(yj), dz * zk); + g(xi, yj, zk) = MS_g(0., mesh->GlobalX(xi), mesh->GlobalY(yj), dz * zk); } } } @@ -101,7 +99,7 @@ class Wave1D : public PhysicsModel { E_f.allocate(); E_g.allocate(); SAVE_REPEAT(E_f, E_g); - + return 0; } @@ -171,12 +169,13 @@ const Field3D Wave1D::solution_f(BoutReal t) { int bx = (mesh->LocalNx - (mesh->xend - mesh->xstart + 1)) / 2; int by = (mesh->LocalNy - (mesh->yend - mesh->ystart + 1)) / 2; + BoutReal dz = getUniform(coord->dz); for (int xi = mesh->xstart - bx; xi < mesh->xend + bx + 1; xi++){ for (int yj = mesh->ystart - by; yj < mesh->yend + by + 1; yj++){ BoutReal x = mesh->GlobalX(xi); BoutReal y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal z = coord->dz(xi, yj, zk) * zk; + BoutReal z = dz * zk; S(xi, yj, zk) = MS_f(t,x,y,z); } } @@ -226,6 +225,7 @@ const Field3D Wave1D::solution_g(BoutReal t) { int bx = (mesh->LocalNx - (mesh->xend - mesh->xstart + 1)) / 2; int by = (mesh->LocalNy - (mesh->yend - mesh->ystart + 1)) / 2; + BoutReal dz = getUniform(coord->dz); for (int xi = mesh->xstart - bx; xi < mesh->xend + bx + 1; xi++){ for (int yj = mesh->ystart - by; yj < mesh->yend + by + 1; yj++){ BoutReal x = mesh->GlobalX(xi); @@ -234,7 +234,7 @@ const Field3D Wave1D::solution_g(BoutReal t) { } BoutReal y = mesh->GlobalY(yj);//GlobalY not fixed yet for (int zk = 0; zk < mesh->LocalNz; zk++) { - BoutReal z = coord->dz(xi, yj, zk) * zk; + BoutReal z = dz * zk; S(xi, yj, zk) = MS_g(t,x,y,z); } } From 036177b3bda81c4999666883097b4c354174f91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 16 Feb 2021 11:41:46 +0100 Subject: [PATCH 279/293] Switch back to hypre preconditioner lu doesn't work on GHA because superlu_dist isn't available --- tests/integrated/test-laplacexz/data/BOUT.inp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrated/test-laplacexz/data/BOUT.inp b/tests/integrated/test-laplacexz/data/BOUT.inp index 70f698adbc..f20c3d6c11 100644 --- a/tests/integrated/test-laplacexz/data/BOUT.inp +++ b/tests/integrated/test-laplacexz/data/BOUT.inp @@ -22,7 +22,7 @@ atol=1e-11 ksptype = gmres # Linear iterative method -pctype = lu # Preconditioner. Direct "lu" or "ilu"; iterative "jacobi", "sor" +pctype = hypre # Preconditioner. Direct "lu" or "ilu"; iterative "jacobi", "sor" # Set package to perform factorisation for direct solves # "petsc" built-in solver only serial From 086b7c63bdcee02e887234a489affe62948a3287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 19 Feb 2021 16:22:57 +0100 Subject: [PATCH 280/293] black format everything --- bin/bout-add-mod-path | 65 +- bin/bout-boutdata-restart-create | 55 +- bin/bout-pylib-cmd-to-bin | 254 +- bin/bout-sonnet | 12 +- bin/bout-squashoutput | 23 +- bin/bout-v5-factory-upgrader.py | 11 +- bin/bout-v5-format-upgrader.py | 28 +- bin/bout-v5-input-file-upgrader.py | 8 +- bin/bout-v5-macro-upgrader.py | 23 +- bin/bout-v5-physics-model-upgrader.py | 21 +- bin/bout-v5-xzinterpolation-upgrader.py | 7 +- bin/bout_3to4.py | 145 +- tests/MMS/GBS/circle.py | 139 +- tests/MMS/GBS/mms-slab2d.py | 208 +- tests/MMS/GBS/mms-slab3d.py | 310 ++- tests/MMS/GBS/runtest-slab2d | 73 +- tests/MMS/GBS/runtest-slab3d | 85 +- tests/MMS/advection/arakawa/runtest | 8 +- tests/MMS/advection/central/runtest | 8 +- tests/MMS/advection/mms.py | 30 +- tests/MMS/advection/runtest | 63 +- tests/MMS/advection/upwind/runtest | 8 +- tests/MMS/advection/weno3/runtest | 9 +- tests/MMS/bracket/runtest | 50 +- tests/MMS/derivatives3/runtest | 205 +- tests/MMS/diffusion/runtest | 80 +- tests/MMS/diffusion2/Z/plot_error.py | 38 +- tests/MMS/diffusion2/mms.py | 70 +- tests/MMS/diffusion2/runtest | 105 +- tests/MMS/elm-pb/makegrids.py | 25 +- tests/MMS/elm-pb/mms.py | 109 +- tests/MMS/elm-pb/runtest.broken | 119 +- tests/MMS/fieldalign/mms.py | 67 +- tests/MMS/fieldalign/runtest.broken | 100 +- tests/MMS/hw/mms.py | 49 +- tests/MMS/hw/runtest | 74 +- tests/MMS/laplace/mms.py | 18 +- tests/MMS/laplace/runtest | 48 +- tests/MMS/shiftedmetricinterp/runtest | 1 - tests/MMS/spatial/advection/mms.py | 10 +- tests/MMS/spatial/advection/runtest | 147 +- tests/MMS/spatial/d2dx2/runtest | 48 +- tests/MMS/spatial/d2dz2/runtest | 41 +- tests/MMS/spatial/diffusion/mms.py | 44 +- tests/MMS/spatial/diffusion/runtest | 70 +- tests/MMS/spatial/fci/mms.py | 14 +- tests/MMS/spatial/fci/runtest | 70 +- tests/MMS/time/runtest | 103 +- tests/MMS/tokamak/mms.py | 48 +- tests/MMS/tokamak/runtest.broken | 85 +- tests/MMS/upwinding3/runtest | 207 +- tests/MMS/wave-1d-y/mms.py | 5 +- tests/MMS/wave-1d-y/runtest | 105 +- tests/MMS/wave-1d/mms.py | 9 +- tests/MMS/wave-1d/runtest | 82 +- tests/integrated/test-attribs/runtest | 8 +- .../test-boutcore/collect-staggered/runtest | 12 +- .../integrated/test-boutcore/collect/runtest | 16 +- .../test-boutcore/legacy-model/runtest | 2 +- .../integrated/test-boutcore/mms-ddz/runtest | 13 +- .../test-boutcore/simple-model/runtest | 1 + tests/integrated/test-collect/runtest | 4 +- tests/integrated/test-command-args/runtest | 132 +- tests/integrated/test-communications/runtest | 649 ++--- tests/integrated/test-cyclic/runtest | 17 +- tests/integrated/test-delp2/runtest | 86 +- .../test-drift-instability/runtest.py | 185 +- tests/integrated/test-fieldfactory/runtest | 64 +- tests/integrated/test-fieldgroupComm/runtest | 78 +- .../test-griddata-yboundary-guards/runtest | 274 +- tests/integrated/test-griddata/runtest | 45 +- tests/integrated/test-gyro/runtest | 82 +- tests/integrated/test-initial/runtest | 59 +- .../test-interchange-instability/runtest | 40 +- tests/integrated/test-interpolate-z/runtest | 42 +- tests/integrated/test-interpolate/runtest | 42 +- .../test-invertable-operator/runtest | 32 +- tests/integrated/test-invpar/runtest | 23 +- tests/integrated/test-io/generate.py | 42 +- tests/integrated/test-io/runtest | 14 +- .../test-laplace-petsc3d/plotcheck.py | 16 +- tests/integrated/test-laplace-petsc3d/runtest | 30 +- tests/integrated/test-laplace/runtest | 99 +- .../integrated/test-laplacexy-fv/plotcheck.py | 26 +- .../test-laplacexy-short/plotcheck.py | 26 +- tests/integrated/test-laplacexy-short/runtest | 109 +- tests/integrated/test-laplacexy/plotcheck.py | 26 +- .../integrated/test-laplacexy/plotmetrics.py | 82 +- tests/integrated/test-laplacexy/plotresult.py | 44 +- tests/integrated/test-laplacexy/runtest | 111 +- .../test-multigrid_laplace/plotresults.py | 28 +- .../integrated/test-multigrid_laplace/runtest | 33 +- .../runtest_multiple_grids | 31 +- .../test-multigrid_laplace/runtest_unsheared | 31 +- tests/integrated/test-naulin-laplace/runtest | 33 +- .../runtest_multiple_grids | 31 +- .../test-naulin-laplace/runtest_unsheared | 31 +- tests/integrated/test-options-netcdf/runtest | 20 +- tests/integrated/test-petsc_laplace/runtest | 92 +- .../test-petsc_laplace_MAST-grid/runtest | 99 +- tests/integrated/test-region-iterator/runtest | 43 +- tests/integrated/test-restart-io/runtest | 151 +- tests/integrated/test-slepc-solver/runtest | 4 +- tests/integrated/test-smooth/runtest | 73 +- tests/integrated/test-squash/runtest | 4 +- tests/integrated/test-stopCheck-file/runtest | 6 +- .../test-twistshift-staggered/runtest | 48 +- tests/integrated/test-twistshift/runtest | 62 +- tests/integrated/test_suite | 169 +- tests/requirements/metric_3d | 6 +- tests/requirements/requirements.py | 21 +- tests/requirements/scipy | 7 +- tools/pylib/_boutcore_build/debug.py | 1 + tools/pylib/_boutcore_build/debug_setup.py | 9 +- tools/pylib/_boutcore_build/geninput.py | 14 +- tools/pylib/_boutcore_build/helper.py | 35 +- tools/pylib/post_bout/ListDict.py | 67 +- tools/pylib/post_bout/__init__.py | 50 +- tools/pylib/post_bout/basic_info.py | 529 ++-- tools/pylib/post_bout/grate2.py | 41 +- tools/pylib/post_bout/pb_corral.py | 803 +++--- tools/pylib/post_bout/pb_draw.py | 2255 ++++++++++------- tools/pylib/post_bout/pb_nonlinear.py | 98 +- tools/pylib/post_bout/pb_present.py | 337 +-- tools/pylib/post_bout/read_cxx.py | 163 +- tools/pylib/post_bout/read_inp.py | 694 ++--- tools/pylib/post_bout/rms.py | 43 +- tools/tokamak_grids/all/grid2bout.py | 49 +- tools/tokamak_grids/cyclone/cyclone.py | 108 +- tools/tokamak_grids/elite/elite2nc | 62 +- tools/tokamak_grids/gato/gato2nc | 67 +- 131 files changed, 7019 insertions(+), 5799 deletions(-) diff --git a/bin/bout-add-mod-path b/bin/bout-add-mod-path index 941018d86e..9785ab03da 100755 --- a/bin/bout-add-mod-path +++ b/bin/bout-add-mod-path @@ -30,20 +30,22 @@ root, you can extend this. Create a new folder and at it to your def ask_modpath(): try: - modpath = os.environ['MODULEPATH'] + modpath = os.environ["MODULEPATH"] except KeyError: raise RuntimeError( - "MODULEPATH not set. Please ensure environment modules are loaded.") + "MODULEPATH not set. Please ensure environment modules are loaded." + ) writeable = [] - for modulepath in modpath.split(':'): + for modulepath in modpath.split(":"): if os.access(modulepath, os.W_OK): if modulepath not in writeable: writeable.append(modulepath) if writeable == []: raise RuntimeError( - "Did not find a writeable directory in $MODULEPATH.\nPlease append a writable path.") + "Did not find a writeable directory in $MODULEPATH.\nPlease append a writable path." + ) if len(writeable) == 1: return modulepath[0] @@ -77,11 +79,11 @@ def ask_bouttop(): def create_mod(modulepath, name, top): - pathlib.Path(modulepath+"/bout++").mkdir(parents=True, exist_ok=True) - filename = modulepath+"/bout++/"+name - if 'LOADEDMODULES' in os.environ: + pathlib.Path(modulepath + "/bout++").mkdir(parents=True, exist_ok=True) + filename = modulepath + "/bout++/" + name + if "LOADEDMODULES" in os.environ: prereq = [] - for pr in os.environ['LOADEDMODULES'].split(":"): + for pr in os.environ["LOADEDMODULES"].split(":"): if pr.startswith("bout++/"): continue prereq.append(f"prereq {pr}\n") @@ -89,7 +91,8 @@ def create_mod(modulepath, name, top): else: prereq = "" with open(filename, "w") as f: - f.write(f"""#%Module 1.0 + f.write( + f"""#%Module 1.0 # # BOUT++ module for use with 'environment-modules' package # Created by bout-add-mod-path v0.9 @@ -104,35 +107,53 @@ prepend-path PATH {top}/bin prepend-path LD_LIBRARY_PATH {top}/lib prepend-path PYTHONPATH {top}/tools/pylib prepend-path IDL_PATH +{top}/tools/idllib:'' -""") +""" + ) print(f"created `{filename}`") + class writeable_dir(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): prospective_dir = values if not os.path.isdir(prospective_dir): raise argparse.ArgumentTypeError( - "writeable_dir: {0} is not a valid path".format(prospective_dir)) + "writeable_dir: {0} is not a valid path".format(prospective_dir) + ) if os.access(prospective_dir, os.W_OK): setattr(namespace, self.dest, prospective_dir) else: raise argparse.ArgumentTypeError( - "writeable_dir: {0} is not a writeable dir".format(prospective_dir)) + "writeable_dir: {0} is not a writeable dir".format(prospective_dir) + ) if __name__ == "__main__": - parser = argparse.ArgumentParser(description=_info, - formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument('--modpath', '-m', action=writeable_dir, nargs=1, - help='The modulepath to install the bout++ module') - parser.add_argument('--name', '-n', nargs=1, - help='''Can by any name by which you will be later able to recognise + parser = argparse.ArgumentParser( + description=_info, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--modpath", + "-m", + action=writeable_dir, + nargs=1, + help="The modulepath to install the bout++ module", + ) + parser.add_argument( + "--name", + "-n", + nargs=1, + help="""Can by any name by which you will be later able to recognise this specific bout++ installation, e.g. `3d-metrics`. You can later load the module with `module load bout++/name` e.g. `module load - bout++/3d-metrics`.''') - parser.add_argument('--bout-top', '-t', nargs=1, - help="""bout-top is the root directory of the BOUT++ installation. Note that - it only works with in-source-builds.""") + bout++/3d-metrics`.""", + ) + parser.add_argument( + "--bout-top", + "-t", + nargs=1, + help="""bout-top is the root directory of the BOUT++ installation. Note that + it only works with in-source-builds.""", + ) args = parser.parse_args() modulepath = args.modpath name = args.name diff --git a/bin/bout-boutdata-restart-create b/bin/bout-boutdata-restart-create index 0663185880..d7163efef4 100755 --- a/bin/bout-boutdata-restart-create +++ b/bin/bout-boutdata-restart-create @@ -2,26 +2,51 @@ # PYTHON_ARGCOMPLETE_OK import argparse + try: import argcomplete except ImportError: - argcomplete=None + argcomplete = None parser = argparse.ArgumentParser("Create restart files from data (dmp) files.") -parser.add_argument("--averagelast", type=int, default=1 - ,help= "Number of time points (counting from `final`, inclusive) to" - " average over (default is 1 i.e. just take last time-point)") -parser.add_argument("--final", type=int, default=-1 - ,help= "The last time point to use (default is last, -1)") -parser.add_argument("path", type=str, default="data" - ,help= 'Path to original restart files (default: "data")') -parser.add_argument("--output", type=str, default="./" - ,help= "Path to write new restart files (default: current directory)") -parser.add_argument("--informat", type=str, default="nc" - ,help= 'File extension of original files (default: "nc")') -parser.add_argument("--outformat", type=str, default=None - ,help= "File extension of new files (default: use the same as `informat`)") +parser.add_argument( + "--averagelast", + type=int, + default=1, + help="Number of time points (counting from `final`, inclusive) to" + " average over (default is 1 i.e. just take last time-point)", +) +parser.add_argument( + "--final", + type=int, + default=-1, + help="The last time point to use (default is last, -1)", +) +parser.add_argument( + "path", + type=str, + default="data", + help='Path to original restart files (default: "data")', +) +parser.add_argument( + "--output", + type=str, + default="./", + help="Path to write new restart files (default: current directory)", +) +parser.add_argument( + "--informat", + type=str, + default="nc", + help='File extension of original files (default: "nc")', +) +parser.add_argument( + "--outformat", + type=str, + default=None, + help="File extension of new files (default: use the same as `informat`)", +) if argcomplete: argcomplete.autocomplete(parser) @@ -33,5 +58,3 @@ args = parser.parse_args() # Call the function create, using command line arguments create(**args.__dict__) - - diff --git a/bin/bout-pylib-cmd-to-bin b/bin/bout-pylib-cmd-to-bin index 16217544df..d329be42c8 100755 --- a/bin/bout-pylib-cmd-to-bin +++ b/bin/bout-pylib-cmd-to-bin @@ -9,94 +9,100 @@ import inspect readline.parse_and_bind("tab: complete") -def debug(*args,**kwargs): - #print(*args,**kwargs) + +def debug(*args, **kwargs): + # print(*args,**kwargs) pass class completer(object): - def __init__(self,lst): - self.lst=lst - def complete(self,txt,state): - matches=0 + def __init__(self, lst): + self.lst = lst + + def complete(self, txt, state): + matches = 0 for a in self.lst: if a.startswith(txt): if state == matches: return a matches += 1 return None + + class boutmodules(object): - def __init__(self,lst): - self.modules=[] + def __init__(self, lst): + self.modules = [] for a in lst: self.parseModule(a) debug(self.modules) - def parseModule(self,name): + def parseModule(self, name): try: mod = importlib.import_module(name) except: - debug("Failed to import %s"%name) + debug("Failed to import %s" % name) return try: for loader, module_name, is_pkg in pkgutil.walk_packages(path=mod.__path__): - self.parseModule(name+"."+module_name) + self.parseModule(name + "." + module_name) except AttributeError: - debug("Failed to scan %s for submodues"%name) + debug("Failed to scan %s for submodues" % name) for b in inspect.getmembers(mod): if inspect.isfunction(b[1]): if not name in self.modules: self.modules.append(name) return - def returnCached(self,state): + def returnCached(self, state): if len(self.cache) > state: return self.cache[state] else: return None - def scanFunctions(self,module): - self.functions=[] - self.funcs={} - mod=importlib.import_module(module) + def scanFunctions(self, module): + self.functions = [] + self.funcs = {} + mod = importlib.import_module(module) for b in inspect.getmembers(mod): if inspect.isfunction(b[1]): self.functions.append(b[0]) - self.funcs[b[0]]=b[1] - + self.funcs[b[0]] = b[1] def esc(astr): - astr=str(astr) + astr = str(astr) if '"' in astr: if "'" in astr: - astr=astr.replace("\\","\\\\") - return('"'+astr.replace('"','\"')+'"') - return "'"+astr+"'" - astr=astr.replace("\\","\\\\") - return '"'+astr+'"' + astr = astr.replace("\\", "\\\\") + return '"' + astr.replace('"', '"') + '"' + return "'" + astr + "'" + astr = astr.replace("\\", "\\\\") + return '"' + astr + '"' + def parse_type(typestr): - typearr_=typestr.split(',') - typearr=[] + typearr_ = typestr.split(",") + typearr = [] for t in typearr_: - for t2 in t.split(' or '): + for t2 in t.split(" or "): typearr.append(t2) - opt=False + opt = False if "optional" in typearr[-1]: - opt=True - typearr=typearr[:-1] + opt = True + typearr = typearr[:-1] for type_ in typearr: - knowns={"str" : "str", - "int" : "int", - "slice" : "str_to_slice", - "bool" : "str_to_bool"} + knowns = { + "str": "str", + "int": "int", + "slice": "str_to_slice", + "bool": "str_to_bool", + } if type_ in knowns: - return knowns[type_],opt - raise ValueError("unknown type '%s'"%typestr) + return knowns[type_], opt + raise ValueError("unknown type '%s'" % typestr) -def createwrapper(mod,func_name,func,name): +def createwrapper(mod, func_name, func, name): """ mod : str @@ -108,18 +114,20 @@ def createwrapper(mod,func_name,func,name): name : str The filename """ - filename=name - with open(name,"w") as f: - def fprint(*args,end="\n"): - out="" - sep="" + filename = name + with open(name, "w") as f: + + def fprint(*args, end="\n"): + out = "" + sep = "" for i in args: - out+=sep+i - sep=" " - out+=end + out += sep + i + sep = " " + out += end f.write(out) - fprint("""#!/usr/bin/env python3 + fprint( + """#!/usr/bin/env python3 # PYTHON_ARGCOMPLETE_OK import argparse @@ -128,29 +136,30 @@ try: except ImportError: argcomplete=None -""") - doc=True - para=False - ret=False - docs="" - arg_type={} - arg_opt={} - arg_help={} +""" + ) + doc = True + para = False + ret = False + docs = "" + arg_type = {} + arg_opt = {} + arg_help = {} - paraopen=False + paraopen = False for bla in func.__doc__.splitlines(): - blas=bla.strip() + blas = bla.strip() if doc: if "Parameters" == blas: - doc=False - para=True - off=0 + doc = False + para = True + off = 0 while bla[off] == " ": - off+=1 + off += 1 if doc and blas: if docs: - docs+=" " - docs+=blas + docs += " " + docs += blas if para: if blas == "Return": ret = True @@ -160,7 +169,7 @@ except ImportError: elif blas == "Parameters" or blas == "----------": pass elif len(bla) > off and bla[off] != " ": - arg=blas.split(" : ") + arg = blas.split(" : ") curarg = arg[0] t, o = parse_type(arg[1]) @@ -168,22 +177,25 @@ except ImportError: arg_opt[curarg] = o else: if curarg in arg_help: - arg_help[curarg].append(esc(" "+blas)) + arg_help[curarg].append(esc(" " + blas)) else: - arg_help[curarg]=[] + arg_help[curarg] = [] arg_help[curarg].append(esc(blas)) # Print functions that are needed if "str_to_slice" in arg_type.values(): - fprint(""" + fprint( + """ def str_to_slice(sstr): args=[] for s in sstr.split(','): args.append(int(s)) print(args) return slice(*args) -""") +""" + ) if "str_to_bool" in arg_type.values(): - fprint(""" + fprint( + """ def str_to_bool(sstr): low=sstr.lower() # no or false @@ -194,101 +206,113 @@ def str_to_bool(sstr): return True else: raise ArgumentTypeError("Cannot parse %s to bool type"%sstr) -""") +""" + ) # Create the parser - fprint("parser = argparse.ArgumentParser(%s)"%(esc(docs))) - spec=inspect.signature(func) + fprint("parser = argparse.ArgumentParser(%s)" % (esc(docs))) + spec = inspect.signature(func) for name in spec.parameters: - item=spec.parameters[name] - #print(item) - t=arg_type[name] + item = spec.parameters[name] + # print(item) + t = arg_type[name] if item.default == inspect._empty: # No default value present. Make positional argument - fprint("parser.add_argument(\"%s\", type=%s"%(name,t),end="") + fprint('parser.add_argument("%s", type=%s' % (name, t), end="") else: if t == "str_to_bool" and item.default == False: - fprint("parser.add_argument(\"--%s\", action=\"store_true\", default=False"%(name),end="") + fprint( + 'parser.add_argument("--%s", action="store_true", default=False' + % (name), + end="", + ) else: - fprint("parser.add_argument(\"--%s\", type=%s"%(name,t),end="") - fprint(", default=",end="") + fprint('parser.add_argument("--%s", type=%s' % (name, t), end="") + fprint(", default=", end="") if type(item.default) == str: - fprint(esc(item.default),end="") + fprint(esc(item.default), end="") else: - fprint(str(item.default),end="") + fprint(str(item.default), end="") if t == "str_to_slice": if not name in arg_help: - arg_help[name]=[] - arg_help[name].append(esc("Pass slice object as comma separated list without spaces.")) + arg_help[name] = [] + arg_help[name].append( + esc( + "Pass slice object as comma separated list without spaces." + ) + ) if item.name in arg_help: - pre="\n ,help=" + pre = "\n ,help=" for helps in arg_help[item.name]: - fprint(pre,helps,end="") - pre="\n " + fprint(pre, helps, end="") + pre = "\n " fprint(")") - fprint(""" + fprint( + """ if argcomplete: argcomplete.autocomplete(parser) -# late import for faster auto-complete""") - fprint("from %s import %s"%(mod,func_name)) - fprint(""" +# late import for faster auto-complete""" + ) + fprint("from %s import %s" % (mod, func_name)) + fprint( + """ args = parser.parse_args() # Call the function %s, using command line arguments %s(**args.__dict__) -"""%(func_name,func_name)) +""" + % (func_name, func_name) + ) # alternative, but I think 0o755 is easier to read - #import stat - #os.chmod(filename,stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) + # import stat + # os.chmod(filename,stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) os.chmod(filename, 0o755) + if __name__ == "__main__": - realfun=None + realfun = None if len(sys.argv) < 3: print("Please wait, scanning modules ...") - x=boutmodules(["boutcore", - "boutdata", - "boututils", - "post_bout", - "zoidberg"]) + x = boutmodules(["boutcore", "boutdata", "boututils", "post_bout", "zoidberg"]) readline.set_completer(completer(x.modules).complete) - mod=input("Module: ") + mod = input("Module: ") x.scanFunctions(mod) readline.set_completer(completer(x.functions).complete) - fun=input("Function: ") - realfun=x.funcs[fun] + fun = input("Function: ") + realfun = x.funcs[fun] else: - mod=sys.argv[1] - fun=sys.argv[2] + mod = sys.argv[1] + fun = sys.argv[2] if len(sys.argv) < 4: - name="bin/bout-%s-%s"%(mod,fun) - name=name.replace(".","-") + name = "bin/bout-%s-%s" % (mod, fun) + name = name.replace(".", "-") readline.set_completer() else: - name=sys.argv[3] + name = sys.argv[3] while True: if len(sys.argv) > 4: if sys.argv[4] == "-f": break readline.set_startup_hook(lambda: readline.insert_text(name)) - name=input("Filename: ") + name = input("Filename: ") readline.set_startup_hook() if os.path.exists(name): - print("File %s already exists. If you continue it will be overwritten."%name) - doit=input("Do you want to continue? [y/N] ") + print( + "File %s already exists. If you continue it will be overwritten." % name + ) + doit = input("Do you want to continue? [y/N] ") if "y" in doit.lower(): break else: break - #print("Creating wrapper; rerun with %s %s %s %s"%(sys.argv[0],mod,fun,name)) + # print("Creating wrapper; rerun with %s %s %s %s"%(sys.argv[0],mod,fun,name)) if realfun is None: - exec("from %s import %s as realfun"%(mod,fun)) + exec("from %s import %s as realfun" % (mod, fun)) try: - createwrapper(mod,fun,realfun,name) + createwrapper(mod, fun, realfun, name) except: print("Creating failed. To rerun and overwrite the file without asking run:") - print("%s %s %s %s -f"%(sys.argv[0],mod,fun,name)) + print("%s %s %s %s -f" % (sys.argv[0], mod, fun, name)) raise - diff --git a/bin/bout-sonnet b/bin/bout-sonnet index 4df96e619b..5dc95fdffd 100755 --- a/bin/bout-sonnet +++ b/bin/bout-sonnet @@ -11,25 +11,25 @@ from boutdata.griddata import bout2sonnet # Check command line arguments import sys -nargs = len(sys.argv) # Number of arguments + +nargs = len(sys.argv) # Number of arguments if (nargs < 2) or (nargs > 3): print("Useage:") - print(" "+ sys.argv[0]+" [ ]") + print(" " + sys.argv[0] + " [ ]") print("Input file is a BOUT++ grid file") print("Output is (optionally) a Sonnet output file") raise SystemExit elif nargs == 2: # Only specified input file infile = sys.argv[1] - + # Add ".sonnet" to the end of the name - outfile = infile+".sonnet" + outfile = infile + ".sonnet" else: infile = sys.argv[1] outfile = sys.argv[2] - + with open(outfile, "wt") as f: bout2sonnet(infile, f) print("=> Output written to '%s'" % outfile) - diff --git a/bin/bout-squashoutput b/bin/bout-squashoutput index 804e68ab7f..edbab4f292 100755 --- a/bin/bout-squashoutput +++ b/bin/bout-squashoutput @@ -6,6 +6,7 @@ import argparse from sys import exit + try: import argcomplete except ImportError: @@ -13,8 +14,7 @@ except ImportError: 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): @@ -25,23 +25,22 @@ 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("datadir", nargs="?", default=".") 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("--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("-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) diff --git a/bin/bout-v5-factory-upgrader.py b/bin/bout-v5-factory-upgrader.py index c245f4068d..29fc07db30 100755 --- a/bin/bout-v5-factory-upgrader.py +++ b/bin/bout-v5-factory-upgrader.py @@ -173,9 +173,7 @@ def fix_deletions(variables, source): def fix_create_method(factory, source): - """Fix change of name of factory `create` method - - """ + """Fix change of name of factory `create` method""" if "old_create_method" not in factory: return source @@ -199,9 +197,7 @@ def fix_create_method(factory, source): def yes_or_no(question): - """Convert user input from yes/no variations to True/False - - """ + """Convert user input from yes/no variations to True/False""" while True: reply = input(question + " [y/N] ").lower().strip() if not reply or reply[0] == "n": @@ -236,8 +232,7 @@ def apply_fixes(factories, source, all_declarations=False): def create_patch(filename, original, modified): - """Create a unified diff between original and modified - """ + """Create a unified diff between original and modified""" patch = "\n".join( difflib.unified_diff( diff --git a/bin/bout-v5-format-upgrader.py b/bin/bout-v5-format-upgrader.py index 215fc8be38..7c7d13ac7f 100755 --- a/bin/bout-v5-format-upgrader.py +++ b/bin/bout-v5-format-upgrader.py @@ -23,9 +23,7 @@ def fix_format_replacement(format_replacement, source): - """Replace printf format with fmt format - - """ + """Replace printf format with fmt format""" return re.sub( r"%([0-9]*\.?[0-9]*){}".format(format_replacement[0]), r"{{:\1{}}}".format(format_replacement[1]), @@ -34,9 +32,7 @@ def fix_format_replacement(format_replacement, source): def fix_trivial_format(source): - """Reduce trivial formatting of strings to just the string - - """ + """Reduce trivial formatting of strings to just the string""" def trivial_replace(match): if match.group(2): @@ -60,9 +56,7 @@ def trivial_replace(match): def fix_string_c_str(source): - """Fix formats that use {:s} where the replacement is using std::string::c_str - - """ + """Fix formats that use {:s} where the replacement is using std::string::c_str""" return re.sub( r""" (".*{:s}[^;]*?",) # A format string containing {:s} @@ -75,9 +69,7 @@ def fix_string_c_str(source): def fix_trace(source): - """Fix TRACE macros where fix_string_c_str has failed for some reason - - """ + """Fix TRACE macros where fix_string_c_str has failed for some reason""" return re.sub( r""" (TRACE\(".*{:s}.*",) @@ -90,10 +82,7 @@ def fix_trace(source): def fix_toString_c_str(source): - """Fix formats that call toString where the replacement is using std::string::c_str - - - """ + """Fix formats that call toString where the replacement is using std::string::c_str""" return re.sub( r""" (".*{:s}[^;]*?",.*?) # A format string containing {:s} @@ -130,9 +119,7 @@ def apply_fixes(format_replacements, source): def yes_or_no(question): - """Convert user input from yes/no variations to True/False - - """ + """Convert user input from yes/no variations to True/False""" while True: reply = input(question + " [y/N] ").lower().strip() if not reply or reply[0] == "n": @@ -142,8 +129,7 @@ def yes_or_no(question): def create_patch(filename, original, modified): - """Create a unified diff between original and modified - """ + """Create a unified diff between original and modified""" patch = "\n".join( difflib.unified_diff( diff --git a/bin/bout-v5-input-file-upgrader.py b/bin/bout-v5-input-file-upgrader.py index ff44277d26..dad6b0b0b7 100755 --- a/bin/bout-v5-input-file-upgrader.py +++ b/bin/bout-v5-input-file-upgrader.py @@ -18,8 +18,12 @@ {"old": "mesh:paralleltransform", "new": "mesh:paralleltransform:type"}, {"old": "fci", "new": "mesh:paralleltransform"}, {"old": "interpolation", "new": "mesh:paralleltransform:xzinterpolation"}, - {"old": "fft:fft_measure", "new": "fft:fft_measurement_flag", - "type": bool, "values": {False: "estimate", True: "measure"}} + { + "old": "fft:fft_measure", + "new": "fft:fft_measurement_flag", + "type": bool, + "values": {False: "estimate", True: "measure"}, + }, ] diff --git a/bin/bout-v5-macro-upgrader.py b/bin/bout-v5-macro-upgrader.py index b6db6da427..11b4926255 100755 --- a/bin/bout-v5-macro-upgrader.py +++ b/bin/bout-v5-macro-upgrader.py @@ -178,8 +178,7 @@ def fix_include_version_header(old, headers, source): - """Make sure version.hxx header is included - """ + """Make sure version.hxx header is included""" if not isinstance(headers, list): headers = [headers] @@ -217,9 +216,7 @@ def fix_include_version_header(old, headers, source): def fix_ifdefs(old, source): - """Remove any code inside #ifdef/#ifndef blocks that would now not be compiled - - """ + """Remove any code inside #ifdef/#ifndef blocks that would now not be compiled""" source_lines = source.splitlines() # Something to keep track of nested sections @@ -280,21 +277,18 @@ def fix_ifdefs(old, source): def fix_always_defined_macros(old, new, source): - """Fix '#ifdef's that should become plain '#if' - """ + """Fix '#ifdef's that should become plain '#if'""" new_source = re.sub(r"#ifdef\s+{}\b".format(old), r"#if {}".format(new), source) return re.sub(r"#ifndef\s+{}\b".format(old), r"#if !{}".format(new), new_source) def fix_replacement(old, new, source): - """Straight replacements - """ + """Straight replacements""" return re.sub(r'([^"_])\b{}\b([^"_])'.format(old), r"\1{}\2".format(new), source) def apply_fixes(replacements, source): - """Apply all fixes in this module - """ + """Apply all fixes in this module""" modified = copy.deepcopy(source) for replacement in replacements: @@ -320,9 +314,7 @@ def apply_fixes(replacements, source): def yes_or_no(question): - """Convert user input from yes/no variations to True/False - - """ + """Convert user input from yes/no variations to True/False""" while True: reply = input(question + " [y/N] ").lower().strip() if not reply or reply[0] == "n": @@ -332,8 +324,7 @@ def yes_or_no(question): def create_patch(filename, original, modified): - """Create a unified diff between original and modified - """ + """Create a unified diff between original and modified""" patch = "\n".join( difflib.unified_diff( diff --git a/bin/bout-v5-physics-model-upgrader.py b/bin/bout-v5-physics-model-upgrader.py index 8a309004eb..b518d65c4b 100755 --- a/bin/bout-v5-physics-model-upgrader.py +++ b/bin/bout-v5-physics-model-upgrader.py @@ -46,9 +46,7 @@ class {name} : public PhysicsModel {{ def has_split_operator(source): - """Return the names of the split operator functions if set, otherwise False - - """ + """Return the names of the split operator functions if set, otherwise False""" match = SPLIT_OPERATOR_RE.search(source) if not match: @@ -58,15 +56,12 @@ def has_split_operator(source): def is_legacy_model(source): - """Return true if the source is a legacy physics model - - """ + """Return true if the source is a legacy physics model""" return LEGACY_MODEL_INCLUDE_RE.search(source) is not None def find_last_include(source_lines): - """Return the line number after the last #include (or 0 if no includes) - """ + """Return the line number after the last #include (or 0 if no includes)""" for number, line in enumerate(reversed(source_lines)): if line.startswith("#include"): return len(source_lines) - number @@ -171,8 +166,7 @@ def fix_bout_constrain(source, error_on_warning): def convert_legacy_model(source, name, error_on_warning): - """Convert a legacy physics model to a PhysicsModel - """ + """Convert a legacy physics model to a PhysicsModel""" if not is_legacy_model(source): return source @@ -227,9 +221,7 @@ def convert_legacy_model(source, name, error_on_warning): def yes_or_no(question): - """Convert user input from yes/no variations to True/False - - """ + """Convert user input from yes/no variations to True/False""" while True: reply = input(question + " [y/N] ").lower().strip() if not reply or reply[0] == "n": @@ -239,8 +231,7 @@ def yes_or_no(question): def create_patch(filename, original, modified): - """Create a unified diff between original and modified - """ + """Create a unified diff between original and modified""" patch = "\n".join( difflib.unified_diff( diff --git a/bin/bout-v5-xzinterpolation-upgrader.py b/bin/bout-v5-xzinterpolation-upgrader.py index 5aa565ec0b..1e19c6a034 100755 --- a/bin/bout-v5-xzinterpolation-upgrader.py +++ b/bin/bout-v5-xzinterpolation-upgrader.py @@ -132,8 +132,7 @@ def fix_factories(old_factory, new_factory, source): def create_patch(filename, original, modified): - """Create a unified diff between original and modified - """ + """Create a unified diff between original and modified""" patch = "\n".join( difflib.unified_diff( @@ -149,9 +148,7 @@ def create_patch(filename, original, modified): def yes_or_no(question): - """Convert user input from yes/no variations to True/False - - """ + """Convert user input from yes/no variations to True/False""" while True: reply = input(question + " [y/N] ").lower().strip() if not reply or reply[0] == "n": diff --git a/bin/bout_3to4.py b/bin/bout_3to4.py index 3fa788d55a..02481fcf6e 100755 --- a/bin/bout_3to4.py +++ b/bin/bout_3to4.py @@ -6,25 +6,57 @@ import sys nonmembers = { - 'DC': ['DC', 1], - 'slice': ['sliceXZ', 2], + "DC": ["DC", 1], + "slice": ["sliceXZ", 2], } coordinates = [ "outputVars", - "dx", "dy", "dz", + "dx", + "dy", + "dz", "zlength", "non_uniform", - "d1_dx", "d1_dy", - "J", "Bxy", - "g11", "g22", "g33", "g12", "g13", "g23", - "g_11", "g_22", "g_33", "g_12", "g_13", "g_23", - "G1_11", "G1_22", "G1_33", "G1_12", "G1_13", - "G2_11", "G2_22", "G2_33", "G2_12", "G2_23", - "G3_11", "G3_22", "G3_33", "G3_13", "G3_23", - "G1", "G2", "G3", - "ShiftTorsion", "IntShiftTorsion", - "geometry", "calcCovariant", "calcContravariant", "jacobian" + "d1_dx", + "d1_dy", + "J", + "Bxy", + "g11", + "g22", + "g33", + "g12", + "g13", + "g23", + "g_11", + "g_22", + "g_33", + "g_12", + "g_13", + "g_23", + "G1_11", + "G1_22", + "G1_33", + "G1_12", + "G1_13", + "G2_11", + "G2_22", + "G2_33", + "G2_12", + "G2_23", + "G3_11", + "G3_22", + "G3_33", + "G3_13", + "G3_23", + "G1", + "G2", + "G3", + "ShiftTorsion", + "IntShiftTorsion", + "geometry", + "calcCovariant", + "calcContravariant", + "jacobian", ] local_mesh = [ @@ -35,16 +67,20 @@ warnings = [ (r"\^", "Use pow(a,b) instead of a^b"), (r"\.max\(", "Use max(a) instead of a.max()"), - ("ngz", ("ngz is changed to LocalNz in v4." - " The extra point in z has been removed." - " Change ngz -> LocalNz, and ensure that" - " the number of points are correct") - ) + ( + "ngz", + ( + "ngz is changed to LocalNz in v4." + " The extra point in z has been removed." + " Change ngz -> LocalNz, and ensure that" + " the number of points are correct" + ), + ), ] + def fix_nonmembers(line_text, filename, line_num, replace=False): - """Replace member functions with nonmembers - """ + """Replace member functions with nonmembers""" old_line_text = line_text @@ -58,8 +94,11 @@ def fix_nonmembers(line_text, filename, line_num, replace=False): line_text = re.sub(pattern, replacement, line_text) if not replace: name_num = "{name}:{num}:".format(name=filename, num=line_num) - print("{name_num}{line}".format(name_num=name_num, line=old_line_text), end='') - print(" "*len(name_num) + line_text) + print( + "{name_num}{line}".format(name_num=name_num, line=old_line_text), + end="", + ) + print(" " * len(name_num) + line_text) if replace: return line_text @@ -83,15 +122,16 @@ def fix_subscripts(line_text, filename, line_num, replace=False): line_text = re.sub(pattern, replacement, line_text) if not replace: name_num = "{name}:{num}:".format(name=filename, num=line_num) - print("{name_num}{line}".format(name_num=name_num, line=old_line_text), end='') - print(" "*len(name_num) + line_text) + print( + "{name_num}{line}".format(name_num=name_num, line=old_line_text), end="" + ) + print(" " * len(name_num) + line_text) if replace: return line_text def fix_coordinates(line_text, filename, line_num, replace=False): - """Fix variables that have moved from mesh to coordinates - """ + """Fix variables that have moved from mesh to coordinates""" old_line_text = line_text @@ -99,18 +139,22 @@ def fix_coordinates(line_text, filename, line_num, replace=False): pattern = re.compile("mesh->{}".format(var)) matches = re.findall(pattern, line_text) for match in matches: - line_text = re.sub(pattern, "mesh->coordinates()->{}".format(var), line_text) + line_text = re.sub( + pattern, "mesh->coordinates()->{}".format(var), line_text + ) if not replace: name_num = "{name}:{num}:".format(name=filename, num=line_num) - print("{name_num}{line}".format(name_num=name_num, line=old_line_text), end='') - print(" "*len(name_num) + line_text) + print( + "{name_num}{line}".format(name_num=name_num, line=old_line_text), + end="", + ) + print(" " * len(name_num) + line_text) if replace: return line_text def fix_local_mesh_size(line_text, filename, line_num, replace=False): - """Replaces ng@ with LocalNg@, where @ is in {x,y,z} - """ + """Replaces ng@ with LocalNg@, where @ is in {x,y,z}""" old_line_text = line_text @@ -121,15 +165,17 @@ def fix_local_mesh_size(line_text, filename, line_num, replace=False): line_text = re.sub(pattern, lm[1], line_text) if not replace: name_num = "{name}:{num}:".format(name=filename, num=line_num) - print("{name_num}{line}".format(name_num=name_num, line=old_line_text), end='') - print(" "*len(name_num) + line_text) + print( + "{name_num}{line}".format(name_num=name_num, line=old_line_text), + end="", + ) + print(" " * len(name_num) + line_text) if replace: return line_text def throw_warnings(line_text, filename, line_num): - """Throws a warning for ^, .max() and ngz - """ + """Throws a warning for ^, .max() and ngz""" for warn in warnings: pattern = re.compile(warn[0]) @@ -138,12 +184,17 @@ def throw_warnings(line_text, filename, line_num): name_num = "{name}:{num}:".format(name=filename, num=line_num) # stdout is redirected to the file if --replace is given, # therefore use stderr - sys.stderr.write("{name_num}{line}".format(name_num=name_num, line=line_text)) + sys.stderr.write( + "{name_num}{line}".format(name_num=name_num, line=line_text) + ) # Coloring with \033[91m, end coloring with \033[0m\n - sys.stderr.write(" "*len(name_num) + "\033[91m!!!WARNING: {}\033[0m\n\n".format(warn[1])) + sys.stderr.write( + " " * len(name_num) + + "\033[91m!!!WARNING: {}\033[0m\n\n".format(warn[1]) + ) -if __name__ == '__main__': +if __name__ == "__main__": epilog = """ Currently bout_3to4 can detect the following transformations are needed: @@ -156,13 +207,15 @@ def throw_warnings(line_text, filename, line_num): to the correct scopes """ - parser = argparse.ArgumentParser(description="A little helper for upgrading from BOUT++ version 3 to version 4", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=epilog) - parser.add_argument("-r", "--replace", action="store_true", - help="Actually make the fix") - parser.add_argument("files", nargs='+', - help="Files to process") + parser = argparse.ArgumentParser( + description="A little helper for upgrading from BOUT++ version 3 to version 4", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=epilog, + ) + parser.add_argument( + "-r", "--replace", action="store_true", help="Actually make the fix" + ) + parser.add_argument("files", nargs="+", help="Files to process") args = parser.parse_args() @@ -188,4 +241,4 @@ def throw_warnings(line_text, filename, line_num): # If we're doing a replacement, then we need to print all lines, without a newline if args.replace: - print(line, end='') + print(line, end="") diff --git a/tests/MMS/GBS/circle.py b/tests/MMS/GBS/circle.py index 9ca9d1f62b..4fa77105ed 100644 --- a/tests/MMS/GBS/circle.py +++ b/tests/MMS/GBS/circle.py @@ -14,70 +14,74 @@ from __future__ import print_function from builtins import range -from numpy import zeros, ndarray, pi, cos, sin, outer, linspace,sqrt - -from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries - -def generate(nx, ny, - R = 2.0, r=0.2, # Major & minor radius - dr=0.05, # Radial width of domain - Bt=1.0, # Toroidal magnetic field - q=5.0, # Safety factor - mxg=2, - file="circle.nc" - ): - +from numpy import zeros, ndarray, pi, cos, sin, outer, linspace, sqrt + +from boututils.datafile import DataFile # Wrapper around NetCDF4 libraries + + +def generate( + nx, + ny, + R=2.0, + r=0.2, # Major & minor radius + dr=0.05, # Radial width of domain + Bt=1.0, # Toroidal magnetic field + q=5.0, # Safety factor + mxg=2, + file="circle.nc", +): + # q = rBt / RBp - Bp = r*Bt / (R*q) + Bp = r * Bt / (R * q) # Minor radius as function of x. Choose so boundary # is half-way between grid points - h = dr / (nx - 2.*mxg) # Grid spacing in r - rminor = linspace(r - 0.5*dr - (mxg-0.5)*h, - r + 0.5*dr + (mxg-0.5)*h, - nx) - + h = dr / (nx - 2.0 * mxg) # Grid spacing in r + rminor = linspace( + r - 0.5 * dr - (mxg - 0.5) * h, r + 0.5 * dr + (mxg - 0.5) * h, nx + ) + # mesh spacing in x and y - dx = ndarray([nx,ny]) - dx[:,:] = r*Bt*h # NOTE: dx is toroidal flux + dx = ndarray([nx, ny]) + dx[:, :] = r * Bt * h # NOTE: dx is toroidal flux - dy = ndarray([nx,ny]) - dy[:,:] = 2.*pi / ny + dy = ndarray([nx, ny]) + dy[:, :] = 2.0 * pi / ny # LogB = log(1/(1+r/R cos(theta))) =(approx) -(r/R)*cos(theta) - logB = zeros([nx, ny, 3]) # (constant, n=1 real, n=1 imag) + logB = zeros([nx, ny, 3]) # (constant, n=1 real, n=1 imag) # At y = 0, Rmaj = R + r*cos(theta) - logB[:,0,1] = -(rminor/R) + logB[:, 0, 1] = -(rminor / R) # Moving in y, phase shift by (toroidal angle) / q - for y in range(1,ny): - dtheta = y * 2.*pi / ny / q # Change in poloidal angle + for y in range(1, ny): + dtheta = y * 2.0 * pi / ny / q # Change in poloidal angle - logB[:,y,1] = -(rminor/R)*cos(dtheta) - logB[:,y,2] = -(rminor/R)*sin(dtheta) + logB[:, y, 1] = -(rminor / R) * cos(dtheta) + logB[:, y, 2] = -(rminor / R) * sin(dtheta) # Shift angle from one end of y to the other ShiftAngle = ndarray([nx]) - ShiftAngle[:] = 2.*pi / q - - Rxy = ndarray([nx,ny]) - Rxy[:,:] = r # NOTE : opposite to standard BOUT convention + ShiftAngle[:] = 2.0 * pi / q + + Rxy = ndarray([nx, ny]) + Rxy[:, :] = r # NOTE : opposite to standard BOUT convention - Btxy = ndarray([nx,ny]) - Btxy[:,:] = Bp + Btxy = ndarray([nx, ny]) + Btxy[:, :] = Bp - Bpxy = ndarray([nx,ny]) - Bpxy[:,:] = Bt + Bpxy = ndarray([nx, ny]) + Bpxy[:, :] = Bt - Bxy = ndarray([nx,ny]) - Bxy[:,:] = sqrt(Bt**2 + Bp**2) + Bxy = ndarray([nx, ny]) + Bxy[:, :] = sqrt(Bt ** 2 + Bp ** 2) - hthe = ndarray([nx,ny]) - hthe[:,:] = R + hthe = ndarray([nx, ny]) + hthe[:, :] = R - print("Writing to file '"+file+"'") + print("Writing to file '" + file + "'") f = DataFile() f.open(file, create=True) @@ -98,7 +102,7 @@ def generate(nx, ny, f.write("hthe", hthe) # Shift - f.write("ShiftAngle", ShiftAngle); + f.write("ShiftAngle", ShiftAngle) # Curvature f.write("logB", logB) @@ -114,34 +118,37 @@ def generate(nx, ny, f.close() -def coordinates(nx, ny, nz, - R = 2.0, r=0.2, # Major & minor radius - dr=0.05, # Radial width of domain - Bt=1.0, # Toroidal magnetic field - q=5.0, # Safety factor - mxg=2 - ): +def coordinates( + nx, + ny, + nz, + R=2.0, + r=0.2, # Major & minor radius + dr=0.05, # Radial width of domain + Bt=1.0, # Toroidal magnetic field + q=5.0, # Safety factor + mxg=2, +): """ Returns coordinates (R,Z) as a pair of arrays - + """ - h = dr / (nx - 2.*mxg) # Grid spacing in r - rminor = linspace(r - 0.5*dr - (mxg-0.5)*h, - r + 0.5*dr + (mxg-0.5)*h, - nx) - - print("Grid spacing: Lx = %e, Lz = %e" % (h, 2.*pi*r/nz)) - + h = dr / (nx - 2.0 * mxg) # Grid spacing in r + rminor = linspace( + r - 0.5 * dr - (mxg - 0.5) * h, r + 0.5 * dr + (mxg - 0.5) * h, nx + ) + + print("Grid spacing: Lx = %e, Lz = %e" % (h, 2.0 * pi * r / nz)) + Rxyz = ndarray([nx, ny, nz]) Zxyz = ndarray([nx, ny, nz]) - - for y in range(0,ny): - dtheta = y * 2.*pi / ny / q # Change in poloidal angle - theta = linspace(0,2.*pi, nz, endpoint=False) + dtheta - - Rxyz[:,y,:] = R + outer(rminor, cos(theta)) - Zxyz[:,y,:] = outer(rminor, sin(theta)) - return Rxyz, Zxyz + for y in range(0, ny): + dtheta = y * 2.0 * pi / ny / q # Change in poloidal angle + theta = linspace(0, 2.0 * pi, nz, endpoint=False) + dtheta + + Rxyz[:, y, :] = R + outer(rminor, cos(theta)) + Zxyz[:, y, :] = outer(rminor, sin(theta)) + return Rxyz, Zxyz diff --git a/tests/MMS/GBS/mms-slab2d.py b/tests/MMS/GBS/mms-slab2d.py index 4e8bb089b4..061474edd5 100644 --- a/tests/MMS/GBS/mms-slab2d.py +++ b/tests/MMS/GBS/mms-slab2d.py @@ -1,68 +1,69 @@ from __future__ import print_function from __future__ import division from past.utils import old_div + # # Generate the test case using SymPy # # Equations are: # -# +# # Delp2(phi) = vort + Sphi from boutdata.mms import * #### -#from sympy import Integral -#def rms(expr): +# from sympy import Integral +# def rms(expr): # """ Calculates the RMS value of a function over space # """ # ix = Integral(expr**2, (x, 0, 1)) # ixy = Integral(ix, (y, 0, 2*pi)) -# ixyz = +# ixyz = # return sqrt( , (y, 0, 2*pi), (z, 0, 2*pi)).evalf() ) - + def C(f): - """ Curvature - """ + """Curvature""" return bxcvz * diff(f, metric.z) + ####################################### # Inputs, essentially as in BOUT.inp # Switches -ionvis = False # Ion Viscosity -Ti = 10 # Ion temperature for viscosity calculation -elecvis = False # Electron viscosity +ionvis = False # Ion Viscosity +Ti = 10 # Ion temperature for viscosity calculation +elecvis = False # Electron viscosity resistivity = True parallel = False # Parallel dynamics # Parameters -Tnorm = 5 # Electron Temperature (eV) +Tnorm = 5 # Electron Temperature (eV) Nnorm = 2e18 # Background plasma density (m^-3) Bnorm = 0.35 # Magnetic field [T] -AA = 2 # Ion atomic mass +AA = 2 # Ion atomic mass ####################################### -# +# mi_me = AA * 1.67262158e-27 / 9.109e-31 -beta_e = qe*Tnorm*Nnorm / (old_div(Bnorm**2,mu0)) +beta_e = qe * Tnorm * Nnorm / (old_div(Bnorm ** 2, mu0)) # Normalisation parameters -Cs0 = sqrt(qe*Tnorm / (AA*Mp)) -Omega_ci = qe*Bnorm / (AA*Mp) -rho_s0 = old_div(Cs0, Omega_ci) +Cs0 = sqrt(qe * Tnorm / (AA * Mp)) +Omega_ci = qe * Bnorm / (AA * Mp) +rho_s0 = old_div(Cs0, Omega_ci) # Define a metric -Rxy = 1.5 # Major radius +Rxy = 1.5 # Major radius Bpxy = 0.35 # Poloidal magnetic field -Bxy = 0.35 # Total magnetic field -Btxy = 0.0 # Toroidal magnetic field -hthe = 1.0 # Poloidal arc length +Bxy = 0.35 # Total magnetic field +Btxy = 0.0 # Toroidal magnetic field +hthe = 1.0 # Poloidal arc length sinty = 0.0 sbp = 1.0 @@ -75,70 +76,72 @@ def C(f): MXG = 1 MYG = 0 -bxcvz = 100 # Curvature +bxcvz = 100 # Curvature # Normalise Rxy /= rho_s0 Bpxy /= Bnorm Btxy /= Bnorm -Bxy /= Bnorm +Bxy /= Bnorm hthe /= rho_s0 -dx /= rho_s0**2 * Bnorm +dx /= rho_s0 ** 2 * Bnorm -bxcvz *= rho_s0**2; +bxcvz *= rho_s0 ** 2 # Define a metric -metric = Metric() # Identity +metric = Metric() # Identity -Lx = dx * (nx - 2.*MXG) # Size of the X domain +Lx = dx * (nx - 2.0 * MXG) # Size of the X domain -metric.g11 = (Rxy*Bpxy)**2 -metric.g22 = old_div(1.0, (hthe**2)) -metric.g33 = (sinty**2)*metric.g11 + old_div((Bxy**2),metric.g11) +metric.g11 = (Rxy * Bpxy) ** 2 +metric.g22 = old_div(1.0, (hthe ** 2)) +metric.g33 = (sinty ** 2) * metric.g11 + old_div((Bxy ** 2), metric.g11) metric.g12 = 0.0 -metric.g13 = -sinty*metric.g11 -metric.g23 = -sbp*Btxy/(hthe*Bpxy*Rxy) - +metric.g13 = -sinty * metric.g11 +metric.g23 = -sbp * Btxy / (hthe * Bpxy * Rxy) + metric.J = old_div(hthe, Bpxy) B = metric.B = Bxy - -metric.g_11 = old_div(1.0,metric.g11) + ((sinty*Rxy)**2) -metric.g_22 = (Bxy*hthe/Bpxy)**2 -metric.g_33 = Rxy*Rxy -metric.g_12 = sbp*Btxy*hthe*sinty*Rxy/Bpxy -metric.g_13 = sinty*Rxy*Rxy -metric.g_23 = sbp*Btxy*hthe*Rxy/Bpxy + +metric.g_11 = old_div(1.0, metric.g11) + ((sinty * Rxy) ** 2) +metric.g_22 = (Bxy * hthe / Bpxy) ** 2 +metric.g_33 = Rxy * Rxy +metric.g_12 = sbp * Btxy * hthe * sinty * Rxy / Bpxy +metric.g_13 = sinty * Rxy * Rxy +metric.g_23 = sbp * Btxy * hthe * Rxy / Bpxy # Define the manufactured solution in terms of input x,y and z -Ne = 0.9 + 0.9*x + 0.2*cos(t)*sin(5.*x**2 - 5.*z) -Te = 1 + 0.5*cos(t)*cos(3*x**2 - 4*z) -Vort = sin(2*t)*cos(x - z) -VePsi = 0.5*cos(7*t)*cos(3*x**2 - 3*z) -Vi = -0.1*cos(7*t)*cos(3*x**2 - 3*z) +Ne = 0.9 + 0.9 * x + 0.2 * cos(t) * sin(5.0 * x ** 2 - 5.0 * z) +Te = 1 + 0.5 * cos(t) * cos(3 * x ** 2 - 4 * z) +Vort = sin(2 * t) * cos(x - z) +VePsi = 0.5 * cos(7 * t) * cos(3 * x ** 2 - 3 * z) +Vi = -0.1 * cos(7 * t) * cos(3 * x ** 2 - 3 * z) -phi = sin(z - x + t)*sin(2.*pi*x) # Must satisfy Dirichlet BCs for now -psi = sin(pi*x) *(0.5*x - cos(7*t)*sin(3.*x**2 - 3*z)) # Must satisfy Dirichlet BCs for now +phi = sin(z - x + t) * sin(2.0 * pi * x) # Must satisfy Dirichlet BCs for now +psi = sin(pi * x) * ( + 0.5 * x - cos(7 * t) * sin(3.0 * x ** 2 - 3 * z) +) # Must satisfy Dirichlet BCs for now # Substitute to get in terms of actual x,y,z coordinates -replace = [ (x, old_div(metric.x, Lx)), (z, old_div(metric.z, ZMAX)) ] +replace = [(x, old_div(metric.x, Lx)), (z, old_div(metric.z, ZMAX))] -Ne = Ne.subs(replace) -Te = Te.subs(replace) -Vort = Vort.subs(replace) +Ne = Ne.subs(replace) +Te = Te.subs(replace) +Vort = Vort.subs(replace) VePsi = VePsi.subs(replace) -Vi = Vi.subs(replace) -phi = phi.subs(replace) -psi = psi.subs(replace) +Vi = Vi.subs(replace) +phi = phi.subs(replace) +psi = psi.subs(replace) # Calculate RHS function Pe = Ne * Te -Ve = VePsi - 0.5*mi_me*beta_e*psi +Ve = VePsi - 0.5 * mi_me * beta_e * psi Gi = 0.0 Ge = 0.0 @@ -147,49 +150,49 @@ def C(f): ### Electron density -dNedt = ( - - bracket(phi, Ne, metric) - + (old_div(2,B)) * ( C(Pe) - Ne*C(phi) ) - ) +dNedt = -bracket(phi, Ne, metric) + (old_div(2, B)) * (C(Pe) - Ne * C(phi)) if parallel: - dNedt -= Ne*Grad_par(Ve, metric) + Vpar_Grad_par(Ve, Ne, metric) + dNedt -= Ne * Grad_par(Ve, metric) + Vpar_Grad_par(Ve, Ne, metric) ### Electron temperature -dTedt = ( - - bracket(phi, Te, metric) - + (old_div(4.,3))*(old_div(Te,B)) * ( (old_div(7.,2))*C(Te) + (old_div(Te,Ne))*C(Ne) - C(phi) ) - ) +dTedt = -bracket(phi, Te, metric) + (old_div(4.0, 3)) * (old_div(Te, B)) * ( + (old_div(7.0, 2)) * C(Te) + (old_div(Te, Ne)) * C(Ne) - C(phi) +) if parallel: - dTedt -= Vpar_Grad_par(Ve, Te, metric); - dTedt += (old_div(2.,3.))*Te*( 0.71*Grad_par(Vi, metric) - 1.71*Grad_par(Ve, metric) + 0.71*(Vi-Ve)*Grad_par(log(Ne), metric)) + dTedt -= Vpar_Grad_par(Ve, Te, metric) + dTedt += ( + (old_div(2.0, 3.0)) + * Te + * ( + 0.71 * Grad_par(Vi, metric) + - 1.71 * Grad_par(Ve, metric) + + 0.71 * (Vi - Ve) * Grad_par(log(Ne), metric) + ) + ) ### Vorticity -dVortdt = ( - - bracket(phi, Vort, metric) - + 2.*B*C(Pe)/Ne + B*C(Gi)/(3.*Ne) - ) +dVortdt = -bracket(phi, Vort, metric) + 2.0 * B * C(Pe) / Ne + B * C(Gi) / (3.0 * Ne) if parallel: - dVortdt += ( - - Vpar_Grad_par(Vi, Vort, metric) - + B^2 * (Grad_par(Vi - Ve, metric) + (Vi - Ve)*Grad_par(log(Ne), metric)) - ) + dVortdt += -Vpar_Grad_par(Vi, Vort, metric) + B ^ 2 * ( + Grad_par(Vi - Ve, metric) + (Vi - Ve) * Grad_par(log(Ne), metric) + ) ### Parallel Ohm's law if parallel: dVePsidt = ( - - bracket(phi, Ve, metric) + -bracket(phi, Ve, metric) - Vpar_Grad_par(Ve, Ve, metric) - - mi_me*(old_div(2.,3.))*Grad_par(Ge, metric) - - mi_me*nu*(Ve - Vi) - + mi_me*Grad_par(phi, metric) - - mi_me*( Te*Grad_par(log(Ne), metric) + 1.71*Grad_par(Te, metric) ) - ) + - mi_me * (old_div(2.0, 3.0)) * Grad_par(Ge, metric) + - mi_me * nu * (Ve - Vi) + + mi_me * Grad_par(phi, metric) + - mi_me * (Te * Grad_par(log(Ne), metric) + 1.71 * Grad_par(Te, metric)) + ) else: dVePsidt = 0.0 @@ -197,11 +200,11 @@ def C(f): if parallel: dVidt = ( - - bracket(phi, Vi, metric) + -bracket(phi, Vi, metric) - Vpar_Grad_par(Vi, Vi, metric) - - (old_div(2.,3.))*Grad_par(Gi, metric) - - (Grad_par(Te, metric) + Te*Grad_par(log(Ne), metric)) - ) + - (old_div(2.0, 3.0)) * Grad_par(Gi, metric) + - (Grad_par(Te, metric) + Te * Grad_par(log(Ne), metric)) + ) else: dVidt = 0.0 @@ -213,16 +216,16 @@ def C(f): (Te, dTedt, "Te"), (Vort, dVortdt, "Vort"), (VePsi, dVePsidt, "VePsi"), - (Vi, dVidt, "Vi") - ] + (Vi, dVidt, "Vi"), +] -replace = [ (metric.x, x * Lx), (metric.z, z * ZMAX) ] +replace = [(metric.x, x * Lx), (metric.z, z * ZMAX)] # Loop over variables and print solution, source etc. for v, dvdt, name in vars: # Calculate source S = diff(v, t) - dvdt - + dvdx = diff(v, metric.x) dvdy = diff(v, metric.y) @@ -231,8 +234,8 @@ def C(f): dvdx = dvdx.subs(replace) dvdy = dvdy.subs(replace) S = S.subs(replace) - - print("["+name+"]") + + print("[" + name + "]") print("solution = " + exprToStr(v)) print("\nddx = " + exprToStr(dvdx)) print("\nddy = " + exprToStr(dvdy)) @@ -253,19 +256,24 @@ def C(f): print("\n\nDensity terms:") print(" bracket : ", (-bracket(phi, Ne, metric)).subs(replace), "\n") -print(" (2/B)*C(Pe) : ", ((old_div(2,B)) * C(Pe)).subs(replace), "\n") -print(" (2/B)*Ne*C(phi) : ", ((old_div(2,B))*Ne*C(phi)).subs(replace), "\n") +print(" (2/B)*C(Pe) : ", ((old_div(2, B)) * C(Pe)).subs(replace), "\n") +print(" (2/B)*Ne*C(phi) : ", ((old_div(2, B)) * Ne * C(phi)).subs(replace), "\n") print("\n\nTemperature terms:") -print(" bracket : ", (- bracket(phi, Te, metric)).subs(replace)) -print(" C(Te) : ", ((old_div(4.,3))*(old_div(Te,B)) *(old_div(7.,2))*C(Te)).subs(replace)) -print(" (Te/Ne)*C(Ne) : ", ((old_div(4.,3))*(old_div(Te,B)) *(old_div(Te,Ne))*C(Ne)).subs(replace)) -print(" C(phi) : ", (-(old_div(4.,3))*(old_div(Te,B)) * C(phi)).subs(replace)) - +print(" bracket : ", (-bracket(phi, Te, metric)).subs(replace)) +print( + " C(Te) : ", + ((old_div(4.0, 3)) * (old_div(Te, B)) * (old_div(7.0, 2)) * C(Te)).subs(replace), +) +print( + " (Te/Ne)*C(Ne) : ", + ((old_div(4.0, 3)) * (old_div(Te, B)) * (old_div(Te, Ne)) * C(Ne)).subs(replace), +) +print(" C(phi) : ", (-(old_div(4.0, 3)) * (old_div(Te, B)) * C(phi)).subs(replace)) print("\n\nVorticity terms:") -print(" bracket : ", (- bracket(phi, Vort, metric)).subs(replace)) -print(" C(Pe) : ", (2.*B*C(Pe)/Ne).subs(replace)) -print(" C(Gi) : ", B*C(Gi)/(3.*Ne)) +print(" bracket : ", (-bracket(phi, Vort, metric)).subs(replace)) +print(" C(Pe) : ", (2.0 * B * C(Pe) / Ne).subs(replace)) +print(" C(Gi) : ", B * C(Gi) / (3.0 * Ne)) diff --git a/tests/MMS/GBS/mms-slab3d.py b/tests/MMS/GBS/mms-slab3d.py index eb746eb563..5e050d84ec 100644 --- a/tests/MMS/GBS/mms-slab3d.py +++ b/tests/MMS/GBS/mms-slab3d.py @@ -1,12 +1,13 @@ from __future__ import print_function from __future__ import division from past.utils import old_div + # # Generate the test case using SymPy # # Equations are: # -# +# # Delp2(phi) = vort + Sphi from boutdata.mms import * @@ -15,40 +16,43 @@ #### + def C(f): - """ Curvature - """ + """Curvature""" return bxcvz * diff(f, metric.z) + ####################################### # Inputs, essentially as in BOUT.inp # Switches -ionvis = False # Ion Viscosity -Ti = 10 # Ion temperature for viscosity calculation -elecvis = False # Electron viscosity +ionvis = False # Ion Viscosity +Ti = 10 # Ion temperature for viscosity calculation +elecvis = False # Electron viscosity resistivity = True parallel = True # Parallel dynamics # Parameters -Tnorm = 3 # Electron Temperature (eV) +Tnorm = 3 # Electron Temperature (eV) Nnorm = 1e19 # Background plasma density (m^-3) Bnorm = 0.1 # Magnetic field [T] -AA = 0.1 # Ion atomic mass +AA = 0.1 # Ion atomic mass ####################################### -# +# mi_me = AA * 1.67262158e-27 / 9.109e-31 -beta_e = qe*Tnorm*Nnorm / (old_div(Bnorm**2,mu0)) +beta_e = qe * Tnorm * Nnorm / (old_div(Bnorm ** 2, mu0)) # Normalisation parameters -Cs0 = sqrt(qe*Tnorm / (AA*Mp)) -Omega_ci = qe*Bnorm / (AA*Mp) -rho_s0 = old_div(Cs0, Omega_ci) -Coulomb = 6.6 - 0.5*log(Nnorm * 1e-20) + 1.5*log(Tnorm); -tau_e0 = old_div(1., (2.91e-6 * (old_div(Nnorm, 1e6)) * Coulomb * Tnorm **(old_div(-3.,2)))) +Cs0 = sqrt(qe * Tnorm / (AA * Mp)) +Omega_ci = qe * Bnorm / (AA * Mp) +rho_s0 = old_div(Cs0, Omega_ci) +Coulomb = 6.6 - 0.5 * log(Nnorm * 1e-20) + 1.5 * log(Tnorm) +tau_e0 = old_div( + 1.0, (2.91e-6 * (old_div(Nnorm, 1e6)) * Coulomb * Tnorm ** (old_div(-3.0, 2))) +) # Input settings ZMAX = 1e-3 @@ -56,13 +60,13 @@ def C(f): MXG = 2 MYG = 2 -bxcvz = 100 # Curvature +bxcvz = 100 # Curvature -Rxy = 1.5 # Major radius +Rxy = 1.5 # Major radius Bpxy = 0.35 # Poloidal magnetic field -Bxy = 0.35 # Total magnetic field -Btxy = 0.0 # Toroidal magnetic field -hthe = 0.1 # Poloidal arc length +Bxy = 0.35 # Total magnetic field +Btxy = 0.0 # Toroidal magnetic field +hthe = 0.1 # Poloidal arc length sinty = 0.0 sbp = 1.0 @@ -80,35 +84,35 @@ def C(f): Rxy /= rho_s0 Bpxy /= Bnorm Btxy /= Bnorm -Bxy /= Bnorm +Bxy /= Bnorm hthe /= rho_s0 -dx /= rho_s0**2 * Bnorm +dx /= rho_s0 ** 2 * Bnorm -bxcvz *= rho_s0**2; +bxcvz *= rho_s0 ** 2 # Define a metric -metric = Metric() # Identity +metric = Metric() # Identity -Lx = dx * (nx - 2.*MXG) # Size of the X domain -Ly = dy * ny # Size of the Y domain +Lx = dx * (nx - 2.0 * MXG) # Size of the X domain +Ly = dy * ny # Size of the Y domain -metric.g11 = (Rxy*Bpxy)**2 -metric.g22 = old_div(1.0, (hthe**2)) -metric.g33 = (sinty**2)*metric.g11 + old_div((Bxy**2),metric.g11) +metric.g11 = (Rxy * Bpxy) ** 2 +metric.g22 = old_div(1.0, (hthe ** 2)) +metric.g33 = (sinty ** 2) * metric.g11 + old_div((Bxy ** 2), metric.g11) metric.g12 = 0.0 -metric.g13 = -sinty*metric.g11 -metric.g23 = -sbp*Btxy/(hthe*Bpxy*Rxy) - +metric.g13 = -sinty * metric.g11 +metric.g23 = -sbp * Btxy / (hthe * Bpxy * Rxy) + metric.J = old_div(hthe, Bpxy) B = metric.B = Bxy - -metric.g_11 = old_div(1.0,metric.g11) + ((sinty*Rxy)**2) -metric.g_22 = (Bxy*hthe/Bpxy)**2 -metric.g_33 = Rxy*Rxy -metric.g_12 = sbp*Btxy*hthe*sinty*Rxy/Bpxy -metric.g_13 = sinty*Rxy*Rxy -metric.g_23 = sbp*Btxy*hthe*Rxy/Bpxy + +metric.g_11 = old_div(1.0, metric.g11) + ((sinty * Rxy) ** 2) +metric.g_22 = (Bxy * hthe / Bpxy) ** 2 +metric.g_33 = Rxy * Rxy +metric.g_12 = sbp * Btxy * hthe * sinty * Rxy / Bpxy +metric.g_13 = sinty * Rxy * Rxy +metric.g_23 = sbp * Btxy * hthe * Rxy / Bpxy print("dx = %e, dy = %e" % (dx, dy)) @@ -119,27 +123,35 @@ def C(f): # Define the manufactured solution in terms of input x,y and z -Ne = 0.9 + 0.9*x + 0.5*cos(t)*sin(5.*x**2 - z) + 0.01*sin(y - z) -Te = 1 + 0.5*cos(t)*cos(3*x**2 - 2*z) + 0.005*sin(y-z)*sin(t) -Vort = 2.*sin(2*t)*cos(x - z + 4*y) -VePsi = cos(1.5*t)*(2.*sin((x-0.5)**2 + z) + 0.05*cos(3*x**2 + y - z)) -Vi = -0.01*cos(7*t)*cos(3*x**2 + 2*y - 2*z) +Ne = 0.9 + 0.9 * x + 0.5 * cos(t) * sin(5.0 * x ** 2 - z) + 0.01 * sin(y - z) +Te = 1 + 0.5 * cos(t) * cos(3 * x ** 2 - 2 * z) + 0.005 * sin(y - z) * sin(t) +Vort = 2.0 * sin(2 * t) * cos(x - z + 4 * y) +VePsi = cos(1.5 * t) * (2.0 * sin((x - 0.5) ** 2 + z) + 0.05 * cos(3 * x ** 2 + y - z)) +Vi = -0.01 * cos(7 * t) * cos(3 * x ** 2 + 2 * y - 2 * z) -#phi = sin(z - x + t)*sin(2.*pi*x) -phi = (sin(z - x + t) + 0.001*cos(y - z))*sin(2.*pi*x) # Must satisfy Dirichlet BCs for now -psi = sin(pi*x) *(0.5*x - 0.1*cos(7*t)*sin(3.*x**2 + y - z)) # Must satisfy Dirichlet BCs for now +# phi = sin(z - x + t)*sin(2.*pi*x) +phi = (sin(z - x + t) + 0.001 * cos(y - z)) * sin( + 2.0 * pi * x +) # Must satisfy Dirichlet BCs for now +psi = sin(pi * x) * ( + 0.5 * x - 0.1 * cos(7 * t) * sin(3.0 * x ** 2 + y - z) +) # Must satisfy Dirichlet BCs for now # Substitute to get in terms of actual x,y,z coordinates -replace = [ (x, old_div(metric.x, Lx)), (y, 2*pi*metric.y / Ly), (z, old_div(metric.z, ZMAX)) ] +replace = [ + (x, old_div(metric.x, Lx)), + (y, 2 * pi * metric.y / Ly), + (z, old_div(metric.z, ZMAX)), +] -Ne = Ne.subs(replace) -Te = Te.subs(replace) -Vort = Vort.subs(replace) +Ne = Ne.subs(replace) +Te = Te.subs(replace) +Vort = Vort.subs(replace) VePsi = VePsi.subs(replace) -Vi = Vi.subs(replace) -phi = phi.subs(replace) -psi = psi.subs(replace) +Vi = Vi.subs(replace) +phi = phi.subs(replace) +psi = psi.subs(replace) # Calculate RHS function @@ -147,64 +159,65 @@ def C(f): if estatic: Ve = VePsi else: - Ve = VePsi - 0.5*mi_me*beta_e*psi + Ve = VePsi - 0.5 * mi_me * beta_e * psi print("mi_me = ", mi_me) print("beta_e = ", beta_e) -print("mi_me*beta_e = ", mi_me*beta_e) +print("mi_me*beta_e = ", mi_me * beta_e) Gi = 0.0 Ge = 0.0 -tau_e = Omega_ci*tau_e0 * (Te**1.5)/Ne; # Normalised collision time +tau_e = Omega_ci * tau_e0 * (Te ** 1.5) / Ne +# Normalised collision time -nu = old_div(1., (1.96 * Ne * tau_e * mi_me)) +nu = old_div(1.0, (1.96 * Ne * tau_e * mi_me)) ### Electron density -dNedt = ( - - bracket(phi, Ne, metric) - + (old_div(2,B)) * ( C(Pe) - Ne*C(phi) ) - ) +dNedt = -bracket(phi, Ne, metric) + (old_div(2, B)) * (C(Pe) - Ne * C(phi)) if parallel: - dNedt -= Ne*Grad_par(Ve, metric) + Vpar_Grad_par(Ve, Ne, metric) + dNedt -= Ne * Grad_par(Ve, metric) + Vpar_Grad_par(Ve, Ne, metric) ### Electron temperature -dTedt = ( - - bracket(phi, Te, metric) - + (old_div(4.,3))*(old_div(Te,B)) * ( (old_div(7.,2))*C(Te) + (old_div(Te,Ne))*C(Ne) - C(phi) ) - ) +dTedt = -bracket(phi, Te, metric) + (old_div(4.0, 3)) * (old_div(Te, B)) * ( + (old_div(7.0, 2)) * C(Te) + (old_div(Te, Ne)) * C(Ne) - C(phi) +) if parallel: dTedt -= Vpar_Grad_par(Ve, Te, metric) - dTedt += (old_div(2.,3.))*Te*( 0.71*Grad_par(Vi, metric) - 1.71*Grad_par(Ve, metric) + 0.71*(Vi-Ve)*Grad_par(Ne, metric)/Ne) + dTedt += ( + (old_div(2.0, 3.0)) + * Te + * ( + 0.71 * Grad_par(Vi, metric) + - 1.71 * Grad_par(Ve, metric) + + 0.71 * (Vi - Ve) * Grad_par(Ne, metric) / Ne + ) + ) ### Vorticity -dVortdt = ( - - bracket(phi, Vort, metric) - + 2.*B*C(Pe)/Ne + B*C(Gi)/(3.*Ne) - ) +dVortdt = -bracket(phi, Vort, metric) + 2.0 * B * C(Pe) / Ne + B * C(Gi) / (3.0 * Ne) if parallel: - dVortdt += ( - - Vpar_Grad_par(Vi, Vort, metric) - + B**2 * (Grad_par(Vi - Ve, metric) + (Vi - Ve)*Grad_par(Ne, metric)/Ne) - ) + dVortdt += -Vpar_Grad_par(Vi, Vort, metric) + B ** 2 * ( + Grad_par(Vi - Ve, metric) + (Vi - Ve) * Grad_par(Ne, metric) / Ne + ) ### Parallel Ohm's law if parallel: dVePsidt = ( - - bracket(phi, Ve, metric) + -bracket(phi, Ve, metric) - Vpar_Grad_par(Ve, Ve, metric) - - mi_me*(old_div(2.,3.))*Grad_par(Ge, metric) - - mi_me*nu*(Ve - Vi) - + mi_me*Grad_par(phi, metric) - - mi_me*( Te*Grad_par(Ne, metric)/Ne + 1.71*Grad_par(Te, metric) ) - ) + - mi_me * (old_div(2.0, 3.0)) * Grad_par(Ge, metric) + - mi_me * nu * (Ve - Vi) + + mi_me * Grad_par(phi, metric) + - mi_me * (Te * Grad_par(Ne, metric) / Ne + 1.71 * Grad_par(Te, metric)) + ) else: dVePsidt = 0.0 @@ -212,11 +225,11 @@ def C(f): if parallel: dVidt = ( - - bracket(phi, Vi, metric) + -bracket(phi, Vi, metric) - Vpar_Grad_par(Vi, Vi, metric) - - (old_div(2.,3.))*Grad_par(Gi, metric) - - (Grad_par(Te, metric) + Te*Grad_par(Ne, metric)/Ne) - ) + - (old_div(2.0, 3.0)) * Grad_par(Gi, metric) + - (Grad_par(Te, metric) + Te * Grad_par(Ne, metric) / Ne) + ) else: dVidt = 0.0 @@ -228,16 +241,16 @@ def C(f): (Te, dTedt, "Te"), (Vort, dVortdt, "Vort"), (VePsi, dVePsidt, "VePsi"), - (Vi, dVidt, "Vi") - ] + (Vi, dVidt, "Vi"), +] -replace = [ (metric.x, x * Lx), (metric.y, y * Ly / (2*pi)), (metric.z, z * ZMAX) ] +replace = [(metric.x, x * Lx), (metric.y, y * Ly / (2 * pi)), (metric.z, z * ZMAX)] # Loop over variables and print solution, source etc. for v, dvdt, name in vars: # Calculate source S = diff(v, t) - dvdt - + dvdx = diff(v, metric.x) dvdy = diff(v, metric.y) @@ -246,8 +259,8 @@ def C(f): dvdx = dvdx.subs(replace) dvdy = dvdy.subs(replace) S = S.subs(replace) - - print("["+name+"]") + + print("[" + name + "]") print("solution = " + exprToStr(trySimplify(v))) print("\nddx = " + exprToStr(trySimplify(dvdx))) print("\nddy = " + exprToStr(trySimplify(dvdy))) @@ -261,11 +274,11 @@ def C(f): print("\nsource = " + exprToStr(Sphi.subs(replace))) -#print "\n\nDelp2 phi = ", Delp2(phi, metric).subs(replace) +# print "\n\nDelp2 phi = ", Delp2(phi, metric).subs(replace) if not estatic: - - Spsi = Delp2(psi, metric) - 0.5*Ne*mi_me*beta_e*psi - Ne*(Vi - VePsi) + + Spsi = Delp2(psi, metric) - 0.5 * Ne * mi_me * beta_e * psi - Ne * (Vi - VePsi) print("\n[psi]") print("\nsolution = " + exprToStr(psi.subs(replace))) print("\nsource = " + exprToStr(Spsi.subs(replace))) @@ -274,77 +287,112 @@ def C(f): ########################################## # Check magnitudes of individual terms + def exprmag(expr): """ Estimate the magnitude of an expression - + """ # First put into the BOUT.inp x,y,z expr = expr.subs(replace) # Replace all sin, cos with 1 - any = Wild('a') # Wildcard + any = Wild("a") # Wildcard expr = expr.replace(sin(any), 1.0) expr = expr.replace(cos(any), 1.0) # Pick maximum values of x,y,z expr = expr.subs(x, 1.0) - expr = expr.subs(y, 2.*pi) - expr = expr.subs(z, 2.*pi) + expr = expr.subs(y, 2.0 * pi) + expr = expr.subs(z, 2.0 * pi) return expr.evalf() - print("\n\n########################################") print("\n\nDensity terms:") print(" bracket : ", exprmag(-bracket(phi, Ne, metric)), "\n") -print(" (2/B)*C(Pe) : ", exprmag((old_div(2,B)) * C(Pe)), "\n") -print(" (2/B)*Ne*C(phi) : ", exprmag((old_div(2,B))*Ne*C(phi)), "\n") -print(" Ne*Grad_par(Ve) :", exprmag(Ne*Grad_par(Ve, metric)), "\n") +print(" (2/B)*C(Pe) : ", exprmag((old_div(2, B)) * C(Pe)), "\n") +print(" (2/B)*Ne*C(phi) : ", exprmag((old_div(2, B)) * Ne * C(phi)), "\n") +print(" Ne*Grad_par(Ve) :", exprmag(Ne * Grad_par(Ve, metric)), "\n") print(" Vpar_Grad_par(Ve, Ne)", exprmag(Vpar_Grad_par(Ve, Ne, metric))) print("\n\n########################################") print("\n\nTemperature terms:") -print(" bracket : ", exprmag(- bracket(phi, Te, metric)), "\n") -print(" C(Te) : ", exprmag((old_div(4.,3))*(old_div(Te,B)) *(old_div(7.,2))*C(Te)), "\n") -print(" (Te/Ne)*C(Ne) : ", exprmag((old_div(4.,3))*(old_div(Te,B)) *(old_div(Te,Ne))*C(Ne)), "\n") -print(" C(phi) : ", exprmag(-(old_div(4.,3))*(old_div(Te,B)) * C(phi)), "\n") +print(" bracket : ", exprmag(-bracket(phi, Te, metric)), "\n") +print( + " C(Te) : ", + exprmag((old_div(4.0, 3)) * (old_div(Te, B)) * (old_div(7.0, 2)) * C(Te)), + "\n", +) +print( + " (Te/Ne)*C(Ne) : ", + exprmag((old_div(4.0, 3)) * (old_div(Te, B)) * (old_div(Te, Ne)) * C(Ne)), + "\n", +) +print(" C(phi) : ", exprmag(-(old_div(4.0, 3)) * (old_div(Te, B)) * C(phi)), "\n") print(" Vpar_Grad_par(Ve, Te)", exprmag(Vpar_Grad_par(Ve, Te, metric)), "\n") -print(" (2./3.)*Te*( 0.71*Grad_par(Vi)", exprmag((old_div(2.,3.))*Te*0.71*Grad_par(Vi, metric)), "\n") -print(" (2./3.)*Te*1.71*Grad_par(Ve)", exprmag(-(old_div(2.,3.))*Te*1.71*Grad_par(Ve, metric)) , "\n") -print(" (2./3.)*Te*0.71*(Vi-Ve)*Grad_par(log(Ne))", exprmag((old_div(2.,3.))*Te*0.71*(Vi-Ve)*Grad_par(log(Ne), metric)), "\n") +print( + " (2./3.)*Te*( 0.71*Grad_par(Vi)", + exprmag((old_div(2.0, 3.0)) * Te * 0.71 * Grad_par(Vi, metric)), + "\n", +) +print( + " (2./3.)*Te*1.71*Grad_par(Ve)", + exprmag(-(old_div(2.0, 3.0)) * Te * 1.71 * Grad_par(Ve, metric)), + "\n", +) +print( + " (2./3.)*Te*0.71*(Vi-Ve)*Grad_par(log(Ne))", + exprmag((old_div(2.0, 3.0)) * Te * 0.71 * (Vi - Ve) * Grad_par(log(Ne), metric)), + "\n", +) print("\n\n########################################") print("\n\nVorticity terms:") -print(" bracket : ", exprmag(- bracket(phi, Vort, metric)), "\n") -print(" C(Pe) : ", exprmag(2.*B*C(Pe)/Ne), "\n") -print(" C(Gi) : ", exprmag(B*C(Gi)/(3.*Ne)), "\n") -print(" Vpar_Grad_par(Vi, Vort) : ", exprmag(- Vpar_Grad_par(Vi, Vort, metric)), "\n") -print(" B**2*Grad_par(Vi - Ve) :", exprmag(B**2*Grad_par(Vi - Ve, metric)), "\n") -print(" B**2*(Vi - Ve)*Grad_par(log(Ne)) :", exprmag(B**2 * (Vi - Ve)*Grad_par(log(Ne), metric)), "\n") +print(" bracket : ", exprmag(-bracket(phi, Vort, metric)), "\n") +print(" C(Pe) : ", exprmag(2.0 * B * C(Pe) / Ne), "\n") +print(" C(Gi) : ", exprmag(B * C(Gi) / (3.0 * Ne)), "\n") +print(" Vpar_Grad_par(Vi, Vort) : ", exprmag(-Vpar_Grad_par(Vi, Vort, metric)), "\n") +print(" B**2*Grad_par(Vi - Ve) :", exprmag(B ** 2 * Grad_par(Vi - Ve, metric)), "\n") +print( + " B**2*(Vi - Ve)*Grad_par(log(Ne)) :", + exprmag(B ** 2 * (Vi - Ve) * Grad_par(log(Ne), metric)), + "\n", +) print("\n\n########################################") print("\n\nOhm's law terms:") -print(" bracket : ", exprmag(- bracket(phi, Ve, metric)), "\n") -print(" Vpar_Grad_par(Ve, Ve) : ", exprmag(- Vpar_Grad_par(Ve, Ve, metric)), "\n") -print(" mi_me*(2./3.)*Grad_par(Ge)", exprmag(- mi_me*(old_div(2.,3.))*Grad_par(Ge, metric)), "\n") -print(" mi_me*nu*(Ve - Vi)", exprmag(- mi_me*nu*(Ve - Vi)), "\n") -print(" mi_me*Grad_par(phi)", exprmag(mi_me*Grad_par(phi, metric)), "\n") -print(" mi_me*Te*Grad_par(log(Ne))", exprmag(- mi_me*Te*Grad_par(log(Ne), metric)), "\n") -print(" mi_me*1.71*Grad_par(Te) : ", exprmag(- mi_me*1.71*Grad_par(Te, metric)), "\n") - - -print("\nVe mag: ", exprmag(Ve), exprmag(VePsi), exprmag(0.5*mi_me*beta_e*psi)) +print(" bracket : ", exprmag(-bracket(phi, Ve, metric)), "\n") +print(" Vpar_Grad_par(Ve, Ve) : ", exprmag(-Vpar_Grad_par(Ve, Ve, metric)), "\n") +print( + " mi_me*(2./3.)*Grad_par(Ge)", + exprmag(-mi_me * (old_div(2.0, 3.0)) * Grad_par(Ge, metric)), + "\n", +) +print(" mi_me*nu*(Ve - Vi)", exprmag(-mi_me * nu * (Ve - Vi)), "\n") +print(" mi_me*Grad_par(phi)", exprmag(mi_me * Grad_par(phi, metric)), "\n") +print( + " mi_me*Te*Grad_par(log(Ne))", + exprmag(-mi_me * Te * Grad_par(log(Ne), metric)), + "\n", +) +print( + " mi_me*1.71*Grad_par(Te) : ", exprmag(-mi_me * 1.71 * Grad_par(Te, metric)), "\n" +) + + +print("\nVe mag: ", exprmag(Ve), exprmag(VePsi), exprmag(0.5 * mi_me * beta_e * psi)) print("\n\n########################################") print("\n\nVi terms:") -print(" bracket : ", exprmag(- bracket(phi, Vi, metric)), "\n") -print(" Vpar_Grad_par(Vi, Vi)", exprmag(- Vpar_Grad_par(Vi, Vi, metric)), "\n") -print(" (2./3.)*Grad_par(Gi)", exprmag((old_div(2.,3.))*Grad_par(Gi, metric)), "\n") +print(" bracket : ", exprmag(-bracket(phi, Vi, metric)), "\n") +print(" Vpar_Grad_par(Vi, Vi)", exprmag(-Vpar_Grad_par(Vi, Vi, metric)), "\n") +print( + " (2./3.)*Grad_par(Gi)", exprmag((old_div(2.0, 3.0)) * Grad_par(Gi, metric)), "\n" +) print(" Grad_par(Te", exprmag(-Grad_par(Te, metric)), "\n") -print(" Te*Grad_par(log(Ne))", exprmag(-Te*Grad_par(log(Ne), metric)), "\n") - +print(" Te*Grad_par(log(Ne))", exprmag(-Te * Grad_par(log(Ne), metric)), "\n") diff --git a/tests/MMS/GBS/runtest-slab2d b/tests/MMS/GBS/runtest-slab2d index d468bc2534..282bbd0520 100755 --- a/tests/MMS/GBS/runtest-slab2d +++ b/tests/MMS/GBS/runtest-slab2d @@ -18,55 +18,64 @@ build_and_log("MMS test") # List of NX values to use nxlist = [16, 32, 64, 128, 256] -path="mms-slab2d" +path = "mms-slab2d" -nxdx = 128*2e-5 # Nx * dx held constant +nxdx = 128 * 2e-5 # Nx * dx held constant varlist = ["Ne", "Te", "Vort"] nproc = 4 -success=True +success = True error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # The L2 error (RMS) + error_2[var] = [] # The L2 error (RMS) error_inf[var] = [] # The maximum error for nx in nxlist: - args = "-d " + path + " mesh:nx="+str(nx+2)+" mesh:dx="+str(nxdx/nx)+" MZ="+str(nx) - + args = ( + "-d " + + path + + " mesh:nx=" + + str(nx + 2) + + " mesh:dx=" + + str(nxdx / nx) + + " MZ=" + + str(nx) + ) + print("Running with " + args) # Delete old data shell("rm %s/BOUT.dmp.*.nc" % (path,)) - + # Command to run - cmd = "./gbs "+args + cmd = "./gbs " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open(path+"/run.log."+str(nx), "w") + f = open(path + "/run.log." + str(nx), "w") f.write(out) f.close() - + for var in varlist: # Collect data - E = collect("E_"+var, tind=[1,1], path=path) - E = E[0,1:-1,0,:] + E = collect("E_" + var, tind=[1, 1], path=path) + E = E[0, 1:-1, 0, :] - l2 = sqrt(mean(E**2)) + l2 = sqrt(mean(E ** 2)) linf = max(abs(E)) - - error_2[var].append( l2 ) - error_inf[var].append( linf ) + + error_2[var].append(l2) + error_inf[var].append(linf) print("%s : l-2 %f l-inf %f" % (var, l2, linf)) # Calculate grid spacing -dx = 1. / (array(nxlist) - 2.) +dx = 1.0 / (array(nxlist) - 2.0) # plot errors @@ -77,33 +86,37 @@ for var in varlist: if 1.9 < order < 2.1: pass else: - success=False + success = False try: import matplotlib.pyplot as plt for var in varlist: - plt.plot(dx, error_2[var], '-o', label=r'$l^2$ '+var) - plt.plot(dx, error_inf[var], '-x', label=r'$l^\infty$ '+var) - + plt.plot(dx, error_2[var], "-o", label=r"$l^2$ " + var) + plt.plot(dx, error_inf[var], "-x", label=r"$l^\infty$ " + var) order = log(error_2[var][-1] / error_2[var][-2]) / log(dx[-1] / dx[-2]) - plt.plot(dx, error_2[var][-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot( + dx, + error_2[var][-1] * (dx / dx[-1]) ** order, + "--", + label="Order %.1f" % (order), + ) plt.legend(loc="upper left") plt.grid() - - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Mesh spacing $\delta x$') + + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - + plt.savefig("norm-slab2d.pdf") - - #plt.show() + + # plt.show() except: pass diff --git a/tests/MMS/GBS/runtest-slab3d b/tests/MMS/GBS/runtest-slab3d index 5d73e9a3ff..e072c93733 100755 --- a/tests/MMS/GBS/runtest-slab3d +++ b/tests/MMS/GBS/runtest-slab3d @@ -18,59 +18,72 @@ import pickle build_and_log("MMS test") # List of NX values to use -nxlist = [8, 16, 32, 64, 128]#, 256] +nxlist = [8, 16, 32, 64, 128] # , 256] -path="mms-slab3d" +path = "mms-slab3d" -nxdx = 128*2e-5 # Nx * dx held constant -nydy = 64*1e-3 +nxdx = 128 * 2e-5 # Nx * dx held constant +nydy = 64 * 1e-3 varlist = ["Ne", "Te", "Vort", "VePsi", "Vi"] -markers = ['bo', 'r^', "gs", "k+", "mx"] +markers = ["bo", "r^", "gs", "k+", "mx"] -success=True +success = True nproc = 4 error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # The L2 error (RMS) + error_2[var] = [] # The L2 error (RMS) error_inf[var] = [] # The maximum error for nx in nxlist: - args = "-d " + path + " mesh:nx="+str(nx+4)+" mesh:dx="+str(nxdx/nx)+" MZ="+str(nx)+" mesh:ny="+str(nx)+" mesh:dy="+str(nydy/nx) - + args = ( + "-d " + + path + + " mesh:nx=" + + str(nx + 4) + + " mesh:dx=" + + str(nxdx / nx) + + " MZ=" + + str(nx) + + " mesh:ny=" + + str(nx) + + " mesh:dy=" + + str(nydy / nx) + ) + print("Running with " + args) - + # Delete old data shell("rm %s/BOUT.dmp.*.nc" % (path,)) - + # Command to run - cmd = "./gbs "+args + cmd = "./gbs " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open(path+"/run.log."+str(nx), "w") + f = open(path + "/run.log." + str(nx), "w") f.write(out) f.close() - + for var in varlist: # Collect data - E = collect("E_"+var, tind=[1,1], path=path, info=False) - E = E[0,2:-2,:,:] + E = collect("E_" + var, tind=[1, 1], path=path, info=False) + E = E[0, 2:-2, :, :] - l2 = sqrt(mean(E**2)) + l2 = sqrt(mean(E ** 2)) linf = max(abs(E)) - - error_2[var].append( l2 ) - error_inf[var].append( linf ) + + error_2[var].append(l2) + error_inf[var].append(linf) print("%s : l-2 %f l-inf %f" % (var, l2, linf)) # Calculate grid spacing -dx = 1. / (array(nxlist) - 2.) +dx = 1.0 / (array(nxlist) - 2.0) # Save data with open("mms-slab3d.pkl", "wb") as output: @@ -81,37 +94,37 @@ with open("mms-slab3d.pkl", "wb") as output: # plot errors -for var,mark in zip(varlist, markers): +for var, mark in zip(varlist, markers): order = log(error_2[var][-1] / error_2[var][-2]) / log(dx[-1] / dx[-2]) print("%s Convergence order = %f" % (var, order)) if 1.9 < order < 2.1: pass else: - success=False - #plt.plot(dx, error_2[var][-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + success = False + # plt.plot(dx, error_2[var][-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) try: import matplotlib.pyplot as plt - for var,mark in zip(varlist, markers): - plt.plot(dx, error_2[var], '-'+mark, label=var) - plt.plot(dx, error_inf[var], '--'+mark) + for var, mark in zip(varlist, markers): + plt.plot(dx, error_2[var], "-" + mark, label=var) + plt.plot(dx, error_inf[var], "--" + mark) - #plt.plot(dx, error_2[var][-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + # plt.plot(dx, error_2[var][-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) plt.legend(loc="upper left") plt.grid() - - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Mesh spacing $\delta x$') + + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - + plt.savefig("norm-slab3d.pdf") - - #plt.show() + + # plt.show() except: pass diff --git a/tests/MMS/advection/arakawa/runtest b/tests/MMS/advection/arakawa/runtest index 201db29825..44a07c8f56 100755 --- a/tests/MMS/advection/arakawa/runtest +++ b/tests/MMS/advection/arakawa/runtest @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -#requires: all_tests -#Requires: not make +# requires: all_tests +# Requires: not make import parent parent.make_parent() -parent.nxlist=[64,128] +parent.nxlist = [64, 128] -parent.run_mms([["method=2",2]]) +parent.run_mms([["method=2", 2]]) diff --git a/tests/MMS/advection/central/runtest b/tests/MMS/advection/central/runtest index 50927335a7..66e9450160 100755 --- a/tests/MMS/advection/central/runtest +++ b/tests/MMS/advection/central/runtest @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -#requires: all_tests -#Requires: not make +# requires: all_tests +# Requires: not make import parent parent.make_parent() -parent.nxlist=[64,128] +parent.nxlist = [64, 128] -parent.run_mms([["method=0 mesh:ddx:upwind=c2 mesh:ddz:upwind=c2",2]]) +parent.run_mms([["method=0 mesh:ddx:upwind=c2 mesh:ddz:upwind=c2", 2]]) diff --git a/tests/MMS/advection/mms.py b/tests/MMS/advection/mms.py index d44f45fef4..646b78da9a 100644 --- a/tests/MMS/advection/mms.py +++ b/tests/MMS/advection/mms.py @@ -5,21 +5,21 @@ from math import pi -Lx = 2*pi -Lz = 2*pi +Lx = 2 * pi +Lz = 2 * pi -ZMAX = Lz / (2*pi) +ZMAX = Lz / (2 * pi) -metric = Metric() # Identity metric +metric = Metric() # Identity metric # Define solution in terms of input x,y,z -g = sin(6*x**2 - z) # Constant drive for advection +g = sin(6 * x ** 2 - z) # Constant drive for advection -f = cos(4*x**2 + z) + sin(t)*sin(3*x + 2*z) +f = cos(4 * x ** 2 + z) + sin(t) * sin(3 * x + 2 * z) # Turn solution into real x and z coordinates -replace = [ (x, metric.x / Lx), (z, metric.z / ZMAX) ] +replace = [(x, metric.x / Lx), (z, metric.z / ZMAX)] f = f.subs(replace) g = g.subs(replace) @@ -35,18 +35,18 @@ dfdx = diff(f, metric.x) # Substitute back to get input x and z coordinates -replace = [ (metric.x, x * Lx), (metric.z, z * ZMAX) ] +replace = [(metric.x, x * Lx), (metric.z, z * ZMAX)] -g = g.subs(replace) -f = f.subs(replace) +g = g.subs(replace) +f = f.subs(replace) dfdt = dfdt.subs(replace) -S = S.subs(replace) +S = S.subs(replace) dfdx = dfdx.subs(replace) print("[g]") -print("solution = "+exprToStr(g)) +print("solution = " + exprToStr(g)) print("\n[f]") -print("solution = "+exprToStr(f)) -print("\nddx = "+exprToStr(dfdx)) -print("\nsource = "+exprToStr(S)) +print("solution = " + exprToStr(f)) +print("\nddx = " + exprToStr(dfdx)) +print("\nsource = " + exprToStr(S)) diff --git a/tests/MMS/advection/runtest b/tests/MMS/advection/runtest index 16d653f887..487ae32cc2 100755 --- a/tests/MMS/advection/runtest +++ b/tests/MMS/advection/runtest @@ -5,9 +5,9 @@ # Tests a range of different schemes # -#requires: all_tests -#requires: make -#cores: 8 +# requires: all_tests +# requires: make +# cores: 8 from boututils.run_wrapper import shell, shell_safe, launch_safe from boutdata.collect import collect @@ -21,39 +21,49 @@ import pickle import time - if __name__ == "__main__": print("Making MMS advection test") shell_safe("make > make.log") + def make_parent(): print("Making MMS advection test") shell_safe("make -C .. > make.log") + # List of NX values to use -#[16, 32, 64, 128, 256, 512, 1024] -nxlist = [16,32,64, 128, 256, 512, 1024] +# [16, 32, 64, 128, 256, 512, 1024] +nxlist = [16, 32, 64, 128, 256, 512, 1024] nproc = 8 dt0 = 0.15 -def run_mms(options,exit=True): + +def run_mms(options, exit=True): success = True err_2_all = [] err_inf_all = [] - for opts,exp_order in options: - error_2 = [] # The L2 error (RMS) + for opts, exp_order in options: + error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: # Set the X and Z mesh size - dx = 2.*pi / (nx) + dx = 2.0 * pi / (nx) - args = opts + " mesh:nx="+str(nx+4)+" mesh:dx="+str(dx)+" MZ="+str(nx) #+" solver:timestep="+str(dt0/nx) + args = ( + opts + + " mesh:nx=" + + str(nx + 4) + + " mesh:dx=" + + str(dx) + + " MZ=" + + str(nx) + ) # +" solver:timestep="+str(dt0/nx) print(" Running with " + args) @@ -61,57 +71,56 @@ def run_mms(options,exit=True): shell("rm data/BOUT.dmp.*.nc") # Command to run - cmd = "./advection "+args + cmd = "./advection " + args # Launch using MPI start_time_ = time.time() - + s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E_f = collect("E_f", xguards=False, tind=[1,1], info=False, path="data") + E_f = collect("E_f", xguards=False, tind=[1, 1], info=False, path="data") # Average error over domain - l2 = sqrt(mean(E_f**2)) - linf = max(abs( E_f )) + l2 = sqrt(mean(E_f ** 2)) + linf = max(abs(E_f)) - error_2.append( l2 ) - error_inf.append( linf ) + error_2.append(l2) + error_inf.append(linf) if len(error_2) > 1: - order = log(error_2[-1] / error_2[-2]) / log(.5) - print(" %d | %7.3f s | %.6f"%(nx,time.time() - start_time_,order)) + order = log(error_2[-1] / error_2[-2]) / log(0.5) + print(" %d | %7.3f s | %.6f" % (nx, time.time() - start_time_, order)) else: - print(" %d | %7.3f s | ?"%(nx,time.time() - start_time_)) - + print(" %d | %7.3f s | ?" % (nx, time.time() - start_time_)) print(" -> Error norm: l-2 %f l-inf %f" % (l2, linf)) - - dx = 1. / array(nxlist) + dx = 1.0 / array(nxlist) # Calculate convergence order order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) print("Convergence order = %f" % (order)) - if exp_order-.25 < order < exp_order+0.75: + if exp_order - 0.25 < order < exp_order + 0.75: print("............ PASS") else: success = False print("............ FAIL") - if exit: _exit(success) return success + def _exit(success): from sys import exit + if success: print(" => All tests passed") exit(0) diff --git a/tests/MMS/advection/upwind/runtest b/tests/MMS/advection/upwind/runtest index e526079722..a0fed59ee9 100755 --- a/tests/MMS/advection/upwind/runtest +++ b/tests/MMS/advection/upwind/runtest @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -#requires: all_tests -#Requires: not make +# requires: all_tests +# Requires: not make import parent parent.make_parent() -parent.nxlist=[64,128] +parent.nxlist = [64, 128] -parent.run_mms([["method=0 mesh:ddx:upwind=u1 mesh:ddz:upwind=u1",1]]) +parent.run_mms([["method=0 mesh:ddx:upwind=u1 mesh:ddz:upwind=u1", 1]]) diff --git a/tests/MMS/advection/weno3/runtest b/tests/MMS/advection/weno3/runtest index dfdadc008b..773e3f044c 100755 --- a/tests/MMS/advection/weno3/runtest +++ b/tests/MMS/advection/weno3/runtest @@ -1,13 +1,12 @@ #!/usr/bin/env python3 -#requires: all_tests -#Requires: not make +# requires: all_tests +# Requires: not make import parent parent.make_parent() -parent.nxlist=[64,128] - -parent.run_mms([["method=0 mesh:ddx:upwind=w3 mesh:ddz:upwind=w3",3]]) +parent.nxlist = [64, 128] +parent.run_mms([["method=0 mesh:ddx:upwind=w3 mesh:ddz:upwind=w3", 3]]) diff --git a/tests/MMS/bracket/runtest b/tests/MMS/bracket/runtest index ac316316db..1219138109 100755 --- a/tests/MMS/bracket/runtest +++ b/tests/MMS/bracket/runtest @@ -11,17 +11,15 @@ from builtins import str import numpy as np -#Requires: boutcore -#requires: not make +# Requires: boutcore +# requires: not make import boutcore as bc bc.init("-q -q -q") -funcs = [ - ['sin(z)', 'sin(4*x)', '4*cos(z)*cos(4*x)'] -] +funcs = [["sin(z)", "sin(4*x)", "4*cos(z)*cos(4*x)"]] # List of NX values to use nlist = [8, 16, 32] @@ -45,19 +43,16 @@ def genMesh(nx, ny, nz, **kwargs): errlist = "" -brackets = [["ARAKAWA", 2, {}], - ["STD", 1, {"mesh:ddx:upwind": "U1", - "mesh:ddz:upwind": "U1"} - ], - ["STD", 2, {"mesh:ddx:upwind": "C2", - "mesh:ddz:upwind": "C2"} - ], - # Weno convergence order is currently under discusision: - # https://github.com/boutproject/BOUT-dev/issues/1049 - # ["STD", 3 , {"mesh:ddx:upwind":"W3", - # "mesh:ddz:upwind":"W3"} - # ] - ] +brackets = [ + ["ARAKAWA", 2, {}], + ["STD", 1, {"mesh:ddx:upwind": "U1", "mesh:ddz:upwind": "U1"}], + ["STD", 2, {"mesh:ddx:upwind": "C2", "mesh:ddz:upwind": "C2"}], + # Weno convergence order is currently under discusision: + # https://github.com/boutproject/BOUT-dev/issues/1049 + # ["STD", 3 , {"mesh:ddx:upwind":"W3", + # "mesh:ddz:upwind":"W3"} + # ] +] for in1, in2, outfunc in funcs: for name, order, args in brackets: errors = [] @@ -67,19 +62,24 @@ for in1, in2, outfunc in funcs: inf2 = bc.create3D(in2, mesh) inf = bc.bracket(inf1, inf2, method=name) outf = bc.create3D(outfunc, mesh) - err = (inf-outf) + err = inf - outf slize = [slice(2, -2), 0, slice(None)] err = err[slize] - err = np.sqrt(np.mean(err**2)) + err = np.sqrt(np.mean(err ** 2)) errors.append(err) - errc = np.log(errors[-2]/errors[-1]) - difc = np.log(nlist[-1]/nlist[-2]) - conv = errc/difc - if order-prec < conv < order+prec: + errc = np.log(errors[-2] / errors[-1]) + difc = np.log(nlist[-1] / nlist[-2]) + conv = errc / difc + if order - prec < conv < order + prec: pass else: err = "{%s,%s} -> %s failed (conv: %f - expected: %f)\n" % ( - in1, in2, outfunc, conv, order) + in1, + in2, + outfunc, + conv, + order, + ) errlist += err if errlist: diff --git a/tests/MMS/derivatives3/runtest b/tests/MMS/derivatives3/runtest index a2242c153a..c13baa5f3c 100755 --- a/tests/MMS/derivatives3/runtest +++ b/tests/MMS/derivatives3/runtest @@ -2,125 +2,144 @@ import boutcore -#requires boutcore -#requires not make +# requires boutcore +# requires not make import numpy as np import itertools from sys import exit -errorlist=[] +errorlist = [] boutcore.init("-d data -q -q -q".split(" ")) -def runtests(functions,derivatives,directions,stag,msg): + +def runtests(functions, derivatives, directions, stag, msg): global errorlist for direction in directions: - direction, fac,guards, diff_func = direction - locations=['centre'] - if stag: - locations.append(direction.lower()+"low") - for funcs, derivative , inloc, outloc in itertools.product(functions, - derivatives, locations,locations): - infunc, outfunc = funcs - order, diff = derivative - - errors=[] - for nz in nzs: - boutcore.setOption("meshD:nD".replace("D",direction) - ,"%d"% (nz+ (2*guards if direction == "x" else 0)),force=True) - boutcore.setOption("meshD:dD".replace("D",direction,) - ,"2*pi/(%d)"%(nz),force=True) - dirnfac=direction+"*"+fac - mesh=boutcore.Mesh(section="mesh"+direction) - f=boutcore.create3D(infunc.replace("%s",dirnfac),mesh - ,outloc=inloc) - sim=diff_func(f,method=diff,outloc=outloc) - if sim.getLocation() != outloc: - cent=['CENTRE','CENTER'] - if outloc in cent and sim.getLocation() in cent: - pass - else: - errorlist.append("Location does not match - expected %s but got %s"%(outloc,sim.getLocation())) - ana=boutcore.create3D(outfunc.replace("%s",dirnfac),mesh, outloc=outloc) - err=sim-ana - err=err.getAll().flatten() - if guards: - err=err[guards:-guards] - err=np.max(np.abs(err)) - errors.append(err) - errc=np.log(errors[-2]/errors[-1]) - difc=np.log(nzs[-1]/nzs[-2]) - conv=errc/difc - if order-.1 < conv < order+.1: - pass - else: - info="%s - %s - %s - %s -> %s "%(infunc,diff, direction,inloc,outloc) - error="%s: %s is not working. Expected %f got %f"%(msg,info,order,conv) - errorlist.append(error) - if doPlot: - from matplotlib import pyplot as plt - plt.plot((ana).getAll().flatten()) - plt.plot((sim).getAll().flatten()) - plt.show() - - -mmax=7 -start=6 -doPlot=False -nzs=np.logspace(start,mmax,num=mmax-start+1,base=2) - -functions=[ - ["sin(%s)","cos(%s)"] , - ["cos(%s)", "-sin(%s)"] -] - -derivatives=[ - [2,"C2"] , - [4,"C4"] , - #[2,"W2"] , - #[3,"W3"] , - #[2,"S2"] , + direction, fac, guards, diff_func = direction + locations = ["centre"] + if stag: + locations.append(direction.lower() + "low") + for funcs, derivative, inloc, outloc in itertools.product( + functions, derivatives, locations, locations + ): + infunc, outfunc = funcs + order, diff = derivative + + errors = [] + for nz in nzs: + boutcore.setOption( + "meshD:nD".replace("D", direction), + "%d" % (nz + (2 * guards if direction == "x" else 0)), + force=True, + ) + boutcore.setOption( + "meshD:dD".replace( + "D", + direction, + ), + "2*pi/(%d)" % (nz), + force=True, + ) + dirnfac = direction + "*" + fac + mesh = boutcore.Mesh(section="mesh" + direction) + f = boutcore.create3D(infunc.replace("%s", dirnfac), mesh, outloc=inloc) + sim = diff_func(f, method=diff, outloc=outloc) + if sim.getLocation() != outloc: + cent = ["CENTRE", "CENTER"] + if outloc in cent and sim.getLocation() in cent: + pass + else: + errorlist.append( + "Location does not match - expected %s but got %s" + % (outloc, sim.getLocation()) + ) + ana = boutcore.create3D( + outfunc.replace("%s", dirnfac), mesh, outloc=outloc + ) + err = sim - ana + err = err.getAll().flatten() + if guards: + err = err[guards:-guards] + err = np.max(np.abs(err)) + errors.append(err) + errc = np.log(errors[-2] / errors[-1]) + difc = np.log(nzs[-1] / nzs[-2]) + conv = errc / difc + if order - 0.1 < conv < order + 0.1: + pass + else: + info = "%s - %s - %s - %s -> %s " % ( + infunc, + diff, + direction, + inloc, + outloc, + ) + error = "%s: %s is not working. Expected %f got %f" % ( + msg, + info, + order, + conv, + ) + errorlist.append(error) + if doPlot: + from matplotlib import pyplot as plt + + plt.plot((ana).getAll().flatten()) + plt.plot((sim).getAll().flatten()) + plt.show() + + +mmax = 7 +start = 6 +doPlot = False +nzs = np.logspace(start, mmax, num=mmax - start + 1, base=2) + +functions = [["sin(%s)", "cos(%s)"], ["cos(%s)", "-sin(%s)"]] + +derivatives = [ + [2, "C2"], + [4, "C4"], + # [2,"W2"] , + # [3,"W3"] , + # [2,"S2"] , ] -directions=[ - ["x","2*pi",2 ,boutcore.DDX], - ["y","1" ,2 ,boutcore.DDY], -# ["z","1" ,0 ,boutcore.DDZ] +directions = [ + ["x", "2*pi", 2, boutcore.DDX], + ["y", "1", 2, boutcore.DDY], + # ["z","1" ,0 ,boutcore.DDZ] ] -runtests(functions,derivatives,directions,stag=False,msg="DD") +runtests(functions, derivatives, directions, stag=False, msg="DD") -derivatives=[ - [2,"C2"], - [4,"C4"], +derivatives = [ + [2, "C2"], + [4, "C4"], ] -runtests(functions,derivatives,directions,stag=True,msg="DD") +runtests(functions, derivatives, directions, stag=True, msg="DD") -functions=[ - ["sin(%s)","-sin(%s)"], - ["cos(%s)" , "-cos(%s)"] -] +functions = [["sin(%s)", "-sin(%s)"], ["cos(%s)", "-cos(%s)"]] -derivatives=[ - [2,"C2"], - [4,"C4"] ] +derivatives = [[2, "C2"], [4, "C4"]] -directions=[ - ["x","2*pi",2 ,boutcore.D2DX2], - ["y","1" ,2 ,boutcore.D2DY2], -# ["z","1" ,0 ,boutcore.D2DZ2] +directions = [ + ["x", "2*pi", 2, boutcore.D2DX2], + ["y", "1", 2, boutcore.D2DY2], + # ["z","1" ,0 ,boutcore.D2DZ2] ] -runtests(functions,derivatives,directions,False,"D2D2") +runtests(functions, derivatives, directions, False, "D2D2") -derivatives=[ - [2,"C2"], +derivatives = [ + [2, "C2"], ] -runtests(functions,derivatives,directions,True,"D2D2") +runtests(functions, derivatives, directions, True, "D2D2") boutcore.finalise() diff --git a/tests/MMS/diffusion/runtest b/tests/MMS/diffusion/runtest index e1c04252c6..a25b3519a6 100755 --- a/tests/MMS/diffusion/runtest +++ b/tests/MMS/diffusion/runtest @@ -4,10 +4,11 @@ from __future__ import division from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -25,79 +26,80 @@ timestep = 0.1 nproc = 1 -error_2 = [] # The L2 error (RMS) +error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - args = "mesh:nx="+str(nx)+" nout="+str(nout)+" timestep="+str(timestep) - + args = "mesh:nx=" + str(nx) + " nout=" + str(nout) + " timestep=" + str(timestep) + print("Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./cyto "+args + cmd = "./cyto " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E_N = collect("E_N", tind=[nout,nout], path="data", info=False) + E_N = collect("E_N", tind=[nout, nout], path="data", info=False) - E_N = E_N[0,:,0,0] + E_N = E_N[0, :, 0, 0] # Average error over domain, not including guard cells - l2 = sqrt(mean(E_N[1:-1]**2)) - linf = max(abs( E_N[1:-1] )) - - error_2.append( l2 ) - error_inf.append( linf ) + l2 = sqrt(mean(E_N[1:-1] ** 2)) + linf = max(abs(E_N[1:-1])) + + error_2.append(l2) + error_inf.append(linf) print("Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing -dx = 1. / (array(nxlist) - 2.) +dx = 1.0 / (array(nxlist) - 2.0) order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) print("Convergence order = %f" % (order)) # Attempt to plot errors try: - import matplotlib.pyplot as plt + import matplotlib.pyplot as plt - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) - plt.legend(loc="upper left") - plt.grid() + plt.legend(loc="upper left") + plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') - plt.ylabel("Error norm") + plt.xlabel(r"Mesh spacing $\delta x$") + plt.ylabel("Error norm") - plt.savefig("norm.pdf") + plt.savefig("norm.pdf") - #plt.show() - plt.close() + # plt.show() + plt.close() except: - # Plotting could fail for any number of reasons, and the actual - # error raised may depend on, among other things, the current - # matplotlib backend, so catch everything - pass + # Plotting could fail for any number of reasons, and the actual + # error raised may depend on, among other things, the current + # matplotlib backend, so catch everything + pass if order > 1.8 and order < 2.2: - # test for success - print(" => Test passed") - exit(0) + # test for success + print(" => Test passed") + exit(0) else: - print(" => Test failed") - exit(1) - + print(" => Test failed") + exit(1) diff --git a/tests/MMS/diffusion2/Z/plot_error.py b/tests/MMS/diffusion2/Z/plot_error.py index 052c49e9bd..5c4e1164c1 100644 --- a/tests/MMS/diffusion2/Z/plot_error.py +++ b/tests/MMS/diffusion2/Z/plot_error.py @@ -7,27 +7,25 @@ import boutdata import matplotlib.pyplot as plt -path = '.' -E_n_ = boutdata.collect('E_N',xguards=False, yguards = False, path = path) -#S_n_ = boutdata.collect('S_N',xguards=False, yguards = False, path = path) -n= boutdata.collect('N',xguards=False, path = path) +path = "." +E_n_ = boutdata.collect("E_N", xguards=False, yguards=False, path=path) +# S_n_ = boutdata.collect('S_N',xguards=False, yguards = False, path = path) +n = boutdata.collect("N", xguards=False, path=path) -print('shape E_n = {}'.format(E_n_.shape)) -#n_source_ = boutdata.collect('n_source_',xguards=False) +print("shape E_n = {}".format(E_n_.shape)) +# n_source_ = boutdata.collect('n_source_',xguards=False) -plt.subplot(2,2,1) -plt.plot(E_n_[1,0,0,:],'ro') -plt.title('error') -#plt.colorbar() -plt.subplot(2,2,2) -plt.plot(n[1,0,0,:],'ro') -plt.title('solution') -#plt.colorbar() -#plt.subplot(2,2,3) -#plt.plot(S_n_[1,1,0,:],'ro') -#plt.title('source') -#plt.colorbar() +plt.subplot(2, 2, 1) +plt.plot(E_n_[1, 0, 0, :], "ro") +plt.title("error") +# plt.colorbar() +plt.subplot(2, 2, 2) +plt.plot(n[1, 0, 0, :], "ro") +plt.title("solution") +# plt.colorbar() +# plt.subplot(2,2,3) +# plt.plot(S_n_[1,1,0,:],'ro') +# plt.title('source') +# plt.colorbar() plt.show() - - diff --git a/tests/MMS/diffusion2/mms.py b/tests/MMS/diffusion2/mms.py index b69d0b0e30..d849e88657 100644 --- a/tests/MMS/diffusion2/mms.py +++ b/tests/MMS/diffusion2/mms.py @@ -1,5 +1,6 @@ from __future__ import print_function from builtins import str + # # Generate the test case using SymPy # @@ -12,73 +13,84 @@ #### + def bracket(f, g): """ Calculates [f,g] symbolically """ - + dfdx = diff(f, x) dfdz = diff(f, z) dgdx = diff(g, x) dgdz = diff(g, z) - + return dfdz * dgdx - dfdx * dgdz + def DDZ(f): return diff(f, z) + def Delp2(f): - """ Laplacian in X-Z - """ + """Laplacian in X-Z""" d2fdx2 = diff(f, x, 2) d2fdz2 = diff(f, z, 2) return d2fdx2 + d2fdz2 + def Delp4(f): d4fdx4 = diff(f, x, 4) d4fdz4 = diff(f, z, 4) return d4fdx4 + d4fdz4 + def D2DX2(f): return diff(f, x, 2) + def D2DY2(f): return diff(f, y, 2) + def D2DZ2(f): return diff(f, z, 2) + def exprToStr(expr): - """ Convert a sympy expression to a string for BOUT++ input - """ - tmp = str(expr).replace("**", "^")# Replace exponent operator - tmp = tmp.replace("xl","N:xl") - return tmp.replace("yl","N:yl") + """Convert a sympy expression to a string for BOUT++ input""" + tmp = str(expr).replace("**", "^") # Replace exponent operator + tmp = tmp.replace("xl", "N:xl") + return tmp.replace("yl", "N:yl") + #### # Parameters -Dx = 1. -Dy = 1. -Dz = 1. +Dx = 1.0 +Dy = 1.0 +Dz = 1.0 # Define symbols -x = symbols('x') -y = symbols('y') -xl = symbols('xl') -yl = symbols('yl') -z = symbols('z') -t = symbols('t') -pi = symbols('pi') +x = symbols("x") +y = symbols("y") +xl = symbols("xl") +yl = symbols("yl") +z = symbols("z") +t = symbols("t") +pi = symbols("pi") # Define the manufactured solution -n = 0.9 + 0.9*x + 0.2*sin(5.*x**2 - 2*z) + cos(10*z)*cos(y)*sin(y*7+1.234) - +n = ( + 0.9 + + 0.9 * x + + 0.2 * sin(5.0 * x ** 2 - 2 * z) + + cos(10 * z) * cos(y) * sin(y * 7 + 1.234) +) # Calculate gradients for boundaries @@ -88,21 +100,17 @@ def exprToStr(expr): # Calculate RHS function -dndt = ( - Dx * D2DX2(n) - + Dy * D2DY2(n) - + Dz * D2DZ2(n) - ) +dndt = Dx * D2DX2(n) + Dy * D2DY2(n) + Dz * D2DZ2(n) # Calculate sources Sn = diff(n, t) - dndt -#x and y-domains are Lx and Ly long, respectively -# change to corresponding coordinates. Standard BOUT++ coordinates -#have Lx = 1, Ly = 2pi. -#Scaling takes place in BOUT.inp -scale_coordinates = [(x,xl), (y,yl)] +# x and y-domains are Lx and Ly long, respectively +# change to corresponding coordinates. Standard BOUT++ coordinates +# have Lx = 1, Ly = 2pi. +# Scaling takes place in BOUT.inp +scale_coordinates = [(x, xl), (y, yl)] n = n.subs(scale_coordinates) dndx = dndx.subs(scale_coordinates) dndy = dndy.subs(scale_coordinates) diff --git a/tests/MMS/diffusion2/runtest b/tests/MMS/diffusion2/runtest index 3c5e98c281..954af9f52d 100755 --- a/tests/MMS/diffusion2/runtest +++ b/tests/MMS/diffusion2/runtest @@ -6,8 +6,8 @@ # Checks that the convergence is 2nd order # Exits with status 1 if any test failed -#requires: all_tests -#cores: 2 +# requires: all_tests +# cores: 2 from __future__ import division from __future__ import print_function @@ -26,68 +26,68 @@ build_and_log("MMS diffusion test") # List of input directories inputs = [ ("X", ["mesh:nx"]), - ("Y",["mesh:ny"]), - ("Z",["MZ"])#, - #("XYZ", ["mesh:nx", "mesh:ny", "MZ"]) - ] + ("Y", ["mesh:ny"]), + ("Z", ["MZ"]) # , + # ("XYZ", ["mesh:nx", "mesh:ny", "MZ"]) +] # List of NX values to use nxlist = [4, 8, 16, 32, 64, 128, 256] -#nxlist = [128,256,512,1024,2048,4096] +# nxlist = [128,256,512,1024,2048,4096] nout = 1 -#timestep = 0.1 +# timestep = 0.1 timestep = 0.1 nproc = 2 success = True -for dir,sizes in inputs: +for dir, sizes in inputs: print("Running test in '%s'" % (dir)) - error_2 = [] # The L2 error (RMS) + error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - args = "-d "+dir+" nout="+str(nout)+" timestep="+str(timestep) + args = "-d " + dir + " nout=" + str(nout) + " timestep=" + str(timestep) for s in sizes: - args += " "+s+"="+str(nx) - + args += " " + s + "=" + str(nx) + print(" Running with " + args) # Delete old data - shell("rm "+dir+"/BOUT.dmp.*.nc") - + shell("rm " + dir + "/BOUT.dmp.*.nc") + # Command to run - cmd = "./cyto "+args + cmd = "./cyto " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) - + # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() - + # Collect data - E_N = collect("E_N", tind=[nout,nout], path=dir,info=False) - + E_N = collect("E_N", tind=[nout, nout], path=dir, info=False) + # Average error over domain, not including guard cells - l2 = sqrt(mean(E_N**2)) - linf = max(abs( E_N )) - - error_2.append( l2 ) - error_inf.append( linf ) - + l2 = sqrt(mean(E_N ** 2)) + linf = max(abs(E_N)) + + error_2.append(l2) + error_inf.append(linf) + print(" -> Error norm: l-2 %f l-inf %f" % (l2, linf)) - + # Calculate grid spacing - #This is only correct in the x-direction if MXG = 1. In the other directions - #dy = 1/ny, dz = 1/(MZ-1) - dx = 1. / (array(nxlist) - 2.) + # This is only correct in the x-direction if MXG = 1. In the other directions + # dy = 1/ny, dz = 1/(MZ-1) + dx = 1.0 / (array(nxlist) - 2.0) # Calculate convergence order - + order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) print("Convergence order = %f" % (order)) @@ -96,37 +96,40 @@ for dir,sizes in inputs: else: success = False print("=> FAILED\n") - + # plot errors try: import matplotlib.pyplot as plt + plt.figure() - - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') - - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) - + + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") + + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) + plt.legend(loc="upper left") plt.grid() - - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Mesh spacing $\delta x$') + + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - - plt.savefig(join(dir,"norm.pdf")) - #plt.show() + plt.savefig(join(dir, "norm.pdf")) + + # plt.show() plt.close() except: pass if success: - print(" => All tests passed") - exit(0) + print(" => All tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/MMS/elm-pb/makegrids.py b/tests/MMS/elm-pb/makegrids.py index 06e42c5e41..939b66795c 100644 --- a/tests/MMS/elm-pb/makegrids.py +++ b/tests/MMS/elm-pb/makegrids.py @@ -24,17 +24,17 @@ shape = SimpleTokamak() ## Add equilibrium profiles -MU0 = 4.0e-7*pi +MU0 = 4.0e-7 * pi -J0 = 1 - x - sin(x*pi)**2 * cos(y) # Parallel current -P0 = 2 + cos(x*pi) # Pressure pedestal -bxcvz = -(1./shape.Rxy)**2*cos(y) # Curvature +J0 = 1 - x - sin(x * pi) ** 2 * cos(y) # Parallel current +P0 = 2 + cos(x * pi) # Pressure pedestal +bxcvz = -((1.0 / shape.Rxy) ** 2) * cos(y) # Curvature # Normalisation -Lbar = 1. -Bbar = 1. -J0 = - J0 * shape.Bxy / (MU0 * Lbar) # Turn into A/m^2 -P0 = P0 * Bbar**2 / (2.0*MU0) # Pascals +Lbar = 1.0 +Bbar = 1.0 +J0 = -J0 * shape.Bxy / (MU0 * Lbar) # Turn into A/m^2 +P0 = P0 * Bbar ** 2 / (2.0 * MU0) # Pascals shape.add(P0, "pressure") shape.add(J0, "Jpar0") @@ -50,13 +50,16 @@ else: print("Creating grid file '%s'" % filename) f = DataFile(filename, create=True) - shape.write(nx,nx, f) + shape.write(nx, nx, f) f.close() # Generate BOUT.inp file directory = "grid%d" % nx shell("mkdir " + directory) - shell("cp data/BOUT.inp "+directory) + shell("cp data/BOUT.inp " + directory) shell("sed -i 's/MZ = 17/MZ = %d/g' %s/BOUT.inp" % (nx, directory)) - shell("sed -i 's/grid = \"grid16.nc\"/grid = \"%s\"/g' %s/BOUT.inp" % (filename, directory)) + shell( + 'sed -i \'s/grid = "grid16.nc"/grid = "%s"/g\' %s/BOUT.inp' + % (filename, directory) + ) diff --git a/tests/MMS/elm-pb/mms.py b/tests/MMS/elm-pb/mms.py index 0eceb59c05..d55fc295a8 100644 --- a/tests/MMS/elm-pb/mms.py +++ b/tests/MMS/elm-pb/mms.py @@ -1,4 +1,3 @@ - # Generate MMS solutions for tokamak geometry from __future__ import division @@ -18,20 +17,22 @@ # NOTE: These are orthogonal tokamak coordinates # so y is poloidal angle, not parallel coordinate -phi = (sin(z - x + t) + 0.001*cos(y - z))*sin(2.*pi*x) # Must satisfy Dirichlet BCs for now +phi = (sin(z - x + t) + 0.001 * cos(y - z)) * sin( + 2.0 * pi * x +) # Must satisfy Dirichlet BCs for now -Psi = 1e-2*cos(4*x**2 + z - y) # + sin(t)*sin(3*x + 2*z - y)) +Psi = 1e-2 * cos(4 * x ** 2 + z - y) # + sin(t)*sin(3*x + 2*z - y)) -U = 2.*cos(2*t)*cos(x - z + 4*y) +U = 2.0 * cos(2 * t) * cos(x - z + 4 * y) -P = 1 + 0.5*cos(t)*cos(3*x**2 - z + y) + 0.005*sin(y-z)*sin(t) +P = 1 + 0.5 * cos(t) * cos(3 * x ** 2 - z + y) + 0.005 * sin(y - z) * sin(t) -P0 = 2 + cos(x*pi) # Pressure pedestal -J0 = 1 - x - sin(x*pi)**2 * cos(y) # Parallel current -bxcvz = -(1./shape.Rxy)**2*cos(y) # Curvature +P0 = 2 + cos(x * pi) # Pressure pedestal +J0 = 1 - x - sin(x * pi) ** 2 * cos(y) # Parallel current +bxcvz = -((1.0 / shape.Rxy) ** 2) * cos(y) # Curvature -eta = 1e-1 # core_resist = 1 / core_lund -hyperresist = -1e-6 # negative -> none +eta = 1e-1 # core_resist = 1 / core_lund +hyperresist = -1e-6 # negative -> none viscos_par = 1.0 @@ -42,9 +43,9 @@ # Turn solution into real x and z coordinates # NOTE: Z is shifted, so y is now the parallel coordinate -zShift = shape.zShift.subs(x, metric.x/metric.Lx) -sinty = shape.sinty.subs(x, metric.x/metric.Lx) -replace = [ (x, metric.x/metric.Lx), (z, metric.z / ZMAX + zShift) ] +zShift = shape.zShift.subs(x, metric.x / metric.Lx) +sinty = shape.sinty.subs(x, metric.x / metric.Lx) +replace = [(x, metric.x / metric.Lx), (z, metric.z / ZMAX + zShift)] phi = phi.subs(replace) Psi = Psi.subs(replace) @@ -58,18 +59,20 @@ B0 = metric.B + def Grad_parP(f): result = Grad_par(f, metric) if nonlinear: - result -= B0*bracket(Psi, f, metric) - + result -= B0 * bracket(Psi, f, metric) + return result + ########################################## # Normalise -MU0 = 4.0e-7*pi -Mi = 2.0*1.6726e-27 # Ion mass [kg] +MU0 = 4.0e-7 * pi +Mi = 2.0 * 1.6726e-27 # Ion mass [kg] Bbar = 1 # Tesla Lbar = 1 # meters @@ -82,72 +85,71 @@ def Grad_parP(f): dPsidt = -Grad_parP(phi) + eta * Jpar -if hyperresist > 0.: - dPsidt -= eta*hyperresist * Delp2(Jpar, metric) +if hyperresist > 0.0: + dPsidt -= eta * hyperresist * Delp2(Jpar, metric) -#a = Grad_par(B0*phi, metric)/B0 -#b = bracket(Psi, B0*phi, metric) -#c = eta * Jpar -#d = eta*hyperresist * Delp2(Jpar, metric) +# a = Grad_par(B0*phi, metric)/B0 +# b = bracket(Psi, B0*phi, metric) +# c = eta * Jpar +# d = eta*hyperresist * Delp2(Jpar, metric) ########################################## # Vorticity dUdt = ( - B0**2 * b0xGrad_dot_Grad(Psi, J0, metric) - + bxcvz*diff(P, metric.z) - - (B0**2) * Grad_parP(Jpar) + B0 ** 2 * b0xGrad_dot_Grad(Psi, J0, metric) + + bxcvz * diff(P, metric.z) + - (B0 ** 2) * Grad_parP(Jpar) ) if nonlinear: # Bracket method '0' (STD) goes to b0xGrad_dot_Grad dUdt -= b0xGrad_dot_Grad(phi, U, metric) -#a = B0**2 * b0xGrad_dot_Grad(Psi, J0, metric) -#b = bxcvz*diff(P, metric.z) -#c = (B0**2) * Grad_parP(Jpar) +# a = B0**2 * b0xGrad_dot_Grad(Psi, J0, metric) +# b = bxcvz*diff(P, metric.z) +# c = (B0**2) * Grad_parP(Jpar) ########################################## # Pressure -dPdt = -b0xGrad_dot_Grad(phi, P0, metric); +dPdt = -b0xGrad_dot_Grad(phi, P0, metric) if nonlinear: # Bracket method '0' (STD) goes to b0xGrad_dot_Grad dPdt -= b0xGrad_dot_Grad(phi, P, metric) -vars = [ - (Psi, dPsidt, "Psi"), - (U, dUdt, "U"), - (P, dPdt, "P") - ] +vars = [(Psi, dPsidt, "Psi"), (U, dUdt, "U"), (P, dPdt, "P")] # Change back to normalised coordinates # NOTE: Z remains shifted, so y is still parallel coordinate # Need to scale the toroidal angle part of z, not zShift part -replace = [ (metric.x, x * metric.Lx), (metric.z, (z - shape.zShift) * ZMAX + shape.zShift) ] +replace = [ + (metric.x, x * metric.Lx), + (metric.z, (z - shape.zShift) * ZMAX + shape.zShift), +] # For applying boundary conditions to shifted fields, remove zShift -replace_shiftbc = [ (metric.x, x * metric.Lx), (metric.z, (z - shape.zShift) * ZMAX) ] +replace_shiftbc = [(metric.x, x * metric.Lx), (metric.z, (z - shape.zShift) * ZMAX)] -#print "MAG: ", exprMag(a.subs(replace)), exprMag(b.subs(replace)), exprMag(c.subs(replace))#, exprMag(d.subs(replace)) +# print "MAG: ", exprMag(a.subs(replace)), exprMag(b.subs(replace)), exprMag(c.subs(replace))#, exprMag(d.subs(replace)) # Potential if diamag: # Delp2(phi + 0.5*P/B0) = U + Sphi - Sphi = Delp2(phi + 0.5*P/B0, metric) - U + Sphi = Delp2(phi + 0.5 * P / B0, metric) - U else: # Delp2(phi) = U + Sphi Sphi = Delp2(phi, metric) - U phi = phi.subs(replace) Sphi = Sphi.subs(replace) print("[phi]") -print("solution = "+exprToStr(phi)) -print("\nsource = "+exprToStr(Sphi)) +print("solution = " + exprToStr(phi)) +print("\nsource = " + exprToStr(Sphi)) Jpar = Jpar.subs(replace) print("\n[J]") -print("solution = "+exprToStr(Jpar)) +print("solution = " + exprToStr(Jpar)) # Loop over variables and print solution, source etc. @@ -160,20 +162,19 @@ def Grad_parP(f): dfdy = diff(f, metric.y) # Substitute back to get in terms of x,y,z - - fbc = f.subs(replace_shiftbc) - f = f.subs(replace) + + fbc = f.subs(replace_shiftbc) + f = f.subs(replace) dfdt = dfdt.subs(replace) - S = S.subs(replace) + S = S.subs(replace) dfdx = dfdx.subs(replace) dfdy = dfdy.subs(replace) - - print("\n["+name+"]") - print("solution = "+exprToStr(f)) - print("solution_zshift = "+exprToStr(fbc)) - print("\nddx = "+exprToStr(dfdx)) - print("\nddy = "+exprToStr(dfdy)) - print("\nsource = "+exprToStr(S)) - #print("\nSource magnitude: %e" % exprMag(S)) + print("\n[" + name + "]") + print("solution = " + exprToStr(f)) + print("solution_zshift = " + exprToStr(fbc)) + print("\nddx = " + exprToStr(dfdx)) + print("\nddy = " + exprToStr(dfdy)) + print("\nsource = " + exprToStr(S)) + # print("\nSource magnitude: %e" % exprMag(S)) diff --git a/tests/MMS/elm-pb/runtest.broken b/tests/MMS/elm-pb/runtest.broken index e62fcac971..672e7e7031 100755 --- a/tests/MMS/elm-pb/runtest.broken +++ b/tests/MMS/elm-pb/runtest.broken @@ -5,7 +5,7 @@ # Tests a range of different schemes # -#requires: all_tests +# requires: all_tests from __future__ import division from __future__ import print_function @@ -30,22 +30,23 @@ from sys import stdout ## Note: This must be the same as in the mms.py code from boutdata.mms import SimpleTokamak, x, y from sympy import sin, cos + shape = SimpleTokamak() m = shape.metric() ## Add equilibrium profiles B0 = m.B -MU0 = 4.0e-7*pi +MU0 = 4.0e-7 * pi -J0 = 1 - x - sin(x*pi)**2 * cos(y) # Parallel current -P0 = 2 + cos(x*pi) # Pressure pedestal -bxcvz = -(1./shape.Rxy)**2*cos(y) # Curvature +J0 = 1 - x - sin(x * pi) ** 2 * cos(y) # Parallel current +P0 = 2 + cos(x * pi) # Pressure pedestal +bxcvz = -((1.0 / shape.Rxy) ** 2) * cos(y) # Curvature # Normalisation -Lbar = 1. -Bbar = 1. -J0 = - J0 * shape.Bxy / (MU0 * Lbar) # Turn into A/m^2 -P0 = P0 * Bbar**2 / (2.0*MU0) # Pascals +Lbar = 1.0 +Bbar = 1.0 +J0 = -J0 * shape.Bxy / (MU0 * Lbar) # Turn into A/m^2 +P0 = P0 * Bbar ** 2 / (2.0 * MU0) # Pascals shape.add(P0, "pressure") shape.add(J0, "Jpar0") @@ -55,79 +56,79 @@ shape.add(bxcvz, "bxcvz") build_and_log("MMS elm-pb test") # List of NX values to use -nxlist = [8, 16, 32, 64]#, 128]#, 256] -nprocs = [4, 4, 8, 8, 8, 8] +nxlist = [8, 16, 32, 64] # , 128]#, 256] +nprocs = [4, 4, 8, 8, 8, 8] success = True varlist = ["P", "Psi", "U"] -markers = ['bo', 'r^', "gs"] -labels = [r'$P$', r'$\psi$', r'$U$'] +markers = ["bo", "r^", "gs"] +labels = [r"$P$", r"$\psi$", r"$U$"] error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # The L2 error (RMS) + error_2[var] = [] # The L2 error (RMS) error_inf[var] = [] # The maximum error -running = True # Run the simulations? +running = True # Run the simulations? -for nx,nproc in zip(nxlist, nprocs): +for nx, nproc in zip(nxlist, nprocs): directory = "grid%d" % nx - + if running: # Generate a mesh file if needed - + filename = "grid%d.nc" % nx - + if isfile(filename): print("Grid file '%s' already exists" % filename) else: print("Creating grid file '%s'" % filename) f = DataFile(filename, create=True) - shape.write(nx,nx, f) + shape.write(nx, nx, f) f.close() - - args = " MZ="+str(nx)+" grid="+filename #+" solver:timestep="+str(0.1/nx) - - print(" Running with " + args) - + args = ( + " MZ=" + str(nx) + " grid=" + filename + ) # +" solver:timestep="+str(0.1/nx) + + print(" Running with " + args) # Run each simulation in a different directory shell("mkdir " + directory) - shell_safe("cp data/BOUT.inp "+directory) + shell_safe("cp data/BOUT.inp " + directory) # Delete old data shell("rm %s/BOUT.dmp.*.nc" % directory) - - args = " -d "+directory+" "+args - + + args = " -d " + directory + " " + args + # Command to run - cmd = "./elm_pb "+args + cmd = "./elm_pb " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) - + # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() - + for var in varlist: # Collect data - E = collect("E_"+var, tind=[1,1], info=False, path=directory) - E = E[:,2:-2, :,:] - + E = collect("E_" + var, tind=[1, 1], info=False, path=directory) + E = E[:, 2:-2, :, :] + # Average error over domain - l2 = sqrt(mean(E**2)) - linf = max(abs( E )) - - error_2[var].append( l2 ) - error_inf[var].append( linf ) + l2 = sqrt(mean(E ** 2)) + linf = max(abs(E)) + + error_2[var].append(l2) + error_inf[var].append(linf) print("%s : l-2 %f l-inf %f" % (var, l2, linf)) - - -dx = 1. / array(nxlist) + + +dx = 1.0 / array(nxlist) # Save data with open("elm_pb.pkl", "wb") as output: @@ -139,14 +140,14 @@ with open("elm_pb.pkl", "wb") as output: plt.figure() # Calculate convergence order -for var,mark,label in zip(varlist, markers, labels): - plt.plot(dx, error_2[var], '-'+mark, label=label) - plt.plot(dx, error_inf[var], '--'+mark) +for var, mark, label in zip(varlist, markers, labels): + plt.plot(dx, error_2[var], "-" + mark, label=label) + plt.plot(dx, error_inf[var], "--" + mark) order = log(error_2[var][-1] / error_2[var][-2]) / log(dx[-1] / dx[-2]) stdout.write("%s Convergence order = %f" % (var, order)) - - if 1.8 < order < 2.2: # Should be second order accurate + + if 1.8 < order < 2.2: # Should be second order accurate print("............ PASS") else: success = False @@ -155,21 +156,21 @@ for var,mark,label in zip(varlist, markers, labels): plt.legend(loc="upper left") plt.grid() - -plt.yscale('log') -plt.xscale('log') - -plt.xlabel(r'Mesh spacing $\delta x$') + +plt.yscale("log") +plt.xscale("log") + +plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - + plt.savefig("norm.pdf") plt.show() plt.close() if success: - print(" => All tests passed") - exit(0) + print(" => All tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/MMS/fieldalign/mms.py b/tests/MMS/fieldalign/mms.py index 65eff39a87..e2c0381867 100644 --- a/tests/MMS/fieldalign/mms.py +++ b/tests/MMS/fieldalign/mms.py @@ -8,33 +8,33 @@ # Define symbols for orthogonal (theta, phi) coordinates theta = symbols("theta") -phi = symbols("phi") -psi = symbols("psi") -t = symbols("t") -pi = symbols("pi") +phi = symbols("phi") +psi = symbols("psi") +t = symbols("t") +pi = symbols("pi") # Define solution (theta, phi) -#f = cos(theta + phi - t)**2 -f = cos(psi + theta + phi - t)**2 +# f = cos(theta + phi - t)**2 +f = cos(psi + theta + phi - t) ** 2 # Calculate solution in (theta, phi) -dfdt = diff(f, theta) + diff(f, phi) + diff(f,psi) -dfdpsi = diff(f,psi) -dfdtheta = diff(f,theta) +dfdt = diff(f, theta) + diff(f, phi) + diff(f, psi) +dfdpsi = diff(f, psi) +dfdtheta = diff(f, theta) # Source Sf = diff(f, t) - dfdt # Define new coordinate system -# +# # y = theta # z = phi - zShift # -# where -# +# where +# # zShift = int_{theta_0}^{theta} nu(theta) dtheta # # and nu(theta) is the field-line pitch @@ -44,36 +44,35 @@ y = symbols("y") z = symbols("z") -zShift = 0.1*theta#*psi +zShift = 0.1 * theta # *psi nu = diff(zShift, theta) -I = diff(zShift,psi) -H = diff(zShift,theta) -shiftangle = zShift.subs( [(theta, 2*pin)] ) - zShift.subs( [(theta, 0.0)] ) +I = diff(zShift, psi) +H = diff(zShift, theta) +shiftangle = zShift.subs([(theta, 2 * pin)]) - zShift.subs([(theta, 0.0)]) -yShift = 0.2*psi#0.05*(0.5-psi)*sin(theta) #0.2*psi # -eta = diff(yShift,psi) -G = 1 - diff(yShift,theta) +yShift = 0.2 * psi # 0.05*(0.5-psi)*sin(theta) #0.2*psi # +eta = diff(yShift, psi) +G = 1 - diff(yShift, theta) -replace = [ (phi, z + zShift), (theta, y + yShift), (psi, x) ] # z = phi - zShift -#replace = [ (phi, z + zShift), (psi, x) ] # z = phi - zShift +replace = [(phi, z + zShift), (theta, y + yShift), (psi, x)] # z = phi - zShift +# replace = [ (phi, z + zShift), (psi, x) ] # z = phi - zShift # Replace and print sources, solutions etc. print("[mesh]") -print("zShift = "+exprToStr( zShift.subs(replace) )) -print("nu = "+exprToStr( nu.subs(replace) )) -print("shiftangle = "+exprToStr(shiftangle.subs(replace))) -print("I = "+exprToStr(I.subs(replace))) -print("HH = "+exprToStr(H.subs(replace))) +print("zShift = " + exprToStr(zShift.subs(replace))) +print("nu = " + exprToStr(nu.subs(replace))) +print("shiftangle = " + exprToStr(shiftangle.subs(replace))) +print("I = " + exprToStr(I.subs(replace))) +print("HH = " + exprToStr(H.subs(replace))) print("") -print("eta = "+exprToStr(eta.subs(replace))) -print("yShift = "+exprToStr(yShift.subs(replace))) -print("G = "+exprToStr(G.subs(replace))) +print("eta = " + exprToStr(eta.subs(replace))) +print("yShift = " + exprToStr(yShift.subs(replace))) +print("G = " + exprToStr(G.subs(replace))) print("\n[f]") -print("solution = "+exprToStr( f.subs(replace) )) -print("\nsource = "+exprToStr( Sf.subs(replace) )) -print("dfdpsi = "+exprToStr( dfdpsi.subs(replace) )) -print("dfdtheta = "+exprToStr( dfdtheta.subs(replace) )) - +print("solution = " + exprToStr(f.subs(replace))) +print("\nsource = " + exprToStr(Sf.subs(replace))) +print("dfdpsi = " + exprToStr(dfdpsi.subs(replace))) +print("dfdtheta = " + exprToStr(dfdtheta.subs(replace))) diff --git a/tests/MMS/fieldalign/runtest.broken b/tests/MMS/fieldalign/runtest.broken index fc5e17ab14..bf59f95588 100755 --- a/tests/MMS/fieldalign/runtest.broken +++ b/tests/MMS/fieldalign/runtest.broken @@ -2,7 +2,7 @@ # Python script to run and analyse MMS test -#requires: all_tests +# requires: all_tests from __future__ import division from __future__ import print_function @@ -21,7 +21,7 @@ import time build_and_log("MMS test") -#nxlist = [256, 128, 64, 32, 16, 8] # do in reverse order to save disk space +# nxlist = [256, 128, 64, 32, 16, 8] # do in reverse order to save disk space nxlist = [32, 64] nout = 1 @@ -31,55 +31,90 @@ nproc = 8 mxg = 2 # Input directories -inputs = ["orthogonal", "shifted", "shear", "nonorthogonal","nonorth_shifted", "nonorth_shear", "polshear", "polshear_shifted", "polshear_shear"] -input_legend_names = ["orthogonal", "z-shifted", "z-shear", "y-shifted", "y-z shifted", "y-shifted z-shear", "y-shear", "y-shear z-shifted", "y-z shear"] +inputs = [ + "orthogonal", + "shifted", + "shear", + "nonorthogonal", + "nonorth_shifted", + "nonorth_shear", + "polshear", + "polshear_shifted", + "polshear_shear", +] +input_legend_names = [ + "orthogonal", + "z-shifted", + "z-shear", + "y-shifted", + "y-z shifted", + "y-shifted z-shear", + "y-shear", + "y-shear z-shifted", + "y-z shear", +] success = True ninputs = len(inputs) -tot_error = zeros((ninputs,len(nxlist))) +tot_error = zeros((ninputs, len(nxlist))) -i=0 +i = 0 for dir in inputs: - directory = "./"+dir + directory = "./" + dir print("Running test in '%s'" % (directory)) - error_2 = [] # The L2 error (RMS) + error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - args = "-d "+directory+" nout="+str(nout)+" timestep="+str(timestep)+" mesh:ny="+str(nx)+" mesh:nz="+str(nx)+" mesh:nx="+str(nx+2*mxg)+" mxg="+str(mxg) + args = ( + "-d " + + directory + + " nout=" + + str(nout) + + " timestep=" + + str(timestep) + + " mesh:ny=" + + str(nx) + + " mesh:nz=" + + str(nx) + + " mesh:nx=" + + str(nx + 2 * mxg) + + " mxg=" + + str(mxg) + ) print(" Running with " + args) # Delete old data - shell("rm "+directory+"/BOUT.dmp.*.nc") + shell("rm " + directory + "/BOUT.dmp.*.nc") # Command to run - cmd = "./fieldalign "+args + cmd = "./fieldalign " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E_f = collect("E_f", tind=[nout,nout], path=directory,info=False) + E_f = collect("E_f", tind=[nout, nout], path=directory, info=False) # Average error over domain, not including guard cells - l2 = sqrt(mean(E_f**2)) - linf = max(abs( E_f )) + l2 = sqrt(mean(E_f ** 2)) + linf = max(abs(E_f)) - error_2.append( l2 ) - error_inf.append( linf ) + error_2.append(l2) + error_inf.append(linf) print(" -> Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing - dx = 1. / (array(nxlist) - 2.) + dx = 1.0 / (array(nxlist) - 2.0) # Calculate convergence order @@ -94,27 +129,30 @@ for dir in inputs: try: import matplotlib.pyplot as plt + # plot errors plt.figure() - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - plt.savefig(join(dir,"norm.pdf")) + plt.savefig(join(dir, "norm.pdf")) - #plt.show() + # plt.show() plt.close() except: @@ -122,14 +160,14 @@ for dir in inputs: plt.ylabel("Error norm") plt.grid() -plt.yscale('log') -plt.xscale('log') +plt.yscale("log") +plt.xscale("log") -marker = ["-o","-p","-x","-v","-*","-^","-D","-s","-8"] +marker = ["-o", "-p", "-x", "-v", "-*", "-^", "-D", "-s", "-8"] for i in range(ninputs): - plt.plot(dx,tot_error[i,:],marker[i],label=str(input_legend_names[i])) + plt.plot(dx, tot_error[i, :], marker[i], label=str(input_legend_names[i])) plt.legend(loc="upper left") -plt.savefig(join("./","norm.pdf")) +plt.savefig(join("./", "norm.pdf")) plt.close() if success: diff --git a/tests/MMS/hw/mms.py b/tests/MMS/hw/mms.py index 12988b1519..11962de15a 100644 --- a/tests/MMS/hw/mms.py +++ b/tests/MMS/hw/mms.py @@ -1,5 +1,6 @@ from __future__ import print_function from builtins import str + # # Generate the test case using SymPy # @@ -14,40 +15,43 @@ #### + def bracket(f, g): """ Calculates [f,g] symbolically """ - + dfdx = diff(f, x) dfdz = diff(f, z) dgdx = diff(g, x) dgdz = diff(g, z) - + return dfdz * dgdx - dfdx * dgdz + def DDZ(f): return diff(f, z) + def Delp2(f): - """ Laplacian in X-Z - """ + """Laplacian in X-Z""" d2fdx2 = diff(f, x, 2) d2fdz2 = diff(f, z, 2) return d2fdx2 + d2fdz2 + def Delp4(f): d4fdx4 = diff(f, x, 4) d4fdz4 = diff(f, z, 4) return d4fdx4 + d4fdz4 + def exprToStr(expr): - """ Convert a sympy expression to a string for BOUT++ input - """ - return str(expr).replace("**", "^") # Replace exponent operator + """Convert a sympy expression to a string for BOUT++ input""" + return str(expr).replace("**", "^") # Replace exponent operator #### @@ -60,16 +64,18 @@ def exprToStr(expr): # Define symbols -x = symbols('x') -z = symbols('z') -t = symbols('t') -pi = symbols('pi') +x = symbols("x") +z = symbols("z") +t = symbols("t") +pi = symbols("pi") # Define the manufactured solution -n = 0.9 + 0.9*x + 0.2*cos(10*t)*sin(5.*x**2 - 2*z) -vort = 0.9 + 0.7*x + 0.2*cos(7*t)*sin(2.*x**2 - 3*z) -phi = sin(pi*x) *(0.5*x - cos(7*t)*sin(3.*x**2 - 3*z)) # Must satisfy Dirichlet BCs for now +n = 0.9 + 0.9 * x + 0.2 * cos(10 * t) * sin(5.0 * x ** 2 - 2 * z) +vort = 0.9 + 0.7 * x + 0.2 * cos(7 * t) * sin(2.0 * x ** 2 - 3 * z) +phi = sin(pi * x) * ( + 0.5 * x - cos(7 * t) * sin(3.0 * x ** 2 - 3 * z) +) # Must satisfy Dirichlet BCs for now # Calculate gradients in x for boundaries @@ -79,18 +85,9 @@ def exprToStr(expr): # Calculate RHS function -dndt = ( - - bracket(phi, n) - + alpha*(phi - n) - - kappa*DDZ(phi) - + Dn*Delp2(n) - ) - -dvortdt = ( - - bracket(phi, vort) - + alpha*(phi - n) - + Dvort*Delp2(vort) - ) +dndt = -bracket(phi, n) + alpha * (phi - n) - kappa * DDZ(phi) + Dn * Delp2(n) + +dvortdt = -bracket(phi, vort) + alpha * (phi - n) + Dvort * Delp2(vort) # Calculate sources diff --git a/tests/MMS/hw/runtest b/tests/MMS/hw/runtest index 14c47a0f36..03ea7d585e 100755 --- a/tests/MMS/hw/runtest +++ b/tests/MMS/hw/runtest @@ -2,9 +2,9 @@ # Python script to run and analyse MMS test -#requires: all_tests -#requires: not metric_3d -#cores: 4 +# requires: all_tests +# requires: not metric_3d +# cores: 4 from __future__ import division from __future__ import print_function @@ -28,47 +28,56 @@ timestep = 0.1 nproc = 4 -error_2 = [] # The L2 error (RMS) +error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - args = "mesh:nx="+str(nx+2)+" MZ="+str(nx)+" nout="+str(nout)+" timestep="+str(timestep) - + args = ( + "mesh:nx=" + + str(nx + 2) + + " MZ=" + + str(nx) + + " nout=" + + str(nout) + + " timestep=" + + str(timestep) + ) + print("Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./hw "+args + cmd = "./hw " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E_n = collect("E_n", tind=[nout,nout], path="data", info=False) - E_n = E_n[0,:,0,:] - - E_vort = collect("E_vort", tind=[nout,nout], path="data", info=False) - E_vort = E_vort[0,:,0,:] + E_n = collect("E_n", tind=[nout, nout], path="data", info=False) + E_n = E_n[0, :, 0, :] + + E_vort = collect("E_vort", tind=[nout, nout], path="data", info=False) + E_vort = E_vort[0, :, 0, :] # Average error over domain, not including guard cells - E = concatenate([E_n[1:-1,:], E_vort[2:-1,:]]) + E = concatenate([E_n[1:-1, :], E_vort[2:-1, :]]) - l2 = sqrt(mean(E**2)) + l2 = sqrt(mean(E ** 2)) linf = max(abs(E)) - - error_2.append( l2 ) - error_inf.append( linf ) + + error_2.append(l2) + error_inf.append(linf) print("Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing -dx = 1. / array(nxlist) +dx = 1.0 / array(nxlist) # plot errors @@ -77,26 +86,27 @@ order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) try: import matplotlib.pyplot as plt - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') - + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") print("Convergence order = %f" % (order)) - - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) - + + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) + plt.legend(loc="upper left") plt.grid() - - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Mesh spacing $\delta x$') + + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") plt.savefig("norm.pdf") - #plt.show() + # plt.show() except: pass diff --git a/tests/MMS/laplace/mms.py b/tests/MMS/laplace/mms.py index 64d3db622d..4232056c1e 100644 --- a/tests/MMS/laplace/mms.py +++ b/tests/MMS/laplace/mms.py @@ -4,25 +4,26 @@ ### + def Delp2(f): - """ Laplacian in X-Z - """ + """Laplacian in X-Z""" d2fdx2 = diff(f, x, 2) d2fdz2 = diff(f, z, 2) return d2fdx2 + d2fdz2 + ### # Define symbols -x = symbols('x') -z = symbols('z') -pi = symbols('pi') +x = symbols("x") +z = symbols("z") +pi = symbols("pi") # Define manufactured solution -solution = sin( x*pi ) +solution = sin(x * pi) # Calculate input @@ -30,6 +31,5 @@ def Delp2(f): # Print -print("solution = "+str(solution)) -print("input = "+str(input)) - +print("solution = " + str(solution)) +print("input = " + str(input)) diff --git a/tests/MMS/laplace/runtest b/tests/MMS/laplace/runtest index e580442362..00bddbc57e 100755 --- a/tests/MMS/laplace/runtest +++ b/tests/MMS/laplace/runtest @@ -2,8 +2,8 @@ # Python script to run and analyse MMS test -#requires: all_tests -#cores: 2 +# requires: all_tests +# cores: 2 from __future__ import division from __future__ import print_function @@ -25,41 +25,41 @@ timestep = 0.1 nproc = 2 -error_2 = [] # The L2 error (RMS) +error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - args = "mesh:nx="+str(nx+4)+" MZ="+str(nx) - + args = "mesh:nx=" + str(nx + 4) + " MZ=" + str(nx) + print("Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./laplace "+args + cmd = "./laplace " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E = collect("error", tind=[nout,nout], path="data") - E = E[1:-1,0,:] - - l2 = sqrt(mean(E**2)) + E = collect("error", tind=[nout, nout], path="data") + E = E[1:-1, 0, :] + + l2 = sqrt(mean(E ** 2)) linf = max(abs(E)) - - error_2.append( l2 ) - error_inf.append( linf ) + + error_2.append(l2) + error_inf.append(linf) print("Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing -dx = 1. / (array(nxlist) - 2.) +dx = 1.0 / (array(nxlist) - 2.0) # plot errors @@ -68,25 +68,27 @@ order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) try: import matplotlib.pyplot as plt - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") print("Convergence order = %f" % (order)) - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") plt.savefig("norm.pdf") - #plt.show() + # plt.show() except: pass diff --git a/tests/MMS/shiftedmetricinterp/runtest b/tests/MMS/shiftedmetricinterp/runtest index 0291563f32..4799997520 100755 --- a/tests/MMS/shiftedmetricinterp/runtest +++ b/tests/MMS/shiftedmetricinterp/runtest @@ -138,7 +138,6 @@ derivatives = [ ] - functions = [ ["sin(%s + (z-mesh:zShift))", "-sin(%s + (z-mesh:zShift))"], ["cos(%s + (z-mesh:zShift))", "-cos(%s + (z-mesh:zShift))"], diff --git a/tests/MMS/spatial/advection/mms.py b/tests/MMS/spatial/advection/mms.py index a75ab3e39b..48c9c8a8ea 100644 --- a/tests/MMS/spatial/advection/mms.py +++ b/tests/MMS/spatial/advection/mms.py @@ -5,18 +5,18 @@ from math import pi -Lx = 2*pi -Lz = 2*pi +Lx = 2 * pi +Lz = 2 * pi -ZMAX = Lz / (2*pi) +ZMAX = Lz / (2 * pi) metric = Metric() # Identity metric # Define solution in terms of input x,y,z -g = sin(6*x**2 - z) # Constant drive for advection +g = sin(6 * x ** 2 - z) # Constant drive for advection -f = cos(4*x**2 + z) +f = cos(4 * x ** 2 + z) # Turn solution into real x and z coordinates replace = [(x, metric.x / Lx), (z, metric.z / ZMAX)] diff --git a/tests/MMS/spatial/advection/runtest b/tests/MMS/spatial/advection/runtest index 921dd99269..9114664b47 100755 --- a/tests/MMS/spatial/advection/runtest +++ b/tests/MMS/spatial/advection/runtest @@ -5,8 +5,8 @@ # Tests a range of different schemes # -#requires: all_tests -#cores: 4 +# requires: all_tests +# cores: 4 from __future__ import division from __future__ import print_function @@ -22,11 +22,19 @@ from numpy import array, log, pi import argparse import pickle -parser = argparse.ArgumentParser(description="Check the error scaling of bracket operators") -parser.add_argument("-p", "--plot", action="store_true", - help="Plot graphs of the errors") -parser.add_argument("-n", "--no-show", action="store_false", dest="show", - help="Don't show the plots, just save to file") +parser = argparse.ArgumentParser( + description="Check the error scaling of bracket operators" +) +parser.add_argument( + "-p", "--plot", action="store_true", help="Plot graphs of the errors" +) +parser.add_argument( + "-n", + "--no-show", + action="store_false", + dest="show", + help="Don't show the plots, just save to file", +) cli_args = parser.parse_args() @@ -36,16 +44,66 @@ build_and_log("MMS steady-state advection test") options = [ ("method=2", "Arakawa", "-^", 2), ("method=4", "Arakawa-old", "-.", 2), - ("method=1 mesh:ddx:upwind=u1 mesh:ddz:upwind=u1", "SIMPLE: 1st order upwind", "-o", 1), - ("method=1 mesh:ddx:upwind=u2 mesh:ddz:upwind=u2", "SIMPLE: 2nd order upwind", "-^", 2), - ("method=1 mesh:ddx:upwind=u3 mesh:ddz:upwind=u3", "SIMPLE: 3rd order upwind", "-v", 3), - ("method=1 mesh:ddx:upwind=c2 mesh:ddz:upwind=c2", "SIMPLE: 2nd order central", "-x", 2), - ("method=1 mesh:ddx:upwind=c4 mesh:ddz:upwind=c4", "SIMPLE: 4th order central", "-+", 4), - ("method=0 mesh:ddx:upwind=u1 mesh:ddz:upwind=u1", "STD: 1st order upwind", "-o", 1), - ("method=0 mesh:ddx:upwind=u2 mesh:ddz:upwind=u2", "STD: 2nd order upwind", "-^", 2), - ("method=0 mesh:ddx:upwind=u3 mesh:ddz:upwind=u3", "STD: 3rd order upwind", "-v", 3), - ("method=0 mesh:ddx:upwind=c2 mesh:ddz:upwind=c2", "STD: 2nd order central", "-x", 2), - ("method=0 mesh:ddx:upwind=c4 mesh:ddz:upwind=c4", "STD: 4th order central", "-+", 4), + ( + "method=1 mesh:ddx:upwind=u1 mesh:ddz:upwind=u1", + "SIMPLE: 1st order upwind", + "-o", + 1, + ), + ( + "method=1 mesh:ddx:upwind=u2 mesh:ddz:upwind=u2", + "SIMPLE: 2nd order upwind", + "-^", + 2, + ), + ( + "method=1 mesh:ddx:upwind=u3 mesh:ddz:upwind=u3", + "SIMPLE: 3rd order upwind", + "-v", + 3, + ), + ( + "method=1 mesh:ddx:upwind=c2 mesh:ddz:upwind=c2", + "SIMPLE: 2nd order central", + "-x", + 2, + ), + ( + "method=1 mesh:ddx:upwind=c4 mesh:ddz:upwind=c4", + "SIMPLE: 4th order central", + "-+", + 4, + ), + ( + "method=0 mesh:ddx:upwind=u1 mesh:ddz:upwind=u1", + "STD: 1st order upwind", + "-o", + 1, + ), + ( + "method=0 mesh:ddx:upwind=u2 mesh:ddz:upwind=u2", + "STD: 2nd order upwind", + "-^", + 2, + ), + ( + "method=0 mesh:ddx:upwind=u3 mesh:ddz:upwind=u3", + "STD: 3rd order upwind", + "-v", + 3, + ), + ( + "method=0 mesh:ddx:upwind=c2 mesh:ddz:upwind=c2", + "STD: 2nd order central", + "-x", + 2, + ), + ( + "method=0 mesh:ddx:upwind=c4 mesh:ddz:upwind=c4", + "STD: 4th order central", + "-+", + 4, + ), # NOTE: WENO3 seems to have two different regimes, one < 3, one > # 3, so it's possible to make it pass by judicious choice of grid # sizes, which is suspicious. It does seem to work correctly in @@ -76,19 +134,23 @@ for opts, label, sym, exp_ord in options: shell("rm data/BOUT.dmp.*.nc") # Set the X and Z mesh size - dx = 2.*pi / (nx) - args = opts + " mesh:nx="+str(nx+4)+" mesh:dx="+str(dx)+" MZ="+str(nx) + dx = 2.0 * pi / (nx) + args = ( + opts + " mesh:nx=" + str(nx + 4) + " mesh:dx=" + str(dx) + " MZ=" + str(nx) + ) print(" Running with " + args) - cmd = "./advection "+args + cmd = "./advection " + args s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) - with open("run.log."+str(nx), "w") as f: + with open("run.log." + str(nx), "w") as f: f.write(out) - l2 = collect("l_2", tind=-1, xguards=False, - yguards=False, info=False, path="data") - linf = collect("l_inf", tind=-1, xguards=False, - yguards=False, info=False, path="data") + l2 = collect( + "l_2", tind=-1, xguards=False, yguards=False, info=False, path="data" + ) + linf = collect( + "l_inf", tind=-1, xguards=False, yguards=False, info=False, path="data" + ) error_2.append(l2) error_inf.append(linf) @@ -98,7 +160,7 @@ for opts, label, sym, exp_ord in options: err_2_all.append((error_2, label, sym)) err_inf_all.append((error_inf, label, sym)) - dx = 1. / array(nxlist) + dx = 1.0 / array(nxlist) order = check_scaling.get_order(dx, error_2) print("Convergence order = {:f} ({:f} at small spacing)".format(*order)) @@ -112,21 +174,23 @@ for opts, label, sym, exp_ord in options: # plot errors if cli_args.plot: import matplotlib.pyplot as plt + plt.figure() - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, - '--', label="Order %.1f" % (order)) + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") if cli_args.show: @@ -142,6 +206,7 @@ with open("advection.pkl", "wb") as output: # Plot all errors if cli_args.plot: import matplotlib.pyplot as plt + # Plot all results for comparison plt.figure() for e, label, sym in err_2_all: @@ -149,11 +214,11 @@ if cli_args.plot: plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') - plt.ylabel(r'$l_2$ error norm') + plt.xlabel(r"Mesh spacing $\delta x$") + plt.ylabel(r"$l_2$ error norm") plt.savefig("advection_norm_l2.png") if cli_args.show: plt.show() @@ -167,11 +232,11 @@ if cli_args.plot: plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') - plt.ylabel(r'$l_\infty$ error norm') + plt.xlabel(r"Mesh spacing $\delta x$") + plt.ylabel(r"$l_\infty$ error norm") plt.savefig("advection_norm_linf.png") if cli_args.show: plt.show() diff --git a/tests/MMS/spatial/d2dx2/runtest b/tests/MMS/spatial/d2dx2/runtest index ff6a821234..afd293d5d9 100755 --- a/tests/MMS/spatial/d2dx2/runtest +++ b/tests/MMS/spatial/d2dx2/runtest @@ -12,35 +12,35 @@ from numpy import sqrt, max, abs, mean, array, log try: import matplotlib.pyplot as plt except: - plt=None + plt = None -#requires: all_tests +# requires: all_tests build_and_log("Making MMS d2dx2 test") nproc = 1 -error_2 = [] # The L2 error (RMS) +error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error # List of MZ values to use nxlist = [8, 16, 32, 64, 128, 256, 512, 1024] for nx in nxlist: - args = "mesh:nx="+str(nx) + " mesh:dx="+str(1./(nx - 2)) + args = "mesh:nx=" + str(nx) + " mesh:dx=" + str(1.0 / (nx - 2)) # Delete old data shell("rm data/BOUT.dmp.*.nc") # Command to run - cmd = "./test_d2dx2 "+args + cmd = "./test_d2dx2 " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() @@ -51,28 +51,28 @@ for nx in nxlist: if plt: try: plt.figure() - plt.plot(result[1:-1,0,0], label="Result") - plt.plot(solution[1:-1,0,0], label="Solution") + plt.plot(result[1:-1, 0, 0], label="Result") + plt.plot(solution[1:-1, 0, 0], label="Solution") plt.legend() plt.xlabel("X") - plt.savefig("result."+str(nx)+".pdf") + plt.savefig("result." + str(nx) + ".pdf") plt.close() except: - plt=None - err = result[1:-1,0,0] - solution[1:-1,0,0] + plt = None + err = result[1:-1, 0, 0] - solution[1:-1, 0, 0] # Average error - l2 = sqrt(mean(err**2)) - linf = max(abs( err )) + l2 = sqrt(mean(err ** 2)) + linf = max(abs(err)) - error_2.append( l2 ) - error_inf.append( linf ) + error_2.append(l2) + error_inf.append(linf) print("Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing -dx = 1. / (array(nxlist) - 2.) +dx = 1.0 / (array(nxlist) - 2.0) order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) print("Convergence order = %f" % (order)) @@ -81,23 +81,25 @@ print("Convergence order = %f" % (order)) # plot errors if plt: try: - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") plt.savefig("norm.pdf") - #plt.show() + # plt.show() plt.close() except: pass diff --git a/tests/MMS/spatial/d2dz2/runtest b/tests/MMS/spatial/d2dz2/runtest index c7e9b33d11..081f13dc96 100755 --- a/tests/MMS/spatial/d2dz2/runtest +++ b/tests/MMS/spatial/d2dz2/runtest @@ -12,35 +12,35 @@ from numpy import sqrt, max, abs, mean, array, log try: import matplotlib.pyplot as plt except: - plt=None + plt = None -#requires: all_tests +# requires: all_tests build_and_log("Making MMS d2dz2 test") nproc = 1 -error_2 = [] # The L2 error (RMS) -error_inf = [] # The maximum error +error_2 = [] # The L2 error (RMS) +error_inf = [] # The maximum error # List of MZ values to use mzlist = [8, 16, 32, 64, 128, 256, 512, 1024] for mz in mzlist: - args = "MZ="+str(mz) + args = "MZ=" + str(mz) # Delete old data shell("rm data/BOUT.dmp.*.nc") # Command to run - cmd = "./test_d2dz2 "+args + cmd = "./test_d2dz2 " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(mz), "w") + f = open("run.log." + str(mz), "w") f.write(out) f.close() @@ -51,17 +51,17 @@ for mz in mzlist: err = result - solution # Average error - l2 = sqrt(mean(err**2)) - linf = max(abs( err )) + l2 = sqrt(mean(err ** 2)) + linf = max(abs(err)) - error_2.append( l2 ) - error_inf.append( linf ) + error_2.append(l2) + error_inf.append(linf) print("Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing -dx = 1. / (array(mzlist) - 2.) +dx = 1.0 / (array(mzlist) - 2.0) order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) print("Convergence order = %f" % (order)) @@ -69,24 +69,25 @@ print("Convergence order = %f" % (order)) # plot errors try: - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") - - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta z$') + plt.xlabel(r"Mesh spacing $\delta z$") plt.ylabel("Error norm") plt.savefig("norm.pdf") - #plt.show() + # plt.show() plt.close() except: pass diff --git a/tests/MMS/spatial/diffusion/mms.py b/tests/MMS/spatial/diffusion/mms.py index 55ceef339b..6a54b2948e 100644 --- a/tests/MMS/spatial/diffusion/mms.py +++ b/tests/MMS/spatial/diffusion/mms.py @@ -1,5 +1,6 @@ from __future__ import print_function from builtins import str + # # Generate the test case using SymPy # @@ -12,69 +13,76 @@ #### + def bracket(f, g): """ Calculates [f,g] symbolically """ - + dfdx = diff(f, x) dfdz = diff(f, z) dgdx = diff(g, x) dgdz = diff(g, z) - + return dfdz * dgdx - dfdx * dgdz + def DDZ(f): return diff(f, z) + def Delp2(f): - """ Laplacian in X-Z - """ + """Laplacian in X-Z""" d2fdx2 = diff(f, x, 2) d2fdz2 = diff(f, z, 2) return d2fdx2 + d2fdz2 + def Delp4(f): d4fdx4 = diff(f, x, 4) d4fdz4 = diff(f, z, 4) return d4fdx4 + d4fdz4 + def D2DX2(f): return diff(f, x, 2) + def D2DY2(f): return diff(f, y, 2) + def D2DZ2(f): return diff(f, z, 2) + def exprToStr(expr): - """ Convert a sympy expression to a string for BOUT++ input - """ - return str(expr).replace("**", "^") # Replace exponent operator + """Convert a sympy expression to a string for BOUT++ input""" + return str(expr).replace("**", "^") # Replace exponent operator + #### # Parameters -Dx = 1. +Dx = 1.0 Dy = 0 Dz = 0 # Define symbols -x = symbols('x') -y = symbols('y') -z = symbols('z') -t = symbols('t') -pi = symbols('pi') +x = symbols("x") +y = symbols("y") +z = symbols("z") +t = symbols("t") +pi = symbols("pi") # Define the manufactured solution -#n = 0.9 + 0.9*x + 0.2*sin(5.*x**2 - 2*z) + cos(y) -n = 0.9 + 0.9*x + 0.2*sin(5.*x**2) +# n = 0.9 + 0.9*x + 0.2*sin(5.*x**2 - 2*z) + cos(y) +n = 0.9 + 0.9 * x + 0.2 * sin(5.0 * x ** 2) # Calculate gradients for boundaries @@ -84,11 +92,7 @@ def exprToStr(expr): # Calculate RHS function -dndt = ( - Dx * D2DX2(n) - + Dy * D2DY2(n) - + Dz * D2DZ2(n) - ) +dndt = Dx * D2DX2(n) + Dy * D2DY2(n) + Dz * D2DZ2(n) # Calculate sources diff --git a/tests/MMS/spatial/diffusion/runtest b/tests/MMS/spatial/diffusion/runtest index aa366b34fe..5f4c31f6aa 100755 --- a/tests/MMS/spatial/diffusion/runtest +++ b/tests/MMS/spatial/diffusion/runtest @@ -6,8 +6,8 @@ # Checks that the convergence is 2nd order # Exits with status 1 if any test failed -#requires: all_tests -#cores: 2 +# requires: all_tests +# cores: 2 from __future__ import division from __future__ import print_function @@ -27,10 +27,10 @@ build_and_log("MMS diffusion test") # List of input directories inputs = [ - ("X", ["mesh:nx"])#, - #("Y",["mesh:ny"]), - #("XYZ", ["mesh:nx", "mesh:ny", "MZ"]) - ] + ("X", ["mesh:nx"]) # , + # ("Y",["mesh:ny"]), + # ("XYZ", ["mesh:nx", "mesh:ny", "MZ"]) +] # List of NX values to use nxlist = [8, 16, 32, 64, 128, 256, 512, 1024] @@ -41,50 +41,50 @@ nproc = 2 success = True -for dir,sizes in inputs: +for dir, sizes in inputs: print("Running test in '%s'" % (dir)) - error_2 = [] # The L2 error (RMS) + error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - #args = "-d "+dir+" nout="+str(nout)+" timestep="+str(timestep)+" solver:type=rk4 solver:timestep="+str(0.01*timestep/nx) - args = "-d "+dir+" nout="+str(nout) + # args = "-d "+dir+" nout="+str(nout)+" timestep="+str(timestep)+" solver:type=rk4 solver:timestep="+str(0.01*timestep/nx) + args = "-d " + dir + " nout=" + str(nout) for s in sizes: - args += " "+s+"="+str(nx) + args += " " + s + "=" + str(nx) print(" Running with " + args) # Delete old data - shell("rm "+dir+"/BOUT.dmp.*.nc") + shell("rm " + dir + "/BOUT.dmp.*.nc") # Command to run - cmd = "./diffusion "+args + cmd = "./diffusion " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E_N = collect("E_N", tind=[nout,nout], path=dir,info=False) + E_N = collect("E_N", tind=[nout, nout], path=dir, info=False) # Remove guard cells - E_N = E_N[:,1:-1,:,:] + E_N = E_N[:, 1:-1, :, :] # Average error over domain - l2 = sqrt(mean(E_N**2)) - linf = max(abs( E_N )) + l2 = sqrt(mean(E_N ** 2)) + linf = max(abs(E_N)) - error_2.append( l2 ) - error_inf.append( linf ) + error_2.append(l2) + error_inf.append(linf) print(" -> Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing - dx = 1. / (array(nxlist) - 2.) + dx = 1.0 / (array(nxlist) - 2.0) # Calculate convergence order @@ -92,7 +92,7 @@ for dir,sizes in inputs: print("Convergence order = %f" % (order)) if 1.8 < order < 2.2: - #success + # success pass else: success = False @@ -103,30 +103,32 @@ for dir,sizes in inputs: try: plt.figure() - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - plt.savefig(join(dir,"norm.pdf")) + plt.savefig(join(dir, "norm.pdf")) - #plt.show() + # plt.show() plt.close() except: pass if success: - print(" => All tests passed") - exit(0) + print(" => All tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/MMS/spatial/fci/mms.py b/tests/MMS/spatial/fci/mms.py index 477c605e84..ba13724d7e 100755 --- a/tests/MMS/spatial/fci/mms.py +++ b/tests/MMS/spatial/fci/mms.py @@ -12,21 +12,23 @@ from math import pi -f = sin(y - z) + sin(y - 2*z) +f = sin(y - z) + sin(y - 2 * z) Lx = 0.1 -Ly = 10. -Lz = 1. +Ly = 10.0 +Lz = 1.0 Bt = 1.0 Bp = 0.05 Bpprime = 0.1 -Bpx = Bp + (x-0.5)*Lx * Bpprime # Note: x in range [0,1] -B = sqrt(Bpx**2 + Bt**2) +Bpx = Bp + (x - 0.5) * Lx * Bpprime # Note: x in range [0,1] +B = sqrt(Bpx ** 2 + Bt ** 2) + def FCI_ddy(f): - return ( Bt * diff(f, y)*2.*pi/Ly + Bpx * diff(f, z)*2.*pi/Lz ) / B + return (Bt * diff(f, y) * 2.0 * pi / Ly + Bpx * diff(f, z) * 2.0 * pi / Lz) / B + ############################################ # Equations solved diff --git a/tests/MMS/spatial/fci/runtest b/tests/MMS/spatial/fci/runtest index a0724ff791..1613155ed2 100755 --- a/tests/MMS/spatial/fci/runtest +++ b/tests/MMS/spatial/fci/runtest @@ -33,7 +33,6 @@ nproc = 2 mthread = 2 - success = True error_2 = {} @@ -53,45 +52,45 @@ for nslice in nslices: # Which central difference scheme to use and its expected order order = nslice * 2 - method_orders[nslice] = { - "name": "C{}".format(order), - "order": order - } + method_orders[nslice] = {"name": "C{}".format(order), "order": order} for n in nlist: # Define the magnetic field using new poloidal gridding method # Note that the Bz and Bzprime parameters here must be the same as in mms.py field = zb.field.Slab(Bz=0.05, Bzprime=0.1) # Create rectangular poloidal grids - poloidal_grid = zb.poloidal_grid.RectangularPoloidalGrid(nx, n, 0.1, 1.) + poloidal_grid = zb.poloidal_grid.RectangularPoloidalGrid(nx, n, 0.1, 1.0) # Set the ylength and y locations - ylength = 10. + ylength = 10.0 if yperiodic: ycoords = linspace(0.0, ylength, n, endpoint=False) else: # Doesn't include the end points - ycoords = (arange(n) + 0.5)*ylength/float(n) + ycoords = (arange(n) + 0.5) * ylength / float(n) # Create the grid grid = zb.grid.Grid(poloidal_grid, ycoords, ylength, yperiodic=yperiodic) # Make and write maps maps = zb.make_maps(grid, field, nslice=nslice, quiet=True) - zb.write_maps(grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True) + zb.write_maps( + grid, field, maps, new_names=False, metric2d=conf.isMetric2D(), quiet=True + ) - args = (" MZ={} MYG={} mesh:paralleltransform:y_periodic={} mesh:ddy:first={}" - .format(n, nslice, yperiodic, method_orders[nslice]["name"])) + args = " MZ={} MYG={} mesh:paralleltransform:y_periodic={} mesh:ddy:first={}".format( + n, nslice, yperiodic, method_orders[nslice]["name"] + ) # Command to run - cmd = "./fci_mms "+args + cmd = "./fci_mms " + args - print("Running command: "+cmd) + print("Running command: " + cmd) # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) # Save output to log file - with open("run.log."+str(n), "w") as f: + with open("run.log." + str(n), "w") as f: f.write(out) if s: @@ -100,24 +99,31 @@ for nslice in nslices: exit(s) # Collect data - l_2 = collect("l_2", tind=[1, 1], info=False, - path=directory, xguards=False, yguards=False) - l_inf = collect("l_inf", tind=[1, 1], info=False, - path=directory, xguards=False, yguards=False) + l_2 = collect( + "l_2", tind=[1, 1], info=False, path=directory, xguards=False, yguards=False + ) + l_inf = collect( + "l_inf", + tind=[1, 1], + info=False, + path=directory, + xguards=False, + yguards=False, + ) error_2[nslice].append(l_2) error_inf[nslice].append(l_inf) print("Errors : l-2 {:f} l-inf {:f}".format(l_2, l_inf)) - dx = 1. / array(nlist) + dx = 1.0 / array(nlist) # Calculate convergence order fit = polyfit(log(dx), log(error_2[nslice]), 1) order = fit[0] stdout.write("Convergence order = {:f} (fit)".format(order)) - order = log(error_2[nslice][-2]/error_2[nslice][-1])/log(dx[-2]/dx[-1]) + order = log(error_2[nslice][-2] / error_2[nslice][-1]) / log(dx[-2] / dx[-1]) stdout.write(", {:f} (small spacing)".format(order)) # Should be close to the expected order @@ -146,16 +152,24 @@ if False: fig, ax = plt.subplots(1, 1) for nslice in nslices: - ax.plot(dx, error_2[nslice], '-', - label="{} $l_2$".format(method_orders[nslice]["name"])) - ax.plot(dx, error_inf[nslice], '--', - label="{} $l_\inf$".format(method_orders[nslice]["name"])) + ax.plot( + dx, + error_2[nslice], + "-", + label="{} $l_2$".format(method_orders[nslice]["name"]), + ) + ax.plot( + dx, + error_inf[nslice], + "--", + label="{} $l_\inf$".format(method_orders[nslice]["name"]), + ) ax.legend(loc="upper left") ax.grid() - ax.set_yscale('log') - ax.set_xscale('log') - ax.set_title('error scaling') - ax.set_xlabel(r'Mesh spacing $\delta x$') + ax.set_yscale("log") + ax.set_xscale("log") + ax.set_title("error scaling") + ax.set_xlabel(r"Mesh spacing $\delta x$") ax.set_ylabel("Error norm") plt.savefig("fci_mms.pdf") diff --git a/tests/MMS/time/runtest b/tests/MMS/time/runtest index c9e3eff717..003f401e00 100755 --- a/tests/MMS/time/runtest +++ b/tests/MMS/time/runtest @@ -12,9 +12,9 @@ from builtins import str from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect -#requires: all_tests +# requires: all_tests -verbose=False +verbose = False from numpy import sqrt, max, abs, mean, array, log, pi @@ -25,7 +25,7 @@ import sys try: import matplotlib.pyplot as plt except: - plt=None + plt = None build_and_log("MMS time integration test") @@ -33,17 +33,17 @@ build_and_log("MMS time integration test") # List of options to be passed for each test if "only_petsc" in sys.argv: # this requires petsc: - options = [("solver:type=imexbdf2 -snes_mf", "IMEX-BDF2", "-+",2)] + options = [("solver:type=imexbdf2 -snes_mf", "IMEX-BDF2", "-+", 2)] else: options = [ - ("solver:type=euler", "Euler", "-^",1) - ,("solver:type=rk3ssp", "RK3-SSP", "-s",3) - ,("solver:type=rk4", "RK4", "-o",4) - ,("solver:type=rkgeneric", "RK-generic", "-o",4) - ,("solver:type=splitrk", "SplitRK", "-x", 2) + ("solver:type=euler", "Euler", "-^", 1), + ("solver:type=rk3ssp", "RK3-SSP", "-s", 3), + ("solver:type=rk4", "RK4", "-o", 4), + ("solver:type=rkgeneric", "RK-generic", "-o", 4), + ("solver:type=splitrk", "SplitRK", "-x", 2), ] -#Missing: cvode, ida, slepc, power, arkode, snes +# Missing: cvode, ida, slepc, power, arkode, snes # Is there a better way to check a certain solver should be enabled? # List of NX values to use @@ -55,55 +55,54 @@ success = True err_2_all = [] err_inf_all = [] -for opts,label,sym,expected_order in options: - error_2 = [] # The L2 error (RMS) +for opts, label, sym, expected_order in options: + error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nt in timesteps: - args = " solver:timestep="+str(1./nt) + " " + opts + args = " solver:timestep=" + str(1.0 / nt) + " " + opts if verbose: print(" Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./time "+args + cmd = "./time " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) - + # Save output to log file - f = open("run.log."+label+"."+str(nt), "w") + f = open("run.log." + label + "." + str(nt), "w") f.write(out) f.close() - + # Collect data - E_f = collect("E_f", tind=[1,1], info=False, path="data") + E_f = collect("E_f", tind=[1, 1], info=False, path="data") # Average error over domain - l2 = sqrt(mean(E_f**2)) - linf = max(abs( E_f )) - - error_2.append( l2 ) - error_inf.append( linf ) + l2 = sqrt(mean(E_f ** 2)) + linf = max(abs(E_f)) + + error_2.append(l2) + error_inf.append(linf) if verbose: print(" -> Error norm: l-2 %f l-inf %f" % (l2, linf)) - - + # Append to list of all results - err_2_all.append( (error_2, label, sym) ) - err_inf_all.append( (error_inf, label, sym) ) + err_2_all.append((error_2, label, sym)) + err_inf_all.append((error_inf, label, sym)) # Calculate grid spacing - dt = 1. / array(timesteps) + dt = 1.0 / array(timesteps) # Calculate convergence order - + order = log(error_2[-1] / error_2[-2]) / log(dt[-1] / dt[-2]) - print("Convergence order = %f (expected: %f) %s" % (order,expected_order,label)) - - if expected_order - 0.2 < order < expected_order + 0.2: + print("Convergence order = %f (expected: %f) %s" % (order, expected_order, label)) + + if expected_order - 0.2 < order < expected_order + 0.2: pass else: success = False @@ -112,22 +111,24 @@ for opts,label,sym,expected_order in options: # plot errors if False: plt.figure() - - plt.plot(dt, error_2, '-o', label=r'$l^2$') - plt.plot(dt, error_inf, '-x', label=r'$l^\infty$') - - plt.plot(dt, error_2[-1]*(dt/dt[-1])**order, '--', label="Order %.1f"%(order)) - + + plt.plot(dt, error_2, "-o", label=r"$l^2$") + plt.plot(dt, error_inf, "-x", label=r"$l^\infty$") + + plt.plot( + dt, error_2[-1] * (dt / dt[-1]) ** order, "--", label="Order %.1f" % (order) + ) + plt.legend(loc="lower right") plt.grid() - - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Time step $\delta t$') + + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Time step $\delta t$") plt.ylabel("Error norm") - - #plt.savefig("norm.pdf") + + # plt.savefig("norm.pdf") plt.show() plt.close() @@ -140,11 +141,11 @@ try: plt.legend(loc="lower right") plt.grid() - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Time step $\delta t$') - plt.ylabel(r'$l^2$ error norm') + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Time step $\delta t$") + plt.ylabel(r"$l^2$ error norm") plt.savefig("time_norm.pdf") plt.close() except: diff --git a/tests/MMS/tokamak/mms.py b/tests/MMS/tokamak/mms.py index 4e388b711f..6c31538947 100644 --- a/tests/MMS/tokamak/mms.py +++ b/tests/MMS/tokamak/mms.py @@ -16,19 +16,19 @@ # NOTE: These are orthogonal tokamak coordinates # so y is poloidal angle, not parallel coordinate -drive = sin(6*x**2 - z + y) # Constant drive for advection +drive = sin(6 * x ** 2 - z + y) # Constant drive for advection -advect = cos(4*x**2 + z - y) + sin(t)*sin(3*x + 2*z - y) -delp2 = cos(4*x**2 + z - y) + sin(t)*sin(3*x + 2*z - y) -laplacepar = cos(4*x**2 + z - y) + sin(t)*sin(3*x + 2*z - y) +advect = cos(4 * x ** 2 + z - y) + sin(t) * sin(3 * x + 2 * z - y) +delp2 = cos(4 * x ** 2 + z - y) + sin(t) * sin(3 * x + 2 * z - y) +laplacepar = cos(4 * x ** 2 + z - y) + sin(t) * sin(3 * x + 2 * z - y) ZMAX = 1 # Turn solution into real x and z coordinates # NOTE: Z is shifted, so y is now the parallel coordinate -zShift = shape.zShift.subs(x, old_div(metric.x,metric.Lx)) -sinty = shape.sinty.subs(x, old_div(metric.x,metric.Lx)) -replace = [ (x, old_div(metric.x,metric.Lx)), (z, old_div(metric.z, ZMAX) + zShift) ] +zShift = shape.zShift.subs(x, old_div(metric.x, metric.Lx)) +sinty = shape.sinty.subs(x, old_div(metric.x, metric.Lx)) +replace = [(x, old_div(metric.x, metric.Lx)), (z, old_div(metric.z, ZMAX) + zShift)] drive = drive.subs(replace) advect = advect.subs(replace) @@ -37,26 +37,29 @@ # Calculate time derivatives -dadt = -1e-3*bracket(drive, advect, metric) +dadt = -1e-3 * bracket(drive, advect, metric) -dddt = 1e-5*Delp2(delp2, metric) +dddt = 1e-5 * Delp2(delp2, metric) dgdt = Laplace_par(laplacepar, metric) vars = [ (advect, dadt, "advect"), (delp2, dddt, "delp2"), - (laplacepar, dgdt, "laplacepar") - ] + (laplacepar, dgdt, "laplacepar"), +] # Change back to normalised coordinates # NOTE: Z remains shifted, so y is still parallel coordinate # Need to scale the toroidal angle part of z, not zShift part -replace = [ (metric.x, x * metric.Lx), (metric.z, (z - shape.zShift) * ZMAX + shape.zShift) ] +replace = [ + (metric.x, x * metric.Lx), + (metric.z, (z - shape.zShift) * ZMAX + shape.zShift), +] drive = drive.subs(replace) print("[drive]") -print("solution = "+exprToStr(drive)) +print("solution = " + exprToStr(drive)) # Loop over variables and print solution, source etc. for f, dfdt, name in vars: @@ -68,18 +71,17 @@ dfdy = diff(f, metric.y) # Substitute back to get in terms of x,y,z - - f = f.subs(replace) + + f = f.subs(replace) dfdt = dfdt.subs(replace) - S = S.subs(replace) + S = S.subs(replace) dfdx = dfdx.subs(replace) dfdy = dfdy.subs(replace) - - print("\n["+name+"]") - print("solution = "+exprToStr(f)) - print("\nddx = "+exprToStr(dfdx)) - print("\nddy = "+exprToStr(dfdy)) - print("\nsource = "+exprToStr(S)) - #print("\nSource magnitude: %e" % exprMag(S)) + print("\n[" + name + "]") + print("solution = " + exprToStr(f)) + print("\nddx = " + exprToStr(dfdx)) + print("\nddy = " + exprToStr(dfdy)) + print("\nsource = " + exprToStr(S)) + # print("\nSource magnitude: %e" % exprMag(S)) diff --git a/tests/MMS/tokamak/runtest.broken b/tests/MMS/tokamak/runtest.broken index 3f8051d431..e833126016 100755 --- a/tests/MMS/tokamak/runtest.broken +++ b/tests/MMS/tokamak/runtest.broken @@ -5,7 +5,7 @@ # Tests a range of different schemes # -#requires: all_tests +# requires: all_tests from __future__ import division from __future__ import print_function @@ -27,78 +27,79 @@ from sys import stdout ## Get the tokamak shape ## Note: This must be the same as in the mms.py code from boutdata.mms import SimpleTokamak + shape = SimpleTokamak() build_and_log("MMS tokamak geometry test") # List of NX values to use -nxlist = [4, 8, 16, 32]#, 64]#, 128]#, 256] -nprocs = [2, 4, 4, 8, 8, 8, 8] +nxlist = [4, 8, 16, 32] # , 64]#, 128]#, 256] +nprocs = [2, 4, 4, 8, 8, 8, 8] success = True varlist = ["advect", "delp2", "laplacepar"] -markers = ['bo', 'r^', "gs"] -labels = [r'$\left[\phi, f\right]$', r'$\nabla_\perp^2$', r'$\nabla_{||}^2$'] +markers = ["bo", "r^", "gs"] +labels = [r"$\left[\phi, f\right]$", r"$\nabla_\perp^2$", r"$\nabla_{||}^2$"] error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # The L2 error (RMS) + error_2[var] = [] # The L2 error (RMS) error_inf[var] = [] # The maximum error -dx=[] +dx = [] -for nx,nproc in zip(nxlist, nprocs): +for nx, nproc in zip(nxlist, nprocs): # Generate a new mesh file - + filename = "grid%d.nc" % nx - + if isfile(filename): print("Grid file '%s' already exists" % filename) else: print("Creating grid file '%s'" % filename) f = DataFile(filename, create=True) - shape.write(nx,nx, f) + shape.write(nx, nx, f) f.close() - - args = " MZ="+str(nx)+" grid="+filename #+" solver:timestep="+str(0.001/nx) - + + args = " MZ=" + str(nx) + " grid=" + filename # +" solver:timestep="+str(0.001/nx) + print(" Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./tokamak "+args + cmd = "./tokamak " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) - + # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() - dx.append(1./nx) + dx.append(1.0 / nx) for var in varlist: # Collect data - E = collect("E_"+var, tind=[1,1], info=False, path="data") - E = E[:,2:-2, :,:] - + E = collect("E_" + var, tind=[1, 1], info=False, path="data") + E = E[:, 2:-2, :, :] + # Average error over domain - l2 = sqrt(mean(E**2)) - linf = max(abs( E )) - - error_2[var].append( l2 ) - error_inf[var].append( linf ) + l2 = sqrt(mean(E ** 2)) + linf = max(abs(E)) + + error_2[var].append(l2) + error_inf[var].append(linf) print("%s : l-2 %f l-inf %f" % (var, l2, linf)) if len(dx) > 1: # Calculate convergence order - for var,mark,label in zip(varlist, markers, labels): + for var, mark, label in zip(varlist, markers, labels): order = log(error_2[var][-1] / error_2[var][-2]) / log(dx[-1] / dx[-2]) stdout.write("%s Convergence order = %f" % (var, order)) - - if 1.8 < order < 2.2: # Should be second order accurate + + if 1.8 < order < 2.2: # Should be second order accurate print("............ PASS") else: success = False @@ -112,31 +113,29 @@ with open("tokamak.pkl", "wb") as output: pickle.dump(error_inf, output) - # plot errors try: import matplotlib.pyplot as plt - + plt.figure() # Calculate convergence order - for var,mark,label in zip(varlist, markers, labels): - plt.plot(dx, error_2[var], '-'+mark, label=label) - plt.plot(dx, error_inf[var], '--'+mark) - + for var, mark, label in zip(varlist, markers, labels): + plt.plot(dx, error_2[var], "-" + mark, label=label) + plt.plot(dx, error_inf[var], "--" + mark) plt.legend(loc="upper left") plt.grid() - - plt.yscale('log') - plt.xscale('log') - - plt.xlabel(r'Mesh spacing $\delta x$') + + plt.yscale("log") + plt.xscale("log") + + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") - + plt.savefig("norm.pdf") - #plt.show() + # plt.show() plt.close() except: pass diff --git a/tests/MMS/upwinding3/runtest b/tests/MMS/upwinding3/runtest index 5dc7bcbf60..8f6c4927cf 100755 --- a/tests/MMS/upwinding3/runtest +++ b/tests/MMS/upwinding3/runtest @@ -2,108 +2,147 @@ import boutcore -#requires boutcore -#requires not make +# requires boutcore +# requires not make import numpy as np import itertools from sys import exit -errorlist=[] -passlist=[] +errorlist = [] +passlist = [] boutcore.init("-d data -q -q -q".split(" ")) -def runtests(functions,derivatives,directions,stag,msg): + +def runtests(functions, derivatives, directions, stag, msg): global errorlist - global passlist + global passlist for direction in directions: - direction, fac,guards, diff_func = direction - locations=['centre'] - if stag: - locations.append(direction.lower()+"low") - for funcs, derivative , floc, vloc in itertools.product(functions, - derivatives, locations,locations): - vfunc, ffunc, outfunc = funcs - order, diff = derivative - - errors=[] - for nz in nzs: - boutcore.setOption("meshD:nD".replace("D",direction) - ,"%d"% (nz+ (2*guards if direction == "x" else 0)),force=True) - boutcore.setOption("meshD:dD".replace("D",direction,) - ,"2*pi/(%d)"%(nz),force=True) - dirnfac=direction+"*"+fac - mesh=boutcore.Mesh(section="mesh"+direction) - f=boutcore.create3D(ffunc.replace("%s",dirnfac),mesh - ,outloc=floc) - v=boutcore.create3D(vfunc.replace("%s",dirnfac),mesh - ,outloc=vloc) - sim=diff_func(v,f,method=diff,outloc=floc) - if sim.getLocation() != floc: - if floc == 'centre' and sim.getLocation() == 'centre': - pass - else: - errorlist.append("Location does not match - expected %s but got %s"%(floc,sim.getLocation())) - ana=boutcore.create3D(outfunc.replace("%s",dirnfac),mesh, outloc=floc) - err=sim-ana - err=err.getAll().flatten() - if guards: - err=err[guards:-guards] - err=np.max(np.abs(err)) - errors.append(err) - errc=np.log(errors[-2]/errors[-1]) - difc=np.log(nzs[-1]/nzs[-2]) - conv=errc/difc - if order-.1 < conv < order+.1: - info="%s - %s - %s - %s - %s -> %s "%(vfunc,ffunc,diff,direction,floc,vloc) - passMsg="%s: %s is working. Expected %f got %f"%(msg,info,order,conv) - passlist.append(passMsg) - else: - info="%s - %s - %s - %s - %s -> %s "%(vfunc,ffunc,diff,direction,floc,vloc) - error="%s: %s is not working. Expected %f got %f"%(msg,info,order,conv) - errorlist.append(error) - if doPlot: - from matplotlib import pyplot as plt - plt.plot((ana).getAll().flatten()) - plt.plot((sim).getAll().flatten()) - plt.show() - - -mmax=7 -start=6 -doPlot=False -nzs=np.logspace(start,mmax,num=mmax-start+1,base=2) - -functions=[ - ["sin(%s)","sin(%s)","sin(%s)*cos(%s)"] , - ["sin(%s)", "cos(%s)", "-sin(%s)*sin(%s)"] + direction, fac, guards, diff_func = direction + locations = ["centre"] + if stag: + locations.append(direction.lower() + "low") + for funcs, derivative, floc, vloc in itertools.product( + functions, derivatives, locations, locations + ): + vfunc, ffunc, outfunc = funcs + order, diff = derivative + + errors = [] + for nz in nzs: + boutcore.setOption( + "meshD:nD".replace("D", direction), + "%d" % (nz + (2 * guards if direction == "x" else 0)), + force=True, + ) + boutcore.setOption( + "meshD:dD".replace( + "D", + direction, + ), + "2*pi/(%d)" % (nz), + force=True, + ) + dirnfac = direction + "*" + fac + mesh = boutcore.Mesh(section="mesh" + direction) + f = boutcore.create3D(ffunc.replace("%s", dirnfac), mesh, outloc=floc) + v = boutcore.create3D(vfunc.replace("%s", dirnfac), mesh, outloc=vloc) + sim = diff_func(v, f, method=diff, outloc=floc) + if sim.getLocation() != floc: + if floc == "centre" and sim.getLocation() == "centre": + pass + else: + errorlist.append( + "Location does not match - expected %s but got %s" + % (floc, sim.getLocation()) + ) + ana = boutcore.create3D( + outfunc.replace("%s", dirnfac), mesh, outloc=floc + ) + err = sim - ana + err = err.getAll().flatten() + if guards: + err = err[guards:-guards] + err = np.max(np.abs(err)) + errors.append(err) + errc = np.log(errors[-2] / errors[-1]) + difc = np.log(nzs[-1] / nzs[-2]) + conv = errc / difc + if order - 0.1 < conv < order + 0.1: + info = "%s - %s - %s - %s - %s -> %s " % ( + vfunc, + ffunc, + diff, + direction, + floc, + vloc, + ) + passMsg = "%s: %s is working. Expected %f got %f" % ( + msg, + info, + order, + conv, + ) + passlist.append(passMsg) + else: + info = "%s - %s - %s - %s - %s -> %s " % ( + vfunc, + ffunc, + diff, + direction, + floc, + vloc, + ) + error = "%s: %s is not working. Expected %f got %f" % ( + msg, + info, + order, + conv, + ) + errorlist.append(error) + if doPlot: + from matplotlib import pyplot as plt + + plt.plot((ana).getAll().flatten()) + plt.plot((sim).getAll().flatten()) + plt.show() + + +mmax = 7 +start = 6 +doPlot = False +nzs = np.logspace(start, mmax, num=mmax - start + 1, base=2) + +functions = [ + ["sin(%s)", "sin(%s)", "sin(%s)*cos(%s)"], + ["sin(%s)", "cos(%s)", "-sin(%s)*sin(%s)"], ] -derivatives=[ - [2,"C2"] , - [4,"C4"] , - [1,"U1"] , - [2,"U2"] , - #[3,"W3"] , +derivatives = [ + [2, "C2"], + [4, "C4"], + [1, "U1"], + [2, "U2"], + # [3,"W3"] , ] -directions=[ - ["x","2*pi",2 ,boutcore.VDDX], - ["y","1" ,2 ,boutcore.VDDY], - ["z","1" ,0 ,boutcore.VDDZ] +directions = [ + ["x", "2*pi", 2, boutcore.VDDX], + ["y", "1", 2, boutcore.VDDY], + ["z", "1", 0, boutcore.VDDZ], ] -runtests(functions,derivatives,directions,stag=False,msg="DD") +runtests(functions, derivatives, directions, stag=False, msg="DD") -derivatives=[ - [2,"C2"] , - [4,"C4"] , - [1,"U1"] , - [2,"U2"] , - #[3,"W3"] , +derivatives = [ + [2, "C2"], + [4, "C4"], + [1, "U1"], + [2, "U2"], + # [3,"W3"] , ] -runtests(functions,derivatives,directions,stag=True,msg="DD") +runtests(functions, derivatives, directions, stag=True, msg="DD") boutcore.finalise() diff --git a/tests/MMS/wave-1d-y/mms.py b/tests/MMS/wave-1d-y/mms.py index 75852cd855..e5306d954b 100644 --- a/tests/MMS/wave-1d-y/mms.py +++ b/tests/MMS/wave-1d-y/mms.py @@ -1,4 +1,5 @@ from __future__ import print_function + # # Generate the test case using SymPy # @@ -15,8 +16,8 @@ # Define the manufactured solution -f = y + cos(y) - sin(t)*cos(0.5*y) -g = y**2 + sin(y) + cos(t)*cos(0.1*y*y) +f = y + cos(y) - sin(t) * cos(0.5 * y) +g = y ** 2 + sin(y) + cos(t) * cos(0.1 * y * y) # Calculate gradients in x for boundaries diff --git a/tests/MMS/wave-1d-y/runtest b/tests/MMS/wave-1d-y/runtest index b8894070ee..e398b940cf 100755 --- a/tests/MMS/wave-1d-y/runtest +++ b/tests/MMS/wave-1d-y/runtest @@ -4,11 +4,12 @@ from __future__ import division from __future__ import print_function + try: - from builtins import zip - from builtins import str + from builtins import zip + from builtins import str except: - pass + pass from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -31,45 +32,54 @@ timestep = 1 nproc = 1 varlist = ["f", "g"] -markers = ['bo', 'r^'] +markers = ["bo", "r^"] labels = ["f", "g"] error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # The L2 error (RMS) + error_2[var] = [] # The L2 error (RMS) error_inf[var] = [] # The maximum error for ny in nylist: - dy = 2.*pi / ny - args = "mesh:ny="+str(ny)+" mesh:dy="+str(dy)+" nout="+str(nout)+" timestep="+str(timestep) - + dy = 2.0 * pi / ny + args = ( + "mesh:ny=" + + str(ny) + + " mesh:dy=" + + str(dy) + + " nout=" + + str(nout) + + " timestep=" + + str(timestep) + ) + print("Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./wave "+args + cmd = "./wave " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - with open("run.log."+str(ny), "w") as f: + with open("run.log." + str(ny), "w") as f: f.write(out) for var in varlist: # Collect data - E = collect("E_"+var, tind=[nout,nout], info=False, path="data") - E = E[0,0,:,0] - + E = collect("E_" + var, tind=[nout, nout], info=False, path="data") + E = E[0, 0, :, 0] + # Average error over domain - l2 = sqrt(mean(E**2)) + l2 = sqrt(mean(E ** 2)) linf = max(abs(E)) - - error_2[var].append( l2 ) - error_inf[var].append( linf ) + + error_2[var].append(l2) + error_inf[var].append(linf) print("Error norm %s: l-2 %f l-inf %f" % (var, l2, linf)) @@ -80,49 +90,50 @@ with open("wave.pkl", "wb") as output: pickle.dump(error_inf, output) # Calculate grid spacing -dy = 1. / array(nylist) +dy = 1.0 / array(nylist) # Calculate convergence order success = True for var in varlist: - order = log(error_2[var][-1] / error_2[var][-2]) / log(dy[-1] / dy[-2]) - stdout.write("%s Convergence order = %f" % (var, order)) + order = log(error_2[var][-1] / error_2[var][-2]) / log(dy[-1] / dy[-2]) + stdout.write("%s Convergence order = %f" % (var, order)) - if 1.8 < order < 2.2: # Should be second order accurate - print("............ PASS") - else: - success = False - print("............ FAIL") + if 1.8 < order < 2.2: # Should be second order accurate + print("............ PASS") + else: + success = False + print("............ FAIL") # plot errors try: - import matplotlib.pyplot as plt - for var,mark,label in zip(varlist, markers, labels): - plt.plot(dy, error_2[var], '-'+mark, label="%s order=%.2f" % (label, order)) - plt.plot(dy, error_inf[var], '--'+mark) + import matplotlib.pyplot as plt + + for var, mark, label in zip(varlist, markers, labels): + plt.plot(dy, error_2[var], "-" + mark, label="%s order=%.2f" % (label, order)) + plt.plot(dy, error_inf[var], "--" + mark) - plt.legend(loc="upper left") - plt.grid() + plt.legend(loc="upper left") + plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta y$') - plt.ylabel("Error norm") + plt.xlabel(r"Mesh spacing $\delta y$") + plt.ylabel("Error norm") - plt.savefig("norm.pdf") + plt.savefig("norm.pdf") - #plt.show() - plt.close() + # plt.show() + plt.close() except: - # Plotting could fail for any number of reasons, and the actual - # error raised may depend on, among other things, the current - # matplotlib backend, so catch everything - pass + # Plotting could fail for any number of reasons, and the actual + # error raised may depend on, among other things, the current + # matplotlib backend, so catch everything + pass if success: - print(" => Test passed") - exit(0) + print(" => Test passed") + exit(0) else: - print(" => Test failed") - exit(1) + print(" => Test failed") + exit(1) diff --git a/tests/MMS/wave-1d/mms.py b/tests/MMS/wave-1d/mms.py index bcd986c99f..2cc0e20b57 100644 --- a/tests/MMS/wave-1d/mms.py +++ b/tests/MMS/wave-1d/mms.py @@ -1,5 +1,6 @@ from __future__ import print_function from builtins import str + # # Generate the test case using SymPy # @@ -14,13 +15,13 @@ # Define symbols -x = symbols('x') -t = symbols('t') +x = symbols("x") +t = symbols("t") # Define the manufactured solution -f = 0.9 + 0.9*x + 0.2*cos(10*t)*sin(5.*x**2) -g = 0.9 + 0.7*x + 0.2*cos(7*t)*sin(2.*x**2) +f = 0.9 + 0.9 * x + 0.2 * cos(10 * t) * sin(5.0 * x ** 2) +g = 0.9 + 0.7 * x + 0.2 * cos(7 * t) * sin(2.0 * x ** 2) # Calculate gradients in x for boundaries diff --git a/tests/MMS/wave-1d/runtest b/tests/MMS/wave-1d/runtest index 5122548d92..44ab4aa0e3 100755 --- a/tests/MMS/wave-1d/runtest +++ b/tests/MMS/wave-1d/runtest @@ -6,9 +6,9 @@ from __future__ import division from __future__ import print_function try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -26,82 +26,84 @@ timestep = 0.1 nproc = 1 -error_2 = [] # The L2 error (RMS) +error_2 = [] # The L2 error (RMS) error_inf = [] # The maximum error for nx in nxlist: - args = "mesh:nx="+str(nx)+" nout="+str(nout)+" timestep="+str(timestep) - + args = "mesh:nx=" + str(nx) + " nout=" + str(nout) + " timestep=" + str(timestep) + print("Running with " + args) # Delete old data shell("rm data/BOUT.dmp.*.nc") - + # Command to run - cmd = "./wave "+args + cmd = "./wave " + args # Launch using MPI s, out = launch_safe(cmd, nproc=nproc, pipe=True) # Save output to log file - f = open("run.log."+str(nx), "w") + f = open("run.log." + str(nx), "w") f.write(out) f.close() # Collect data - E_f = collect("E_f", tind=[nout,nout], path="data", info=False) - E_f = E_f[0,:,0,0] - - E_g = collect("E_g", tind=[nout,nout], path="data", info=False) - E_g = E_g[0,:,0,0] + E_f = collect("E_f", tind=[nout, nout], path="data", info=False) + E_f = E_f[0, :, 0, 0] + + E_g = collect("E_g", tind=[nout, nout], path="data", info=False) + E_g = E_g[0, :, 0, 0] # Average error over domain, not including guard cells E = concatenate([E_f[1:-1], E_g[2:-1]]) - l2 = sqrt(mean(E**2)) + l2 = sqrt(mean(E ** 2)) linf = max(abs(E)) - - error_2.append( l2 ) - error_inf.append( linf ) + + error_2.append(l2) + error_inf.append(linf) print("Error norm: l-2 %f l-inf %f" % (l2, linf)) # Calculate grid spacing -dx = 1. / (array(nxlist) - 2.) +dx = 1.0 / (array(nxlist) - 2.0) order = log(error_2[-1] / error_2[-2]) / log(dx[-1] / dx[-2]) print("Convergence order = %f" % (order)) # plot errors try: - import matplotlib.pyplot as plt + import matplotlib.pyplot as plt - plt.plot(dx, error_2, '-o', label=r'$l^2$') - plt.plot(dx, error_inf, '-x', label=r'$l^\infty$') - plt.plot(dx, error_2[-1]*(dx/dx[-1])**order, '--', label="Order %.1f"%(order)) + plt.plot(dx, error_2, "-o", label=r"$l^2$") + plt.plot(dx, error_inf, "-x", label=r"$l^\infty$") + plt.plot( + dx, error_2[-1] * (dx / dx[-1]) ** order, "--", label="Order %.1f" % (order) + ) - plt.legend(loc="upper left") - plt.grid() + plt.legend(loc="upper left") + plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') - plt.ylabel("Error norm") + plt.xlabel(r"Mesh spacing $\delta x$") + plt.ylabel("Error norm") - plt.savefig("wave_norm.pdf") + plt.savefig("wave_norm.pdf") - #plt.show() - plt.close() + # plt.show() + plt.close() except: - # Plotting could fail for any number of reasons, and the actual - # error raised may depend on, among other things, the current - # matplotlib backend, so catch everything - pass + # Plotting could fail for any number of reasons, and the actual + # error raised may depend on, among other things, the current + # matplotlib backend, so catch everything + pass if 2.2 > order > 1.8: - # test for success - print(" => Test passed") - exit(0) + # test for success + print(" => Test passed") + exit(0) else: - print(" => Test failed") - exit(1) + print(" => Test failed") + exit(1) diff --git a/tests/integrated/test-attribs/runtest b/tests/integrated/test-attribs/runtest index 6f69ce4a3c..05808827cf 100755 --- a/tests/integrated/test-attribs/runtest +++ b/tests/integrated/test-attribs/runtest @@ -1,7 +1,7 @@ #!/usr/bin/env python3 from boututils.run_wrapper import build_and_log, launch_safe -#requires: all_tests +# requires: all_tests build_and_log("test-attribs test") @@ -17,14 +17,14 @@ success = True attr = attributes("g12", path="data") -if attr['value'] != 42: +if attr["value"] != 42: print("Field2D integer attribute FAIL. Attributes: ", attr) success = False # Get attributes for 3D field variable "a" - + attr = attributes("a", path="data") -if attr['meta'] != "something useful": +if attr["meta"] != "something useful": print("Field3D integer attribute FAIL. Attributes: ", attr) success = False diff --git a/tests/integrated/test-boutcore/collect-staggered/runtest b/tests/integrated/test-boutcore/collect-staggered/runtest index 7f683a862e..dd8e460b56 100755 --- a/tests/integrated/test-boutcore/collect-staggered/runtest +++ b/tests/integrated/test-boutcore/collect-staggered/runtest @@ -7,7 +7,7 @@ import boutcore as bc bc.init("-q -q -q") fail = 0 -f = bc.create3D("sin(y)", outloc='YLOW') +f = bc.create3D("sin(y)", outloc="YLOW") dump = bc.Datafile() # get global :( dump.add(f3d_evolve=f, save_repeat=True) @@ -15,10 +15,10 @@ dump.add(f3d_once=f, save_repeat=False) dump.write() -fc = bc.create3D("sin(y)", outloc='CENTRE') +fc = bc.create3D("sin(y)", outloc="CENTRE") -fe = bc.Field3D.fromCollect("f3d_evolve", path='data', info=False) -fo = bc.Field3D.fromCollect("f3d_once", path='data', info=False) +fe = bc.Field3D.fromCollect("f3d_evolve", path="data", info=False) +fo = bc.Field3D.fromCollect("f3d_once", path="data", info=False) if fe.getLocation() == fc.getLocation(): print("The loaded field should not be at CELL_CENTRE") @@ -30,8 +30,8 @@ if fo.getLocation() == fc.getLocation(): def compare(a, b): - diff = a-bc.interp_to(b, a.getLocation()) - err = bc.max(bc.sqrt(diff*diff)) + diff = a - bc.interp_to(b, a.getLocation()) + err = bc.max(bc.sqrt(diff * diff)) return err diff --git a/tests/integrated/test-boutcore/collect/runtest b/tests/integrated/test-boutcore/collect/runtest index b1ba11fa7b..454acc90b2 100755 --- a/tests/integrated/test-boutcore/collect/runtest +++ b/tests/integrated/test-boutcore/collect/runtest @@ -9,9 +9,9 @@ from boutdata import collect bc.init("-d input".split(" ")) f = bc.Field3D.fromMesh(None) -f.setAll(np.array([[[1.]]])) +f.setAll(np.array([[[1.0]]])) f2 = bc.Field3D.fromMesh(None) -f2.setAll(np.array([[[2.]]])) +f2.setAll(np.array([[[2.0]]])) print(f.getAll()) dump = bc.Datafile() # get global :( dump.add(f3d=f, f2d=f2, save_repeat=True) @@ -19,9 +19,9 @@ dump.write() errorlist = "" -n = collect("f2d", path='input', tind=-1, yguards=True) +n = collect("f2d", path="input", tind=-1, yguards=True) print(n.shape) -T = collect("f3d", path='input', tind=-1, yguards=True) +T = collect("f3d", path="input", tind=-1, yguards=True) print(n.shape) print("initialized mesh") @@ -31,16 +31,16 @@ print("initialized mesh") dens = bc.Field3D.fromMesh(mesh) dens[:, :, :] = n.reshape((1, 1, 1)) temp = bc.Field3D.fromCollect("f3d", path="input") -pres = dens+temp +pres = dens + temp print(slice(None, None, -2).indices(5)) p = pres[::5, 0, ::-2] -pn = (n+T) +pn = n + T pn = pn.reshape(p.shape) if not ((p == pn).all()): errorlist += "addition not working\n" -pres = dens*temp*1 +pres = dens * temp * 1 p = pres.getAll() -pn = n*T +pn = n * T pn = pn.reshape(p.shape) if not ((p == pn).all()): errorlist += "multiplication not working\n" diff --git a/tests/integrated/test-boutcore/legacy-model/runtest b/tests/integrated/test-boutcore/legacy-model/runtest index 9d84b27741..99c49d8e4e 100755 --- a/tests/integrated/test-boutcore/legacy-model/runtest +++ b/tests/integrated/test-boutcore/legacy-model/runtest @@ -12,7 +12,7 @@ dens = boutcore.create3D("0") def rhs(time): n_ddt = dens.ddt() - n_ddt[:, :, :] = dens*0 + n_ddt[:, :, :] = dens * 0 n_ddt += 1 diff --git a/tests/integrated/test-boutcore/mms-ddz/runtest b/tests/integrated/test-boutcore/mms-ddz/runtest index aa1ef07c9e..1d95c9d70c 100755 --- a/tests/integrated/test-boutcore/mms-ddz/runtest +++ b/tests/integrated/test-boutcore/mms-ddz/runtest @@ -13,7 +13,7 @@ errors = [] mmax = 7 start = 6 doPlot = False -nzs = np.logspace(start, mmax, num=mmax-start+1, base=2) +nzs = np.logspace(start, mmax, num=mmax - start + 1, base=2) for nz in nzs: boutcore.setOption("meshz:nz", "%d" % nz, force=True) boutcore.setOption("meshz:dz", "2*Pi/%d" % nz, force=True) @@ -21,18 +21,19 @@ for nz in nzs: f = boutcore.create3D("sin(z)", mesh) sim = boutcore.DDZ(f) ana = boutcore.create3D("cos(z)", mesh) - err = sim-ana + err = sim - ana err = np.max(np.abs(err.getAll())) errors.append(err) if doPlot: from matplotlib import pyplot as plt - plt.plot(1/np.array(nzs), errors, '-o') + + plt.plot(1 / np.array(nzs), errors, "-o") plt.show() -errc = np.log(errors[-2]/errors[-1]) -difc = np.log(nzs[-1]/nzs[-2]) -conv = errc/difc +errc = np.log(errors[-2] / errors[-1]) +difc = np.log(nzs[-1] / nzs[-2]) +conv = errc / difc if 1.9 < conv < 2.1: print("The convergence is: %f" % conv) diff --git a/tests/integrated/test-boutcore/simple-model/runtest b/tests/integrated/test-boutcore/simple-model/runtest index 9748cc4b0c..fbeca7de57 100755 --- a/tests/integrated/test-boutcore/simple-model/runtest +++ b/tests/integrated/test-boutcore/simple-model/runtest @@ -4,6 +4,7 @@ # requires not make from boutcore import * + init("-d mini") diff --git a/tests/integrated/test-collect/runtest b/tests/integrated/test-collect/runtest index f1129ac48b..a1ebb8e3c7 100755 --- a/tests/integrated/test-collect/runtest +++ b/tests/integrated/test-collect/runtest @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -#requires: all_tests +# requires: all_tests from boututils.run_wrapper import shell, shell_safe @@ -22,5 +22,3 @@ if not np.allclose(a, 1.23): print("Passed") exit(0) - - diff --git a/tests/integrated/test-command-args/runtest b/tests/integrated/test-command-args/runtest index d267f4f99b..2333feecc5 100755 --- a/tests/integrated/test-command-args/runtest +++ b/tests/integrated/test-command-args/runtest @@ -30,70 +30,101 @@ class TestCommandLineArgs(unittest.TestCase): launch_safe(self.command, pipe=True, nproc=1, mthread=1) with open("stderr.log") as f: contents = f.read() - self.assertIn('"data" does not exist', contents, - msg="FAIL: Error message not printed when missing input directory") + self.assertIn( + '"data" does not exist', + contents, + msg="FAIL: Error message not printed when missing input directory", + ) def testHelpArgument(self): self.makeDirAndCopyInput("data") _, out = launch_safe(self.command + " --help", pipe=True, nproc=1, mthread=1) # Not a great test! - self.assertNotIn("Writing options", out, - msg="FAIL: Attempting to write options") + self.assertNotIn( + "Writing options", out, msg="FAIL: Attempting to write options" + ) def testNoArgumentsDefaultDirectory(self): self.makeDirAndCopyInput("data") launch_safe(self.command, pipe=True, nproc=1, mthread=1) - self.assertTrue(os.path.exists("data/BOUT.settings"), - msg="FAIL: No BOUT.settings file in data directory") - self.assertTrue(os.path.exists("data/BOUT.log.0"), - msg="FAIL: No BOUT.log.0 file in data directory") + self.assertTrue( + os.path.exists("data/BOUT.settings"), + msg="FAIL: No BOUT.settings file in data directory", + ) + self.assertTrue( + os.path.exists("data/BOUT.log.0"), + msg="FAIL: No BOUT.log.0 file in data directory", + ) def testShortLogArgument(self): self.makeDirAndCopyInput("data") launch_safe(self.command + " -l different.log", pipe=True, nproc=1, mthread=1) - self.assertFalse(os.path.exists("data/BOUT.log.0"), - msg="FAIL: BOUT.log.0 file in data directory") - self.assertTrue(os.path.exists("data/different.log.0"), - msg="FAIL: no different.log.0 file in data directory") + self.assertFalse( + os.path.exists("data/BOUT.log.0"), + msg="FAIL: BOUT.log.0 file in data directory", + ) + self.assertTrue( + os.path.exists("data/different.log.0"), + msg="FAIL: no different.log.0 file in data directory", + ) def testLongLogArgument(self): self.makeDirAndCopyInput("data") launch_safe(self.command + " --log log", pipe=True, nproc=1, mthread=1) - self.assertFalse(os.path.exists("data/BOUT.log.0"), - msg="FAIL: BOUT.log.0 file in data directory") - self.assertTrue(os.path.exists("data/log.0"), - msg="FAIL: no log.0 file in data directory") + self.assertFalse( + os.path.exists("data/BOUT.log.0"), + msg="FAIL: BOUT.log.0 file in data directory", + ) + self.assertTrue( + os.path.exists("data/log.0"), msg="FAIL: no log.0 file in data directory" + ) def testDirectoryArgument(self): self.makeDirAndCopyInput("test") launch_safe(self.command + " -d test", pipe=True, nproc=1, mthread=1) - self.assertTrue(os.path.exists("test/BOUT.settings"), - msg="FAIL: No BOUT.settings file in test directory") - self.assertTrue(os.path.exists("test/BOUT.log.0"), - msg="FAIL: No BOUT.log.0 file in data directory") + self.assertTrue( + os.path.exists("test/BOUT.settings"), + msg="FAIL: No BOUT.settings file in test directory", + ) + self.assertTrue( + os.path.exists("test/BOUT.log.0"), + msg="FAIL: No BOUT.log.0 file in data directory", + ) def testDirectoryArgumentNonExistentDirectory(self): with self.assertRaises(RuntimeError): - launch_safe(self.command + " -d non_existent", pipe=True, nproc=1, mthread=1) + launch_safe( + self.command + " -d non_existent", pipe=True, nproc=1, mthread=1 + ) with open("stderr.log") as f: contents = f.read() - self.assertIn('"non_existent" does not exist', contents, - msg="FAIL: Error message not printed when missing input directory") + self.assertIn( + '"non_existent" does not exist', + contents, + msg="FAIL: Error message not printed when missing input directory", + ) def testDirectoryArgumentNonDirectory(self): with self.assertRaises(RuntimeError): launch_safe(self.command + " -d runtest", pipe=True, nproc=1, mthread=1) with open("stderr.log") as f: contents = f.read() - self.assertIn('"runtest" is not a directory', contents, - msg="FAIL: Error message not printed when missing input directory") + self.assertIn( + '"runtest" is not a directory', + contents, + msg="FAIL: Error message not printed when missing input directory", + ) def testDirectoryArgumentOldSettingsFile(self): self.makeDirAndCopyInput("test") launch_safe(self.command + " -d test", pipe=True, nproc=1, mthread=1) shutil.copytree("test", "test_copy") - launch_safe(self.command + - " -d test_copy -f BOUT.settings -o testsettings", pipe=True, nproc=1, mthread=1) + launch_safe( + self.command + " -d test_copy -f BOUT.settings -o testsettings", + pipe=True, + nproc=1, + mthread=1, + ) with open("test_copy/testsettings") as f: contents = f.readlines() @@ -105,28 +136,50 @@ class TestCommandLineArgs(unittest.TestCase): datadir = line.split()[2] break - self.assertIn("test_copy", datadir, - msg="FAIL: datadir from command line clobbered by BOUT.settings") + self.assertIn( + "test_copy", + datadir, + msg="FAIL: datadir from command line clobbered by BOUT.settings", + ) def testShortOptionsAreCleaned(self): self.makeDirAndCopyInput("test") launch_safe(self.command + " -d test", pipe=True, nproc=1, mthread=1) shutil.copytree("test", "test_copy") - launch_safe(self.command + - " -d test_copy -f BOUT.settings -o testsettings", pipe=True, nproc=1, mthread=1) + launch_safe( + self.command + " -d test_copy -f BOUT.settings -o testsettings", + pipe=True, + nproc=1, + mthread=1, + ) with open("test_copy/testsettings") as f: contents = f.read() - self.assertNotIn("Command line", contents, - msg="FAIL: command line short options written to BOUT.settings") + self.assertNotIn( + "Command line", + contents, + msg="FAIL: command line short options written to BOUT.settings", + ) def testCommandLineOptionsArePrinted(self): self.makeDirAndCopyInput("test") launch_safe(self.command + " -d test", pipe=True, nproc=1, mthread=1) shutil.copytree("test", "test_copy") - extra_options = ["-d", "test_copy", "-f", "BOUT.settings", "-o", - "testsettings", "-l", "bout.log", "--foo_flag", "some:option=value"] - _, out = launch_safe(self.command + " " + " ".join(extra_options), pipe=True, nproc=1, mthread=1) + extra_options = [ + "-d", + "test_copy", + "-f", + "BOUT.settings", + "-o", + "testsettings", + "-l", + "bout.log", + "--foo_flag", + "some:option=value", + ] + _, out = launch_safe( + self.command + " " + " ".join(extra_options), pipe=True, nproc=1, mthread=1 + ) command_line_options = None for line in out.splitlines(): @@ -134,8 +187,11 @@ class TestCommandLineArgs(unittest.TestCase): command_line_options = line for option in extra_options: - self.assertIn(option, command_line_options, - msg="FAIL: option {} not printed out".format(option)) + self.assertIn( + option, + command_line_options, + msg="FAIL: option {} not printed out".format(option), + ) if __name__ == "__main__": diff --git a/tests/integrated/test-communications/runtest b/tests/integrated/test-communications/runtest index d329a6139a..2ba80b0171 100755 --- a/tests/integrated/test-communications/runtest +++ b/tests/integrated/test-communications/runtest @@ -16,314 +16,319 @@ from boututils.run_wrapper import build_and_log, shell, launch_safe # Test disconnected-double-null diverted topology ################################################# -nype = 6 # need at least 6 to include all regions +nype = 6 # need at least 6 to include all regions # run with processor splitting at separatrices ################################################## # With nxpe=3, both separatrices are on processor boundaries nxpe = 3 -command = './test-communications nxpe='+str(nxpe) +command = "./test-communications nxpe=" + str(nxpe) -build_and_log('Communications Test') +build_and_log("Communications Test") # remove old outputs -shell('rm data/BOUT.dmp.*') +shell("rm data/BOUT.dmp.*") -print('Running Communications Test, nproc='+str(nxpe*nype)) +print("Running Communications Test, nproc=" + str(nxpe * nype)) -s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) -with open('run.log.'+str(nxpe), 'w') as f: +s, out = launch_safe(command, nproc=nxpe * nype, pipe=True) +with open("run.log." + str(nxpe), "w") as f: f.write(out) + def test(actual, expected, procnum, region, boundary): if not np.all(np.array(np.rint(actual).astype(int)) == np.array(expected)): - print('failed in {} boundary of region {} ({}). Expected: {} Actual: {}' - .format(boundary, procnum, region, expected, actual)) + print( + "failed in {} boundary of region {} ({}). Expected: {} Actual: {}".format( + boundary, procnum, region, expected, actual + ) + ) exit(1) -region = 'lower, inner PF' -f = DataFile("data/BOUT.dmp.0.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [72, 73], 0, region, 'inner x') -test(f[-1, 1:-1], [24, 25], 0, region, 'outer x') -test(f[:, 0], [96, 97, 98, 99], 0, region, 'lower y') -test(f[:, -1], [82, 10, 22, 26], 0, region, 'upper y') - -region = 'lower, inner between separatrices' -f = DataFile("data/BOUT.dmp.1.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [12, 13], 0, region, 'inner x') -test(f[-1, 1:-1], [48, 49], 0, region, 'outer x') -test(f[:, 0], [98, 99, 100, 101], 0, region, 'lower y') -test(f[:, -1], [22, 26, 38, 50], 0, region, 'upper y') - -region = 'lower, inner SOL' -f = DataFile("data/BOUT.dmp.2.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [36, 37], 0, region, 'inner x') -test(f[-1, 1:-1], [84, 85], 0, region, 'outer x') -test(f[:, 0], [100, 101, 102, 103], 0, region, 'lower y') -test(f[:, -1], [38, 50, 62, 86], 0, region, 'upper y') - -region = 'inner core' -f = DataFile("data/BOUT.dmp.3.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [74, 75], 0, region, 'inner x') -test(f[-1, 1:-1], [26, 27], 0, region, 'outer x') -test(f[:, 0], [81, 9, 21, 25], 0, region, 'lower y') -test(f[:, -1], [80, 8, 20, 32], 0, region, 'upper y') - -region = 'inner between separatrices' -f = DataFile("data/BOUT.dmp.4.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [14, 15], 0, region, 'inner x') -test(f[-1, 1:-1], [50, 51], 0, region, 'outer x') -test(f[:, 0], [21, 25, 37, 49], 0, region, 'lower y') -test(f[:, -1], [20, 32, 44, 52], 0, region, 'upper y') - -region = 'inner SOL' -f = DataFile("data/BOUT.dmp.5.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [38, 39], 0, region, 'inner x') -test(f[-1, 1:-1], [86, 87], 0, region, 'outer x') -test(f[:, 0], [37, 49, 61, 85], 0, region, 'lower y') -test(f[:, -1], [44, 52, 64, 88], 0, region, 'upper y') - -region = 'upper inner PF' -f = DataFile("data/BOUT.dmp.6.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [76, 77], 0, region, 'inner x') -test(f[-1, 1:-1], [28, 29], 0, region, 'outer x') -test(f[:, 0], [79, 7, 19, 31], 0, region, 'lower y') -test(f[:, -1], [104, 105, 106, 107], 0, region, 'upper y') - -region = 'upper inner SOL, nearer PF' -f = DataFile("data/BOUT.dmp.7.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [16, 17], 0, region, 'inner x') -test(f[-1, 1:-1], [52, 53], 0, region, 'outer x') -test(f[:, 0], [19, 31, 43, 51], 0, region, 'lower y') -test(f[:, -1], [106, 107, 108, 109], 0, region, 'upper y') - -region = 'upper inner SOL, further from PF' -f = DataFile("data/BOUT.dmp.8.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [40, 41], 0, region, 'inner x') -test(f[-1, 1:-1], [88, 89], 0, region, 'outer x') -test(f[:, 0], [43, 51, 63, 87], 0, region, 'lower y') -test(f[:, -1], [108, 109, 110, 111], 0, region, 'upper y') - -region = 'upper outer PF' -f = DataFile("data/BOUT.dmp.9.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [78, 79], 0, region, 'inner x') -test(f[-1, 1:-1], [30, 31], 0, region, 'outer x') -test(f[:, 0], [96, 97, 98, 99], 0, region, 'lower y') -test(f[:, -1], [76, 4, 16, 28], 0, region, 'upper y') - -region = 'upper outer SOL, nearer PF' -f = DataFile("data/BOUT.dmp.10.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [18, 19], 0, region, 'inner x') -test(f[-1, 1:-1], [54, 55], 0, region, 'outer x') -test(f[:, 0], [98, 99, 100, 101], 0, region, 'lower y') -test(f[:, -1], [16, 28, 40, 56], 0, region, 'upper y') - -region = 'upper outer SOL, further from PF' -f = DataFile("data/BOUT.dmp.11.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [42, 43], 0, region, 'inner x') -test(f[-1, 1:-1], [90, 91], 0, region, 'outer x') -test(f[:, 0], [100, 101, 102, 103], 0, region, 'lower y') -test(f[:, -1], [40, 56, 68, 92], 0, region, 'upper y') - -region = 'outer core' -f = DataFile("data/BOUT.dmp.12.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [80, 81], 0, region, 'inner x') -test(f[-1, 1:-1], [32, 33], 0, region, 'outer x') -test(f[:, 0], [75, 3, 15, 27], 0, region, 'lower y') -test(f[:, -1], [74, 2, 14, 34], 0, region, 'upper y') - -region = 'outer between separatrices' -f = DataFile("data/BOUT.dmp.13.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [20, 21], 0, region, 'inner x') -test(f[-1, 1:-1], [56, 57], 0, region, 'outer x') -test(f[:, 0], [15, 27, 39, 55], 0, region, 'lower y') -test(f[:, -1], [14, 34, 46, 58], 0, region, 'upper y') - -region = 'outer SOL' -f = DataFile("data/BOUT.dmp.14.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [44, 45], 0, region, 'inner x') -test(f[-1, 1:-1], [92, 93], 0, region, 'outer x') -test(f[:, 0], [39, 55, 67, 91], 0, region, 'lower y') -test(f[:, -1], [46, 58, 70, 94], 0, region, 'upper y') - -region = 'lower outer PF' -f = DataFile("data/BOUT.dmp.15.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [82, 83], 0, region, 'inner x') -test(f[-1, 1:-1], [34, 35], 0, region, 'outer x') -test(f[:, 0], [73, 1, 13, 33], 0, region, 'lower y') -test(f[:, -1], [104, 105, 106, 107], 0, region, 'upper y') - -region = 'lower outer between separatrices' -f = DataFile("data/BOUT.dmp.16.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [22, 23], 0, region, 'inner x') -test(f[-1, 1:-1], [58, 59], 0, region, 'outer x') -test(f[:, 0], [13, 33, 45, 57], 0, region, 'lower y') -test(f[:, -1], [106, 107, 108, 109], 0, region, 'upper y') - -region = 'lower outer SOL' -f = DataFile("data/BOUT.dmp.17.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [46, 47], 0, region, 'inner x') -test(f[-1, 1:-1], [94, 95], 0, region, 'outer x') -test(f[:, 0], [45, 57, 69, 93], 0, region, 'lower y') -test(f[:, -1], [108, 109, 110, 111], 0, region, 'upper y') + +region = "lower, inner PF" +f = DataFile("data/BOUT.dmp.0.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [72, 73], 0, region, "inner x") +test(f[-1, 1:-1], [24, 25], 0, region, "outer x") +test(f[:, 0], [96, 97, 98, 99], 0, region, "lower y") +test(f[:, -1], [82, 10, 22, 26], 0, region, "upper y") + +region = "lower, inner between separatrices" +f = DataFile("data/BOUT.dmp.1.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [12, 13], 0, region, "inner x") +test(f[-1, 1:-1], [48, 49], 0, region, "outer x") +test(f[:, 0], [98, 99, 100, 101], 0, region, "lower y") +test(f[:, -1], [22, 26, 38, 50], 0, region, "upper y") + +region = "lower, inner SOL" +f = DataFile("data/BOUT.dmp.2.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [36, 37], 0, region, "inner x") +test(f[-1, 1:-1], [84, 85], 0, region, "outer x") +test(f[:, 0], [100, 101, 102, 103], 0, region, "lower y") +test(f[:, -1], [38, 50, 62, 86], 0, region, "upper y") + +region = "inner core" +f = DataFile("data/BOUT.dmp.3.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [74, 75], 0, region, "inner x") +test(f[-1, 1:-1], [26, 27], 0, region, "outer x") +test(f[:, 0], [81, 9, 21, 25], 0, region, "lower y") +test(f[:, -1], [80, 8, 20, 32], 0, region, "upper y") + +region = "inner between separatrices" +f = DataFile("data/BOUT.dmp.4.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [14, 15], 0, region, "inner x") +test(f[-1, 1:-1], [50, 51], 0, region, "outer x") +test(f[:, 0], [21, 25, 37, 49], 0, region, "lower y") +test(f[:, -1], [20, 32, 44, 52], 0, region, "upper y") + +region = "inner SOL" +f = DataFile("data/BOUT.dmp.5.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [38, 39], 0, region, "inner x") +test(f[-1, 1:-1], [86, 87], 0, region, "outer x") +test(f[:, 0], [37, 49, 61, 85], 0, region, "lower y") +test(f[:, -1], [44, 52, 64, 88], 0, region, "upper y") + +region = "upper inner PF" +f = DataFile("data/BOUT.dmp.6.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [76, 77], 0, region, "inner x") +test(f[-1, 1:-1], [28, 29], 0, region, "outer x") +test(f[:, 0], [79, 7, 19, 31], 0, region, "lower y") +test(f[:, -1], [104, 105, 106, 107], 0, region, "upper y") + +region = "upper inner SOL, nearer PF" +f = DataFile("data/BOUT.dmp.7.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [16, 17], 0, region, "inner x") +test(f[-1, 1:-1], [52, 53], 0, region, "outer x") +test(f[:, 0], [19, 31, 43, 51], 0, region, "lower y") +test(f[:, -1], [106, 107, 108, 109], 0, region, "upper y") + +region = "upper inner SOL, further from PF" +f = DataFile("data/BOUT.dmp.8.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [40, 41], 0, region, "inner x") +test(f[-1, 1:-1], [88, 89], 0, region, "outer x") +test(f[:, 0], [43, 51, 63, 87], 0, region, "lower y") +test(f[:, -1], [108, 109, 110, 111], 0, region, "upper y") + +region = "upper outer PF" +f = DataFile("data/BOUT.dmp.9.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [78, 79], 0, region, "inner x") +test(f[-1, 1:-1], [30, 31], 0, region, "outer x") +test(f[:, 0], [96, 97, 98, 99], 0, region, "lower y") +test(f[:, -1], [76, 4, 16, 28], 0, region, "upper y") + +region = "upper outer SOL, nearer PF" +f = DataFile("data/BOUT.dmp.10.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [18, 19], 0, region, "inner x") +test(f[-1, 1:-1], [54, 55], 0, region, "outer x") +test(f[:, 0], [98, 99, 100, 101], 0, region, "lower y") +test(f[:, -1], [16, 28, 40, 56], 0, region, "upper y") + +region = "upper outer SOL, further from PF" +f = DataFile("data/BOUT.dmp.11.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [42, 43], 0, region, "inner x") +test(f[-1, 1:-1], [90, 91], 0, region, "outer x") +test(f[:, 0], [100, 101, 102, 103], 0, region, "lower y") +test(f[:, -1], [40, 56, 68, 92], 0, region, "upper y") + +region = "outer core" +f = DataFile("data/BOUT.dmp.12.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [80, 81], 0, region, "inner x") +test(f[-1, 1:-1], [32, 33], 0, region, "outer x") +test(f[:, 0], [75, 3, 15, 27], 0, region, "lower y") +test(f[:, -1], [74, 2, 14, 34], 0, region, "upper y") + +region = "outer between separatrices" +f = DataFile("data/BOUT.dmp.13.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [20, 21], 0, region, "inner x") +test(f[-1, 1:-1], [56, 57], 0, region, "outer x") +test(f[:, 0], [15, 27, 39, 55], 0, region, "lower y") +test(f[:, -1], [14, 34, 46, 58], 0, region, "upper y") + +region = "outer SOL" +f = DataFile("data/BOUT.dmp.14.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [44, 45], 0, region, "inner x") +test(f[-1, 1:-1], [92, 93], 0, region, "outer x") +test(f[:, 0], [39, 55, 67, 91], 0, region, "lower y") +test(f[:, -1], [46, 58, 70, 94], 0, region, "upper y") + +region = "lower outer PF" +f = DataFile("data/BOUT.dmp.15.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [82, 83], 0, region, "inner x") +test(f[-1, 1:-1], [34, 35], 0, region, "outer x") +test(f[:, 0], [73, 1, 13, 33], 0, region, "lower y") +test(f[:, -1], [104, 105, 106, 107], 0, region, "upper y") + +region = "lower outer between separatrices" +f = DataFile("data/BOUT.dmp.16.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [22, 23], 0, region, "inner x") +test(f[-1, 1:-1], [58, 59], 0, region, "outer x") +test(f[:, 0], [13, 33, 45, 57], 0, region, "lower y") +test(f[:, -1], [106, 107, 108, 109], 0, region, "upper y") + +region = "lower outer SOL" +f = DataFile("data/BOUT.dmp.17.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [46, 47], 0, region, "inner x") +test(f[-1, 1:-1], [94, 95], 0, region, "outer x") +test(f[:, 0], [45, 57, 69, 93], 0, region, "lower y") +test(f[:, -1], [108, 109, 110, 111], 0, region, "upper y") # run with processor splitting not at separatrices ################################################## # With nxpe=2, neither separatrix is on a processor boundary nxpe = 2 -command = './test-communications nxpe='+str(nxpe) +command = "./test-communications nxpe=" + str(nxpe) # remove old outputs -shell('rm data/BOUT.dmp.*') +shell("rm data/BOUT.dmp.*") -print('Running Communications Test, nproc='+str(nxpe*nype)) +print("Running Communications Test, nproc=" + str(nxpe * nype)) -s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) -with open('run.log.'+str(nxpe), 'w') as f: +s, out = launch_safe(command, nproc=nxpe * nype, pipe=True) +with open("run.log." + str(nxpe), "w") as f: f.write(out) -region = 'lower, inner leg, interior' -f = DataFile("data/BOUT.dmp.0.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [72, 73], 0, region, 'inner x') -test(f[-1, 1:-1], [36, 37], 0, region, 'outer x') -test(f[:, 0], [96, 97, 98, 99, 100], 0, region, 'lower y') -test(f[:, -1], [82, 10, 22, 26, 38], 0, region, 'upper y') - -region = 'lower, inner leg, exterior' -f = DataFile("data/BOUT.dmp.1.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [24, 25], 0, region, 'inner x') -test(f[-1, 1:-1], [84, 85], 0, region, 'outer x') -test(f[:, 0], [99, 100, 101, 102, 103], 0, region, 'lower y') -test(f[:, -1], [26, 38, 50, 62, 86], 0, region, 'upper y') - -region = 'inner, interior' -f = DataFile("data/BOUT.dmp.2.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [74, 75], 0, region, 'inner x') -test(f[-1, 1:-1], [38, 39], 0, region, 'outer x') -test(f[:, 0], [81, 9, 21, 25, 37], 0, region, 'lower y') -test(f[:, -1], [80, 8, 20, 32, 44], 0, region, 'upper y') - -region = 'inner, exterior' -f = DataFile("data/BOUT.dmp.3.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [26, 27], 0, region, 'inner x') -test(f[-1, 1:-1], [86, 87], 0, region, 'outer x') -test(f[:, 0], [25, 37, 49, 61, 85], 0, region, 'lower y') -test(f[:, -1], [32, 44, 52, 64, 88], 0, region, 'upper y') - -region = 'upper, inner leg, interior' -f = DataFile("data/BOUT.dmp.4.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [76, 77], 0, region, 'inner x') -test(f[-1, 1:-1], [40, 41], 0, region, 'outer x') -test(f[:, 0], [79, 7, 19, 31, 43], 0, region, 'lower y') -test(f[:, -1], [104, 105, 106, 107, 108], 0, region, 'upper y') - -region = 'upper, inner leg, exterior' -f = DataFile("data/BOUT.dmp.5.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [28, 29], 0, region, 'inner x') -test(f[-1, 1:-1], [88, 89], 0, region, 'outer x') -test(f[:, 0], [31, 43, 51, 63, 87], 0, region, 'lower y') -test(f[:, -1], [107, 108, 109, 110, 111], 0, region, 'upper y') - -region = 'upper, outer leg, interior' -f = DataFile("data/BOUT.dmp.6.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [78, 79], 0, region, 'inner x') -test(f[-1, 1:-1], [42, 43], 0, region, 'outer x') -test(f[:, 0], [96, 97, 98, 99, 100], 0, region, 'lower y') -test(f[:, -1], [76, 4, 16, 28, 40], 0, region, 'upper y') - -region = 'upper, outer leg, exterior' -f = DataFile("data/BOUT.dmp.7.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [30, 31], 0, region, 'inner x') -test(f[-1, 1:-1], [90, 91], 0, region, 'outer x') -test(f[:, 0], [99, 100, 101, 102, 103], 0, region, 'lower y') -test(f[:, -1], [28, 40, 56, 68, 92], 0, region, 'upper y') - -region = 'outer, interior' -f = DataFile("data/BOUT.dmp.8.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [80, 81], 0, region, 'inner x') -test(f[-1, 1:-1], [44, 45], 0, region, 'outer x') -test(f[:, 0], [75, 3, 15, 27, 39], 0, region, 'lower y') -test(f[:, -1], [74, 2, 14, 34, 46], 0, region, 'upper y') - -region = 'outer, exterior' -f = DataFile("data/BOUT.dmp.9.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [32, 33], 0, region, 'inner x') -test(f[-1, 1:-1], [92, 93], 0, region, 'outer x') -test(f[:, 0], [27, 39, 55, 67, 91], 0, region, 'lower y') -test(f[:, -1], [34, 46, 58, 70, 94], 0, region, 'upper y') - -region = 'lower, outer leg, interior' -f = DataFile("data/BOUT.dmp.10.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [82, 83], 0, region, 'inner x') -test(f[-1, 1:-1], [46, 47], 0, region, 'outer x') -test(f[:, 0], [73, 1, 13, 33, 45], 0, region, 'lower y') -test(f[:, -1], [104, 105, 106, 107, 108], 0, region, 'upper y') - -region = 'lower, outer leg, exterior' -f = DataFile("data/BOUT.dmp.11.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [34, 35], 0, region, 'inner x') -test(f[-1, 1:-1], [94, 95], 0, region, 'outer x') -test(f[:, 0], [33, 45, 57, 69, 93], 0, region, 'lower y') -test(f[:, -1], [107, 108, 109, 110, 111], 0, region, 'upper y') +region = "lower, inner leg, interior" +f = DataFile("data/BOUT.dmp.0.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [72, 73], 0, region, "inner x") +test(f[-1, 1:-1], [36, 37], 0, region, "outer x") +test(f[:, 0], [96, 97, 98, 99, 100], 0, region, "lower y") +test(f[:, -1], [82, 10, 22, 26, 38], 0, region, "upper y") + +region = "lower, inner leg, exterior" +f = DataFile("data/BOUT.dmp.1.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [24, 25], 0, region, "inner x") +test(f[-1, 1:-1], [84, 85], 0, region, "outer x") +test(f[:, 0], [99, 100, 101, 102, 103], 0, region, "lower y") +test(f[:, -1], [26, 38, 50, 62, 86], 0, region, "upper y") + +region = "inner, interior" +f = DataFile("data/BOUT.dmp.2.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [74, 75], 0, region, "inner x") +test(f[-1, 1:-1], [38, 39], 0, region, "outer x") +test(f[:, 0], [81, 9, 21, 25, 37], 0, region, "lower y") +test(f[:, -1], [80, 8, 20, 32, 44], 0, region, "upper y") + +region = "inner, exterior" +f = DataFile("data/BOUT.dmp.3.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [26, 27], 0, region, "inner x") +test(f[-1, 1:-1], [86, 87], 0, region, "outer x") +test(f[:, 0], [25, 37, 49, 61, 85], 0, region, "lower y") +test(f[:, -1], [32, 44, 52, 64, 88], 0, region, "upper y") + +region = "upper, inner leg, interior" +f = DataFile("data/BOUT.dmp.4.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [76, 77], 0, region, "inner x") +test(f[-1, 1:-1], [40, 41], 0, region, "outer x") +test(f[:, 0], [79, 7, 19, 31, 43], 0, region, "lower y") +test(f[:, -1], [104, 105, 106, 107, 108], 0, region, "upper y") + +region = "upper, inner leg, exterior" +f = DataFile("data/BOUT.dmp.5.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [28, 29], 0, region, "inner x") +test(f[-1, 1:-1], [88, 89], 0, region, "outer x") +test(f[:, 0], [31, 43, 51, 63, 87], 0, region, "lower y") +test(f[:, -1], [107, 108, 109, 110, 111], 0, region, "upper y") + +region = "upper, outer leg, interior" +f = DataFile("data/BOUT.dmp.6.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [78, 79], 0, region, "inner x") +test(f[-1, 1:-1], [42, 43], 0, region, "outer x") +test(f[:, 0], [96, 97, 98, 99, 100], 0, region, "lower y") +test(f[:, -1], [76, 4, 16, 28, 40], 0, region, "upper y") + +region = "upper, outer leg, exterior" +f = DataFile("data/BOUT.dmp.7.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [30, 31], 0, region, "inner x") +test(f[-1, 1:-1], [90, 91], 0, region, "outer x") +test(f[:, 0], [99, 100, 101, 102, 103], 0, region, "lower y") +test(f[:, -1], [28, 40, 56, 68, 92], 0, region, "upper y") + +region = "outer, interior" +f = DataFile("data/BOUT.dmp.8.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [80, 81], 0, region, "inner x") +test(f[-1, 1:-1], [44, 45], 0, region, "outer x") +test(f[:, 0], [75, 3, 15, 27, 39], 0, region, "lower y") +test(f[:, -1], [74, 2, 14, 34, 46], 0, region, "upper y") + +region = "outer, exterior" +f = DataFile("data/BOUT.dmp.9.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [32, 33], 0, region, "inner x") +test(f[-1, 1:-1], [92, 93], 0, region, "outer x") +test(f[:, 0], [27, 39, 55, 67, 91], 0, region, "lower y") +test(f[:, -1], [34, 46, 58, 70, 94], 0, region, "upper y") + +region = "lower, outer leg, interior" +f = DataFile("data/BOUT.dmp.10.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [82, 83], 0, region, "inner x") +test(f[-1, 1:-1], [46, 47], 0, region, "outer x") +test(f[:, 0], [73, 1, 13, 33, 45], 0, region, "lower y") +test(f[:, -1], [104, 105, 106, 107, 108], 0, region, "upper y") + +region = "lower, outer leg, exterior" +f = DataFile("data/BOUT.dmp.11.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [34, 35], 0, region, "inner x") +test(f[-1, 1:-1], [94, 95], 0, region, "outer x") +test(f[:, 0], [33, 45, 57, 69, 93], 0, region, "lower y") +test(f[:, -1], [107, 108, 109, 110, 111], 0, region, "upper y") # run with no processor splitting in the x-direction #################################################### nxpe = 1 -command = './test-communications nxpe='+str(nxpe) +command = "./test-communications nxpe=" + str(nxpe) # remove old outputs -shell('rm data/BOUT.dmp.*') +shell("rm data/BOUT.dmp.*") -print('Running Communications Test, nproc='+str(nxpe*nype)) +print("Running Communications Test, nproc=" + str(nxpe * nype)) -s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) -with open('run.log.'+str(nxpe), 'w') as f: +s, out = launch_safe(command, nproc=nxpe * nype, pipe=True) +with open("run.log." + str(nxpe), "w") as f: f.write(out) -region = 'lower, inner leg' -f = DataFile("data/BOUT.dmp.0.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [72, 73], 0, region, 'inner x') -test(f[-1, 1:-1], [84, 85], 0, region, 'outer x') -test(f[:, 0], [96, 97, 98, 99, 100, 101, 102, 103], 0, region, 'lower y') -test(f[:, -1], [82, 10, 22, 26, 38, 50, 62, 86], 0, region, 'upper y') - -region = 'inner' -f = DataFile("data/BOUT.dmp.1.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [74, 75], 0, region, 'inner x') -test(f[-1, 1:-1], [86, 87], 0, region, 'outer x') -test(f[:, 0], [81, 9, 21, 25, 37, 49, 61, 85], 0, region, 'lower y') -test(f[:, -1], [80, 8, 20, 32, 44, 52, 64, 88], 0, region, 'upper y') - -region = 'upper, inner leg' -f = DataFile("data/BOUT.dmp.2.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [76, 77], 0, region, 'inner x') -test(f[-1, 1:-1], [88, 89], 0, region, 'outer x') -test(f[:, 0], [79, 7, 19, 31, 43, 51, 63, 87], 0, region, 'lower y') -test(f[:, -1], [104, 105, 106, 107, 108, 109, 110, 111], 0, region, 'upper y') - -region = 'upper, outer leg' -f = DataFile("data/BOUT.dmp.3.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [78, 79], 0, region, 'inner x') -test(f[-1, 1:-1], [90, 91], 0, region, 'outer x') -test(f[:, 0], [96, 97, 98, 99, 100, 101, 102, 103], 0, region, 'lower y') -test(f[:, -1], [76, 4, 16, 28, 40, 56, 68, 92], 0, region, 'upper y') - -region = 'outer' -f = DataFile("data/BOUT.dmp.4.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [80, 81], 0, region, 'inner x') -test(f[-1, 1:-1], [92, 93], 0, region, 'outer x') -test(f[:, 0], [75, 3, 15, 27, 39, 55, 67, 91], 0, region, 'lower y') -test(f[:, -1], [74, 2, 14, 34, 46, 58, 70, 94], 0, region, 'upper y') - -region = 'lower, outer leg' -f = DataFile("data/BOUT.dmp.5.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [82, 83], 0, region, 'inner x') -test(f[-1, 1:-1], [94, 95], 0, region, 'outer x') -test(f[:, 0], [73, 1, 13, 33, 45, 57, 69, 93], 0, region, 'lower y') -test(f[:, -1], [104, 105, 106, 107, 108, 109, 110, 111], 0, region, 'upper y') +region = "lower, inner leg" +f = DataFile("data/BOUT.dmp.0.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [72, 73], 0, region, "inner x") +test(f[-1, 1:-1], [84, 85], 0, region, "outer x") +test(f[:, 0], [96, 97, 98, 99, 100, 101, 102, 103], 0, region, "lower y") +test(f[:, -1], [82, 10, 22, 26, 38, 50, 62, 86], 0, region, "upper y") + +region = "inner" +f = DataFile("data/BOUT.dmp.1.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [74, 75], 0, region, "inner x") +test(f[-1, 1:-1], [86, 87], 0, region, "outer x") +test(f[:, 0], [81, 9, 21, 25, 37, 49, 61, 85], 0, region, "lower y") +test(f[:, -1], [80, 8, 20, 32, 44, 52, 64, 88], 0, region, "upper y") + +region = "upper, inner leg" +f = DataFile("data/BOUT.dmp.2.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [76, 77], 0, region, "inner x") +test(f[-1, 1:-1], [88, 89], 0, region, "outer x") +test(f[:, 0], [79, 7, 19, 31, 43, 51, 63, 87], 0, region, "lower y") +test(f[:, -1], [104, 105, 106, 107, 108, 109, 110, 111], 0, region, "upper y") + +region = "upper, outer leg" +f = DataFile("data/BOUT.dmp.3.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [78, 79], 0, region, "inner x") +test(f[-1, 1:-1], [90, 91], 0, region, "outer x") +test(f[:, 0], [96, 97, 98, 99, 100, 101, 102, 103], 0, region, "lower y") +test(f[:, -1], [76, 4, 16, 28, 40, 56, 68, 92], 0, region, "upper y") + +region = "outer" +f = DataFile("data/BOUT.dmp.4.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [80, 81], 0, region, "inner x") +test(f[-1, 1:-1], [92, 93], 0, region, "outer x") +test(f[:, 0], [75, 3, 15, 27, 39, 55, 67, 91], 0, region, "lower y") +test(f[:, -1], [74, 2, 14, 34, 46, 58, 70, 94], 0, region, "upper y") + +region = "lower, outer leg" +f = DataFile("data/BOUT.dmp.5.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [82, 83], 0, region, "inner x") +test(f[-1, 1:-1], [94, 95], 0, region, "outer x") +test(f[:, 0], [73, 1, 13, 33, 45, 57, 69, 93], 0, region, "lower y") +test(f[:, -1], [104, 105, 106, 107, 108, 109, 110, 111], 0, region, "upper y") ################################################# @@ -336,89 +341,89 @@ nype = 1 #################################################### nxpe = 3 -command = './test-communications -d data_limiter nxpe='+str(nxpe) +command = "./test-communications -d data_limiter nxpe=" + str(nxpe) # remove old outputs -shell('rm data_limiter/BOUT.dmp.*') +shell("rm data_limiter/BOUT.dmp.*") -print('Running Communications Test, nproc='+str(nxpe*nype)) +print("Running Communications Test, nproc=" + str(nxpe * nype)) -s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) -with open('run_limiter.log.'+str(nxpe), 'w') as f: +s, out = launch_safe(command, nproc=nxpe * nype, pipe=True) +with open("run_limiter.log." + str(nxpe), "w") as f: f.write(out) -region = 'core' -f = DataFile("data_limiter/BOUT.dmp.0.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [12, 13], 0, region, 'inner x') -test(f[-1, 1:-1], [4, 5], 0, region, 'outer x') -test(f[:, 0], [13, 1, 3, 19], 0, region, 'lower y') -test(f[:, -1], [12, 0, 2, 27], 0, region, 'upper y') - -region = 'interior SOL' -f = DataFile("data_limiter/BOUT.dmp.1.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [2, 3], 0, region, 'inner x') -test(f[-1, 1:-1], [8, 9], 0, region, 'outer x') -test(f[:, 0], [3, 19, 20, 21], 0, region, 'lower y') -test(f[:, -1], [2, 27, 28, 29], 0, region, 'upper y') - -region = 'exterior SOL' -f = DataFile("data_limiter/BOUT.dmp.2.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [6, 7], 0, region, 'inner x') -test(f[-1, 1:-1], [14, 15], 0, region, 'outer x') -test(f[:, 0], [20, 21, 22, 23], 0, region, 'lower y') -test(f[:, -1], [28, 29, 30, 31], 0, region, 'upper y') +region = "core" +f = DataFile("data_limiter/BOUT.dmp.0.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [12, 13], 0, region, "inner x") +test(f[-1, 1:-1], [4, 5], 0, region, "outer x") +test(f[:, 0], [13, 1, 3, 19], 0, region, "lower y") +test(f[:, -1], [12, 0, 2, 27], 0, region, "upper y") + +region = "interior SOL" +f = DataFile("data_limiter/BOUT.dmp.1.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [2, 3], 0, region, "inner x") +test(f[-1, 1:-1], [8, 9], 0, region, "outer x") +test(f[:, 0], [3, 19, 20, 21], 0, region, "lower y") +test(f[:, -1], [2, 27, 28, 29], 0, region, "upper y") + +region = "exterior SOL" +f = DataFile("data_limiter/BOUT.dmp.2.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [6, 7], 0, region, "inner x") +test(f[-1, 1:-1], [14, 15], 0, region, "outer x") +test(f[:, 0], [20, 21, 22, 23], 0, region, "lower y") +test(f[:, -1], [28, 29, 30, 31], 0, region, "upper y") # run with processor splitting not at the separatrix #################################################### nxpe = 2 -command = './test-communications -d data_limiter nxpe='+str(nxpe) +command = "./test-communications -d data_limiter nxpe=" + str(nxpe) # remove old outputs -shell('rm data_limiter/BOUT.dmp.*') +shell("rm data_limiter/BOUT.dmp.*") -print('Running Communications Test, nproc='+str(nxpe*nype)) +print("Running Communications Test, nproc=" + str(nxpe * nype)) -s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) -with open('run_limiter.log.'+str(nxpe), 'w') as f: +s, out = launch_safe(command, nproc=nxpe * nype, pipe=True) +with open("run_limiter.log." + str(nxpe), "w") as f: f.write(out) -region = 'interior' -f = DataFile("data_limiter/BOUT.dmp.0.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [12, 13], 0, region, 'inner x') -test(f[-1, 1:-1], [6, 7], 0, region, 'outer x') -test(f[:, 0], [13, 1, 3, 19, 20], 0, region, 'lower y') -test(f[:, -1], [12, 0, 2, 27, 28], 0, region, 'upper y') +region = "interior" +f = DataFile("data_limiter/BOUT.dmp.0.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [12, 13], 0, region, "inner x") +test(f[-1, 1:-1], [6, 7], 0, region, "outer x") +test(f[:, 0], [13, 1, 3, 19, 20], 0, region, "lower y") +test(f[:, -1], [12, 0, 2, 27, 28], 0, region, "upper y") -region = 'exterior' -f = DataFile("data_limiter/BOUT.dmp.1.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [4, 5], 0, region, 'inner x') -test(f[-1, 1:-1], [14, 15], 0, region, 'outer x') -test(f[:, 0], [19, 20, 21, 22, 23], 0, region, 'lower y') -test(f[:, -1], [27, 28, 29, 30, 31], 0, region, 'upper y') +region = "exterior" +f = DataFile("data_limiter/BOUT.dmp.1.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [4, 5], 0, region, "inner x") +test(f[-1, 1:-1], [14, 15], 0, region, "outer x") +test(f[:, 0], [19, 20, 21, 22, 23], 0, region, "lower y") +test(f[:, -1], [27, 28, 29, 30, 31], 0, region, "upper y") # run with no processor splitting in the x-direction #################################################### nxpe = 1 -command = './test-communications -d data_limiter nxpe='+str(nxpe) +command = "./test-communications -d data_limiter nxpe=" + str(nxpe) # remove old outputs -shell('rm data_limiter/BOUT.dmp.*') +shell("rm data_limiter/BOUT.dmp.*") -print('Running Communications Test, nproc='+str(nxpe*nype)) +print("Running Communications Test, nproc=" + str(nxpe * nype)) -s, out = launch_safe(command, nproc=nxpe*nype, pipe=True) -with open('run_limiter.log.'+str(nxpe), 'w') as f: +s, out = launch_safe(command, nproc=nxpe * nype, pipe=True) +with open("run_limiter.log." + str(nxpe), "w") as f: f.write(out) -region = 'all' -f = DataFile("data_limiter/BOUT.dmp.0.nc")['f'][0, :, :, 0] -test(f[0, 1:-1], [12, 13], 0, region, 'inner x') -test(f[-1, 1:-1], [14, 15], 0, region, 'outer x') -test(f[:, 0], [13, 1, 3, 19, 20, 21, 22, 23], 0, region, 'lower y') -test(f[:, -1], [12, 0, 2, 27, 28, 29, 30, 31], 0, region, 'upper y') +region = "all" +f = DataFile("data_limiter/BOUT.dmp.0.nc")["f"][0, :, :, 0] +test(f[0, 1:-1], [12, 13], 0, region, "inner x") +test(f[-1, 1:-1], [14, 15], 0, region, "outer x") +test(f[:, 0], [13, 1, 3, 19, 20, 21, 22, 23], 0, region, "lower y") +test(f[:, -1], [12, 0, 2, 27, 28, 29, 30, 31], 0, region, "upper y") # If we did not exit already, then all tests passed -print('Pass') +print("Pass") exit(0) diff --git a/tests/integrated/test-cyclic/runtest b/tests/integrated/test-cyclic/runtest index b8fc063abb..ae2bca24c7 100755 --- a/tests/integrated/test-cyclic/runtest +++ b/tests/integrated/test-cyclic/runtest @@ -8,10 +8,11 @@ # Cores: 4 from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect from sys import stdout, exit @@ -21,21 +22,21 @@ build_and_log("Cyclic Reduction test") flags = ["", "nsys=2", "nsys=5 periodic", "nsys=7 n=10"] -code = 0 # Return code -for nproc in [1,2,4]: +code = 0 # Return code +for nproc in [1, 2, 4]: cmd = "./test_cyclic" print(" %d processors...." % (nproc)) r = 0 for f in flags: - stdout.write("\tflags '"+f+"' ... ") + stdout.write("\tflags '" + f + "' ... ") shell("rm data/BOUT.dmp.* 2> err.log") # Run the case - s, out = launch_safe(cmd+" "+f, nproc=nproc, mthread=1, pipe=True) - with open("run.log."+str(nproc)+"."+str(r), "w") as f: - f.write(out) + s, out = launch_safe(cmd + " " + f, nproc=nproc, mthread=1, pipe=True) + with open("run.log." + str(nproc) + "." + str(r), "w") as f: + f.write(out) r = r + 1 diff --git a/tests/integrated/test-delp2/runtest b/tests/integrated/test-delp2/runtest index 1ea5563a87..2c684a83e1 100755 --- a/tests/integrated/test-delp2/runtest +++ b/tests/integrated/test-delp2/runtest @@ -1,20 +1,21 @@ #!/usr/bin/env python3 from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass -#requires: fftw -#cores: 4 +# requires: fftw +# cores: 4 from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect import numpy as np from sys import stdout, exit -tol = 1e-10 # Absolute tolerance +tol = 1e-10 # Absolute tolerance build_and_log("Delp2 operator test") @@ -23,47 +24,50 @@ build_and_log("Delp2 operator test") exefile = "./test_delp2" # List of settings to apply -settings = ["mxg=2 mesh:nx=36 diffusion:useFFT=true", - "mxg=1 mesh:nx=34 diffusion:useFFT=true", "mxg=2 mesh:nx=36 diffusion:useFFT=false", - "mxg=1 mesh:nx=34 diffusion:useFFT=false"] +settings = [ + "mxg=2 mesh:nx=36 diffusion:useFFT=true", + "mxg=1 mesh:nx=34 diffusion:useFFT=true", + "mxg=2 mesh:nx=36 diffusion:useFFT=false", + "mxg=1 mesh:nx=34 diffusion:useFFT=false", +] success = True for i, opts in enumerate(settings): - # Read benchmark values - print("Args: " + opts) - cmd = exefile + " " + opts - - s, out = launch_safe(cmd, nproc=1, pipe=True) - with open("run.log."+str(i)+".1", "w") as f: - f.write(out) - - n0 = collect("n", path="data",info=False) - - for nproc in [2,4]: - shell("rm data/BOUT.dmp.*.nc") - - stdout.write(" %d processor...." % (nproc)) - s, out = launch_safe(cmd, nproc=nproc, mthread=1, pipe=True) - with open("run.log."+str(i)+"."+str(nproc), "w") as f: - f.write(out) - - # Collect output data - n = collect("n", path="data",info=False) - if np.shape(n) != np.shape(n0): - print("Fail, wrong shape") - success = False - diff = np.max(np.abs(n - n0)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - else: - print("Pass") + # Read benchmark values + print("Args: " + opts) + cmd = exefile + " " + opts + + s, out = launch_safe(cmd, nproc=1, pipe=True) + with open("run.log." + str(i) + ".1", "w") as f: + f.write(out) + + n0 = collect("n", path="data", info=False) + + for nproc in [2, 4]: + shell("rm data/BOUT.dmp.*.nc") + + stdout.write(" %d processor...." % (nproc)) + s, out = launch_safe(cmd, nproc=nproc, mthread=1, pipe=True) + with open("run.log." + str(i) + "." + str(nproc), "w") as f: + f.write(out) + + # Collect output data + n = collect("n", path="data", info=False) + if np.shape(n) != np.shape(n0): + print("Fail, wrong shape") + success = False + diff = np.max(np.abs(n - n0)) + if diff > tol: + print("Fail, maximum difference = " + str(diff)) + success = False + else: + print("Pass") if success: - print(" => All Delp2 tests passed") - exit(0) + print(" => All Delp2 tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-drift-instability/runtest.py b/tests/integrated/test-drift-instability/runtest.py index b71495da1f..70cfa5d006 100755 --- a/tests/integrated/test-drift-instability/runtest.py +++ b/tests/integrated/test-drift-instability/runtest.py @@ -11,7 +11,7 @@ from math import isnan -nproc = 2 # Number of processors to run on +nproc = 2 # Number of processors to run on # Relative tolerance in frequency and growth rate omega_tol = 1e-2 @@ -26,37 +26,41 @@ import numpy as np from sys import exit, argv -nthreads=1 +nthreads = 1 build_and_log("resistive drift instability test") -zlist = [2, 32, 256] # Just test a few +zlist = [2, 32, 256] # Just test a few # Values from revision c4f7ec92786b333a5502c5256b5e602ba867090f # 26th Oct 2011 -omega_orig = {1:1.00819536681, - 2:0.975756752742, - 4:0.888269347989, - 8:0.741253948437, - 16:0.574003058717, - 32:0.428644078148, #0.430745728591, Changed 25th April 2014, revision fd032da - 64:0.336073734175, - 128:0.2208085, - 256:0.155890075514} #0.156853396108} Changed 25th April 2014 -gamma_orig = {1:0.0784576199501, - 2:0.145174416274, #0.143251663975, Changed 25th April 2014, revision fd032da - 4:0.226979299615, - 8:0.28632661549, - 16:0.295998650267, - 32:0.271288568509, - 64:0.222344013151, - 128:0.1716229, - 256:0.12957680451} #0.130220286897} Changed 25th April 2014 +omega_orig = { + 1: 1.00819536681, + 2: 0.975756752742, + 4: 0.888269347989, + 8: 0.741253948437, + 16: 0.574003058717, + 32: 0.428644078148, # 0.430745728591, Changed 25th April 2014, revision fd032da + 64: 0.336073734175, + 128: 0.2208085, + 256: 0.155890075514, +} # 0.156853396108} Changed 25th April 2014 +gamma_orig = { + 1: 0.0784576199501, + 2: 0.145174416274, # 0.143251663975, Changed 25th April 2014, revision fd032da + 4: 0.226979299615, + 8: 0.28632661549, + 16: 0.295998650267, + 32: 0.271288568509, + 64: 0.222344013151, + 128: 0.1716229, + 256: 0.12957680451, +} # 0.130220286897} Changed 25th April 2014 # Import the grid file grid = file_import("uedge.grd_std.cdl") -code = 0 # Return code +code = 0 # Return code for zeff in zlist: # Create the input file, setting Zeff timestep = 5e3 @@ -70,10 +74,13 @@ print("Running drift instability test, zeff = ", zeff) # Run the case - s, out = launch_safe("./2fluid 2fluid:Zeff={} timestep={}" - .format(zeff, timestep), - nproc=nproc, mthread=nthreads, pipe=True) - f = open("run.log."+str(zeff), "w") + s, out = launch_safe( + "./2fluid 2fluid:Zeff={} timestep={}".format(zeff, timestep), + nproc=nproc, + mthread=nthreads, + pipe=True, + ) + f = open("run.log." + str(zeff), "w") f.write(out) f.close() @@ -81,10 +88,10 @@ Ni = collect("Ni", path="data", xind=2, yind=20, info=False) phi = collect("phi", path="data", xind=2, yind=20, info=False) - zmax = collect("ZMAX", path="data", info=False) - rho_s = collect("rho_s", path="data", info=False) - wci = collect("wci", path="data", info=False) - t_array = collect("t_array", path="data", info=False) + zmax = collect("ZMAX", path="data", info=False) + rho_s = collect("rho_s", path="data", info=False) + wci = collect("wci", path="data", info=False) + t_array = collect("t_array", path="data", info=False) dims = np.shape(Ni) nt = dims[0] @@ -92,34 +99,42 @@ nz = dims[3] ##### Calculate geometric and physical quantities - lZeta = 1e2*zmax*2*np.pi*grid['R0'] # toroidal range [cm] - lbNorm = lZeta*(grid['Bpxy'][0, ny // 2] / grid['Bxy'][0, ny // 2]) # binormal coord range [cm] - zPerp = lbNorm*np.arange(nz)/(nz-1) # binormal coordinate [cm] + lZeta = 1e2 * zmax * 2 * np.pi * grid["R0"] # toroidal range [cm] + lbNorm = lZeta * ( + grid["Bpxy"][0, ny // 2] / grid["Bxy"][0, ny // 2] + ) # binormal coord range [cm] + zPerp = lbNorm * np.arange(nz) / (nz - 1) # binormal coordinate [cm] - cLight = 3e10 # speed of light [cm/s] - vTe = 4.2e7*np.sqrt(grid['Te_x']) # electron thermal speed [cm/s] - kperp = 2*np.pi/lbNorm # binormal wavenumber, [cm-1] - wce = 1.76e7*1e4*grid['bmag'] # electron cyclotron frequency, [rad/s] + cLight = 3e10 # speed of light [cm/s] + vTe = 4.2e7 * np.sqrt(grid["Te_x"]) # electron thermal speed [cm/s] + kperp = 2 * np.pi / lbNorm # binormal wavenumber, [cm-1] + wce = 1.76e7 * 1e4 * grid["bmag"] # electron cyclotron frequency, [rad/s] # Ni scale length [cm] - Ln = np.mean(np.abs(grid['Ni0'][:, ny // 2] / - deriv(grid['Rxy'][:, ny // 2]*1e2, grid['Ni0'][:, ny // 2]))) - - vPe = (vTe)**2 / (wce*Ln) # electron diamagnetic drift speed [cm/s] - wstar = vPe*kperp - - logLam = 24. - np.log(np.sqrt(grid['Ni_x']*1e14 / grid['Te_x'])) - nuei = zeff*2.91e-6*(grid['Ni_x']*1e14)*logLam/(grid['Te_x'])**1.5 - #wci=9.58e3*(1./d.AA)*1e4*du.Bmag - - lpar = np.sum(((grid['Bxy']/grid['Bpxy']))*grid['dlthe']) / grid['nx'] # [m], average over flux surfaces - kpar = 2*np.pi/(1e2*lpar) # cm-1 - spar = (kpar / kperp)**2 * wci * wce / (0.51 * nuei) # [1/s] + Ln = np.mean( + np.abs( + grid["Ni0"][:, ny // 2] + / deriv(grid["Rxy"][:, ny // 2] * 1e2, grid["Ni0"][:, ny // 2]) + ) + ) + + vPe = (vTe) ** 2 / (wce * Ln) # electron diamagnetic drift speed [cm/s] + wstar = vPe * kperp + + logLam = 24.0 - np.log(np.sqrt(grid["Ni_x"] * 1e14 / grid["Te_x"])) + nuei = zeff * 2.91e-6 * (grid["Ni_x"] * 1e14) * logLam / (grid["Te_x"]) ** 1.5 + # wci=9.58e3*(1./d.AA)*1e4*du.Bmag + + lpar = ( + np.sum(((grid["Bxy"] / grid["Bpxy"])) * grid["dlthe"]) / grid["nx"] + ) # [m], average over flux surfaces + kpar = 2 * np.pi / (1e2 * lpar) # cm-1 + spar = (kpar / kperp) ** 2 * wci * wce / (0.51 * nuei) # [1/s] sparn = spar / wstar - wpe = 5.64e4*np.sqrt(1e14*grid['Ni_x']) # electron plasma frequency, [rad/s] - mu = (cLight*kperp/wpe)**2 - sperp = (0.51 * nuei) * mu # [1/s] + wpe = 5.64e4 * np.sqrt(1e14 * grid["Ni_x"]) # electron plasma frequency, [rad/s] + mu = (cLight * kperp / wpe) ** 2 + sperp = (0.51 * nuei) * mu # [1/s] ##### Analyse data @@ -129,46 +144,46 @@ maxVal = np.zeros(nt - nt0) # Track the motion of the peak to infer phase velocity - peak = np.zeros(nt-nt0) + peak = np.zeros(nt - nt0) for t in range(nt0, nt): - ind = np.argmax(Ni[t,0,0,:]) # Index of maximum value - maxVal[t-nt0] = Ni[t,0,0,ind] # Store maximum value (for gamma) + ind = np.argmax(Ni[t, 0, 0, :]) # Index of maximum value + maxVal[t - nt0] = Ni[t, 0, 0, ind] # Store maximum value (for gamma) # Refine maximum location by fitting a quadratic through 3 points - c = Ni[t,0,0,ind] - m = Ni[t,0,0,(ind-1) % nz] # Python '%' always positive - p = Ni[t,0,0,(ind+1) % nz] + c = Ni[t, 0, 0, ind] + m = Ni[t, 0, 0, (ind - 1) % nz] # Python '%' always positive + p = Ni[t, 0, 0, (ind + 1) % nz] # Fit y = c + ax + bx**2 - a = 0.5*(p-m) + a = 0.5 * (p - m) b = p - (c + a) - peak[t-nt0] = ind - 0.5*a/b # Maximum + peak[t - nt0] = ind - 0.5 * a / b # Maximum # Check for periodic recurrence if peak[1] > peak[0]: # Increasing; watch for wrapping around the top - for i in range(nt-nt0): - if peak[i] < peak[i-1]: - peak[i:(nt-nt0)] = peak[i:(nt-nt0)] + nz + for i in range(nt - nt0): + if peak[i] < peak[i - 1]: + peak[i : (nt - nt0)] = peak[i : (nt - nt0)] + nz else: # Decreasing; watch for wrapping around the bottom - for i in range(nt-nt0): - if peak[i] > peak[i-1]: - peak[i:(nt-nt0)] = peak[i:(nt-nt0)] - nz + for i in range(nt - nt0): + if peak[i] > peak[i - 1]: + peak[i : (nt - nt0)] = peak[i : (nt - nt0)] - nz # Fit y = a + gamma*x a, gamma = linear_regression(t_array[nt0:nt] / wci, np.log(maxVal)) # Get phase velocity - a, Vphase = linear_regression(t_array[nt0:nt] / wci, peak*lbNorm/(nz-1)) + a, Vphase = linear_regression(t_array[nt0:nt] / wci, peak * lbNorm / (nz - 1)) # Calculate normalised quantities - omega = np.abs(Vphase)*kperp/wstar + omega = np.abs(Vphase) * kperp / wstar gamma = gamma / wstar # Calculate analytic result - t = 0.5*( np.sqrt(sparn**4 + 16*sparn**2) - sparn**2 ) - wr = 0.5*np.sqrt(t) - wi = sparn / np.sqrt(t) - 0.5*sparn + t = 0.5 * (np.sqrt(sparn ** 4 + 16 * sparn ** 2) - sparn ** 2) + wr = 0.5 * np.sqrt(t) + wi = sparn / np.sqrt(t) - 0.5 * sparn try: origr = omega_orig[zeff] @@ -182,12 +197,32 @@ omegadiff = None gammadiff = None - print(" Normalised omega = ", omega, " analytic = ", wr, " original = ", origr, " (", 100.*omegadiff,"%)") - print(" Normalised gamma = ", gamma, " analytic = ", wi, " original = ", origi, " (",100.*gammadiff,"%)") + print( + " Normalised omega = ", + omega, + " analytic = ", + wr, + " original = ", + origr, + " (", + 100.0 * omegadiff, + "%)", + ) + print( + " Normalised gamma = ", + gamma, + " analytic = ", + wi, + " original = ", + origi, + " (", + 100.0 * gammadiff, + "%)", + ) if omegadiff != None: if isnan(omegadiff) or (omegadiff > omega_tol) or (gammadiff > gamma_tol): - code = 1 # Failed test + code = 1 # Failed test print(" => FAILED") else: print(" => PASSED") diff --git a/tests/integrated/test-fieldfactory/runtest b/tests/integrated/test-fieldfactory/runtest index 5c2283a8ca..2261e44c57 100755 --- a/tests/integrated/test-fieldfactory/runtest +++ b/tests/integrated/test-fieldfactory/runtest @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# +# # Run the test, compare results against the benchmark # @@ -10,12 +10,12 @@ from __future__ import print_function try: - from builtins import str + from builtins import str except: - pass + pass -vars = ['a', 'b', 'c', 'd'] # Variables to compare -tol = 1e-10 # Absolute tolerance +vars = ["a", "b", "c", "d"] # Variables to compare +tol = 1e-10 # Absolute tolerance from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -29,39 +29,39 @@ build_and_log("FieldFactory test") print("Reading benchmark data") bmk = {} for v in vars: - bmk[v] = collect(v, path="data", prefix="benchmark", info=False) + bmk[v] = collect(v, path="data", prefix="benchmark", info=False) print("Running FieldFactory test") success = True -for nproc in [1,2,4]: - cmd = "./test_fieldfactory" - - shell("rm data/BOUT.dmp.*.nc") +for nproc in [1, 2, 4]: + cmd = "./test_fieldfactory" + + shell("rm data/BOUT.dmp.*.nc") - print(" %d processor...." % (nproc)) - s, out = launch_safe(cmd, nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) + print(" %d processor...." % (nproc)) + s, out = launch_safe(cmd, nproc=nproc, pipe=True) + with open("run.log." + str(nproc), "w") as f: + f.write(out) - # Collect output data - for v in vars: - stdout.write(" Checking variable "+v+" ... ") - result = collect(v, path="data", info=False) - # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - print("Fail, wrong shape") - success = False - diff = np.max(np.abs(bmk[v] - result)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - else: - print("Pass") + # Collect output data + for v in vars: + stdout.write(" Checking variable " + v + " ... ") + result = collect(v, path="data", info=False) + # Compare benchmark and output + if np.shape(bmk[v]) != np.shape(result): + print("Fail, wrong shape") + success = False + diff = np.max(np.abs(bmk[v] - result)) + if diff > tol: + print("Fail, maximum difference = " + str(diff)) + success = False + else: + print("Pass") if success: - print(" => All FieldFactory tests passed") - exit(0) + print(" => All FieldFactory tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-fieldgroupComm/runtest b/tests/integrated/test-fieldgroupComm/runtest index 3ae8c5c648..ca6d5f89f3 100755 --- a/tests/integrated/test-fieldgroupComm/runtest +++ b/tests/integrated/test-fieldgroupComm/runtest @@ -11,10 +11,11 @@ # Variables to compare from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -23,10 +24,10 @@ from sys import stdout, exit # Good chance we'll do 0.0/0.0, which generates a warning # Ignore this warning -seterr(divide='ignore', invalid='ignore') +seterr(divide="ignore", invalid="ignore") -varCorrect="fld1" -varsComp = ["fld2", "fld3"] +varCorrect = "fld1" +varsComp = ["fld2", "fld3"] name = "FieldGroup comm" exeName = "test_fieldgroupcomm" tol = 1e-10 # Relative tolerance @@ -37,40 +38,39 @@ build_and_log("{nm} test".format(nm=name)) print("Running {nm} test".format(nm=name)) success = True -for nproc in [1,2,4]: - nxpe = 1 - if nproc > 2: - nxpe = 2 - - cmd = "./{exe} ".format(exe=exeName) - - shell("rm data/BOUT.dmp.*.nc") - - print(" %d processors ...." % (nproc)) - s, out = launch_safe(cmd, nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) - - #Analyse result - #/"Correct" answer - f1 = collect(varCorrect, path="data", info=False) - f1max = abs(f1).max() - #/Two different fields which should be identical to correct - err=[] - for v in varsComp: - tmp = collect(v, path="data", info=False) - err.append(abs((f1-tmp)).max()/f1max) - - for i,e in enumerate(err): - if e>tol: - print("Fail, in {i}th comparison relative error is {re}".format(i=i,re=e)) - success = False - +for nproc in [1, 2, 4]: + nxpe = 1 + if nproc > 2: + nxpe = 2 + + cmd = "./{exe} ".format(exe=exeName) + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processors ...." % (nproc)) + s, out = launch_safe(cmd, nproc=nproc, pipe=True) + with open("run.log." + str(nproc), "w") as f: + f.write(out) + + # Analyse result + # /"Correct" answer + f1 = collect(varCorrect, path="data", info=False) + f1max = abs(f1).max() + # /Two different fields which should be identical to correct + err = [] + for v in varsComp: + tmp = collect(v, path="data", info=False) + err.append(abs((f1 - tmp)).max() / f1max) + + for i, e in enumerate(err): + if e > tol: + print("Fail, in {i}th comparison relative error is {re}".format(i=i, re=e)) + success = False + if success: - print(" => All {nm} passed".format(nm=name)) - exit(0) + print(" => All {nm} passed".format(nm=name)) + exit(0) else: - print(" => Some failed tests") - exit(1) - + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-griddata-yboundary-guards/runtest b/tests/integrated/test-griddata-yboundary-guards/runtest index 276bc6e286..79adae9759 100755 --- a/tests/integrated/test-griddata-yboundary-guards/runtest +++ b/tests/integrated/test-griddata-yboundary-guards/runtest @@ -14,7 +14,7 @@ build_and_log("griddata test") nx = 4 ny = 24 -blocksize = ny/6 +blocksize = ny / 6 # first generate some grid files to test # double null case: @@ -22,172 +22,180 @@ for n_yguards in [0, 1, 2]: datadir = "data-doublenull-" + str(n_yguards) gridname = "grid-doublenull-" + str(n_yguards) + ".nc" - with Dataset(os.path.join(datadir,gridname), 'w') as gridfile: - gridfile.createDimension('x', nx) - gridfile.createDimension('y', ny + 4*n_yguards) + with Dataset(os.path.join(datadir, gridname), "w") as gridfile: + gridfile.createDimension("x", nx) + gridfile.createDimension("y", ny + 4 * n_yguards) - gridfile.createVariable('nx', numpy.int32) - gridfile['nx'][...] = nx + gridfile.createVariable("nx", numpy.int32) + gridfile["nx"][...] = nx - gridfile.createVariable('ny', numpy.int32) - gridfile['ny'][...] = ny + gridfile.createVariable("ny", numpy.int32) + gridfile["ny"][...] = ny - gridfile.createVariable('y_boundary_guards', numpy.int32) - gridfile['y_boundary_guards'][...] = n_yguards + gridfile.createVariable("y_boundary_guards", numpy.int32) + gridfile["y_boundary_guards"][...] = n_yguards - gridfile.createVariable('MXG', numpy.int32) - gridfile['MXG'][...] = 1 + gridfile.createVariable("MXG", numpy.int32) + gridfile["MXG"][...] = 1 - gridfile.createVariable('MYG', numpy.int32) - gridfile['MYG'][...] = 2 if n_yguards==0 else n_yguards + gridfile.createVariable("MYG", numpy.int32) + gridfile["MYG"][...] = 2 if n_yguards == 0 else n_yguards - gridfile.createVariable('ixseps1', numpy.int32) - gridfile['ixseps1'][...] = nx//2 - 1 + gridfile.createVariable("ixseps1", numpy.int32) + gridfile["ixseps1"][...] = nx // 2 - 1 - gridfile.createVariable('ixseps2', numpy.int32) - gridfile['ixseps2'][...] = nx//2 - 1 + gridfile.createVariable("ixseps2", numpy.int32) + gridfile["ixseps2"][...] = nx // 2 - 1 - gridfile.createVariable('jyseps1_1', numpy.int32) - gridfile['jyseps1_1'][...] = blocksize - 1 + gridfile.createVariable("jyseps1_1", numpy.int32) + gridfile["jyseps1_1"][...] = blocksize - 1 - gridfile.createVariable('jyseps2_1', numpy.int32) - gridfile['jyseps2_1'][...] = 2*blocksize - 1 + gridfile.createVariable("jyseps2_1", numpy.int32) + gridfile["jyseps2_1"][...] = 2 * blocksize - 1 - gridfile.createVariable('ny_inner', numpy.int32) - gridfile['ny_inner'][...] = 3*blocksize + gridfile.createVariable("ny_inner", numpy.int32) + gridfile["ny_inner"][...] = 3 * blocksize - gridfile.createVariable('jyseps1_2', numpy.int32) - gridfile['jyseps1_2'][...] = 4*blocksize - 1 + gridfile.createVariable("jyseps1_2", numpy.int32) + gridfile["jyseps1_2"][...] = 4 * blocksize - 1 - gridfile.createVariable('jyseps2_2', numpy.int32) - gridfile['jyseps2_2'][...] = 5*blocksize - 1 + gridfile.createVariable("jyseps2_2", numpy.int32) + gridfile["jyseps2_2"][...] = 5 * blocksize - 1 - testdata = numpy.zeros([nx, ny + 4*n_yguards]) - testdata[:,:] = numpy.arange(ny + 4*n_yguards)[numpy.newaxis,:] - gridfile.createVariable('test', float, ('x', 'y')) - gridfile['test'][...] = testdata + testdata = numpy.zeros([nx, ny + 4 * n_yguards]) + testdata[:, :] = numpy.arange(ny + 4 * n_yguards)[numpy.newaxis, :] + gridfile.createVariable("test", float, ("x", "y")) + gridfile["test"][...] = testdata # grid files for single-null: for n_yguards in [0, 1, 2]: datadir = "data-singlenull-" + str(n_yguards) gridname = "grid-singlenull-" + str(n_yguards) + ".nc" - with Dataset(os.path.join(datadir,gridname), 'w') as gridfile: - gridfile.createDimension('x', nx) - gridfile.createDimension('y', ny + 2*n_yguards) + with Dataset(os.path.join(datadir, gridname), "w") as gridfile: + gridfile.createDimension("x", nx) + gridfile.createDimension("y", ny + 2 * n_yguards) - gridfile.createVariable('nx', numpy.int32) - gridfile['nx'][...] = nx + gridfile.createVariable("nx", numpy.int32) + gridfile["nx"][...] = nx - gridfile.createVariable('ny', numpy.int32) - gridfile['ny'][...] = ny + gridfile.createVariable("ny", numpy.int32) + gridfile["ny"][...] = ny - gridfile.createVariable('y_boundary_guards', numpy.int32) - gridfile['y_boundary_guards'][...] = n_yguards + gridfile.createVariable("y_boundary_guards", numpy.int32) + gridfile["y_boundary_guards"][...] = n_yguards - gridfile.createVariable('MXG', numpy.int32) - gridfile['MXG'][...] = 1 + gridfile.createVariable("MXG", numpy.int32) + gridfile["MXG"][...] = 1 - gridfile.createVariable('MYG', numpy.int32) - gridfile['MYG'][...] = 2 if n_yguards==0 else n_yguards + gridfile.createVariable("MYG", numpy.int32) + gridfile["MYG"][...] = 2 if n_yguards == 0 else n_yguards - gridfile.createVariable('ixseps1', numpy.int32) - gridfile['ixseps1'][...] = nx//2 - 1 + gridfile.createVariable("ixseps1", numpy.int32) + gridfile["ixseps1"][...] = nx // 2 - 1 - gridfile.createVariable('ixseps2', numpy.int32) - gridfile['ixseps2'][...] = nx//2 - 1 + gridfile.createVariable("ixseps2", numpy.int32) + gridfile["ixseps2"][...] = nx // 2 - 1 - gridfile.createVariable('jyseps1_1', numpy.int32) - gridfile['jyseps1_1'][...] = blocksize - 1 + gridfile.createVariable("jyseps1_1", numpy.int32) + gridfile["jyseps1_1"][...] = blocksize - 1 - gridfile.createVariable('jyseps2_1', numpy.int32) - gridfile['jyseps2_1'][...] = ny//2 + gridfile.createVariable("jyseps2_1", numpy.int32) + gridfile["jyseps2_1"][...] = ny // 2 - gridfile.createVariable('ny_inner', numpy.int32) - gridfile['ny_inner'][...] = ny//2 + gridfile.createVariable("ny_inner", numpy.int32) + gridfile["ny_inner"][...] = ny // 2 - gridfile.createVariable('jyseps1_2', numpy.int32) - gridfile['jyseps1_2'][...] = ny//2 + gridfile.createVariable("jyseps1_2", numpy.int32) + gridfile["jyseps1_2"][...] = ny // 2 - gridfile.createVariable('jyseps2_2', numpy.int32) - gridfile['jyseps2_2'][...] = 5*blocksize - 1 + gridfile.createVariable("jyseps2_2", numpy.int32) + gridfile["jyseps2_2"][...] = 5 * blocksize - 1 - testdata = numpy.zeros([nx, ny + 2*n_yguards]) - testdata[:,:] = numpy.arange(ny + 2*n_yguards)[numpy.newaxis,:] - gridfile.createVariable('test', float, ('x', 'y')) - gridfile['test'][...] = testdata + testdata = numpy.zeros([nx, ny + 2 * n_yguards]) + testdata[:, :] = numpy.arange(ny + 2 * n_yguards)[numpy.newaxis, :] + gridfile.createVariable("test", float, ("x", "y")) + gridfile["test"][...] = testdata for nproc in [6]: - stdout.write("Checking %d processors ... " % (nproc)) - - shell("rm ./data*/BOUT.dmp.*.nc run.log.*") - - success = True - - # double null tests - for n_yguards in [0, 1, 2]: - datadir = "data-doublenull-" + str(n_yguards) - - s, out = launch_safe("./test_griddata -d " + datadir, nproc=nproc, pipe=True) - - with open("run.log.doublenull."+str(nproc), "a") as f: - f.write(out) - - testfield = collect("test", path=datadir, info=False, yguards=True) - - if n_yguards == 0: - # output has 2 y-guard cells, but grid file did not - myg = 2 - checkfield = list(numpy.zeros(myg)) - checkfield += list(numpy.arange(ny//2)) - checkfield += list(numpy.arange(ny//2) + checkfield[-1] + 1) - checkfield += list(numpy.zeros(myg) + checkfield[-1]) - else: - checkfield = [] - checkfield += list(numpy.arange(n_yguards)) - checkfield += list(numpy.arange(ny//2) + checkfield[-1] + 1) - checkfield += list(numpy.arange(ny//2) + checkfield[-1] + 1 + 2*n_yguards) - checkfield += list(numpy.arange(n_yguards) + checkfield[-1] + 1) - checkfield = numpy.array(checkfield) - - # Test value of testfield - if numpy.max(numpy.abs(testfield - checkfield)) > 1e-13: - print("Failed: testfield does not match in doublenull case for n_yguards="+str(n_yguards)) - success = False - - # single null tests - for n_yguards in [0, 1, 2]: - datadir = "data-singlenull-" + str(n_yguards) - - s, out = launch_safe("./test_griddata -d " + datadir, nproc=nproc, pipe=True) - - with open("run.log.singlenull."+str(nproc), "a") as f: - f.write(out) - - testfield = collect("test", path=datadir, info=False, yguards=True) - - if n_yguards == 0: - # output has 2 y-guard cells, but grid file did not - myg = 2 - checkfield = list(numpy.zeros(myg)) - checkfield += list(numpy.arange(ny)) - checkfield += list(numpy.zeros(myg) + checkfield[-1]) - else: - checkfield = [] - checkfield += list(numpy.arange(n_yguards)) - checkfield += list(numpy.arange(ny) + checkfield[-1] + 1) - checkfield += list(numpy.arange(n_yguards) + checkfield[-1] + 1) - checkfield = numpy.array(checkfield) - - # Test value of testfield - if numpy.max(numpy.abs(testfield - checkfield)) > 1e-13: - print("Failed: testfield does not match in doublenull case for n_yguards="+str(n_yguards)) - success = False - - if not success: - exit(1) - else: - print("Passed") + stdout.write("Checking %d processors ... " % (nproc)) + + shell("rm ./data*/BOUT.dmp.*.nc run.log.*") + + success = True + + # double null tests + for n_yguards in [0, 1, 2]: + datadir = "data-doublenull-" + str(n_yguards) + + s, out = launch_safe("./test_griddata -d " + datadir, nproc=nproc, pipe=True) + + with open("run.log.doublenull." + str(nproc), "a") as f: + f.write(out) + + testfield = collect("test", path=datadir, info=False, yguards=True) + + if n_yguards == 0: + # output has 2 y-guard cells, but grid file did not + myg = 2 + checkfield = list(numpy.zeros(myg)) + checkfield += list(numpy.arange(ny // 2)) + checkfield += list(numpy.arange(ny // 2) + checkfield[-1] + 1) + checkfield += list(numpy.zeros(myg) + checkfield[-1]) + else: + checkfield = [] + checkfield += list(numpy.arange(n_yguards)) + checkfield += list(numpy.arange(ny // 2) + checkfield[-1] + 1) + checkfield += list( + numpy.arange(ny // 2) + checkfield[-1] + 1 + 2 * n_yguards + ) + checkfield += list(numpy.arange(n_yguards) + checkfield[-1] + 1) + checkfield = numpy.array(checkfield) + + # Test value of testfield + if numpy.max(numpy.abs(testfield - checkfield)) > 1e-13: + print( + "Failed: testfield does not match in doublenull case for n_yguards=" + + str(n_yguards) + ) + success = False + + # single null tests + for n_yguards in [0, 1, 2]: + datadir = "data-singlenull-" + str(n_yguards) + + s, out = launch_safe("./test_griddata -d " + datadir, nproc=nproc, pipe=True) + + with open("run.log.singlenull." + str(nproc), "a") as f: + f.write(out) + + testfield = collect("test", path=datadir, info=False, yguards=True) + + if n_yguards == 0: + # output has 2 y-guard cells, but grid file did not + myg = 2 + checkfield = list(numpy.zeros(myg)) + checkfield += list(numpy.arange(ny)) + checkfield += list(numpy.zeros(myg) + checkfield[-1]) + else: + checkfield = [] + checkfield += list(numpy.arange(n_yguards)) + checkfield += list(numpy.arange(ny) + checkfield[-1] + 1) + checkfield += list(numpy.arange(n_yguards) + checkfield[-1] + 1) + checkfield = numpy.array(checkfield) + + # Test value of testfield + if numpy.max(numpy.abs(testfield - checkfield)) > 1e-13: + print( + "Failed: testfield does not match in doublenull case for n_yguards=" + + str(n_yguards) + ) + success = False + + if not success: + exit(1) + else: + print("Passed") exit(0) diff --git a/tests/integrated/test-griddata/runtest b/tests/integrated/test-griddata/runtest index 47b502538c..1c57bf5be7 100755 --- a/tests/integrated/test-griddata/runtest +++ b/tests/integrated/test-griddata/runtest @@ -2,10 +2,11 @@ from __future__ import print_function from __future__ import division + try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -16,33 +17,33 @@ from sys import stdout, exit build_and_log("griddata test") for nproc in [1]: - stdout.write("Checking %d processors ... " % (nproc)) + stdout.write("Checking %d processors ... " % (nproc)) - shell("rm ./data*nc") - s, out = launch_safe("./test_griddata -d screw", nproc=nproc, pipe=True) + shell("rm ./data*nc") + s, out = launch_safe("./test_griddata -d screw", nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) + with open("run.log." + str(nproc), "w") as f: + f.write(out) - prefix = "data" - Rxy = collect("Rxy", prefix=prefix, info=False) - Bpxy = collect("Bpxy", prefix=prefix, info=False) - dx = collect("dx", prefix=prefix, info=False) + prefix = "data" + Rxy = collect("Rxy", prefix=prefix, info=False) + Bpxy = collect("Bpxy", prefix=prefix, info=False) + dx = collect("dx", prefix=prefix, info=False) - nx,ny = Rxy.shape + nx, ny = Rxy.shape - #Handle 3D metric case - if len(dx.shape) == 3: - dx = dx[:,:,0] + # Handle 3D metric case + if len(dx.shape) == 3: + dx = dx[:, :, 0] - rwidth = 0.4 - dr = float(rwidth) / nx + rwidth = 0.4 + dr = float(rwidth) / nx - # Test value of dx - if not np.allclose(dx, dr*Bpxy*Rxy, atol = 1e-7): - print("Failed: dx does not match") - exit(1) + # Test value of dx + if not np.allclose(dx, dr * Bpxy * Rxy, atol=1e-7): + print("Failed: dx does not match") + exit(1) - print("Passed") + print("Passed") exit(0) diff --git a/tests/integrated/test-gyro/runtest b/tests/integrated/test-gyro/runtest index f74f1cda7e..22c5d0c6af 100755 --- a/tests/integrated/test-gyro/runtest +++ b/tests/integrated/test-gyro/runtest @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -#requires: not metric_3d +# requires: not metric_3d -# +# # Run the test, compare results against the benchmark # @@ -11,14 +11,15 @@ # Variables to compare from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass -vars = ['pade1', 'pade2'] - -tol = 1e-10 # Absolute tolerance +vars = ["pade1", "pade2"] + +tol = 1e-10 # Absolute tolerance from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -32,44 +33,43 @@ build_and_log("Gyro-average inversion test") print("Reading benchmark data") bmk = {} for v in vars: - bmk[v] = collect(v, path="data", prefix="benchmark", info=False, xguards=False) + bmk[v] = collect(v, path="data", prefix="benchmark", info=False, xguards=False) print("Running Gyro-average inversion test") success = True -for nproc in [1,2,4]: - nxpe = 1 - if nproc > 2: - nxpe = 2 - - cmd = "./test_gyro nxpe=" + str(nxpe) - - shell("rm data/BOUT.dmp.*.nc") - - print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) - s, out = launch_safe(cmd, nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) - - # Collect output data - for v in vars: - stdout.write(" Checking variable "+v+" ... ") - result = collect(v, path="data", info=False, xguards=False) - # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - print("Fail, wrong shape") - success = False - diff = np.max(np.abs(bmk[v] - result)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - else: - print("Pass") +for nproc in [1, 2, 4]: + nxpe = 1 + if nproc > 2: + nxpe = 2 + + cmd = "./test_gyro nxpe=" + str(nxpe) + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) + s, out = launch_safe(cmd, nproc=nproc, pipe=True) + with open("run.log." + str(nproc), "w") as f: + f.write(out) + + # Collect output data + for v in vars: + stdout.write(" Checking variable " + v + " ... ") + result = collect(v, path="data", info=False, xguards=False) + # Compare benchmark and output + if np.shape(bmk[v]) != np.shape(result): + print("Fail, wrong shape") + success = False + diff = np.max(np.abs(bmk[v] - result)) + if diff > tol: + print("Fail, maximum difference = " + str(diff)) + success = False + else: + print("Pass") if success: - print(" => All Gyro-average tests passed") - exit(0) + print(" => All Gyro-average tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) - + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-initial/runtest b/tests/integrated/test-initial/runtest index c3f8df60dc..37aa02d162 100755 --- a/tests/integrated/test-initial/runtest +++ b/tests/integrated/test-initial/runtest @@ -11,9 +11,9 @@ from scipy.special import erf import numpy as np import os -#requires not make -#requires scipy -#cores: 4 +# requires not make +# requires scipy +# cores: 4 ######################################## # Implementations of BOUT++ functions @@ -34,7 +34,7 @@ def genRand(seed): seed each time """ # Make sure seed is - if(seed < 0.0): + if seed < 0.0: seed *= -1 # Round the seed to get the number of iterations @@ -43,11 +43,11 @@ def genRand(seed): # Start x between 0 and 1 A = 0.01 B = 1.23456789 - x = (A + np.mod(seed, B)) / (B + 2.*A) + x = (A + np.mod(seed, B)) / (B + 2.0 * A) # Iterate logistic map for i in range(niter): - x = 3.99 * x * (1. - x) + x = 3.99 * x * (1.0 - x) return x @@ -63,7 +63,7 @@ def gauss(x, width=1.0): """ Normalised gaussian """ - return np.exp(-x**2/(2*width**2)) / np.sqrt(2*np.pi) + return np.exp(-(x ** 2) / (2 * width ** 2)) / np.sqrt(2 * np.pi) def mixmode(x, seed=0.5): @@ -72,9 +72,8 @@ def mixmode(x, seed=0.5): """ result = 0.0 for i in range(14): - phase = np.pi * (2.*genRand(seed + i) - 1.) - result += ((1./(1. + np.abs(i-4.))**2) * - np.cos(i * x + phase)) + phase = np.pi * (2.0 * genRand(seed + i) - 1.0) + result += (1.0 / (1.0 + np.abs(i - 4.0)) ** 2) * np.cos(i * x + phase) return result @@ -89,8 +88,10 @@ def tanhhat(x, width, centre, steepness): """ BOUT++ TanhHat function """ - return 0.5*(np.tanh( steepness * (x - (centre - width/2.))) + - np.tanh(-steepness * (x - (centre + width/2.)))) + return 0.5 * ( + np.tanh(steepness * (x - (centre - width / 2.0))) + + np.tanh(-steepness * (x - (centre + width / 2.0))) + ) def atan(x, y=None): @@ -163,10 +164,10 @@ inputfile = os.path.join(datadir, "BOUT.inp") # Read the input file config = configparser.ConfigParser() with open(inputfile, "r") as f: - config.read_file(itertools.chain(['[global]'], f), source=inputfile) + config.read_file(itertools.chain(["[global]"], f), source=inputfile) # Find the variables that have a "function" option -varlist = [key for key, values in config.items() if 'function' in values] +varlist = [key for key, values in config.items() if "function" in values] # Remove the coordinate arrays for coord in ["var_x", "var_y", "var_z"]: @@ -192,10 +193,14 @@ for nproc in nprocs: # Evaluate the functions for var in varlist: - function = config[var]['function'] + function = config[var]["function"] function = function.replace("^", "**") if ":" in function: - print("{} contains reference to variable - not possible to resolve at this time".format(var)) + print( + "{} contains reference to variable - not possible to resolve at this time".format( + var + ) + ) continue try: analytic = eval(function) @@ -203,26 +208,32 @@ for nproc in nprocs: print("{} not implemented, skipping".format(err.args[0])) else: data = collect(var, xguards=True, yguards=True, path=datadir, info=False) - E2 = np.sqrt(np.mean((analytic - data)**2)) + E2 = np.sqrt(np.mean((analytic - data) ** 2)) if E2 < tolerance: success_string = "PASS" else: - if ( var == "mixmode" or var == "mixmode_seed" ) and E2 < 1e-3: + if (var == "mixmode" or var == "mixmode_seed") and E2 < 1e-3: import platform - arch=platform.machine() - if arch=='i686': + + arch = platform.machine() + if arch == "i686": # This can happen due tue excess precision e.g. on X87 architecture success_string = "WARNING" else: - print("This should only happen in i686 with an x87 math architecture.") - print("We detected however an %s architecture."%arch) + print( + "This should only happen in i686 with an x87 math architecture." + ) + print("We detected however an %s architecture." % arch) success_string = "FAIL" success = False else: success_string = "FAIL" success = False - print("\tChecking {var:<12}: l-2: {err:.4e} ... {success}".format(var=var, err=E2, - success=success_string)) + print( + "\tChecking {var:<12}: l-2: {err:.4e} ... {success}".format( + var=var, err=E2, success=success_string + ) + ) if success: print(" => All tests passed") diff --git a/tests/integrated/test-interchange-instability/runtest b/tests/integrated/test-interchange-instability/runtest index 7c9e887bd4..640420ad74 100755 --- a/tests/integrated/test-interchange-instability/runtest +++ b/tests/integrated/test-interchange-instability/runtest @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -#requires: not metric_3d +# requires: not metric_3d -# +# # Run the test, compare results against the benchmark # @@ -11,15 +11,16 @@ from __future__ import print_function from __future__ import division -nproc = 2 # Number of processors to run on -reltol = 1.e-3 # Allowed relative tolerance in growth-rate + +nproc = 2 # Number of processors to run on +reltol = 1.0e-3 # Allowed relative tolerance in growth-rate from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect import numpy as np from sys import stdout, exit -nthreads=1 +nthreads = 1 build_and_log("interchange instability test") @@ -27,11 +28,14 @@ build_and_log("interchange instability test") shell("rm data_1/BOUT.dmp.*") shell("rm data_10/BOUT.dmp.*") + def growth_rate(path, nproc, log=False): pipe = False if log != False: pipe = True - s, out = launch_safe("./2fluid -d "+path, nproc=nproc, mthread=nthreads, pipe=pipe) + s, out = launch_safe( + "./2fluid -d " + path, nproc=nproc, mthread=nthreads, pipe=pipe + ) if pipe: f = open(log, "w") f.write(out) @@ -44,29 +48,34 @@ def growth_rate(path, nproc, log=False): # Read density Ni = collect("Ni", path=path, xind=5, yind=30, info=False) - + # Calculate RMS value in Z Nirms = np.zeros(nt) for t in np.arange(nt): - Nirms[t] = np.sqrt(np.mean(Ni[t,0,0,:]**2)) + Nirms[t] = np.sqrt(np.mean(Ni[t, 0, 0, :] ** 2)) # Get the growth rate ln = np.log(Nirms) - return (ln[nt-5] - 8.*ln[nt-4] + 8.*ln[nt-2] - ln[nt-1]) / (6. * (tarr[nt-2] - tarr[nt-4])) + return (ln[nt - 5] - 8.0 * ln[nt - 4] + 8.0 * ln[nt - 2] - ln[nt - 1]) / ( + 6.0 * (tarr[nt - 2] - tarr[nt - 4]) + ) + -code = 0 # Return code +code = 0 # Return code # Run case 2 print("Test case 1: R = 1m") growth = growth_rate("data_1", nproc, log="run_1.log") print(" Log file run_1.log") -orig = 2.148177e+05 # 24th October 2011, revision c4f7ec92786b333a5502c5256b5e602ba867090f +orig = ( + 2.148177e05 # 24th October 2011, revision c4f7ec92786b333a5502c5256b5e602ba867090f +) analytic = 2.2e5 print(" Growth-rate = %e, original = %e, analytic = %e" % (growth, orig, analytic)) absdev = abs(growth - orig) reldev = absdev / orig -print(" Deviation from original: %e (%e %%)" % (absdev, reldev*100.)) +print(" Deviation from original: %e (%e %%)" % (absdev, reldev * 100.0)) if reldev > reltol: print(" => Failed") @@ -79,13 +88,13 @@ else: print("Test case 2: R = 10m") growth = growth_rate("data_10", nproc, log="run_10.log") print(" Log file run_10.log") -#orig = 65570. # 24th October 2011, revision c4f7ec92786b333a5502c5256b5e602ba867090f -orig = 6.457835e+04 # 25th April 2014, revision fd032da +# orig = 65570. # 24th October 2011, revision c4f7ec92786b333a5502c5256b5e602ba867090f +orig = 6.457835e04 # 25th April 2014, revision fd032da analytic = 6.3e4 print(" Growth-rate = %e, original = %e, analytic = %e" % (growth, orig, analytic)) absdev = abs(growth - orig) reldev = absdev / orig -print(" Deviation from original: %e (%e %%)" % (absdev, reldev*100.)) +print(" Deviation from original: %e (%e %%)" % (absdev, reldev * 100.0)) if reldev > reltol: print(" => Failed") @@ -94,4 +103,3 @@ else: print(" => Passed") exit(code) - diff --git a/tests/integrated/test-interpolate-z/runtest b/tests/integrated/test-interpolate-z/runtest index e9bf567c5e..6596536497 100755 --- a/tests/integrated/test-interpolate-z/runtest +++ b/tests/integrated/test-interpolate-z/runtest @@ -19,9 +19,9 @@ nxlist = [16, 32, 64, 128] nproc = 1 # Variables to compare -varlist = ['a', 'b', 'c'] -markers = ['bo', 'r^', 'kx'] -labels = [r'$'+var+r'$' for var in varlist] +varlist = ["a", "b", "c"] +markers = ["bo", "r^", "kx"] +labels = [r"$" + var + r"$" for var in varlist] methods = { "hermitespline": 4, @@ -40,16 +40,19 @@ for method in methods: error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # L2 error (RMS) - error_inf[var] = [] # Maximum error + error_2[var] = [] # L2 error (RMS) + error_inf[var] = [] # Maximum error for nx in nxlist: - dx = 1. / (nx) + dx = 1.0 / (nx) - args = " mesh:nx={nx4} mesh:dx={dx} MZ={nx} zinterpolation:type={method}".format( - nx4=nx + 4, dx=dx, nx=nx, method=method) + args = ( + " mesh:nx={nx4} mesh:dx={dx} MZ={nx} zinterpolation:type={method}".format( + nx4=nx + 4, dx=dx, nx=nx, method=method + ) + ) - cmd = "./test_interpolate"+args + cmd = "./test_interpolate" + args shell("rm data/BOUT.dmp.*.nc") @@ -59,12 +62,14 @@ for method in methods: # Collect output data for var in varlist: - interp = collect(var+"_interp", path="data", xguards=False, info=False) - solution = collect(var+"_solution", path="data", xguards=False, info=False) + interp = collect(var + "_interp", path="data", xguards=False, info=False) + solution = collect( + var + "_solution", path="data", xguards=False, info=False + ) E = interp - solution - l2 = float(sqrt(mean(E**2))) + l2 = float(sqrt(mean(E ** 2))) linf = float(max(abs(E))) error_2[var].append(l2) @@ -72,7 +77,7 @@ for method in methods: print("{0:s} : l-2 {1:.8f} l-inf {2:.8f}".format(var, l2, linf)) - dx = 1./array(nxlist) + dx = 1.0 / array(nxlist) for var in varlist: fit = polyfit(log(dx), log(error_2[var]), 1) @@ -89,20 +94,21 @@ for method in methods: if False: try: import matplotlib.pyplot as plt + # Plot errors plt.figure() for var, mark, label in zip(varlist, markers, labels): - plt.plot(dx, error_2[var], '-'+mark, label=label) - plt.plot(dx, error_inf[var], '--'+mark) + plt.plot(dx, error_2[var], "-" + mark, label=label) + plt.plot(dx, error_inf[var], "--" + mark) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") plt.title("Error scaling for {}".format(method)) diff --git a/tests/integrated/test-interpolate/runtest b/tests/integrated/test-interpolate/runtest index 72c28806fa..900c95cbf0 100755 --- a/tests/integrated/test-interpolate/runtest +++ b/tests/integrated/test-interpolate/runtest @@ -19,9 +19,9 @@ nxlist = [16, 32, 64, 128] nproc = 1 # Variables to compare -varlist = ['a', 'b', 'c'] -markers = ['bo', 'r^', 'kx'] -labels = [r'$'+var+r'$' for var in varlist] +varlist = ["a", "b", "c"] +markers = ["bo", "r^", "kx"] +labels = [r"$" + var + r"$" for var in varlist] methods = { "hermitespline": 3, @@ -42,16 +42,19 @@ for method in methods: error_2 = {} error_inf = {} for var in varlist: - error_2[var] = [] # L2 error (RMS) - error_inf[var] = [] # Maximum error + error_2[var] = [] # L2 error (RMS) + error_inf[var] = [] # Maximum error for nx in nxlist: - dx = 1. / (nx) + dx = 1.0 / (nx) - args = " mesh:nx={nx4} mesh:dx={dx} MZ={nx} xzinterpolation:type={method}".format( - nx4=nx + 4, dx=dx, nx=nx, method=method) + args = ( + " mesh:nx={nx4} mesh:dx={dx} MZ={nx} xzinterpolation:type={method}".format( + nx4=nx + 4, dx=dx, nx=nx, method=method + ) + ) - cmd = "./test_interpolate"+args + cmd = "./test_interpolate" + args shell("rm data/BOUT.dmp.*.nc") @@ -61,12 +64,14 @@ for method in methods: # Collect output data for var in varlist: - interp = collect(var+"_interp", path="data", xguards=False, info=False) - solution = collect(var+"_solution", path="data", xguards=False, info=False) + interp = collect(var + "_interp", path="data", xguards=False, info=False) + solution = collect( + var + "_solution", path="data", xguards=False, info=False + ) E = interp - solution - l2 = float(sqrt(mean(E**2))) + l2 = float(sqrt(mean(E ** 2))) linf = float(max(abs(E))) error_2[var].append(l2) @@ -74,7 +79,7 @@ for method in methods: print("{0:s} : l-2 {1:.8f} l-inf {2:.8f}".format(var, l2, linf)) - dx = 1./array(nxlist) + dx = 1.0 / array(nxlist) for var in varlist: fit = polyfit(log(dx), log(error_2[var]), 1) @@ -91,20 +96,21 @@ for method in methods: if False: try: import matplotlib.pyplot as plt + # Plot errors plt.figure() for var, mark, label in zip(varlist, markers, labels): - plt.plot(dx, error_2[var], '-'+mark, label=label) - plt.plot(dx, error_inf[var], '--'+mark) + plt.plot(dx, error_2[var], "-" + mark, label=label) + plt.plot(dx, error_inf[var], "--" + mark) plt.legend(loc="upper left") plt.grid() - plt.yscale('log') - plt.xscale('log') + plt.yscale("log") + plt.xscale("log") - plt.xlabel(r'Mesh spacing $\delta x$') + plt.xlabel(r"Mesh spacing $\delta x$") plt.ylabel("Error norm") plt.title("Error scaling for {}".format(method)) diff --git a/tests/integrated/test-invertable-operator/runtest b/tests/integrated/test-invertable-operator/runtest index fe10aad1e7..47fc5f1b53 100755 --- a/tests/integrated/test-invertable-operator/runtest +++ b/tests/integrated/test-invertable-operator/runtest @@ -1,10 +1,10 @@ #!/usr/bin/env python3 -#requires: petsc -#requires: not metric_3d -#cores: 2 +# requires: petsc +# requires: not metric_3d +# cores: 2 -# +# # Run the test, compare results against expected value # @@ -16,9 +16,9 @@ from boutdata.collect import collect import numpy as np from sys import stdout, exit -nprocs = [1,2] # Number of processors to run on -reltol = 1.e-3 # Allowed relative tolerance -nthreads=1 +nprocs = [1, 2] # Number of processors to run on +reltol = 1.0e-3 # Allowed relative tolerance +nthreads = 1 build_and_log("invertable operator test") @@ -26,11 +26,14 @@ build_and_log("invertable operator test") # Delete old output files shell("rm data/BOUT.dmp.*") + def run(path, nproc, log=False): pipe = False if log != False: pipe = True - s, out = launch_safe("./invertable_operator -d "+path, nproc=nproc, mthread=nthreads, pipe=pipe) + s, out = launch_safe( + "./invertable_operator -d " + path, nproc=nproc, mthread=nthreads, pipe=pipe + ) if pipe: f = open(log, "w") f.write(out) @@ -41,17 +44,22 @@ def run(path, nproc, log=False): maxRelErrLaplacians = collect("maxRelErrLaplacians", path=path)[-1] if passVerification == 0: - print(" => Failed (verification step - value is {s})".format(s=passVerification)) + print( + " => Failed (verification step - value is {s})".format(s=passVerification) + ) exit(1) if maxRelErrLaplacians > reltol: - print(" => Failed (relative tolerance step -- difference of {s})".format(s=maxRelErrLaplacians)) + print( + " => Failed (relative tolerance step -- difference of {s})".format( + s=maxRelErrLaplacians + ) + ) exit(1) for np in nprocs: - run("data",np) + run("data", np) print(" => All tests passed") exit(0) - diff --git a/tests/integrated/test-invpar/runtest b/tests/integrated/test-invpar/runtest index 4e00e8fd8d..21ae5424b6 100755 --- a/tests/integrated/test-invpar/runtest +++ b/tests/integrated/test-invpar/runtest @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -#requires: not metric_3d +# requires: not metric_3d -# +# # Run the test, check it completed successfully # @@ -10,10 +10,11 @@ # Cores: 4 from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect from sys import stdout, exit @@ -39,24 +40,22 @@ flags = [f + " test_location=" + l for f in flags for l in locations] regions = ["", " mesh:ixseps1=0 mesh:ixseps2=0"] flags = [f + r for f in flags for r in regions] -code = 0 # Return code -for nproc in [1,2,4]: +code = 0 # Return code +for nproc in [1, 2, 4]: cmd = "./test_invpar" print(" %d processors...." % (nproc)) r = 0 for f in flags: - stdout.write("\tflags '"+f+"' ... ") + stdout.write("\tflags '" + f + "' ... ") shell("rm data/BOUT.dmp.* 2> err.log") # Run the case - s, out = launch_safe( - cmd+" "+f, nproc=nproc, mthread=1, pipe=True - ) + s, out = launch_safe(cmd + " " + f, nproc=nproc, mthread=1, pipe=True) - with open("run.log."+str(nproc)+"."+str(r), "w") as outfile: - outfile.write(out) + with open("run.log." + str(nproc) + "." + str(r), "w") as outfile: + outfile.write(out) r = r + 1 diff --git a/tests/integrated/test-io/generate.py b/tests/integrated/test-io/generate.py index 77bf92d90a..913545c86f 100644 --- a/tests/integrated/test-io/generate.py +++ b/tests/integrated/test-io/generate.py @@ -16,27 +16,27 @@ fperp2 = numpy.random.rand(nx, nz) f3d = numpy.random.rand(nx, ny, nz) -with Dataset('test_io.grd.nc', 'w') as f: - f.createVariable('nx', numpy.int64) - f['nx'][...] = nx - f.createVariable('ny', numpy.int64) - f['ny'][...] = nx - f.createVariable('ivar', numpy.int64) - f['ivar'][...] = ivar - f.createVariable('rvar', numpy.float64) - f['rvar'][...] = rvar +with Dataset("test_io.grd.nc", "w") as f: + f.createVariable("nx", numpy.int64) + f["nx"][...] = nx + f.createVariable("ny", numpy.int64) + f["ny"][...] = nx + f.createVariable("ivar", numpy.int64) + f["ivar"][...] = ivar + f.createVariable("rvar", numpy.float64) + f["rvar"][...] = rvar - f.createDimension('x', nx) - f.createDimension('y', ny) - f.createDimension('z', nz) - f.createVariable('f2d', numpy.float64, ('x', 'y')) - f['f2d'][...] = f2d - f.createVariable('fperp', numpy.float64, ('x', 'z')) - f['fperp'][...] = fperp - f.createVariable('fperp2', numpy.float64, ('x', 'z')) - f['fperp2'][...] = fperp2 - f['fperp2'].yindex_global = 11 - f.createVariable('f3d', numpy.float64, ('x', 'y', 'z')) - f['f3d'][...] = f3d + f.createDimension("x", nx) + f.createDimension("y", ny) + f.createDimension("z", nz) + f.createVariable("f2d", numpy.float64, ("x", "y")) + f["f2d"][...] = f2d + f.createVariable("fperp", numpy.float64, ("x", "z")) + f["fperp"][...] = fperp + f.createVariable("fperp2", numpy.float64, ("x", "z")) + f["fperp2"][...] = fperp2 + f["fperp2"].yindex_global = 11 + f.createVariable("f3d", numpy.float64, ("x", "y", "z")) + f["f3d"][...] = f3d exit(0) diff --git a/tests/integrated/test-io/runtest b/tests/integrated/test-io/runtest index af0708cb26..739c3fee71 100755 --- a/tests/integrated/test-io/runtest +++ b/tests/integrated/test-io/runtest @@ -65,6 +65,7 @@ for v in vars: # Executable name test_exe = "./test_io" + def check_output(): success = True for v in vars: @@ -77,12 +78,15 @@ def check_output(): # Compare benchmark and output if np.shape(bmk[v]) != np.shape(result): - if (isMetric3D() and v.startswith('v2d') - and bmk[v].shape == result.shape[:-1]): - result = result[...,0] + if ( + isMetric3D() + and v.startswith("v2d") + and bmk[v].shape == result.shape[:-1] + ): + result = result[..., 0] else: print("Fail, wrong shape") - print(v,bmk[v].shape, result.shape) + print(v, bmk[v].shape, result.shape) success = False continue @@ -99,7 +103,7 @@ def check_output(): success = False continue - if (isMetric3D() and v.startswith('v2d')): + if isMetric3D() and v.startswith("v2d"): # Vector2Ds are based on Field3Ds for 3D metrics bmk[v].attributes["bout_type"] = "Field3D_t" bmk[v].attributes["direction_z"] = "Standard" diff --git a/tests/integrated/test-laplace-petsc3d/plotcheck.py b/tests/integrated/test-laplace-petsc3d/plotcheck.py index 707e5db1ee..7f2758dd81 100755 --- a/tests/integrated/test-laplace-petsc3d/plotcheck.py +++ b/tests/integrated/test-laplace-petsc3d/plotcheck.py @@ -10,27 +10,27 @@ xg = 2 -f = collect('f', path=datadir)[xg:-xg, :, :] -rhs = collect('rhs', path=datadir)[xg:-xg, :, :] -rhs_check = collect('rhs_check', path=datadir)[xg:-xg, :, :] -error = collect('error', path=datadir)[xg:-xg, :, :] +f = collect("f", path=datadir)[xg:-xg, :, :] +rhs = collect("rhs", path=datadir)[xg:-xg, :, :] +rhs_check = collect("rhs_check", path=datadir)[xg:-xg, :, :] +error = collect("error", path=datadir)[xg:-xg, :, :] pyplot.subplot(221) pyplot.pcolormesh(f[:, yind, :]) pyplot.colorbar() -pyplot.title('f') +pyplot.title("f") pyplot.subplot(222) pyplot.pcolormesh(rhs[:, yind, :]) pyplot.colorbar() -pyplot.title('rhs') +pyplot.title("rhs") pyplot.subplot(223) pyplot.pcolormesh(rhs_check[:, yind, :]) pyplot.colorbar() -pyplot.title('rhs_check') +pyplot.title("rhs_check") pyplot.subplot(224) pyplot.pcolormesh(error[:, yind, :]) pyplot.colorbar() -pyplot.title('error') +pyplot.title("error") pyplot.show() diff --git a/tests/integrated/test-laplace-petsc3d/runtest b/tests/integrated/test-laplace-petsc3d/runtest index b11de7d47b..88f9d76c62 100755 --- a/tests/integrated/test-laplace-petsc3d/runtest +++ b/tests/integrated/test-laplace-petsc3d/runtest @@ -1,36 +1,38 @@ #!/usr/bin/env python3 -#requires: petsc +# requires: petsc from boutdata import collect from boututils.run_wrapper import launch_safe, build_and_log from sys import exit -test_directories = [('data_slab_core', 1), - ('data_slab_sol', 1), - ('data_circular_core', 1), - ('data_circular_core-sol', 1)] +test_directories = [ + ("data_slab_core", 1), + ("data_slab_sol", 1), + ("data_circular_core", 1), + ("data_circular_core-sol", 1), +] -tolerance = 1.e-6 +tolerance = 1.0e-6 -build_and_log('Laplace 3D with PETSc') +build_and_log("Laplace 3D with PETSc") success = True -for directory,nproc in test_directories: - command = './test-laplace3d -d ' + directory - print('running on', nproc, 'processors:', command) +for directory, nproc in test_directories: + command = "./test-laplace3d -d " + directory + print("running on", nproc, "processors:", command) launch_safe(command, nproc=nproc) - error_max = collect('error_max', path=directory, info=False) + error_max = collect("error_max", path=directory, info=False) if error_max > tolerance: - print(directory + ' failed with maximum error {}'.format(error_max)) + print(directory + " failed with maximum error {}".format(error_max)) success = False else: - print(directory + ' passed with maximum error {}'.format(error_max)) + print(directory + " passed with maximum error {}".format(error_max)) if success: - print('All passed') + print("All passed") exit(0) else: exit(1) diff --git a/tests/integrated/test-laplace/runtest b/tests/integrated/test-laplace/runtest index 6f816056b8..3bdf9101a7 100755 --- a/tests/integrated/test-laplace/runtest +++ b/tests/integrated/test-laplace/runtest @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -#requires: not metric_3d +# requires: not metric_3d -# +# # Run the test, compare results against the benchmark # @@ -10,17 +10,32 @@ # Cores: 4 from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass # Variables to compare -vars = ['flag0', 'flag3', 'flagis', 'flagos', - 'flag0a', 'flag3a', 'flagisa', 'flagosa', - 'flag0ac', 'flag3ac','flagisac', 'flagosac', - 'flag0ad', 'flag3ad', 'flagisad', 'flagosad'] -tol = 1e-6 # Absolute tolerance +vars = [ + "flag0", + "flag3", + "flagis", + "flagos", + "flag0a", + "flag3a", + "flagisa", + "flagosa", + "flag0ac", + "flag3ac", + "flagisac", + "flagosac", + "flag0ad", + "flag3ad", + "flagisad", + "flagosad", +] +tol = 1e-6 # Absolute tolerance from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -34,43 +49,43 @@ build_and_log("Laplacian inversion test") print("Reading benchmark data") bmk = {} for v in vars: - bmk[v] = collect(v, path="data", prefix="benchmark", info=False) + bmk[v] = collect(v, path="data", prefix="benchmark", info=False) print("Running Laplacian inversion test") success = True -for nproc in [1,2,4]: - nxpe = 1 - if nproc > 2: - nxpe = 2 - - cmd = "./test_laplace nxpe=" + str(nxpe) - - shell("rm data/BOUT.dmp.*.nc") - - print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) - s, out = launch_safe(cmd, nproc=nproc, mthread=1, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) - - # Collect output data - for v in vars: - stdout.write(" Checking variable "+v+" ... ") - result = collect(v, path="data", info=False) - # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - print("Fail, wrong shape") - success = False - diff = np.max(np.abs(bmk[v] - result)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - else: - print("Pass") +for nproc in [1, 2, 4]: + nxpe = 1 + if nproc > 2: + nxpe = 2 + + cmd = "./test_laplace nxpe=" + str(nxpe) + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processors (nxpe = %d)...." % (nproc, nxpe)) + s, out = launch_safe(cmd, nproc=nproc, mthread=1, pipe=True) + with open("run.log." + str(nproc), "w") as f: + f.write(out) + + # Collect output data + for v in vars: + stdout.write(" Checking variable " + v + " ... ") + result = collect(v, path="data", info=False) + # Compare benchmark and output + if np.shape(bmk[v]) != np.shape(result): + print("Fail, wrong shape") + success = False + diff = np.max(np.abs(bmk[v] - result)) + if diff > tol: + print("Fail, maximum difference = " + str(diff)) + success = False + else: + print("Pass") if success: - print(" => All Laplacian inversion tests passed") - exit(0) + print(" => All Laplacian inversion tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-laplacexy-fv/plotcheck.py b/tests/integrated/test-laplacexy-fv/plotcheck.py index 419612fdfa..9bda880b64 100755 --- a/tests/integrated/test-laplacexy-fv/plotcheck.py +++ b/tests/integrated/test-laplacexy-fv/plotcheck.py @@ -4,10 +4,12 @@ from matplotlib import pyplot from sys import exit -f = collect('f', path='data', yguards=True, info=False)[1:-1,1:-1] -sol = collect('sol', path='data', yguards=True, info=False)[1:-1,1:-1] -error = collect('error', path='data', yguards=True, info=False)[1:-1,1:-1] -absolute_error = collect('absolute_error', path='data', yguards=True, info=False)[1:-1,1:-1] +f = collect("f", path="data", yguards=True, info=False)[1:-1, 1:-1] +sol = collect("sol", path="data", yguards=True, info=False)[1:-1, 1:-1] +error = collect("error", path="data", yguards=True, info=False)[1:-1, 1:-1] +absolute_error = collect("absolute_error", path="data", yguards=True, info=False)[ + 1:-1, 1:-1 +] # Note, cells closest to x-boundary in rhs and rhs_check may be slightly different because # of different way x-boundary cells for D2DXDY are set: in LaplaceXY corner guard cells @@ -16,39 +18,39 @@ # conditions applied, then DDX(dfdy) is returned. # Therefore here exclude cells closest to the x-boundary so that the difference plotted # should be small (as controlled by rtol, atol). -rhs = collect('rhs', path='data', yguards=True, info=False)[3:-3,2:-2] -rhs_check = collect('rhs_check', path='data', yguards=True, info=False)[3:-3,2:-2] +rhs = collect("rhs", path="data", yguards=True, info=False)[3:-3, 2:-2] +rhs_check = collect("rhs_check", path="data", yguards=True, info=False)[3:-3, 2:-2] pyplot.figure() pyplot.subplot(231) pyplot.pcolormesh(f) -pyplot.title('f') +pyplot.title("f") pyplot.colorbar() pyplot.subplot(232) pyplot.pcolormesh(sol) -pyplot.title('sol') +pyplot.title("sol") pyplot.colorbar() pyplot.subplot(233) pyplot.pcolormesh(error) -pyplot.title('error') +pyplot.title("error") pyplot.colorbar() pyplot.subplot(234) pyplot.pcolormesh(absolute_error) -pyplot.title('absolute_error') +pyplot.title("absolute_error") pyplot.colorbar() pyplot.subplot(235) pyplot.pcolormesh(rhs) -pyplot.title('rhs') +pyplot.title("rhs") pyplot.colorbar() pyplot.subplot(236) pyplot.pcolormesh(rhs - rhs_check) -pyplot.title('rhs diff') +pyplot.title("rhs diff") pyplot.colorbar() pyplot.show() diff --git a/tests/integrated/test-laplacexy-short/plotcheck.py b/tests/integrated/test-laplacexy-short/plotcheck.py index 419612fdfa..9bda880b64 100755 --- a/tests/integrated/test-laplacexy-short/plotcheck.py +++ b/tests/integrated/test-laplacexy-short/plotcheck.py @@ -4,10 +4,12 @@ from matplotlib import pyplot from sys import exit -f = collect('f', path='data', yguards=True, info=False)[1:-1,1:-1] -sol = collect('sol', path='data', yguards=True, info=False)[1:-1,1:-1] -error = collect('error', path='data', yguards=True, info=False)[1:-1,1:-1] -absolute_error = collect('absolute_error', path='data', yguards=True, info=False)[1:-1,1:-1] +f = collect("f", path="data", yguards=True, info=False)[1:-1, 1:-1] +sol = collect("sol", path="data", yguards=True, info=False)[1:-1, 1:-1] +error = collect("error", path="data", yguards=True, info=False)[1:-1, 1:-1] +absolute_error = collect("absolute_error", path="data", yguards=True, info=False)[ + 1:-1, 1:-1 +] # Note, cells closest to x-boundary in rhs and rhs_check may be slightly different because # of different way x-boundary cells for D2DXDY are set: in LaplaceXY corner guard cells @@ -16,39 +18,39 @@ # conditions applied, then DDX(dfdy) is returned. # Therefore here exclude cells closest to the x-boundary so that the difference plotted # should be small (as controlled by rtol, atol). -rhs = collect('rhs', path='data', yguards=True, info=False)[3:-3,2:-2] -rhs_check = collect('rhs_check', path='data', yguards=True, info=False)[3:-3,2:-2] +rhs = collect("rhs", path="data", yguards=True, info=False)[3:-3, 2:-2] +rhs_check = collect("rhs_check", path="data", yguards=True, info=False)[3:-3, 2:-2] pyplot.figure() pyplot.subplot(231) pyplot.pcolormesh(f) -pyplot.title('f') +pyplot.title("f") pyplot.colorbar() pyplot.subplot(232) pyplot.pcolormesh(sol) -pyplot.title('sol') +pyplot.title("sol") pyplot.colorbar() pyplot.subplot(233) pyplot.pcolormesh(error) -pyplot.title('error') +pyplot.title("error") pyplot.colorbar() pyplot.subplot(234) pyplot.pcolormesh(absolute_error) -pyplot.title('absolute_error') +pyplot.title("absolute_error") pyplot.colorbar() pyplot.subplot(235) pyplot.pcolormesh(rhs) -pyplot.title('rhs') +pyplot.title("rhs") pyplot.colorbar() pyplot.subplot(236) pyplot.pcolormesh(rhs - rhs_check) -pyplot.title('rhs diff') +pyplot.title("rhs diff") pyplot.colorbar() pyplot.show() diff --git a/tests/integrated/test-laplacexy-short/runtest b/tests/integrated/test-laplacexy-short/runtest index e60abf3ede..8d20d96cdf 100755 --- a/tests/integrated/test-laplacexy-short/runtest +++ b/tests/integrated/test-laplacexy-short/runtest @@ -1,93 +1,98 @@ #!/usr/bin/env python3 -# +# # Run the test, compare results against the benchmark # -#requires: petsc -#cores: 8 +# requires: petsc +# cores: 8 from boututils.run_wrapper import build_and_log, shell, shell_safe, launch, launch_safe from boutdata.collect import collect from sys import exit -tol = 5.e-8 +tol = 5.0e-8 # Note accuracy of test is limited when g12!=0 by inconsistency between the way boundary # conditions are applied in LaplaceXY and the way they are applied in the D2DXDY() # operator called by Laplace_perp(). In D2DXDY(f) 'free_o3' boundary conditions are # applied to dfdy before calculating DDX(dfdy). -tol_nonorth = 2.e-5 +tol_nonorth = 2.0e-5 -argslist = ['laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3', - #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' - #'f:bndry_xin=neumann f:bndry_xout=neumann f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1', - ] +argslist = [ + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3", + #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', + #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', + #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', + #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', + #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' + #'f:bndry_xin=neumann f:bndry_xout=neumann f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann", + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1", + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1", + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1", +] -build_and_log('LaplaceXY inversion test') +build_and_log("LaplaceXY inversion test") -print('Running LaplaceXY inversion test') +print("Running LaplaceXY inversion test") success = True for nproc in [8]: - print(' %d processors....' % nproc) + print(" %d processors...." % nproc) for args in argslist: - cmd = './test-laplacexy ' + args + cmd = "./test-laplacexy " + args - shell('rm data/BOUT.dmp.*.nc > /dev/null 2>&1') + shell("rm data/BOUT.dmp.*.nc > /dev/null 2>&1") - s, out = launch(cmd + ' laplacexy:pctype=hypre', nproc=nproc, pipe=True,verbose=True) + s, out = launch( + cmd + " laplacexy:pctype=hypre", nproc=nproc, pipe=True, verbose=True + ) if s == 134: # PETSc did not recognise pctype option, probably means it # was not compiled with hypre, so skip tests that need # hypre to converge - print('hypre not available as pre-conditioner in PETSc. Re-running with ' - + 'pctype=shell...') - s, out = launch(cmd, nproc=nproc, pipe=True,verbose=True) + print( + "hypre not available as pre-conditioner in PETSc. Re-running with " + + "pctype=shell..." + ) + s, out = launch(cmd, nproc=nproc, pipe=True, verbose=True) - f = open('run.log.'+str(nproc), 'w') + f = open("run.log." + str(nproc), "w") f.write(out) f.close() # Collect output data - error = collect('max_error', path='data', info=False) + error = collect("max_error", path="data", info=False) if error <= 0: - print('Convergence error') + print("Convergence error") success = False elif error > tol: - print('Fail, maximum error is = '+str(error)) + print("Fail, maximum error is = " + str(error)) success = False else: - print('Pass') + print("Pass") if success: - print(' => All LaplaceXY inversion tests passed') - exit(0) + print(" => All LaplaceXY inversion tests passed") + exit(0) else: - print(' => Some failed tests') - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-laplacexy/plotcheck.py b/tests/integrated/test-laplacexy/plotcheck.py index 419612fdfa..9bda880b64 100755 --- a/tests/integrated/test-laplacexy/plotcheck.py +++ b/tests/integrated/test-laplacexy/plotcheck.py @@ -4,10 +4,12 @@ from matplotlib import pyplot from sys import exit -f = collect('f', path='data', yguards=True, info=False)[1:-1,1:-1] -sol = collect('sol', path='data', yguards=True, info=False)[1:-1,1:-1] -error = collect('error', path='data', yguards=True, info=False)[1:-1,1:-1] -absolute_error = collect('absolute_error', path='data', yguards=True, info=False)[1:-1,1:-1] +f = collect("f", path="data", yguards=True, info=False)[1:-1, 1:-1] +sol = collect("sol", path="data", yguards=True, info=False)[1:-1, 1:-1] +error = collect("error", path="data", yguards=True, info=False)[1:-1, 1:-1] +absolute_error = collect("absolute_error", path="data", yguards=True, info=False)[ + 1:-1, 1:-1 +] # Note, cells closest to x-boundary in rhs and rhs_check may be slightly different because # of different way x-boundary cells for D2DXDY are set: in LaplaceXY corner guard cells @@ -16,39 +18,39 @@ # conditions applied, then DDX(dfdy) is returned. # Therefore here exclude cells closest to the x-boundary so that the difference plotted # should be small (as controlled by rtol, atol). -rhs = collect('rhs', path='data', yguards=True, info=False)[3:-3,2:-2] -rhs_check = collect('rhs_check', path='data', yguards=True, info=False)[3:-3,2:-2] +rhs = collect("rhs", path="data", yguards=True, info=False)[3:-3, 2:-2] +rhs_check = collect("rhs_check", path="data", yguards=True, info=False)[3:-3, 2:-2] pyplot.figure() pyplot.subplot(231) pyplot.pcolormesh(f) -pyplot.title('f') +pyplot.title("f") pyplot.colorbar() pyplot.subplot(232) pyplot.pcolormesh(sol) -pyplot.title('sol') +pyplot.title("sol") pyplot.colorbar() pyplot.subplot(233) pyplot.pcolormesh(error) -pyplot.title('error') +pyplot.title("error") pyplot.colorbar() pyplot.subplot(234) pyplot.pcolormesh(absolute_error) -pyplot.title('absolute_error') +pyplot.title("absolute_error") pyplot.colorbar() pyplot.subplot(235) pyplot.pcolormesh(rhs) -pyplot.title('rhs') +pyplot.title("rhs") pyplot.colorbar() pyplot.subplot(236) pyplot.pcolormesh(rhs - rhs_check) -pyplot.title('rhs diff') +pyplot.title("rhs diff") pyplot.colorbar() pyplot.show() diff --git a/tests/integrated/test-laplacexy/plotmetrics.py b/tests/integrated/test-laplacexy/plotmetrics.py index cd4dd7c850..3100856679 100755 --- a/tests/integrated/test-laplacexy/plotmetrics.py +++ b/tests/integrated/test-laplacexy/plotmetrics.py @@ -7,88 +7,88 @@ from sys import exit # Set default colormap -pyplot.rcParams['image.cmap'] = 'viridis' -#pyplot.rcParams['image.cmap'] = 'plasma' - -g11=collect('g11',path='data',xguards=False,yguards=False) -g12=collect('g12',path='data',xguards=False,yguards=False) -g13=collect('g13',path='data',xguards=False,yguards=False) -g22=collect('g22',path='data',xguards=False,yguards=False) -g23=collect('g23',path='data',xguards=False,yguards=False) -g33=collect('g33',path='data',xguards=False,yguards=False) -g_11=collect('g_11',path='data',xguards=False,yguards=False) -g_12=collect('g_12',path='data',xguards=False,yguards=False) -g_13=collect('g_13',path='data',xguards=False,yguards=False) -g_22=collect('g_22',path='data',xguards=False,yguards=False) -g_23=collect('g_23',path='data',xguards=False,yguards=False) -g_33=collect('g_33',path='data',xguards=False,yguards=False) +pyplot.rcParams["image.cmap"] = "viridis" +# pyplot.rcParams['image.cmap'] = 'plasma' + +g11 = collect("g11", path="data", xguards=False, yguards=False) +g12 = collect("g12", path="data", xguards=False, yguards=False) +g13 = collect("g13", path="data", xguards=False, yguards=False) +g22 = collect("g22", path="data", xguards=False, yguards=False) +g23 = collect("g23", path="data", xguards=False, yguards=False) +g33 = collect("g33", path="data", xguards=False, yguards=False) +g_11 = collect("g_11", path="data", xguards=False, yguards=False) +g_12 = collect("g_12", path="data", xguards=False, yguards=False) +g_13 = collect("g_13", path="data", xguards=False, yguards=False) +g_22 = collect("g_22", path="data", xguards=False, yguards=False) +g_23 = collect("g_23", path="data", xguards=False, yguards=False) +g_33 = collect("g_33", path="data", xguards=False, yguards=False) grid = DataFile("data/d3d_119919.nc") -R = grid['Rxy'][2:-2,:] -Z = grid['Zxy'][2:-2,:] +R = grid["Rxy"][2:-2, :] +Z = grid["Zxy"][2:-2, :] pyplot.subplot(231) -pyplot.pcolor(R,Z,g11) +pyplot.pcolor(R, Z, g11) pyplot.colorbar() -pyplot.title('g11') +pyplot.title("g11") pyplot.subplot(232) -pyplot.pcolor(R,Z,g12) +pyplot.pcolor(R, Z, g12) pyplot.colorbar() -pyplot.title('g12') +pyplot.title("g12") pyplot.subplot(233) -pyplot.pcolor(R,Z,g13) +pyplot.pcolor(R, Z, g13) pyplot.colorbar() -pyplot.title('g13') +pyplot.title("g13") pyplot.subplot(234) -pyplot.pcolor(R,Z,g22) +pyplot.pcolor(R, Z, g22) pyplot.colorbar() -pyplot.title('g22') +pyplot.title("g22") pyplot.subplot(235) -pyplot.pcolor(R,Z,g23) +pyplot.pcolor(R, Z, g23) pyplot.colorbar() -pyplot.title('g23') +pyplot.title("g23") pyplot.subplot(236) -pyplot.pcolor(R,Z,g33) +pyplot.pcolor(R, Z, g33) pyplot.colorbar() -pyplot.title('g33') +pyplot.title("g33") pyplot.figure() pyplot.subplot(231) -pyplot.pcolor(R,Z,g_11) +pyplot.pcolor(R, Z, g_11) pyplot.colorbar() -pyplot.title('g_11') +pyplot.title("g_11") pyplot.subplot(232) -pyplot.pcolor(R,Z,g_12) +pyplot.pcolor(R, Z, g_12) pyplot.colorbar() -pyplot.title('g_12') +pyplot.title("g_12") pyplot.subplot(233) -pyplot.pcolor(R,Z,g_13) +pyplot.pcolor(R, Z, g_13) pyplot.colorbar() -pyplot.title('g_13') +pyplot.title("g_13") pyplot.subplot(234) -pyplot.pcolor(R,Z,g_22) +pyplot.pcolor(R, Z, g_22) pyplot.colorbar() -pyplot.title('g_22') +pyplot.title("g_22") pyplot.subplot(235) -pyplot.pcolor(R,Z,g_23) +pyplot.pcolor(R, Z, g_23) pyplot.colorbar() -pyplot.title('g_23') +pyplot.title("g_23") pyplot.subplot(236) -pyplot.pcolor(R,Z,g_33) +pyplot.pcolor(R, Z, g_33) pyplot.colorbar() -pyplot.title('g_33') +pyplot.title("g_33") pyplot.show() diff --git a/tests/integrated/test-laplacexy/plotresult.py b/tests/integrated/test-laplacexy/plotresult.py index 11a7187f12..ccf48baa55 100755 --- a/tests/integrated/test-laplacexy/plotresult.py +++ b/tests/integrated/test-laplacexy/plotresult.py @@ -7,49 +7,49 @@ from sys import exit # Set default colormap -pyplot.rcParams['image.cmap'] = 'viridis' -#pyplot.rcParams['image.cmap'] = 'plasma' +pyplot.rcParams["image.cmap"] = "viridis" +# pyplot.rcParams['image.cmap'] = 'plasma' -x=collect('x',path='data',xguards=False,yguards=False) -rhs=collect('rhs',path='data',xguards=False,yguards=False) -check=collect('check',path='data',xguards=False,yguards=False) -x2=collect('x2',path='data',xguards=False,yguards=False) -rhs2=collect('rhs2',path='data',xguards=False,yguards=False) -check2=collect('check2',path='data',xguards=False,yguards=False) +x = collect("x", path="data", xguards=False, yguards=False) +rhs = collect("rhs", path="data", xguards=False, yguards=False) +check = collect("check", path="data", xguards=False, yguards=False) +x2 = collect("x2", path="data", xguards=False, yguards=False) +rhs2 = collect("rhs2", path="data", xguards=False, yguards=False) +check2 = collect("check2", path="data", xguards=False, yguards=False) grid = DataFile("data/d3d_119919.nc") -R = grid['Rxy'][2:-2,:] -Z = grid['Zxy'][2:-2,:] +R = grid["Rxy"][2:-2, :] +Z = grid["Zxy"][2:-2, :] pyplot.subplot(231) -pyplot.pcolor(R,Z,x) +pyplot.pcolor(R, Z, x) pyplot.colorbar() -pyplot.title('x') +pyplot.title("x") pyplot.subplot(232) -pyplot.pcolor(R,Z,rhs) +pyplot.pcolor(R, Z, rhs) pyplot.colorbar() -pyplot.title('rhs') +pyplot.title("rhs") pyplot.subplot(233) -pyplot.pcolor(R,Z,check) +pyplot.pcolor(R, Z, check) pyplot.colorbar() -pyplot.title('check') +pyplot.title("check") pyplot.subplot(234) -pyplot.pcolor(R,Z,x2) +pyplot.pcolor(R, Z, x2) pyplot.colorbar() -pyplot.title('x2') +pyplot.title("x2") pyplot.subplot(235) -pyplot.pcolor(R,Z,rhs2) +pyplot.pcolor(R, Z, rhs2) pyplot.colorbar() -pyplot.title('rhs2') +pyplot.title("rhs2") pyplot.subplot(236) -pyplot.pcolor(R,Z,check2) +pyplot.pcolor(R, Z, check2) pyplot.colorbar() -pyplot.title('check2') +pyplot.title("check2") pyplot.show() diff --git a/tests/integrated/test-laplacexy/runtest b/tests/integrated/test-laplacexy/runtest index 4014c39703..30a3f36e0e 100755 --- a/tests/integrated/test-laplacexy/runtest +++ b/tests/integrated/test-laplacexy/runtest @@ -1,100 +1,103 @@ #!/usr/bin/env python3 -# +# # Run the test, compare results against the benchmark # -#requires: petsc -#requires: all_tests -#cores: 8 +# requires: petsc +# requires: all_tests +# cores: 8 from boututils.run_wrapper import build_and_log, shell, shell_safe, launch, launch_safe from boutdata.collect import collect from sys import exit -tol_orth = 5.e-8 +tol_orth = 5.0e-8 # Note accuracy of test is limited when g12!=0 by inconsistency between the way boundary # conditions are applied in LaplaceXY and the way they are applied in the D2DXDY() # operator called by Laplace_perp(). In D2DXDY(f) 'free_o3' boundary conditions are # applied to dfdy before calculating DDX(dfdy). -tol_nonorth = 2.e-5 +tol_nonorth = 2.0e-5 -argslist = ['laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3', - #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' - #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', - #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' - #'f:bndry_xin=neumann f:bndry_xout=neumann f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann laplacexy:pctype=hypre', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 laplacexy:pctype=hypre', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1', - 'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1 laplacexy:pctype=hypre', - 'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 ' - 'f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1 laplacexy:pctype=hypre', - ] +argslist = [ + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3", + #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', + #'laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', + #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', + #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann ' + #'f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann', + #'laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=dirichlet ' + #'f:bndry_xin=neumann f:bndry_xout=neumann f:bndry_yup=dirichlet f:bndry_ydown=dirichlet', + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann laplacexy:pctype=hypre", + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 laplacexy:pctype=hypre", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=neumann " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1", + "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=free_o3 " + "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1", + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=neumann " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=neumann f:bndry_ydown=neumann b:function=.1 laplacexy:pctype=hypre", + "laplacexy:core_bndry_dirichlet=false laplacexy:pf_bndry_dirichlet=false laplacexy:y_bndry=free_o3 " + "f:bndry_xin=neumann f:bndry_xout=dirichlet f:bndry_yup=free_o3 f:bndry_ydown=free_o3 b:function=.1 laplacexy:pctype=hypre", +] -build_and_log('LaplaceXY inversion test') +build_and_log("LaplaceXY inversion test") -print('Running LaplaceXY inversion test') +print("Running LaplaceXY inversion test") success = True for nproc in [8]: - print(' %d processors....' % nproc) + print(" %d processors...." % nproc) for nonorth, tol in [(False, tol_orth), (True, tol_nonorth)]: for args in argslist: if not nonorth: - args += ' mesh:g12=0.' + args += " mesh:g12=0." - cmd = './test-laplacexy ' + args + cmd = "./test-laplacexy " + args - shell('rm data/BOUT.dmp.*.nc > /dev/null 2>&1') + shell("rm data/BOUT.dmp.*.nc > /dev/null 2>&1") - if 'hypre' in args: - s, out = launch(cmd, nproc=nproc, pipe=True,verbose=True) + if "hypre" in args: + s, out = launch(cmd, nproc=nproc, pipe=True, verbose=True) if s == 134: # PETSc did not recognise pctype option, probably means it # was not compiled with hypre, so skip tests that need # hypre to converge - print('hypre not available as pre-conditioner in PETSc. Skipping...') + print( + "hypre not available as pre-conditioner in PETSc. Skipping..." + ) continue else: - s, out = launch_safe(cmd, nproc=nproc, pipe=True,verbose=True) + s, out = launch_safe(cmd, nproc=nproc, pipe=True, verbose=True) - f = open('run.log.'+str(nproc), 'w') + f = open("run.log." + str(nproc), "w") f.write(out) f.close() # Collect output data - error = collect('max_error', path='data', info=False) + error = collect("max_error", path="data", info=False) if error <= 0: - print('Convergence error') + print("Convergence error") success = False elif error > tol: - print('Fail, maximum error is = '+str(error)) + print("Fail, maximum error is = " + str(error)) success = False else: - print('Pass') + print("Pass") if success: - print(' => All LaplaceXY inversion tests passed') - exit(0) + print(" => All LaplaceXY inversion tests passed") + exit(0) else: - print(' => Some failed tests') - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-multigrid_laplace/plotresults.py b/tests/integrated/test-multigrid_laplace/plotresults.py index 9917b8f024..37d594e85d 100755 --- a/tests/integrated/test-multigrid_laplace/plotresults.py +++ b/tests/integrated/test-multigrid_laplace/plotresults.py @@ -7,44 +7,44 @@ Ntests = 4 d = BoutOutputs("data") -#d = BoutOutputs("data", caching=True, info=False) +# d = BoutOutputs("data", caching=True, info=False) -for i in range(1,Ntests+1): +for i in range(1, Ntests + 1): pyplot.figure(i) pyplot.subplot(231) - pyplot.pcolor(d["f"+str(i)][1:-1,0,:].T) + pyplot.pcolor(d["f" + str(i)][1:-1, 0, :].T) pyplot.colorbar() - pyplot.title("f"+str(i)) + pyplot.title("f" + str(i)) pyplot.xlabel("X") pyplot.ylabel("Z") pyplot.subplot(232) - pyplot.pcolor(d["sol"+str(i)][1:-1,0,:].T) + pyplot.pcolor(d["sol" + str(i)][1:-1, 0, :].T) pyplot.colorbar() - pyplot.title("sol"+str(i)) + pyplot.title("sol" + str(i)) pyplot.xlabel("X") pyplot.ylabel("Z") pyplot.subplot(233) - pyplot.pcolor(d["absolute_error"+str(i)][1:-1,0,:].T) + pyplot.pcolor(d["absolute_error" + str(i)][1:-1, 0, :].T) pyplot.colorbar() - pyplot.title("absolute_error"+str(i)) + pyplot.title("absolute_error" + str(i)) pyplot.xlabel("X") pyplot.ylabel("Z") pyplot.subplot(234) - pyplot.pcolor(d["b"+str(i)][2:-2,0,:].T) + pyplot.pcolor(d["b" + str(i)][2:-2, 0, :].T) pyplot.colorbar() - pyplot.title("b"+str(i)) + pyplot.title("b" + str(i)) pyplot.xlabel("X") pyplot.ylabel("Z") pyplot.subplot(235) - pyplot.pcolor(d["bcheck"+str(i)][2:-2,0,:].T) + pyplot.pcolor(d["bcheck" + str(i)][2:-2, 0, :].T) pyplot.colorbar() - pyplot.title("bcheck"+str(i)) + pyplot.title("bcheck" + str(i)) pyplot.xlabel("X") pyplot.ylabel("Z") pyplot.subplot(236) - pyplot.pcolor(d["b"+str(i)][2:-2,0,:].T-d["bcheck"+str(i)][2:-2,0,:].T) + pyplot.pcolor(d["b" + str(i)][2:-2, 0, :].T - d["bcheck" + str(i)][2:-2, 0, :].T) pyplot.colorbar() - pyplot.title("b"+str(i)+"-bcheck"+str(i)) + pyplot.title("b" + str(i) + "-bcheck" + str(i)) pyplot.xlabel("X") pyplot.ylabel("Z") diff --git a/tests/integrated/test-multigrid_laplace/runtest b/tests/integrated/test-multigrid_laplace/runtest index 2dbf66ce0a..a9c9c9850a 100755 --- a/tests/integrated/test-multigrid_laplace/runtest +++ b/tests/integrated/test-multigrid_laplace/runtest @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -#requires: not metric_3d +# requires: not metric_3d # # Run the test, check the error @@ -12,13 +12,14 @@ # Cores: 3 from __future__ import print_function + try: from builtins import str except: pass -tol = 2e-7 # Absolute tolerance -numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) +tol = 2e-7 # Absolute tolerance +numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -30,34 +31,36 @@ build_and_log("multigrid Laplacian inversion test") print("Running multigrid Laplacian inversion test") success = True -for nproc in [1,3]: +for nproc in [1, 3]: # Make sure we don't use too many cores: # Reduce number of OpenMP threads when using multiple MPI processes mthread = 2 - if nproc>1: + if nproc > 1: mthread = 1 - + # set nxpe on the command line as we only use solution from one point in y, so splitting in y-direction is redundant (and also doesn't help test the multigrid solver) - cmd = "./test_multigrid_laplace nxpe="+str(nproc) - + cmd = "./test_multigrid_laplace nxpe=" + str(nproc) + shell("rm data/BOUT.dmp.*.nc") - print(" %d processors..." %nproc) + print(" %d processors..." % nproc) s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) - with open("run.log."+str(nproc), "w") as f: + with open("run.log." + str(nproc), "w") as f: f.write(out) # Collect errors - errors = [collect("max_error"+str(i), path="data") for i in range(1,numTests+1)] + errors = [ + collect("max_error" + str(i), path="data") for i in range(1, numTests + 1) + ] - for i,e in enumerate(errors): - print("Checking test "+str(i)) - if e < 0.: + for i, e in enumerate(errors): + print("Checking test " + str(i)) + if e < 0.0: print("Fail, solver did not converge") success = False if e > tol: - print("Fail, maximum absolute error = "+str(e)) + print("Fail, maximum absolute error = " + str(e)) success = False else: print("Pass") diff --git a/tests/integrated/test-multigrid_laplace/runtest_multiple_grids b/tests/integrated/test-multigrid_laplace/runtest_multiple_grids index 609f034c5a..9bde46834b 100755 --- a/tests/integrated/test-multigrid_laplace/runtest_multiple_grids +++ b/tests/integrated/test-multigrid_laplace/runtest_multiple_grids @@ -5,13 +5,14 @@ # from __future__ import print_function + try: from builtins import str except: pass -tol = 2e-6 # Absolute tolerance -numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) +tol = 2e-6 # Absolute tolerance +numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -23,29 +24,31 @@ build_and_log("Multigrid Laplacian inversion test") print("Running multigrid Laplacian inversion test") success = True -for nproc in [1,2,4]: - for inputfile in ["BOUT_jy4.inp","BOUT_jy63.inp","BOUT_jy127.inp"]: - +for nproc in [1, 2, 4]: + for inputfile in ["BOUT_jy4.inp", "BOUT_jy63.inp", "BOUT_jy127.inp"]: + # set nxpe on the command line as we only use solution from one point in y, so splitting in y-direction is redundant (and also doesn't help test the multigrid solver) - cmd = "./test_multigrid_laplace -f "+inputfile+" nxpe="+str(nproc) - + cmd = "./test_multigrid_laplace -f " + inputfile + " nxpe=" + str(nproc) + shell("rm data/BOUT.dmp.*.nc") - print(" %d processors, input file is %s" %(nproc,inputfile)) + print(" %d processors, input file is %s" % (nproc, inputfile)) s, out = launch_safe(cmd, nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: + with open("run.log." + str(nproc), "w") as f: f.write(out) # Collect errors - errors = [collect("max_error"+str(i), path="data") for i in range(1,numTests+1)] + errors = [ + collect("max_error" + str(i), path="data") for i in range(1, numTests + 1) + ] - for i,e in enumerate(errors): - print("Checking test "+str(i)) - if e < 0.: + for i, e in enumerate(errors): + print("Checking test " + str(i)) + if e < 0.0: print("Fail, solver did not converge") success = False if e > tol: - print("Fail, maximum absolute error = "+str(e)) + print("Fail, maximum absolute error = " + str(e)) success = False else: print("Pass") diff --git a/tests/integrated/test-multigrid_laplace/runtest_unsheared b/tests/integrated/test-multigrid_laplace/runtest_unsheared index f395b9f372..fca70442b6 100755 --- a/tests/integrated/test-multigrid_laplace/runtest_unsheared +++ b/tests/integrated/test-multigrid_laplace/runtest_unsheared @@ -5,13 +5,14 @@ # from __future__ import print_function + try: from builtins import str except: pass -tol = 1e-9 # Absolute tolerance -numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) +tol = 1e-9 # Absolute tolerance +numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -23,34 +24,36 @@ build_and_log("Making multigrid Laplacian inversion test") print("Running multigrid Laplacian inversion test") success = True -for nproc in [1,3]: +for nproc in [1, 3]: # Make sure we don't use too many cores: # Reduce number of OpenMP threads when using multiple MPI processes mthread = 2 - if nproc>1: + if nproc > 1: mthread = 1 - + # set nxpe on the command line as we only use solution from one point in y, so splitting in y-direction is redundant (and also doesn't help test the multigrid solver) - cmd = "./test_multigrid_laplace -f BOUT_unsheared.inp nxpe="+str(nproc) - + cmd = "./test_multigrid_laplace -f BOUT_unsheared.inp nxpe=" + str(nproc) + shell("rm data/BOUT.dmp.*.nc") - print(" %d processors..." %nproc) + print(" %d processors..." % nproc) s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) - with open("run.log."+str(nproc), "w") as f: + with open("run.log." + str(nproc), "w") as f: f.write(out) # Collect errors - errors = [collect("max_error"+str(i), path="data") for i in range(1,numTests+1)] + errors = [ + collect("max_error" + str(i), path="data") for i in range(1, numTests + 1) + ] - for i,e in enumerate(errors): - print("Checking test "+str(i)) - if e < 0.: + for i, e in enumerate(errors): + print("Checking test " + str(i)) + if e < 0.0: print("Fail, solver did not converge") success = False if e > tol: - print("Fail, maximum absolute error = "+str(e)) + print("Fail, maximum absolute error = " + str(e)) success = False else: print("Pass") diff --git a/tests/integrated/test-naulin-laplace/runtest b/tests/integrated/test-naulin-laplace/runtest index d49cff5d45..564e6c0a2c 100755 --- a/tests/integrated/test-naulin-laplace/runtest +++ b/tests/integrated/test-naulin-laplace/runtest @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -#requires: not metric_3d +# requires: not metric_3d # # Run the test, check the error @@ -9,13 +9,14 @@ # Cores: 3 from __future__ import print_function + try: from builtins import str except: pass -tol = 2e-7 # Absolute tolerance -numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) +tol = 2e-7 # Absolute tolerance +numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -27,34 +28,36 @@ build_and_log("LaplaceNaulin inversion test") print("Running LaplaceNaulin inversion test") success = True -for nproc in [1,3]: +for nproc in [1, 3]: # Make sure we don't use too many cores: # Reduce number of OpenMP threads when using multiple MPI processes mthread = 2 - if nproc>1: + if nproc > 1: mthread = 1 - + # set nxpe on the command line as we only use solution from one point in y, so splitting in y-direction is redundant (and also doesn't help test the solver) - cmd = "./test_naulin_laplace nxpe="+str(nproc) - + cmd = "./test_naulin_laplace nxpe=" + str(nproc) + shell("rm data/BOUT.dmp.*.nc") - print(" %d processors..." %nproc) + print(" %d processors..." % nproc) s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) - with open("run.log."+str(nproc), "w") as f: + with open("run.log." + str(nproc), "w") as f: f.write(out) # Collect errors - errors = [collect("max_error"+str(i), path="data") for i in range(1,numTests+1)] + errors = [ + collect("max_error" + str(i), path="data") for i in range(1, numTests + 1) + ] - for i,e in enumerate(errors): - print("Checking test "+str(i)) - if e < 0.: + for i, e in enumerate(errors): + print("Checking test " + str(i)) + if e < 0.0: print("Fail, solver did not converge") success = False if e > tol: - print("Fail, maximum absolute error = "+str(e)) + print("Fail, maximum absolute error = " + str(e)) success = False else: print("Pass") diff --git a/tests/integrated/test-naulin-laplace/runtest_multiple_grids b/tests/integrated/test-naulin-laplace/runtest_multiple_grids index 660b277405..d196b445b1 100755 --- a/tests/integrated/test-naulin-laplace/runtest_multiple_grids +++ b/tests/integrated/test-naulin-laplace/runtest_multiple_grids @@ -5,13 +5,14 @@ # from __future__ import print_function + try: from builtins import str except: pass -tol = 2e-6 # Absolute tolerance -numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) +tol = 2e-6 # Absolute tolerance +numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -23,29 +24,31 @@ build_and_log("Making LaplaceNaulin inversion test") print("Running LaplaceNaulin inversion test") success = True -for nproc in [1,2,4]: - for inputfile in ["BOUT_jy4.inp","BOUT_jy63.inp","BOUT_jy127.inp"]: - +for nproc in [1, 2, 4]: + for inputfile in ["BOUT_jy4.inp", "BOUT_jy63.inp", "BOUT_jy127.inp"]: + # set nxpe on the command line as we only use solution from one point in y, so splitting in y-direction is redundant (and also doesn't help test the solver) - cmd = "./test_naulin_laplace -f "+inputfile+" nxpe="+str(nproc) - + cmd = "./test_naulin_laplace -f " + inputfile + " nxpe=" + str(nproc) + shell("rm data/BOUT.dmp.*.nc") - print(" %d processors, input file is %s" %(nproc,inputfile)) + print(" %d processors, input file is %s" % (nproc, inputfile)) s, out = launch_safe(cmd, nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: + with open("run.log." + str(nproc), "w") as f: f.write(out) # Collect errors - errors = [collect("max_error"+str(i), path="data") for i in range(1,numTests+1)] + errors = [ + collect("max_error" + str(i), path="data") for i in range(1, numTests + 1) + ] - for i,e in enumerate(errors): - print("Checking test "+str(i)) - if e < 0.: + for i, e in enumerate(errors): + print("Checking test " + str(i)) + if e < 0.0: print("Fail, solver did not converge") success = False elif e > tol: - print("Fail, maximum absolute error = "+str(e)) + print("Fail, maximum absolute error = " + str(e)) success = False else: print("Pass") diff --git a/tests/integrated/test-naulin-laplace/runtest_unsheared b/tests/integrated/test-naulin-laplace/runtest_unsheared index 5f60e2fd18..c0b56573d4 100755 --- a/tests/integrated/test-naulin-laplace/runtest_unsheared +++ b/tests/integrated/test-naulin-laplace/runtest_unsheared @@ -5,13 +5,14 @@ # from __future__ import print_function + try: from builtins import str except: pass -tol = 1e-9 # Absolute tolerance -numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) +tol = 1e-9 # Absolute tolerance +numTests = 4 # We test 4 different boundary conditions (with slightly different inputs for each) from boututils.run_wrapper import shell, build_and_log, launch_safe from boutdata.collect import collect @@ -23,34 +24,36 @@ build_and_log("LaplaceNaulin inversion test") print("Running LaplaceNaulin inversion test") success = True -for nproc in [1,3]: +for nproc in [1, 3]: # Make sure we don't use too many cores: # Reduce number of OpenMP threads when using multiple MPI processes mthread = 2 - if nproc>1: + if nproc > 1: mthread = 1 - + # set nxpe on the command line as we only use solution from one point in y, so splitting in y-direction is redundant (and also doesn't help test the solver) - cmd = "./test_naulin_laplace -f BOUT_unsheared.inp nxpe="+str(nproc) - + cmd = "./test_naulin_laplace -f BOUT_unsheared.inp nxpe=" + str(nproc) + shell("rm data/BOUT.dmp.*.nc") - print(" %d processors..." %nproc) + print(" %d processors..." % nproc) s, out = launch_safe(cmd, nproc=nproc, mthread=mthread, pipe=True) - with open("run.log."+str(nproc), "w") as f: + with open("run.log." + str(nproc), "w") as f: f.write(out) # Collect errors - errors = [collect("max_error"+str(i), path="data") for i in range(1,numTests+1)] + errors = [ + collect("max_error" + str(i), path="data") for i in range(1, numTests + 1) + ] - for i,e in enumerate(errors): - print("Checking test "+str(i)) - if e < 0.: + for i, e in enumerate(errors): + print("Checking test " + str(i)) + if e < 0.0: print("Fail, solver did not converge") success = False elif e > tol: - print("Fail, maximum absolute error = "+str(e)) + print("Fail, maximum absolute error = " + str(e)) success = False else: print("Pass") diff --git a/tests/integrated/test-options-netcdf/runtest b/tests/integrated/test-options-netcdf/runtest index b02f80ddaf..ab05ee1caf 100755 --- a/tests/integrated/test-options-netcdf/runtest +++ b/tests/integrated/test-options-netcdf/runtest @@ -1,8 +1,8 @@ #!/usr/bin/env python3 # Note: This test requires NCDF4, whereas on Travis NCDF is used -#requires: netcdf -#requires: not legacy_netcdf +# requires: netcdf +# requires: not legacy_netcdf from boututils.datafile import DataFile from boututils.run_wrapper import build_and_log, shell, launch @@ -17,9 +17,9 @@ shell("rm -f test-out.nc") # Create a NetCDF input file with DataFile("test.nc", create=True, format="NETCDF4") as f: - f.write("int", 42); - f.write("real", 3.1415); - f.write("string", "hello"); + f.write("int", 42) + f.write("real", 3.1415) + f.write("string", "hello") # run BOUT++ launch("./test-options-netcdf", nproc=1, mthread=1) @@ -53,8 +53,8 @@ assert settings["mesh"]["ny"] == 2 print("Checking saved fields.nc") with DataFile("fields.nc") as f: - assert f["f2d"].shape == (5,6) # Field2D - assert f["f3d"].shape == (5,6,2) # Field3D + assert f["f2d"].shape == (5, 6) # Field2D + assert f["f3d"].shape == (5, 6, 2) # Field3D assert f["fperp"].shape == (5, 2) # FieldPerp assert np.allclose(f["f2d"], 1.0) assert np.allclose(f["f3d"], 2.0) @@ -63,11 +63,11 @@ with DataFile("fields.nc") as f: print("Checking saved fields2.nc") with DataFile("fields2.nc") as f: - assert f["f2d"].shape == (5,6) # Field2D - assert f["f3d"].shape == (5,6,2) # Field3D + assert f["f2d"].shape == (5, 6) # Field2D + assert f["f3d"].shape == (5, 6, 2) # Field3D assert f["fperp"].shape == (5, 2) # FieldPerp assert np.allclose(f["f2d"], 1.0) assert np.allclose(f["f3d"], 2.0) assert np.allclose(f["fperp"], 3.0) - + print(" => Passed") diff --git a/tests/integrated/test-petsc_laplace/runtest b/tests/integrated/test-petsc_laplace/runtest index e1523cbd5c..ac248c4ce7 100755 --- a/tests/integrated/test-petsc_laplace/runtest +++ b/tests/integrated/test-petsc_laplace/runtest @@ -1,29 +1,33 @@ #!/usr/bin/env python3 -# +# # Run the test, compare results against the benchmark # -#requires: petsc -#requires: all_tests -#cores: 4 +# requires: petsc +# requires: all_tests +# cores: 4 # Variables to compare from __future__ import print_function from builtins import str -vars = [('max_error1',2.e-4), - ('max_error2',2.e-4), - ('max_error3',2.e-4), - ('max_error4',1.e-5), - ('max_error5',2.e-4), - ('max_error6',2.e-5), - ('max_error7',2.e-4), - ('max_error8',2.e-5)] -#tol = 1e-4 # Absolute (?) tolerance + +vars = [ + ("max_error1", 2.0e-4), + ("max_error2", 2.0e-4), + ("max_error3", 2.0e-4), + ("max_error4", 1.0e-5), + ("max_error5", 2.0e-4), + ("max_error6", 2.0e-5), + ("max_error7", 2.0e-4), + ("max_error8", 2.0e-5), +] +# tol = 1e-4 # Absolute (?) tolerance from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect -#import numpy as np + +# import numpy as np from sys import stdout, exit @@ -32,37 +36,37 @@ build_and_log("PETSc Laplacian inversion test") print("Running PETSc Laplacian inversion test") success = True -for nproc in [1,2,4]: -# nxpe = 1 -# if nproc > 2: -# nxpe = 2 - - cmd = "./test_petsc_laplace" - - shell("rm data/BOUT.dmp.*.nc") +for nproc in [1, 2, 4]: + # nxpe = 1 + # if nproc > 2: + # nxpe = 2 + + cmd = "./test_petsc_laplace" + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processors...." % nproc) + s, out = launch_safe(cmd, nproc=nproc, pipe=True, verbose=True) + f = open("run.log." + str(nproc), "w") + f.write(out) + f.close() - print(" %d processors...." % nproc) - s, out = launch_safe(cmd, nproc=nproc, pipe=True,verbose=True) - f = open("run.log."+str(nproc), "w") - f.write(out) - f.close() - - # Collect output data - for varname, tol in vars: - stdout.write(" Checking " + varname + " ... ") - error = collect(varname, path="data", info=False) - if error <= 0: - print("Convergence error") - success = False - elif error > tol: - print("Fail, maximum error is = "+str(error)) - success = False - else: - print("Pass") + # Collect output data + for varname, tol in vars: + stdout.write(" Checking " + varname + " ... ") + error = collect(varname, path="data", info=False) + if error <= 0: + print("Convergence error") + success = False + elif error > tol: + print("Fail, maximum error is = " + str(error)) + success = False + else: + print("Pass") if success: - print(" => All PETSc Laplacian inversion tests passed") - exit(0) + print(" => All PETSc Laplacian inversion tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-petsc_laplace_MAST-grid/runtest b/tests/integrated/test-petsc_laplace_MAST-grid/runtest index 897d26dbdd..c1c973e3b2 100755 --- a/tests/integrated/test-petsc_laplace_MAST-grid/runtest +++ b/tests/integrated/test-petsc_laplace_MAST-grid/runtest @@ -1,68 +1,81 @@ #!/usr/bin/env python3 -# +# # Run the test, compare results against the benchmark # -#requires: all_tests -#requires: petsc -#cores: 4 +# requires: all_tests +# requires: petsc +# cores: 4 # Variables to compare from __future__ import print_function from builtins import str -vars = [['max_error1',2.e-4], - ['max_error2',1.e-4], - ['max_error3',1.e-4], - ['max_error4',1.e-4], - ['max_error5',2.e-3], - ['max_error6',3.e-4], - ['max_error7',2.e-4], - ['max_error8',1.e-4]] -#tol = 1e-4 # Absolute (?) tolerance + +vars = [ + ["max_error1", 2.0e-4], + ["max_error2", 1.0e-4], + ["max_error3", 1.0e-4], + ["max_error4", 1.0e-4], + ["max_error5", 2.0e-3], + ["max_error6", 3.0e-4], + ["max_error7", 2.0e-4], + ["max_error8", 1.0e-4], +] +# tol = 1e-4 # Absolute (?) tolerance from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect from sys import stdout, exit -build_and_log("PETSc Laplacian inversion test with non-identity metric (taken from grid for MAST SOL)") +build_and_log( + "PETSc Laplacian inversion test with non-identity metric (taken from grid for MAST SOL)" +) -print("Running PETSc Laplacian inversion test with non-identity metric (taken from grid for MAST SOL)") +print( + "Running PETSc Laplacian inversion test with non-identity metric (taken from grid for MAST SOL)" +) success = True -for nproc in [1,2,4]: - # nxpe = 1 - # if nproc > 2: - # nxpe = 2 - for jy in [2,34,65,81,113]: +for nproc in [1, 2, 4]: + # nxpe = 1 + # if nproc > 2: + # nxpe = 2 + for jy in [2, 34, 65, 81, 113]: - cmd = "./test_petsc_laplace_MAST_grid grid=grids/grid_MAST_SOL_jyis{}.nc".format(jy) + cmd = ( + "./test_petsc_laplace_MAST_grid grid=grids/grid_MAST_SOL_jyis{}.nc".format( + jy + ) + ) - shell("rm data/BOUT.dmp.*.nc") + shell("rm data/BOUT.dmp.*.nc") - print(" {} processors, grid_MAST_SOL_jyis{}".format(nproc, jy)) - s, out = launch_safe(cmd, nproc=nproc, pipe=True) - f = open("run.log."+str(nproc), "w") - f.write(out) - f.close() + print(" {} processors, grid_MAST_SOL_jyis{}".format(nproc, jy)) + s, out = launch_safe(cmd, nproc=nproc, pipe=True) + f = open("run.log." + str(nproc), "w") + f.write(out) + f.close() - # Collect output data - for v in vars: - stdout.write(" Checking "+v[0]+" ... ") - error = collect(v[0], path="data", info=False) - if error <= 0: - print("Convergence error") - success = False - elif error > v[1]: - print("Fail, maximum error is = "+str(error)) - success = False - else: - print("Pass") + # Collect output data + for v in vars: + stdout.write(" Checking " + v[0] + " ... ") + error = collect(v[0], path="data", info=False) + if error <= 0: + print("Convergence error") + success = False + elif error > v[1]: + print("Fail, maximum error is = " + str(error)) + success = False + else: + print("Pass") if success: - print(" => All PETSc Laplacian inversion with non-identity metric (taken from grid for MAST SOL) tests passed") - exit(0) + print( + " => All PETSc Laplacian inversion with non-identity metric (taken from grid for MAST SOL) tests passed" + ) + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-region-iterator/runtest b/tests/integrated/test-region-iterator/runtest index dbc1c4a34f..e5825285de 100755 --- a/tests/integrated/test-region-iterator/runtest +++ b/tests/integrated/test-region-iterator/runtest @@ -4,14 +4,15 @@ # Run the test, check it completed successfully # -#requires: netcdf -#cores: 2 +# requires: netcdf +# cores: 2 from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass + pass from boututils.run_wrapper import build_and_log, launch_safe from boutdata.collect import collect from sys import exit @@ -21,28 +22,28 @@ build_and_log("Region Iterator test") flags = [""] cmd = "./test_region_iterator" -code = 0 # Return code -pipe=True +code = 0 # Return code +pipe = True -for nproc in [1,2]:#Number of mpi procs - for mthread in [1]:#Number of omp threads (not yet supported) - print("\t{n} processors and {m} threads".format(n=nproc,m=mthread)) +for nproc in [1, 2]: # Number of mpi procs + for mthread in [1]: # Number of omp threads (not yet supported) + print("\t{n} processors and {m} threads".format(n=nproc, m=mthread)) - for f in flags: - # Run the case - s, out = launch_safe(cmd+" "+f, nproc=nproc, pipe=pipe) - if pipe: - f = open("run.log."+str(nproc)+"."+str(mthread), "w") - f.write(out) - f.close() + for f in flags: + # Run the case + s, out = launch_safe(cmd + " " + f, nproc=nproc, pipe=pipe) + if pipe: + f = open("run.log." + str(nproc) + "." + str(mthread), "w") + f.write(out) + f.close() - #If we've got here we know that cmd launched by launch_safe passed - #as otherwise it raises. - print("Passed") + # If we've got here we know that cmd launched by launch_safe passed + # as otherwise it raises. + print("Passed") if code == 0: - print(" => All range iterator tests passed") + print(" => All range iterator tests passed") else: - print(" => Some failed tests") + print(" => Some failed tests") exit(code) diff --git a/tests/integrated/test-restart-io/runtest b/tests/integrated/test-restart-io/runtest index d2b5fae279..69da0aa2d5 100755 --- a/tests/integrated/test-restart-io/runtest +++ b/tests/integrated/test-restart-io/runtest @@ -23,58 +23,68 @@ myg = 2 build_and_log("restart I/O test") -x = numpy.linspace(0., 1., nx+2*mxg)[:, numpy.newaxis, numpy.newaxis] -y = numpy.linspace(0., 1., ny+2*myg)[numpy.newaxis, :, numpy.newaxis] -z = numpy.linspace(0., 1., nz)[numpy.newaxis, numpy.newaxis, :] +x = numpy.linspace(0.0, 1.0, nx + 2 * mxg)[:, numpy.newaxis, numpy.newaxis] +y = numpy.linspace(0.0, 1.0, ny + 2 * myg)[numpy.newaxis, :, numpy.newaxis] +z = numpy.linspace(0.0, 1.0, nz)[numpy.newaxis, numpy.newaxis, :] testvars = {} -testvars['f3d'] = BoutArray(numpy.exp(numpy.sin(x + y + z)), attributes = {'bout_type':'Field3D'}) -testvars['f2d'] = BoutArray(numpy.exp(numpy.sin(x + y + 1.))[:, :, 0], attributes = {'bout_type':'Field2D'}) -testvars['fperp_lower'] = BoutArray(numpy.exp(numpy.sin(x + z + 2.))[:, 0, :], attributes = {'bout_type':'FieldPerp', 'yindex_global':0}) -testvars['fperp_upper'] = BoutArray(numpy.exp(numpy.sin(x + z + 3.))[:, 0, :], attributes = {'bout_type':'FieldPerp', 'yindex_global':ny-1}) +testvars["f3d"] = BoutArray( + numpy.exp(numpy.sin(x + y + z)), attributes={"bout_type": "Field3D"} +) +testvars["f2d"] = BoutArray( + numpy.exp(numpy.sin(x + y + 1.0))[:, :, 0], attributes={"bout_type": "Field2D"} +) +testvars["fperp_lower"] = BoutArray( + numpy.exp(numpy.sin(x + z + 2.0))[:, 0, :], + attributes={"bout_type": "FieldPerp", "yindex_global": 0}, +) +testvars["fperp_upper"] = BoutArray( + numpy.exp(numpy.sin(x + z + 3.0))[:, 0, :], + attributes={"bout_type": "FieldPerp", "yindex_global": ny - 1}, +) # make restart file -restartdir = os.path.join('data', 'restart') +restartdir = os.path.join("data", "restart") try: os.mkdir(restartdir) except FileExistsError: pass -with DataFile(os.path.join(restartdir, 'BOUT.restart.0.nc'), create=True) as base_restart: - base_restart.write('MXSUB', nx) - base_restart.write('MYSUB', ny) - base_restart.write('MZSUB', nz) - base_restart.write('MXG', mxg) - base_restart.write('MYG', myg) - base_restart.write('MZG', 0) - base_restart.write('nx', nx+2*mxg) - base_restart.write('ny', ny) - base_restart.write('nz', nz) - base_restart.write('MZ', nz) - base_restart.write('NXPE', 1) - base_restart.write('NYPE', 1) - base_restart.write('NZPE', 1) - base_restart.write('tt', 0.) - base_restart.write('hist_hi', 0) +with DataFile( + os.path.join(restartdir, "BOUT.restart.0.nc"), create=True +) as base_restart: + base_restart.write("MXSUB", nx) + base_restart.write("MYSUB", ny) + base_restart.write("MZSUB", nz) + base_restart.write("MXG", mxg) + base_restart.write("MYG", myg) + base_restart.write("MZG", 0) + base_restart.write("nx", nx + 2 * mxg) + base_restart.write("ny", ny) + base_restart.write("nz", nz) + base_restart.write("MZ", nz) + base_restart.write("NXPE", 1) + base_restart.write("NYPE", 1) + base_restart.write("NZPE", 1) + base_restart.write("tt", 0.0) + base_restart.write("hist_hi", 0) # set BOUT_VERSION to stop collect from changing nz or printing a warning - base_restart.write('BOUT_VERSION', 4.) - base_restart.write('f3d', testvars['f3d']) - base_restart.write('f2d', testvars['f2d']) - base_restart.write('fperp_lower', testvars['fperp_lower']) - base_restart.write('fperp_upper', testvars['fperp_upper']) + base_restart.write("BOUT_VERSION", 4.0) + base_restart.write("f3d", testvars["f3d"]) + base_restart.write("f2d", testvars["f2d"]) + base_restart.write("fperp_lower", testvars["fperp_lower"]) + base_restart.write("fperp_upper", testvars["fperp_upper"]) # make run_id an array of characters because NetCDF doesn't like generic strings - run_id_string = '36 character run_id test string ****' - run_id = numpy.array(list(run_id_string), dtype='S1') - run_id = BoutArray(run_id, attributes = {'bout_type': 'string'}) - base_restart.write('run_id', run_id) + run_id_string = "36 character run_id test string ****" + run_id = numpy.array(list(run_id_string), dtype="S1") + run_id = BoutArray(run_id, attributes={"bout_type": "string"}) + base_restart.write("run_id", run_id) run_restart_from = numpy.array( - list('36 character run_restart_from string'), dtype='S1' + list("36 character run_restart_from string"), dtype="S1" ) - run_restart_from = BoutArray( - run_restart_from, attributes = {'bout_type': 'string'} - ) - base_restart.write('run_restart_from', run_restart_from) + run_restart_from = BoutArray(run_restart_from, attributes={"bout_type": "string"}) + base_restart.write("run_restart_from", run_restart_from) success = True @@ -88,69 +98,90 @@ for nproc in [1, 2, 4]: shell("rm -f data/BOUT.dmp.*.nc data/BOUT.restart.*.nc") # create restart files for the run - restart.redistribute(nproc, path=restartdir, output='data') + restart.redistribute(nproc, path=restartdir, output="data") print(" %d processor...." % (nproc)) # run the test executable - s, out = launch_safe('./test-restart-io', nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: + s, out = launch_safe("./test-restart-io", nproc=nproc, pipe=True) + with open("run.log." + str(nproc), "w") as f: f.write(out) # check the results for name in testvars.keys(): # check non-evolving version - result = collect(name+"_once", path='data', xguards=True, yguards=True, info=False) + result = collect( + name + "_once", path="data", xguards=True, yguards=True, info=False + ) testvar = testvars[name] if not numpy.all(testvar == result): success = False - print(name+' is different') + print(name + " is different") # Don't plot anything by default if False: from boututils.showdata import showdata + showdata([result, testvar]) - if name == 'fperp_lower' or name == 'fperp_upper': - yindex_result = result.attributes['yindex_global'] - yindex_test = testvar.attributes['yindex_global'] + if name == "fperp_lower" or name == "fperp_upper": + yindex_result = result.attributes["yindex_global"] + yindex_test = testvar.attributes["yindex_global"] if not yindex_result == yindex_test: success = False - print('Fail: yindex_global of '+name+' is '+str(yindex_result)+' should be '+str(yindex_test)) + print( + "Fail: yindex_global of " + + name + + " is " + + str(yindex_result) + + " should be " + + str(yindex_test) + ) # check evolving versions - result = collect(name, path='data', xguards=True, yguards=True, info=False) + result = collect(name, path="data", xguards=True, yguards=True, info=False) for result_timeslice in result: if not numpy.all(testvar == result_timeslice): success = False - print(name+' evolving version is different') - if name == 'fperp_lower' or name == 'fperp_upper': - yindex_result = result.attributes['yindex_global'] - yindex_test = testvar.attributes['yindex_global'] + print(name + " evolving version is different") + if name == "fperp_lower" or name == "fperp_upper": + yindex_result = result.attributes["yindex_global"] + yindex_test = testvar.attributes["yindex_global"] if not yindex_result == yindex_test: success = False - print('Fail: yindex_global of '+name+' evolving version is '+str(yindex_result)+' should be '+str(yindex_test)) + print( + "Fail: yindex_global of " + + name + + " evolving version is " + + str(yindex_result) + + " should be " + + str(yindex_test) + ) # check the run_id - run_id = collect('run_id', path='data', info=False) + run_id = collect("run_id", path="data", info=False) # check run_id can be converted to a valid UUID try: uuid.UUID(run_id.tobytes().decode()) except ValueError: success = False - print('run_id=' + str(run_id) + ' is not a valid UUID') - run_restart_from = collect('run_restart_from', path='data', info=False) + print("run_id=" + str(run_id) + " is not a valid UUID") + run_restart_from = collect("run_restart_from", path="data", info=False) if not run_restart_from.tobytes().decode() == run_id_string: success = False print( - 'incorrect run_restart_from=' + run_restart_from.tobytes().decode() - + '. Expected ' + run_id_string + "incorrect run_restart_from=" + + run_restart_from.tobytes().decode() + + ". Expected " + + run_id_string ) if success: - print('=> All restart I/O tests passed') + print("=> All restart I/O tests passed") # clean up binary files - shell("rm -f data/BOUT.dmp.*.nc data/BOUT.restart.*.nc data/restart/BOUT.restart.0.nc") + shell( + "rm -f data/BOUT.dmp.*.nc data/BOUT.restart.*.nc data/restart/BOUT.restart.0.nc" + ) exit(0) print("=> Some failed tests") diff --git a/tests/integrated/test-slepc-solver/runtest b/tests/integrated/test-slepc-solver/runtest index 333432e09a..baced1bcf3 100755 --- a/tests/integrated/test-slepc-solver/runtest +++ b/tests/integrated/test-slepc-solver/runtest @@ -11,12 +11,12 @@ build_and_log("SLEPc eigen solver test") print("Running SLEPc eigen solver test") status, out = launch_safe("./test-slepc-solver", nproc=1, pipe=True, verbose=True) -with open("run.log", 'w') as f: +with open("run.log", "w") as f: f.write(out) eigenvalues = collect("t_array", path="data", info=False) -expected_eigenvalues = [0., 1.] +expected_eigenvalues = [0.0, 1.0] if isclose(expected_eigenvalues, eigenvalues).all(): print(" => SLEPc test passed") diff --git a/tests/integrated/test-smooth/runtest b/tests/integrated/test-smooth/runtest index 3878763687..a661d18886 100755 --- a/tests/integrated/test-smooth/runtest +++ b/tests/integrated/test-smooth/runtest @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# +# # Run the test, compare results against the benchmark # @@ -9,12 +9,13 @@ # Variables to compare from __future__ import print_function + try: - from builtins import str + from builtins import str except: - pass -vars = ['yavg2d', 'yavg3d', 'sm3d'] -tol = 1e-10 # Absolute tolerance + pass +vars = ["yavg2d", "yavg3d", "sm3d"] +tol = 1e-10 # Absolute tolerance from boututils.run_wrapper import build_and_log, shell, launch_safe from boutdata.collect import collect @@ -28,43 +29,43 @@ build_and_log("smoothing operator test") print("Reading benchmark data") bmk = {} for v in vars: - bmk[v] = collect(v, path="data", prefix="benchmark", info=False) + bmk[v] = collect(v, path="data", prefix="benchmark", info=False) print("Running smoothing operator test") success = True -for nype in [1,2]: - for nxpe in [1,2]: - nproc = nxpe * nype - cmd = "./test_smooth" - - shell("rm data/BOUT.dmp.*.nc") +for nype in [1, 2]: + for nxpe in [1, 2]: + nproc = nxpe * nype + cmd = "./test_smooth" + + shell("rm data/BOUT.dmp.*.nc") + + print(" %d processor (%d x %d)...." % (nproc, nxpe, nype)) + s, out = launch_safe(cmd + " nxpe=" + str(nxpe), nproc=nproc, pipe=True) + with open("run.log." + str(nproc), "w") as f: + f.write(out) - print(" %d processor (%d x %d)...." % (nproc, nxpe, nype)) - s, out = launch_safe(cmd+" nxpe="+str(nxpe), nproc=nproc, pipe=True) - with open("run.log."+str(nproc), "w") as f: - f.write(out) + # Collect output data + for v in vars: + stdout.write(" Checking variable " + v + " ... ") + result = collect(v, path="data", info=False) + # Compare benchmark and output + if np.shape(bmk[v]) != np.shape(result): + print("Fail, wrong shape") + success = False + continue - # Collect output data - for v in vars: - stdout.write(" Checking variable "+v+" ... ") - result = collect(v, path="data", info=False) - # Compare benchmark and output - if np.shape(bmk[v]) != np.shape(result): - print("Fail, wrong shape") - success = False - continue - - diff = np.max(np.abs(bmk[v] - result)) - if diff > tol: - print("Fail, maximum difference = "+str(diff)) - success = False - else: - print("Pass") + diff = np.max(np.abs(bmk[v] - result)) + if diff > tol: + print("Fail, maximum difference = " + str(diff)) + success = False + else: + print("Pass") if success: - print(" => All smoothing operator tests passed") - exit(0) + print(" => All smoothing operator tests passed") + exit(0) else: - print(" => Some failed tests") - exit(1) + print(" => Some failed tests") + exit(1) diff --git a/tests/integrated/test-squash/runtest b/tests/integrated/test-squash/runtest index 6e0051e497..50073b1814 100755 --- a/tests/integrated/test-squash/runtest +++ b/tests/integrated/test-squash/runtest @@ -13,7 +13,9 @@ import re # requires: netcdf # cores: 4 -IGNORED_VARS_PATTERN = re.compile("(wtime|ncalls|arkode|cvode|run_id|run_restart_from).*") +IGNORED_VARS_PATTERN = re.compile( + "(wtime|ncalls|arkode|cvode|run_id|run_restart_from).*" +) class timer(object): diff --git a/tests/integrated/test-stopCheck-file/runtest b/tests/integrated/test-stopCheck-file/runtest index 262bc146a8..f6ada7370f 100755 --- a/tests/integrated/test-stopCheck-file/runtest +++ b/tests/integrated/test-stopCheck-file/runtest @@ -28,7 +28,11 @@ for data_dir, stop_file in zip(data_dirs, stop_files): executable, data_dir, check, stop_file ) - s, out = launch(command, nproc=nproc, pipe=True,) + s, out = launch( + command, + nproc=nproc, + pipe=True, + ) with open("run.log.{}.{}".format(data_dir, check), "w") as f: f.write(out) diff --git a/tests/integrated/test-twistshift-staggered/runtest b/tests/integrated/test-twistshift-staggered/runtest index f0415bab89..2976a80ecd 100755 --- a/tests/integrated/test-twistshift-staggered/runtest +++ b/tests/integrated/test-twistshift-staggered/runtest @@ -5,48 +5,54 @@ from boututils.run_wrapper import build_and_log, launch_safe import numpy from sys import exit -datapath = 'data' +datapath = "data" nproc = 1 -tol = 1.e-13 +tol = 1.0e-13 -build_and_log('twistshift test') +build_and_log("twistshift test") -s, out = launch_safe('./test-twistshift', nproc=nproc, pipe=True) -with open("run.log."+str(nproc), "w") as f: +s, out = launch_safe("./test-twistshift", nproc=nproc, pipe=True) +with open("run.log." + str(nproc), "w") as f: f.write(out) -test = collect('test', path=datapath, yguards=True, info=False) -test_aligned = collect('test_aligned', path=datapath, yguards=True, info=False) -check = collect('check', path=datapath, yguards=True, info=False) +test = collect("test", path=datapath, yguards=True, info=False) +test_aligned = collect("test_aligned", path=datapath, yguards=True, info=False) +check = collect("check", path=datapath, yguards=True, info=False) -#from boututils.showdata import showdata -#showdata([test, test_aligned, check], titles=['test', 'test_aligned', 'check']) +# from boututils.showdata import showdata +# showdata([test, test_aligned, check], titles=['test', 'test_aligned', 'check']) success = True # Check test_aligned is *not* periodic in y def test1(ylower, yupper): global success - if numpy.any(numpy.abs(test_aligned[:, yupper, :] - test_aligned[:, ylower, :]) < 1.e-6): + if numpy.any( + numpy.abs(test_aligned[:, yupper, :] - test_aligned[:, ylower, :]) < 1.0e-6 + ): success = False - print("Fail - test_aligned should not be periodic jy=%i and jy=%i should be " - "different"%( yupper, ylower)) -test1(0,-4) -test1(1,-3) -test1(2,-2) -test1(3,-1) + print( + "Fail - test_aligned should not be periodic jy=%i and jy=%i should be " + "different" % (yupper, ylower) + ) + + +test1(0, -4) +test1(1, -3) +test1(2, -2) +test1(3, -1) # Check test_aligned is the same as check # Cannot check in guard cells, as the expression used for 'zShift' in the input file is # not the same as the corrected zShift used for the transforms in the guard cells if numpy.any(numpy.abs(test_aligned[2:-2, 2:-2, :] - check[2:-2, 2:-2, :]) > tol): success = False - print('Fail - test_aligned is different from the expected value') - print('test_aligned', test_aligned) - print('check', check) + print("Fail - test_aligned is different from the expected value") + print("test_aligned", test_aligned) + print("check", check) if success: - print('Pass') + print("Pass") exit(0) else: exit(1) diff --git a/tests/integrated/test-twistshift/runtest b/tests/integrated/test-twistshift/runtest index 322c7d8071..26b5c2b135 100755 --- a/tests/integrated/test-twistshift/runtest +++ b/tests/integrated/test-twistshift/runtest @@ -5,36 +5,44 @@ from boututils.run_wrapper import build_and_log, launch_safe import numpy from sys import exit -datapath = 'data' +datapath = "data" nproc = 1 -tol = 1.e-13 +tol = 1.0e-13 -build_and_log('twistshift test') +build_and_log("twistshift test") -s, out = launch_safe('./test-twistshift', nproc=nproc, pipe=True) -with open("run.log."+str(nproc), "w") as f: +s, out = launch_safe("./test-twistshift", nproc=nproc, pipe=True) +with open("run.log." + str(nproc), "w") as f: f.write(out) -test = collect('test', path=datapath, yguards=True, info=False) -test_aligned = collect('test_aligned', path=datapath, yguards=True, info=False) -result = collect('result', path=datapath, yguards=True, info=False) +test = collect("test", path=datapath, yguards=True, info=False) +test_aligned = collect("test_aligned", path=datapath, yguards=True, info=False) +result = collect("result", path=datapath, yguards=True, info=False) -#from boututils.showdata import showdata -#showdata([test, test_aligned, result], titles=['test', 'test_aligned', 'result']) +# from boututils.showdata import showdata +# showdata([test, test_aligned, result], titles=['test', 'test_aligned', 'result']) success = True # Check test_aligned is *not* periodic in y def test1(ylower, yupper): global success - if numpy.any(numpy.abs(test_aligned[:, yupper, :] - test_aligned[:, ylower, :]) < 1.e-6): + if numpy.any( + numpy.abs(test_aligned[:, yupper, :] - test_aligned[:, ylower, :]) < 1.0e-6 + ): success = False - print("Fail - test_aligned should not be periodic jy=%i and jy=%i should be " - "different", yupper, ylower) -test1(0,-4) -test1(1,-3) -test1(2,-2) -test1(3,-1) + print( + "Fail - test_aligned should not be periodic jy=%i and jy=%i should be " + "different", + yupper, + ylower, + ) + + +test1(0, -4) +test1(1, -3) +test1(2, -2) +test1(3, -1) # Check test and result are the same if numpy.any(numpy.abs(result - test) > tol): @@ -46,18 +54,24 @@ def test2(ylower, yupper): global success if numpy.any(numpy.abs(result[:, yupper, :] - result[:, ylower, :]) > tol): success = False - print("Fail - result should be periodic jy=%i and jy=%i should not be " - "different", yupper, ylower) + print( + "Fail - result should be periodic jy=%i and jy=%i should not be " + "different", + yupper, + ylower, + ) print(ylower, result[:, ylower, :]) print(yupper, result[:, yupper, :]) print(result[:, ylower, :] - result[:, yupper, :]) -test2(0,-4) -test2(1,-3) -test2(2,-2) -test2(3,-1) + + +test2(0, -4) +test2(1, -3) +test2(2, -2) +test2(3, -1) if success: - print('Pass') + print("Pass") exit(0) else: exit(1) diff --git a/tests/integrated/test_suite b/tests/integrated/test_suite index 680c004d26..6edc23ab0d 100755 --- a/tests/integrated/test_suite +++ b/tests/integrated/test_suite @@ -22,47 +22,72 @@ import select ################################################################## import argparse -parser = argparse.ArgumentParser(description='Run or build some tests.') -parser.add_argument("-g", "--get-list", action='store_true', - help='Return a list of tests that would be run/build') -parser.add_argument("-m", "--make", action='store_true', - help='Build the tests, rather then run them.') -parser.add_argument("-a", "--all", action='store_true', dest="all_tests", - help="Run all tests") -parser.add_argument("-b", "--set-bool", nargs="+", metavar=('value1=False', 'value2=True'), - help='Set a bool value for evaluating what scripts can be run.') -parser.add_argument("-l", "--set-list", nargs="+", metavar=('test1', 'test2'), - help='Set the tests that should be run.') -parser.add_argument("-j", "--jobs", nargs=1, type=int, dest='jobs', - help='Set the number of cores to use in parallel.') + +parser = argparse.ArgumentParser(description="Run or build some tests.") +parser.add_argument( + "-g", + "--get-list", + action="store_true", + help="Return a list of tests that would be run/build", +) +parser.add_argument( + "-m", "--make", action="store_true", help="Build the tests, rather then run them." +) +parser.add_argument( + "-a", "--all", action="store_true", dest="all_tests", help="Run all tests" +) +parser.add_argument( + "-b", + "--set-bool", + nargs="+", + metavar=("value1=False", "value2=True"), + help="Set a bool value for evaluating what scripts can be run.", +) +parser.add_argument( + "-l", + "--set-list", + nargs="+", + metavar=("test1", "test2"), + help="Set the tests that should be run.", +) +parser.add_argument( + "-j", + "--jobs", + nargs=1, + type=int, + dest="jobs", + help="Set the number of cores to use in parallel.", +) args = parser.parse_args() ################################################################## -sys.path.append('..') +sys.path.append("..") from requirements import Requirements + requirements = Requirements() if args.set_bool is not None: - lookup = {'false': False, - 'no': False, - 'true': True, - 'yes': True} + lookup = {"false": False, "no": False, "true": True, "yes": True} for setbool in args.set_bool: k, v = setbool.split("=") v = lookup[v.lower()] requirements.add(k, v, override=True) try: - requirements.add('make', args.make) + requirements.add("make", args.make) except RuntimeError: - raise RuntimeError("The make flag needs to be set by passing --make rather then --set-bool make=True") + raise RuntimeError( + "The make flag needs to be set by passing --make rather then --set-bool make=True" + ) try: - requirements.add('all_tests', args.all_tests) + requirements.add("all_tests", args.all_tests) except RuntimeError: - raise RuntimeError("The all-tests flag needs to be set by passing --all rather then --set-bool all_tests=True") + raise RuntimeError( + "The all-tests flag needs to be set by passing --all rather then --set-bool all_tests=True" + ) ################################################################## # Parallel stuff @@ -78,8 +103,8 @@ except RuntimeError: # The beginning of MAKEFLAGS has some flags that tell us what we are # supposed to be doing. Most of them we can ignore. # Check what we are supposed to be doing: -if 'MAKEFLAGS' in os.environ: - makeflags = os.environ['MAKEFLAGS'] +if "MAKEFLAGS" in os.environ: + makeflags = os.environ["MAKEFLAGS"] for token in makeflags: if token == "n": # Print recipies: @@ -102,14 +127,14 @@ if 'MAKEFLAGS' in os.environ: break else: # Not implemented - print("mode '%s' not implemented"%token) - #sys.exit(42) + print("mode '%s' not implemented" % token) + # sys.exit(42) else: makeflags = "" -num_threads=1 +num_threads = 1 if args.jobs: num_threads = args.jobs[0] -js_read=None +js_read = None # if we are running under make, we only have one thread (called job # in make terms) for sure, but might be able to run more threads # (depending what other jobs are currently running) @@ -118,10 +143,10 @@ js_read=None # https://www.gnu.org/software/make/manual/html_node/POSIX-Jobserver.html if "--jobserver-auth=" in makeflags or "--jobserver-fds=" in makeflags: try: - offset=makeflags.index("--jobserver-auth=") + offset = makeflags.index("--jobserver-auth=") except ValueError: - offset=makeflags.index("--jobserver-fds=") - file_desc=[int(i) for i in re.findall("\d+",makeflags[offset:])[0:2]] + offset = makeflags.index("--jobserver-fds=") + file_desc = [int(i) for i in re.findall("\d+", makeflags[offset:])[0:2]] js_read = file_desc[0] js_write = file_desc[1] js_tokens = b"" @@ -139,46 +164,53 @@ class Test(threading.Thread): def run(self): # Check requirements - self.local.req_met, self.local.req_expr = requirements.check(self.name+"/runtest") + self.local.req_met, self.local.req_expr = requirements.check( + self.name + "/runtest" + ) self.local.start_time = time.time() if not self.local.req_met: - print("{:{width}}".format(self.name, width=self.width) + - "S - {0} => False".format(self.local.req_expr)) + print( + "{:{width}}".format(self.name, width=self.width) + + "S - {0} => False".format(self.local.req_expr) + ) sys.stdout.flush() self.status = 0 else: # Run test, piping stdout so it is not sent to console command = "cd {}; timeout {} {}".format(self.name, self.timeout, self.cmd) self.status, self.output = shell(command, pipe=True) - print("{:{width}}".format(self.name, width=self.width), end='') + print("{:{width}}".format(self.name, width=self.width), end="") if self.status == 0: # ✓ Passed - print(u"\u2713", end='') # No newline + print(u"\u2713", end="") # No newline elif self.status == 124: # 💤 timeout - print(u"\U0001f4a4", end='') # No newline + print(u"\U0001f4a4", end="") # No newline self.output += "\n(It is likely that a timeout occured)" else: # ❌ Failed - print(u"\u274C", end='') # No newline + print(u"\u274C", end="") # No newline print(" %7.3f s" % (time.time() - self.local.start_time), flush=True) def _cost(self): if self.cmd == "make": return 1 - with open(self.name+"/"+self.cmd,"r", encoding='utf8') as filein: + with open(self.name + "/" + self.cmd, "r", encoding="utf8") as filein: contents = filein.read() # Find all lines starting with '#cores' or '#Cores:' - match = re.findall( - "^\s*\#\s?[Cc]ores:\s*?(\d+)", contents, re.MULTILINE) + match = re.findall("^\s*\#\s?[Cc]ores:\s*?(\d+)", contents, re.MULTILINE) if len(match) > 1: - raise RuntimeError("Found more then one match for core-count in "+self.name) + raise RuntimeError( + "Found more then one match for core-count in " + self.name + ) if len(match) == 0: # default; no mpi return 1 c = int(match[0]) if c < 0: - raise RuntimeError("Core-count is %d and thus not positive in "%c+self.name) + raise RuntimeError( + "Core-count is %d and thus not positive in " % c + self.name + ) return c @@ -188,23 +220,23 @@ if args.set_list is None: # Get list of directories containing test cases try: # Requires python >= 3.5 - tests = glob.iglob('**/runtest', recursive=True) + tests = glob.iglob("**/runtest", recursive=True) except TypeError: # Fall back - check only a few folders ... - tests = glob.glob('*/runtest') - tests += glob.glob('*/*/runtest') - tests += glob.glob('*/*/*/runtest') + tests = glob.glob("*/runtest") + tests += glob.glob("*/*/runtest") + tests += glob.glob("*/*/*/runtest") - tests = [x.rsplit('/', 1)[0] for x in tests] + tests = [x.rsplit("/", 1)[0] for x in tests] else: # Take the user provided list - tests = [x.rstrip('/') for x in args.set_list] + tests = [x.rstrip("/") for x in args.set_list] if args.get_list: for test in tests: - req_met, _ = requirements.check(test+"/runtest") + req_met, _ = requirements.check(test + "/runtest") if req_met: print(test) sys.exit(0) @@ -220,7 +252,7 @@ def get_threads(): print("Warning - we are not part of the job pool 😭, running in serial") js_read = None return - isreadable,_,_ = select.select([js_read],[],[],0) + isreadable, _, _ = select.select([js_read], [], [], 0) if isreadable != []: # Only set shortly to non-blocking, and only if we # expect we can read. Old make uses blocking pipes, and @@ -246,19 +278,26 @@ start_time = time.time() test_type = "Making" if args.make else "Running" -print("======= {} {} {} tests ========".format(test_type, len(tests), savepath.split("/")[-1])) +print( + "======= {} {} {} tests ========".format( + test_type, len(tests), savepath.split("/")[-1] + ) +) longest = max([len(s) for s in tests]) avail_threads = num_threads -tester = sorted([Test(t, command, longest+1, timeout) for t in tests], - key=lambda x: x.cost, reverse=True) +tester = sorted( + [Test(t, command, longest + 1, timeout) for t in tests], + key=lambda x: x.cost, + reverse=True, +) cost_remain = sum(x.cost for x in tester) get_threads() -torun=[i for i in range(len(tests))] -running=[] +torun = [i for i in range(len(tests))] +running = [] -while len(torun)+len(running): +while len(torun) + len(running): if avail_threads: # See whether we can start one for i in torun[:]: @@ -280,10 +319,10 @@ while len(torun)+len(running): # Are any jobs finished for job in running: - job.join(.1) + job.join(0.1) if not job.is_alive(): if job.status: - failed.append([job.name,job.output]) + failed.append([job.name, job.output]) avail_threads += job.cost running.remove(job) @@ -295,7 +334,7 @@ while len(torun)+len(running): if avail_threads and js_read: old_tokens = js_tokens[0:avail_threads] js_tokens = js_tokens[avail_threads:] - os.write(js_write,old_tokens) + os.write(js_write, old_tokens) num_threads -= avail_threads avail_threads = 0 @@ -314,11 +353,13 @@ if failed: # Note: need Unicode string in case output contains unicode print(u"\n----- {0} -----\n{1}".format(test, output)) - print("======= {0} failed in {1:.2f} seconds ========".format( - len(failed), elapsed_time)) + print( + "======= {0} failed in {1:.2f} seconds ========".format( + len(failed), elapsed_time + ) + ) sys.exit(1) else: - print("======= All tests passed in {0:.2f} seconds =======".format( - elapsed_time)) + print("======= All tests passed in {0:.2f} seconds =======".format(elapsed_time)) diff --git a/tests/requirements/metric_3d b/tests/requirements/metric_3d index 052813fc84..209ca4e05c 100755 --- a/tests/requirements/metric_3d +++ b/tests/requirements/metric_3d @@ -8,9 +8,9 @@ from boututils.run_wrapper import shell selflocation = os.path.realpath(__file__) selflocation = os.path.dirname(selflocation) -status, out = shell(selflocation+"/../../bin/bout-config --metric-type", pipe=True) +status, out = shell(selflocation + "/../../bin/bout-config --metric-type", pipe=True) if "3D" in out: - exit(0) # True + exit(0) # True -exit(1) # False +exit(1) # False diff --git a/tests/requirements/requirements.py b/tests/requirements/requirements.py index d1085df100..030a4e6e0d 100755 --- a/tests/requirements/requirements.py +++ b/tests/requirements/requirements.py @@ -34,9 +34,11 @@ def __init__(self, path=None, verbose=False): # Get list of files in subdirectory, excluding common temporaries, # hidden files, and python .py and .pyc files - requirements_list = [x for x in os.listdir(path) - if not (("#" in x) or ("~" in x) - or (x[0] == ".") or (".py" in x))] + requirements_list = [ + x + for x in os.listdir(path) + if not (("#" in x) or ("~" in x) or (x[0] == ".") or (".py" in x)) + ] if verbose: print("======= Requirement checks ========") @@ -46,7 +48,7 @@ def __init__(self, path=None, verbose=False): status, out = shell(os.path.join(path, requirement), pipe=True) self.add(requirement, (status == 0)) - with open(selflocation+"/../../bin/bout-config") as configfile: + with open(selflocation + "/../../bin/bout-config") as configfile: config = configfile.read() matches = re.findall("^has_(.*)=(.*)", config, re.MULTILINE) for match in matches: @@ -56,8 +58,9 @@ def __init__(self, path=None, verbose=False): try: value = yesno[value] except KeyError: - print("Error parsing "+match + - " - %s is not \"yes\"/\"no\"" % match[1]) + print( + "Error parsing " + match + ' - %s is not "yes"/"no"' % match[1] + ) else: self.add(key, value) @@ -72,8 +75,7 @@ def check(self, script): contents = filein.read() # Find all lines starting with '#requires' or '#Requires:' - match = re.findall( - "^\s*\#\s?[Rr]equires:?(.*)", contents, re.MULTILINE) + match = re.findall("^\s*\#\s?[Rr]equires:?(.*)", contents, re.MULTILINE) # Iterate over all expressions to evaluate for expr in match: try: @@ -100,7 +102,8 @@ def add(self, requirement, value, override=False): old = self._requirements[requirement] if old != value and override is False: raise RuntimeError( - "Overwriting %s with %s in key %s" % (value, old, requirement)) + "Overwriting %s with %s in key %s" % (value, old, requirement) + ) self._requirements[requirement] = value if self._verbose: print("{0} => {1}".format(requirement, value)) diff --git a/tests/requirements/scipy b/tests/requirements/scipy index d3caa44c9d..f7da79bdaa 100755 --- a/tests/requirements/scipy +++ b/tests/requirements/scipy @@ -5,7 +5,8 @@ from sys import exit try: - import scipy - exit(0) + import scipy + + exit(0) except ImportError: - exit(1) + exit(1) diff --git a/tools/pylib/_boutcore_build/debug.py b/tools/pylib/_boutcore_build/debug.py index 8eb8dea3ed..4d0440f0af 100755 --- a/tools/pylib/_boutcore_build/debug.py +++ b/tools/pylib/_boutcore_build/debug.py @@ -3,6 +3,7 @@ print("Trying import") import debug import sys + print(sys.argv) print("Trying init") debug.blas() diff --git a/tools/pylib/_boutcore_build/debug_setup.py b/tools/pylib/_boutcore_build/debug_setup.py index 74e856030a..ef248036ef 100644 --- a/tools/pylib/_boutcore_build/debug_setup.py +++ b/tools/pylib/_boutcore_build/debug_setup.py @@ -3,10 +3,11 @@ import os os.environ["CXX"] = "mpic++" -os.environ["CC"] = "mpic++" +os.environ["CC"] = "mpic++" setup( - ext_modules = cythonize("debug.pyx", - language="c++", # generate C++ code - ) + ext_modules=cythonize( + "debug.pyx", + language="c++", # generate C++ code + ) ) diff --git a/tools/pylib/_boutcore_build/geninput.py b/tools/pylib/_boutcore_build/geninput.py index 7f28d5e650..88cd0f8d16 100644 --- a/tools/pylib/_boutcore_build/geninput.py +++ b/tools/pylib/_boutcore_build/geninput.py @@ -2,14 +2,14 @@ import boutcore as bc import numpy as np + bc.init("-d input -f ../data/BOUT.inp".split(" ")) -f=bc.Field3D.fromMesh(None) -f.setAll(np.array([[[1.]]])) -f2=bc.Field3D.fromMesh(None) -f2.setAll(np.array([[[2.]]])) +f = bc.Field3D.fromMesh(None) +f.setAll(np.array([[[1.0]]])) +f2 = bc.Field3D.fromMesh(None) +f2.setAll(np.array([[[2.0]]])) print(f.getAll()) -dump=bc.Datafile() # get global :( -dump.add(f3d=f,f2d=f2,save_repeat=True) +dump = bc.Datafile() # get global :( +dump.add(f3d=f, f2d=f2, save_repeat=True) dump.write() - diff --git a/tools/pylib/_boutcore_build/helper.py b/tools/pylib/_boutcore_build/helper.py index 0640deed25..2022ece51a 100644 --- a/tools/pylib/_boutcore_build/helper.py +++ b/tools/pylib/_boutcore_build/helper.py @@ -1,23 +1,26 @@ -def _resolve_slice(ind,num): - if isinstance(ind,slice): - ret=list(ind.indices(num)) - d=ret[1]-ret[0] - rem=d%ret[2] +def _resolve_slice(ind, num): + if isinstance(ind, slice): + ret = list(ind.indices(num)) + d = ret[1] - ret[0] + rem = d % ret[2] if rem != 0: - ret[1]-=rem - ret[1]+=ret[2] + ret[1] -= rem + ret[1] += ret[2] return ret else: if ind < 0: - ind=num+ind + ind = num + ind if ind < 0 or ind >= num: - raise IndexError("%d is out of range [%d:%d]"%(ind,0,num)) - return [ind,ind+1,1] - -def _resolve_slices(inds,nums): - if len(inds)!= len(nums): - raise IndexError("Expexted %d dimensions, but got %d dimensions."%(len(nums),len(inds))) - ret=[] + raise IndexError("%d is out of range [%d:%d]" % (ind, 0, num)) + return [ind, ind + 1, 1] + + +def _resolve_slices(inds, nums): + if len(inds) != len(nums): + raise IndexError( + "Expexted %d dimensions, but got %d dimensions." % (len(nums), len(inds)) + ) + ret = [] for i in range(len(inds)): - ret.append(_resolve_slice(inds[i],nums[i])) + ret.append(_resolve_slice(inds[i], nums[i])) return ret diff --git a/tools/pylib/post_bout/ListDict.py b/tools/pylib/post_bout/ListDict.py index 169b24cc2e..f500825651 100644 --- a/tools/pylib/post_bout/ListDict.py +++ b/tools/pylib/post_bout/ListDict.py @@ -3,51 +3,48 @@ import os try: - boutpath = os.environ['BOUT_TOP'] - pylibpath = boutpath+'/pylib' - pbpath = pylibpath+'/post_bout' - boutdatapath = pylibpath+'/boutdata' - boututilpath = pylibpath+'/boututils' - - allpath = [boutpath,pylibpath,pbpath,boutdatapath,boututilpath] + boutpath = os.environ["BOUT_TOP"] + pylibpath = boutpath + "/pylib" + pbpath = pylibpath + "/post_bout" + boutdatapath = pylibpath + "/boutdata" + boututilpath = pylibpath + "/boututils" + + allpath = [boutpath, pylibpath, pbpath, boutdatapath, boututilpath] [sys.path.append(elem) for elem in allpath] except: - print('meh') + print("meh") import numpy as np -def ListDictKey(input,key): - #given a key and a list of dictionaries this method returns an ordered - #list of requested key values - output = [] - for x in input: - try : - #print x[key] - output.append(x[key]) - except: - print('Key not found') - return 1 - - return output - +def ListDictKey(input, key): + # given a key and a list of dictionaries this method returns an ordered + # list of requested key values + output = [] + for x in input: + try: + # print x[key] + output.append(x[key]) + except: + print("Key not found") + return 1 -def ListDictFilt(input,key,valuelist): - #given a key,value pair and a list of dictionaries this - #method returns an ordered list of dictionaries where (dict(key)==value) = True - #http://stackoverflow.com/questions/5762643/how-to-filter-list-of-dictionaries-with-matching-values-for-a-given-key - try: - x = copyf(input,key,valuelist) - return x - except: - return [] - -def copyf(dictlist, key, valuelist): - return [dictio for dictio in dictlist if dictio[key] in valuelist] + return output +def ListDictFilt(input, key, valuelist): + # given a key,value pair and a list of dictionaries this + # method returns an ordered list of dictionaries where (dict(key)==value) = True + # http://stackoverflow.com/questions/5762643/how-to-filter-list-of-dictionaries-with-matching-values-for-a-given-key + try: + x = copyf(input, key, valuelist) + return x + except: + return [] +def copyf(dictlist, key, valuelist): + return [dictio for dictio in dictlist if dictio[key] in valuelist] # def subset(obj): @@ -62,5 +59,3 @@ def copyf(dictlist, key, valuelist): # LinRes.__init__(self,alldb) # if model==True: # self.model() - - diff --git a/tools/pylib/post_bout/__init__.py b/tools/pylib/post_bout/__init__.py index 07a5701427..a06792ed41 100644 --- a/tools/pylib/post_bout/__init__.py +++ b/tools/pylib/post_bout/__init__.py @@ -1,5 +1,6 @@ from __future__ import print_function from __future__ import absolute_import + ################################################## # BOUT++ data package # @@ -15,41 +16,42 @@ try: - boutpath = os.environ['BOUT_TOP'] - pylibpath = boutpath+'/tools/pylib' - boutdatapath = pylibpath+'/boutdata' - boututilpath = pylibpath+'/boututils' - allpath = [boutpath,pylibpath,boutdatapath,boututilpath] + boutpath = os.environ["BOUT_TOP"] + pylibpath = boutpath + "/tools/pylib" + boutdatapath = pylibpath + "/boutdata" + boututilpath = pylibpath + "/boututils" + allpath = [boutpath, pylibpath, boutdatapath, boututilpath] [sys.path.append(elem) for elem in allpath] print(sys.path) - + # sys.path.append('/home/cryosphere/BOUT/tools/pylib') # sys.path.append('/home/cryosphere/BOUT/tools/pylib/boutdata') # sys.path.append('/home/cryosphere/BOUT/tools/pylib/boututils') - - print('in post_bout/__init__.py') - - import matplotlib - matplotlib.use('pdf') #savemovie must be called as a diff. sesssion - + + print("in post_bout/__init__.py") + + import matplotlib + + matplotlib.use("pdf") # savemovie must be called as a diff. sesssion + import gobject import numpy as np except ImportError: print("can't find the modules I need, you fail") - sys.exit() #no point in going on - - -#import some bout specific modules + sys.exit() # no point in going on + + +# import some bout specific modules try: import boutdata import boututils except: print("can't find bout related modules, you fail") - -#import some home-brewed modules - - -#create some aliases + +# import some home-brewed modules + + +# create some aliases try: @@ -58,7 +60,7 @@ print("Sorry, no read_grid") try: - from .read_inp import parse_inp, read_inp, read_log,metadata + from .read_inp import parse_inp, read_inp, read_log, metadata except: print("Sorry no parse_inp") @@ -78,7 +80,7 @@ print("Sorry, no basic_info") try: - from .pb_corral import corral,LinRes,subset + from .pb_corral import corral, LinRes, subset except: print("No corral") @@ -88,7 +90,7 @@ print("No ListDict") try: - #from rotate_mp import rotate + # from rotate_mp import rotate from rotate2 import rotate except: print("No rotate") diff --git a/tools/pylib/post_bout/basic_info.py b/tools/pylib/post_bout/basic_info.py index 0cb3f390a0..28660c39bc 100644 --- a/tools/pylib/post_bout/basic_info.py +++ b/tools/pylib/post_bout/basic_info.py @@ -3,368 +3,400 @@ from builtins import zip from builtins import range from past.utils import old_div -#basic_info return some statistical averages and harmonic info + +# basic_info return some statistical averages and harmonic info import numpy as np import math -def basic_info(data,meta,rescale=True,rotate=False,user_peak=0,nonlinear=None): - - print('in basic_info') - #from . import read_grid,parse_inp,read_inp,show - + +def basic_info(data, meta, rescale=True, rotate=False, user_peak=0, nonlinear=None): + + print("in basic_info") + # from . import read_grid,parse_inp,read_inp,show + dims = data.shape ndims = len(dims) - - - mxg = meta['MXG']['v'] - if ndims ==4: - nt,nx,ny,nz = data.shape - print(nt,nx,ny) + mxg = meta["MXG"]["v"] + + if ndims == 4: + nt, nx, ny, nz = data.shape + print(nt, nx, ny) else: print("something with dimesions") - dc = data.mean(1).mean(1).mean(1) # there MUST be a way to indicate all axis at once + dc = ( + data.mean(1).mean(1).mean(1) + ) # there MUST be a way to indicate all axis at once amp = abs(data).max(1).max(1).max(1) - dt = meta['dt']['v'] + dt = meta["dt"]["v"] if rescale: amp_o = amp - dc - fourDamp = np.repeat(amp_o,nx*ny*nz) - fourDamp = fourDamp.reshape(nt,nx,ny,nz) - dc_n = old_div(dc,amp_o) - data_n = old_div(data,fourDamp) - + fourDamp = np.repeat(amp_o, nx * ny * nz) + fourDamp = fourDamp.reshape(nt, nx, ny, nz) + dc_n = old_div(dc, amp_o) + data_n = old_div(data, fourDamp) + print(data.shape) dfdt = np.gradient(data)[0] dfdt = abs(dfdt).max(1).max(1).max(1) - + ave = {"amp": amp, "dc": dc, "amp_o": amp_o, "dfdt": dfdt} - ave = {'amp':amp,'dc':dc,'amp_o':amp_o,'dfdt':dfdt} - else: print("no rescaling") - ave = {'amp':amp,'dc':dc} - - if nonlinear is not None: #add nonlinear part if user provides - nl = abs(nonlinear[:,mxg:-1.0*mxg,:,:]).max(1).max(1).max(1) - nl_norm = (old_div(nl,dfdt)) *dt + ave = {"amp": amp, "dc": dc} - ave['nl'] =nl - ave['nl_norm'] = nl_norm + if nonlinear is not None: # add nonlinear part if user provides + nl = abs(nonlinear[:, mxg : -1.0 * mxg, :, :]).max(1).max(1).max(1) + nl_norm = (old_div(nl, dfdt)) * dt + ave["nl"] = nl + ave["nl_norm"] = nl_norm if rotate: - print('rotate stuff') + print("rotate stuff") # will need to provide some grid geometry to do this one - else: print('or not') - - #let's identify the dominant modes, for now at every [t,x] slice - #if the data set is too large we can average over x - peaks_db = fft_info(data,user_peak,meta=meta) #Nt X Nx X (# of loc. max) list of dict - - #print peaks[0]['gamma'] - return peaks_db,ave - -def fft_info(data,user_peak,dimension=[3,4],rescale=False,wavelet=False,show=False,meta=0,edgefix = False): + else: + print("or not") + + # let's identify the dominant modes, for now at every [t,x] slice + # if the data set is too large we can average over x + peaks_db = fft_info( + data, user_peak, meta=meta + ) # Nt X Nx X (# of loc. max) list of dict + + # print peaks[0]['gamma'] + return peaks_db, ave + + +def fft_info( + data, + user_peak, + dimension=[3, 4], + rescale=False, + wavelet=False, + show=False, + meta=0, + edgefix=False, +): import numpy as np import math - - - - print('in fft_inf0') + + print("in fft_inf0") dims = data.shape ndims = len(dims) - - if ndims==4: - nt,nx,ny,nz = data.shape + + if ndims == 4: + nt, nx, ny, nz = data.shape print(data.shape) else: print("something with dimesions") - - # data2 = data + + # data2 = data # if edgefix: # data2 = np.zeros((nt,nx,ny+1,nz+1)) - + # for t in range(nt): # for x in range(nx): # temp = np.append(data[t,x,:,:],[data[t,x,0,:]],0) # data2[t,x,:,:] = np.append(temp, # np.transpose([temp[:,0]]),1) - - - #dt, k labels for the revelant dimensions - - - dt = meta['dt']['v'] - dz = meta['dz'] - #IC = meta['IC'] - ky_max = old_div(ny,2) - kz_max = old_div(nz,2) - amp = abs(data).max(2).max(2) #nt x nx - - print('dt: ',dt) - - #print data[0,2,:,:] - - IC = amp[0,:].max() #intial condition, set + + # dt, k labels for the revelant dimensions + + dt = meta["dt"]["v"] + dz = meta["dz"] + # IC = meta['IC'] + ky_max = old_div(ny, 2) + kz_max = old_div(nz, 2) + amp = abs(data).max(2).max(2) # nt x nx + + print("dt: ", dt) + + # print data[0,2,:,:] + + IC = amp[0, :].max() # intial condition, set print(IC) - fft_data = np.fft.fft2(data)[:,:,0:ky_max,0:kz_max] #by default the last 2 dimensions - + fft_data = np.fft.fft2(data)[ + :, :, 0:ky_max, 0:kz_max + ] # by default the last 2 dimensions + power = fft_data.conj() * fft_data - #print power[0].max(), (IC*(ky_max)*(kz_max))**2 - - cross_pow = old_div((fft_data * (np.roll(fft_data,1,axis=0)).conj()),(ny*nz)) - + # print power[0].max(), (IC*(ky_max)*(kz_max))**2 + + cross_pow = old_div((fft_data * (np.roll(fft_data, 1, axis=0)).conj()), (ny * nz)) + if rescale: - fft_data_n = np.fft.fft2(data_n)[:,:,0:ky_max,0:kz_max] + fft_data_n = np.fft.fft2(data_n)[:, :, 0:ky_max, 0:kz_max] pow_n = np.sqrt((fft_data_n.conj() * fft_data_n).real) - - peaks = [[[] for i in range(nx)] for j in range(nt)] #a list of dictionaries + + peaks = [[[] for i in range(nx)] for j in range(nt)] # a list of dictionaries peaks_db = [] - peak_hist = [[0 for i in range(kz_max)] for j in range(ky_max)] #a 2d bin array + peak_hist = [[0 for i in range(kz_max)] for j in range(ky_max)] # a 2d bin array + + # for now using a lame 2x loop method - #for now using a lame 2x loop method - - if user_peak != 0: for mem in user_peak: print(mem) - peak_hist[int(mem[0])][int(mem[1])] = abs(power.mean(0).mean(0)[int(mem[0]),int(mem[1])]) - - #floor = ((IC*(kz_max*ky_max))**2)/10000 - + peak_hist[int(mem[0])][int(mem[1])] = abs( + power.mean(0).mean(0)[int(mem[0]), int(mem[1])] + ) + + # floor = ((IC*(kz_max*ky_max))**2)/10000 + else: for t in range(nt): for x in range(nx): - peaks[t][x] = local_maxima(power[t,x,:,:],0,floor = (IC*(kz_max*ky_max))**2) - for p in peaks[t][x] : #looping over each returned peakset at some fixed t,x pair - peak_hist[p['y_i']][p['z_i']] +=1 #average across t and x, at least exclude pad - floor = 0 - - - #this array is usefull for determining what the dominant modes are - #but we want to retain the option of observing how the amplitude - #of any give harmonic varies in space - - peak_hist = np.array(peak_hist) - - #let's find the top N overall powerfull harmnonics - net_peak = local_maxima(peak_hist,user_peak,bug=False) - - - print('net_peak: ',net_peak,user_peak != 0) - #dom_mode = [{'amp':[],'amp_n':[],'phase':[],'freq':[],'gamma':[]} for x in net_peak] + peaks[t][x] = local_maxima( + power[t, x, :, :], 0, floor=(IC * (kz_max * ky_max)) ** 2 + ) + for p in peaks[t][ + x + ]: # looping over each returned peakset at some fixed t,x pair + peak_hist[p["y_i"]][ + p["z_i"] + ] += 1 # average across t and x, at least exclude pad + floor = 0 + + # this array is usefull for determining what the dominant modes are + # but we want to retain the option of observing how the amplitude + # of any give harmonic varies in space + + peak_hist = np.array(peak_hist) + + # let's find the top N overall powerfull harmnonics + net_peak = local_maxima(peak_hist, user_peak, bug=False) + + print("net_peak: ", net_peak, user_peak != 0) + # dom_mode = [{'amp':[],'amp_n':[],'phase':[],'freq':[],'gamma':[]} for x in net_peak] dom_mode_db = [] - - - - Bp = meta['Bpxy']['v'][:,old_div(ny,2)] - B = meta['Bxy']['v'][:,old_div(ny,2)] - Bt = meta['Btxy']['v'][:,old_div(ny,2)] - rho_s = meta['rho_s']['v'] - - L_z = old_div(meta['L_z'],rho_s) - #L_z = - L_y = meta['lpar'] #already normalized earlier in read_inp.py - L_norm = old_div(meta['lbNorm'],rho_s) + Bp = meta["Bpxy"]["v"][:, old_div(ny, 2)] + B = meta["Bxy"]["v"][:, old_div(ny, 2)] + Bt = meta["Btxy"]["v"][:, old_div(ny, 2)] + + rho_s = meta["rho_s"]["v"] - hthe0_n = 1e2*meta['hthe0']['v']/rho_s #no x dep - hthe0_n_x = old_div(L_y,(2*np.pi)) #no x dep + L_z = old_div(meta["L_z"], rho_s) + # L_z = + L_y = meta["lpar"] # already normalized earlier in read_inp.py + L_norm = old_div(meta["lbNorm"], rho_s) - print('L_z,Ly: ' , L_z,L_y) + hthe0_n = 1e2 * meta["hthe0"]["v"] / rho_s # no x dep + hthe0_n_x = old_div(L_y, (2 * np.pi)) # no x dep - #if user provides the harmo nic info overide the found peaks + print("L_z,Ly: ", L_z, L_y) + # if user provides the harmo nic info overide the found peaks - #thi is where all the good stuff is picked up + # thi is where all the good stuff is picked up - #look at each mode annd pull out some usefull linear measures - for i,p in enumerate(net_peak): - # print i,p['y_i'],p['z_i'],fft_data.shape,fft_data[:,:,p['y_i'],p['z_i']].shape - - amp = (old_div(np.sqrt(power[:,:,p['y_i'],p['z_i']]),(kz_max*ky_max))).real - - #print (np.angle(fft_data[:,:,p['y_i'],p['z_i']],deg=False)).real + # look at each mode annd pull out some usefull linear measures + for i, p in enumerate(net_peak): + # print i,p['y_i'],p['z_i'],fft_data.shape,fft_data[:,:,p['y_i'],p['z_i']].shape - phase = -np.array(np.gradient(np.squeeze(np.angle(fft_data[:,:,p['y_i'],p['z_i']],deg=False)))[0].real) #nt x nx + amp = ( + old_div(np.sqrt(power[:, :, p["y_i"], p["z_i"]]), (kz_max * ky_max)) + ).real + + # print (np.angle(fft_data[:,:,p['y_i'],p['z_i']],deg=False)).real + + phase = -np.array( + np.gradient( + np.squeeze(np.angle(fft_data[:, :, p["y_i"], p["z_i"]], deg=False)) + )[0].real + ) # nt x nx gamma_instant = np.array(np.gradient(np.log(np.squeeze(amp)))[0]) - - #loop over radaii + + # loop over radaii phasenew = [] - gammanew =[] - from scipy.interpolate import interp2d,interp1d + gammanew = [] + from scipy.interpolate import interp2d, interp1d from scipy import interp + gamma_t = np.transpose(gamma_instant) - for i ,phase_r in enumerate(np.transpose(phase)): + for i, phase_r in enumerate(np.transpose(phase)): gamma_r = gamma_t[i] - jumps = np.where(abs(phase_r) > old_div(np.pi,32)) - #print jumps + jumps = np.where(abs(phase_r) > old_div(np.pi, 32)) + # print jumps if len(jumps[0]) != 0: - - - all_pts = np.array(list(range(0,nt))) - good_pts = (np.where(abs(phase_r) < old_div(np.pi,3)))[0] - #print good_pts,good_pts - #f = interp1d(good_pts,phase_r[good_pts],fill_value=.001) - #print max(all_pts), max(good_pts) - #phasenew.append(f(all_pts)) + + all_pts = np.array(list(range(0, nt))) + good_pts = (np.where(abs(phase_r) < old_div(np.pi, 3)))[0] + # print good_pts,good_pts + # f = interp1d(good_pts,phase_r[good_pts],fill_value=.001) + # print max(all_pts), max(good_pts) + # phasenew.append(f(all_pts)) try: - phase_r = (interp(all_pts,good_pts,phase_r[good_pts])) - gamma_r = (interp(all_pts,good_pts,gamma_r[good_pts])) + phase_r = interp(all_pts, good_pts, phase_r[good_pts]) + gamma_r = interp(all_pts, good_pts, gamma_r[good_pts]) except: - 'no phase smoothing' + "no phase smoothing" phasenew.append(phase_r) gammanew.append(gamma_r) - phase = old_div(np.transpose(phasenew),dt) - - gamma_i = old_div(np.transpose(gammanew),dt) - - - - - amp_n = (old_div(np.sqrt(power[:,:,p['y_i'],p['z_i']]),(kz_max*ky_max*amp))).real - #amp_n = dom_mode[i]['amp_n'] #nt x nx - - #let just look over the nx range - #lnamp = np.log(amp[nt/2:,2:-2]) + phase = old_div(np.transpose(phasenew), dt) + + gamma_i = old_div(np.transpose(gammanew), dt) + + amp_n = ( + old_div(np.sqrt(power[:, :, p["y_i"], p["z_i"]]), (kz_max * ky_max * amp)) + ).real + # amp_n = dom_mode[i]['amp_n'] #nt x nx + + # let just look over the nx range + # lnamp = np.log(amp[nt/2:,2:-2]) try: - lnamp = np.log(amp[old_div(nt,2):,:]) + lnamp = np.log(amp[old_div(nt, 2) :, :]) except: - print('some log(0) stuff in basic_info') + print("some log(0) stuff in basic_info") - t = dt*np.array(list(range(nt))) #dt matters obviouslyww - r = np.polyfit(t[old_div(nt,2):],lnamp,1,full=True) + t = dt * np.array(list(range(nt))) # dt matters obviouslyww + r = np.polyfit(t[old_div(nt, 2) :], lnamp, 1, full=True) - gamma_est = r[0][0] #nx - f0 = np.exp(r[0][1]) #nx + gamma_est = r[0][0] # nx + f0 = np.exp(r[0][1]) # nx res = r[1] - pad =[0,0] - #gamma_est = np.concatenate([pad,gamma_est,pad]) - #f0 = np.concatenate([pad,f0,pad]) - #res = np.concatenate([pad,res,pad]) - - #sig = res/np.sqrt((x['nt']-2)) - sig = np.sqrt(old_div(res,(nt-2))) - #sig0 = sig*np.sqrt(1/(x['nt'])+ ) # who cares - sig1 = sig*np.sqrt(old_div(1.0,(nt * t.var()))) + pad = [0, 0] + # gamma_est = np.concatenate([pad,gamma_est,pad]) + # f0 = np.concatenate([pad,f0,pad]) + # res = np.concatenate([pad,res,pad]) + + # sig = res/np.sqrt((x['nt']-2)) + sig = np.sqrt(old_div(res, (nt - 2))) + # sig0 = sig*np.sqrt(1/(x['nt'])+ ) # who cares + sig1 = sig * np.sqrt(old_div(1.0, (nt * t.var()))) nt = np.array(nt) - print('shapes ', nt.shape, nt, lnamp.shape, res.shape, gamma_est) - #print r - res = 1 - old_div(res,(nt*lnamp.var(0))) #nx + print("shapes ", nt.shape, nt, lnamp.shape, res.shape, gamma_est) + # print r + res = 1 - old_div(res, (nt * lnamp.var(0))) # nx res[0:2] = 0 res[-2:] = 0 - gamma=[gamma_est,sig1,f0,res] - - - + gamma = [gamma_est, sig1, f0, res] + # gamma_est2 = np.gradient(amp)[0]/(amp[:,:]*dt) # gamma_w = np.gradient(gamma_est2)[0] - + # gamma_i = np.abs(gamma_w).argmin(0) #index of the minimum for any given run # for j in range(nx): # gamma_w[0:max([gamma_i[j],nt/3]),j] = np.average(gamma_w)*100000.0 - - freq = np.array(weighted_avg_and_std( - phase[-10:,:],weights=np.ones(phase[-10:,:].shape)) ) - - + freq = np.array( + weighted_avg_and_std(phase[-10:, :], weights=np.ones(phase[-10:, :].shape)) + ) + # gamma = weighted_avg_and_std( - # gamma_est2[-5:,:],weights=np.ones(gamma_est2[-5:,:].shape)) - - - k = [[p['y_i'],p['z_i']], - [2*math.pi*float(p['y_i'])/L_y,2*math.pi*p['z_i']/L_z]] - #L_y is normalized - - #simple k def, works in drift-instability fine + # gamma_est2[-5:,:],weights=np.ones(gamma_est2[-5:,:].shape)) + + k = [ + [p["y_i"], p["z_i"]], + [2 * math.pi * float(p["y_i"]) / L_y, 2 * math.pi * p["z_i"] / L_z], + ] + # L_y is normalized + + # simple k def, works in drift-instability fine # k = [[p['y_i'],p['z_i']], # [(B/Bp)**-1*2*math.pi*float(p['y_i'])/(L_y),(B/Bp)*2*math.pi*p['z_i']/L_z]] # k_r = [[p['y_i'],p['z_i']], # [(Bp/B)*2*math.pi*float(p['y_i'])/(L_y), # (B/Bp)*2*math.pi*p['z_i']/L_z]] - - k_r = [[p['y_i'],p['z_i']], - [2*math.pi*float(p['y_i'])/(L_y), - (old_div(B,Bp))*2*math.pi*p['z_i']/L_z - + (old_div(Bt,B))*2*math.pi*float(p['y_i'])/(L_y)]] - #revised + k_r = [ + [p["y_i"], p["z_i"]], + [ + 2 * math.pi * float(p["y_i"]) / (L_y), + (old_div(B, Bp)) * 2 * math.pi * p["z_i"] / L_z + + (old_div(Bt, B)) * 2 * math.pi * float(p["y_i"]) / (L_y), + ], + ] + + # revised # k_r = [[p['y_i'],p['z_i']], # [2*math.pi*float(p['y_i'])/(L_y), - # (Bp/B)*2*math.pi*p['z_i']/L_z + # (Bp/B)*2*math.pi*p['z_i']/L_z # - (Bt/Bp)*2*math.pi*float(p['y_i'])/(L_y)]] -#revised - - - #what I think is the most general one, works in drift-instability again + # revised + + # what I think is the most general one, works in drift-instability again # seems to work for Bz only helimak, now trying Bp = Bt # k = [[p['y_i'],p['z_i']], # [((Bp/B)*float(p['y_i'])/(hthe0_n)) + # 2*np.pi*p['z_i']*np.sqrt(1-(Bp/B)**2)/L_z, - # 2*math.pi*p['z_i']/L_norm - + # 2*math.pi*p['z_i']/L_norm - # float(p['y_i'])*np.sqrt(1-(Bp/B)**2)/(hthe0_n)]] # k = [[p['y_i'],p['z_i']], # [((Bp/B)*float(p['y_i'])/(hthe0_n)), # 2*math.pi*p['z_i']/L_norm]] - #BOTH SEEM TO PRODOCE SAME RESULTS + # BOTH SEEM TO PRODOCE SAME RESULTS # k = [[p['y_i'],p['z_i']], # [(float(p['y_i'])/(hthe0_n_x)), # 2*math.pi*float(p['z_i'])/L_norm]] - - dom_mode_db.append({'modeid':i,'k':k[1],'gamma':gamma,'freq': freq, - 'amp': amp,'amp_n':amp_n,'phase':phase,'mn':k[0], - 'nt':nt,'k_r':k_r[1],'gamma_i':gamma_i}) + dom_mode_db.append( + { + "modeid": i, + "k": k[1], + "gamma": gamma, + "freq": freq, + "amp": amp, + "amp_n": amp_n, + "phase": phase, + "mn": k[0], + "nt": nt, + "k_r": k_r[1], + "gamma_i": gamma_i, + } + ) - return dom_mode_db -#return a 2d array fof boolean values, a very simple boolian filter -def local_maxima(array2d,user_peak,index=False,count=4,floor=0,bug=False): + +# return a 2d array fof boolean values, a very simple boolian filter +def local_maxima(array2d, user_peak, index=False, count=4, floor=0, bug=False): from operator import itemgetter, attrgetter - + if user_peak == 0: - where = ((array2d >= np.roll(array2d,1,0)) & - (array2d >= np.roll(array2d,-1,0)) & - (array2d >= np.roll(array2d,0,1)) & - (array2d >= np.roll(array2d,0,-1)) & - (array2d >= old_div(array2d.max(),5.0)) & - (array2d > floor*np.ones(array2d.shape)) & - (array2d >= array2d.mean())) - else: #some simpler filter if user indicated some modes + where = ( + (array2d >= np.roll(array2d, 1, 0)) + & (array2d >= np.roll(array2d, -1, 0)) + & (array2d >= np.roll(array2d, 0, 1)) + & (array2d >= np.roll(array2d, 0, -1)) + & (array2d >= old_div(array2d.max(), 5.0)) + & (array2d > floor * np.ones(array2d.shape)) + & (array2d >= array2d.mean()) + ) + else: # some simpler filter if user indicated some modes where = array2d > floor - #ignore the lesser local maxima, throw out anything with a ZERO - if bug==True: - print(array2d,array2d[where.nonzero()],where.nonzero()[0]) - - peaks = list(zip(where.nonzero()[0],where.nonzero()[1],array2d[where.nonzero()])) - - peaks = sorted(peaks,key=itemgetter(2),reverse=True) - - if len(peaks) > count and user_peak==0: + # ignore the lesser local maxima, throw out anything with a ZERO + if bug == True: + print(array2d, array2d[where.nonzero()], where.nonzero()[0]) + + peaks = list(zip(where.nonzero()[0], where.nonzero()[1], array2d[where.nonzero()])) + + peaks = sorted(peaks, key=itemgetter(2), reverse=True) + + if len(peaks) > count and user_peak == 0: peaks = peaks[0:count] - - - keys = ['y_i','z_i','amp'] - - peaks = [dict(list(zip(keys,peaks[x]))) for x in range(len(peaks))] - + + keys = ["y_i", "z_i", "amp"] + + peaks = [dict(list(zip(keys, peaks[x]))) for x in range(len(peaks))] + return peaks - #return np.array(peak_dic) + # return np.array(peak_dic) + def weighted_avg_and_std(values, weights): """ @@ -372,12 +404,21 @@ def weighted_avg_and_std(values, weights): values, weights -- Numpy ndarrays with the same shape. """ - + if len(values.shape) == 2: - average = np.average(values,0)#, weights=weights) - variance = old_div((np.inner(weights.transpose(),((values-average)**2).transpose()).diagonal()),weights.sum(0)) - else: + average = np.average(values, 0) # , weights=weights) + variance = old_div( + ( + np.inner( + weights.transpose(), ((values - average) ** 2).transpose() + ).diagonal() + ), + weights.sum(0), + ) + else: average = np.average(values, weights=weights) - variance = old_div(np.dot(weights, (values-average)**2),weights.sum()) # Fast and numerically precise + variance = old_div( + np.dot(weights, (values - average) ** 2), weights.sum() + ) # Fast and numerically precise - return [average,variance] + return [average, variance] diff --git a/tools/pylib/post_bout/grate2.py b/tools/pylib/post_bout/grate2.py index a6214ce482..58f5a47e2b 100644 --- a/tools/pylib/post_bout/grate2.py +++ b/tools/pylib/post_bout/grate2.py @@ -1,5 +1,6 @@ from __future__ import print_function from builtins import range + ### # compute average growth rate bout variable f and plane y # prints value in plane y and total average @@ -10,37 +11,43 @@ from boutdata.collect import collect from boututils.moment_xyzt import moment_xyzt -def avgrate(p, y=None, tind=None): - if tind is None : tind =0 +def avgrate(p, y=None, tind=None): - rmsp_f=moment_xyzt(p, 'RMS').rms + if tind is None: + tind = 0 - ni=np.shape(rmsp_f)[1] - nj=np.shape(rmsp_f)[2] + rmsp_f = moment_xyzt(p, "RMS").rms - growth=np.zeros((ni,nj)) + ni = np.shape(rmsp_f)[1] + nj = np.shape(rmsp_f)[2] - with np.errstate(divide='ignore'): + growth = np.zeros((ni, nj)) + with np.errstate(divide="ignore"): for i in range(ni): for j in range(nj): - growth[i,j]=np.gradient(np.log(rmsp_f[tind::,i,j]))[-1] - - d=np.ma.masked_array(growth,np.isnan(growth)) + growth[i, j] = np.gradient(np.log(rmsp_f[tind::, i, j]))[-1] -# masked arrays -# http://stackoverflow.com/questions/5480694/numpy-calculate-averages-with-nans-removed + d = np.ma.masked_array(growth, np.isnan(growth)) - print('Total average growth rate= ', np.mean(np.ma.masked_array(d,np.isinf(d)))) - if y is not None : print('Growth rate in plane', y, '= ', np.mean(np.ma.masked_array(growth[:,y],np.isnan(growth[:,y])))) + # masked arrays + # http://stackoverflow.com/questions/5480694/numpy-calculate-averages-with-nans-removed + print("Total average growth rate= ", np.mean(np.ma.masked_array(d, np.isinf(d)))) + if y is not None: + print( + "Growth rate in plane", + y, + "= ", + np.mean(np.ma.masked_array(growth[:, y], np.isnan(growth[:, y]))), + ) -#test -if __name__ == '__main__': - path='/Users/brey/BOUT/bout/examples/elm-pb/data' +# test +if __name__ == "__main__": + path = "/Users/brey/BOUT/bout/examples/elm-pb/data" data = collect("P", path=path) diff --git a/tools/pylib/post_bout/pb_corral.py b/tools/pylib/post_bout/pb_corral.py index 094266ddf4..70c9acf51f 100644 --- a/tools/pylib/post_bout/pb_corral.py +++ b/tools/pylib/post_bout/pb_corral.py @@ -8,20 +8,21 @@ from builtins import object import os import sys + try: - boutpath = os.environ['BOUT_TOP'] - pylibpath = boutpath+'tools/pylib' - pbpath = pylibpath+'/post_bout' - boutdatapath = pylibpath+'/boutdata' - boututilpath = pylibpath+'/boututils' - - allpath = [boutpath,pylibpath,pbpath,boutdatapath,boututilpath] + boutpath = os.environ["BOUT_TOP"] + pylibpath = boutpath + "tools/pylib" + pbpath = pylibpath + "/post_bout" + boutdatapath = pylibpath + "/boutdata" + boututilpath = pylibpath + "/boututils" + + allpath = [boutpath, pylibpath, pbpath, boutdatapath, boututilpath] [sys.path.append(elem) for elem in allpath] except: - print('unable to append needed .py files') + print("unable to append needed .py files") -sys.path.append('/usr/local/pylib') +sys.path.append("/usr/local/pylib") import post_bout as post_bout from .ListDict import ListDictKey, ListDictFilt @@ -30,291 +31,290 @@ from .read_cxx import read_cxx, findlowpass - import os import numpy as np import pickle -import subprocess - - -def corral(cached=True,refresh=False,debug=False,IConly=1, - logname='status.log',skew=False): - - print('in corral') - log = read_log(logname=logname) - #done = log['done'] - runs = log['runs'] #a list of all directories, we need this, - # only need 'runs' if the simulation is done - - current = log['current'] #always return the last data_dir - - print(log) - print('current:', current) - - if refresh==True: - - for i,path in enumerate(runs): - print(i,path) - a = post_bout.save(path=path,IConly=IConly) #re post-process a run - - - - elif cached == False: #if all the ind. simulation pkl files are in place skip this part - - a = post_bout.save(path=current) #save to current dir - #here is really where you shoudl write to status.log - #write_log('status.log', - cached = True - - #if done: - - all_ave = [] - all_modes =[] - print('last_one: ') - for i,val in enumerate(runs): - print(val) - mode_db,ave_db = post_bout.read(path=val) - #alldata.append(array) - all_modes.append(mode_db) - all_ave.append(ave_db) - - #build the end database - - - #remove the read in pickle - - #return alldb - def islist(input): - return isinstance(input,list) - - all_modes = list(filter(islist,all_modes)) - #all_ave = filter(islist,all_ave) - - #alldb = sum(alldb,[]) - #alldata = np.array(alldata) - all_modes = sum(all_modes,[]) - - nt = [] - for mode in all_modes: - nt.append(len(mode['amp'])) - nt = [max(nt)] - - nt = nt[0] - t = list(range(nt)) - i = 0 - - if debug: - return all_modes,all_ave - else: - return LinRes(all_modes) - +import subprocess + + +def corral( + cached=True, refresh=False, debug=False, IConly=1, logname="status.log", skew=False +): + + print("in corral") + log = read_log(logname=logname) + # done = log['done'] + runs = log["runs"] # a list of all directories, we need this, + # only need 'runs' if the simulation is done + + current = log["current"] # always return the last data_dir + + print(log) + print("current:", current) + + if refresh == True: + + for i, path in enumerate(runs): + print(i, path) + a = post_bout.save(path=path, IConly=IConly) # re post-process a run + + elif ( + cached == False + ): # if all the ind. simulation pkl files are in place skip this part + + a = post_bout.save(path=current) # save to current dir + # here is really where you shoudl write to status.log + # write_log('status.log', + cached = True + + # if done: + + all_ave = [] + all_modes = [] + print("last_one: ") + for i, val in enumerate(runs): + print(val) + mode_db, ave_db = post_bout.read(path=val) + # alldata.append(array) + all_modes.append(mode_db) + all_ave.append(ave_db) + + # build the end database + + # remove the read in pickle + + # return alldb + def islist(input): + return isinstance(input, list) + + all_modes = list(filter(islist, all_modes)) + # all_ave = filter(islist,all_ave) + + # alldb = sum(alldb,[]) + # alldata = np.array(alldata) + all_modes = sum(all_modes, []) + + nt = [] + for mode in all_modes: + nt.append(len(mode["amp"])) + nt = [max(nt)] + + nt = nt[0] + t = list(range(nt)) + i = 0 + + if debug: + return all_modes, all_ave + else: + return LinRes(all_modes) + + class LinRes(object): - def __init__(self,all_modes): + def __init__(self, all_modes): - self.mode_db = all_modes self.db = all_modes - #self.ave_db = all_ave - + # self.ave_db = all_ave + alldb = self.db - #self.modekeys = data[0]['fields']['Ni']['modes'][0].keys() - #print len(alldb) - - self.meta = np.array(ListDictKey(self.db,'meta'))[0] - + # self.modekeys = data[0]['fields']['Ni']['modes'][0].keys() + # print len(alldb) + + self.meta = np.array(ListDictKey(self.db, "meta"))[0] self.keys = list((self.mode_db)[0].keys()) - #self.avekeys = data[0]['fields']['Ni']['ave'].keys() - - #self.nrun = len(alldb) #number of runs - - self.path= np.array(ListDictKey(self.db,'path')) - self.cxx =[] - self.maxN =[] - - self.ave = np.array(ListDictKey(alldb,'ave')) - - #[self.cxx.append(read_cxx(path=elem,boutcxx='2fluid.cxx.ref')) for elem in self.path] - #[self.maxN.append(findlowpass(elem)) for elem in self.cxx] - [self.cxx.append(read_cxx(path=elem,boutcxx='physics_code.cxx.ref')) for elem in self.path] - - self.maxZ = np.array(ListDictKey(alldb,'maxZ')) + # self.avekeys = data[0]['fields']['Ni']['ave'].keys() + + # self.nrun = len(alldb) #number of runs + + self.path = np.array(ListDictKey(self.db, "path")) + self.cxx = [] + self.maxN = [] + + self.ave = np.array(ListDictKey(alldb, "ave")) + + # [self.cxx.append(read_cxx(path=elem,boutcxx='2fluid.cxx.ref')) for elem in self.path] + # [self.maxN.append(findlowpass(elem)) for elem in self.cxx] + [ + self.cxx.append(read_cxx(path=elem, boutcxx="physics_code.cxx.ref")) + for elem in self.path + ] + + self.maxZ = np.array(ListDictKey(alldb, "maxZ")) self.maxN = self.maxZ - #self.maxN = findlowpass(self.cxx) #low pass filt from .cxx - - self.nx = np.array(ListDictKey(alldb,'nx'))[0] - self.ny = np.array(ListDictKey(alldb,'ny'))[0] - self.nz = np.array(ListDictKey(alldb,'nz'))[0] - - #self.nt = int(data[0]['meta']['NOUT']['v']+1) - self.Rxy = np.array(ListDictKey(alldb,'Rxy')) - self.Rxynorm = np.array(ListDictKey(alldb,'Rxynorm')) - self.nt = np.array(ListDictKey(alldb,'nt')) - - - self.dt = np.array(ListDictKey(alldb,'dt')) - self.nfields = np.array(ListDictKey(alldb,'nfields')) - - self.field = np.array(ListDictKey(alldb,'field')) - - self.k = np.array(ListDictKey(alldb,'k')) - self.k_r = np.array(ListDictKey(alldb,'k_r')) - - self.mn = np.array(ListDictKey(alldb,'mn')) - - #return ListDictKey(alldb,'phase') - - #self.phase = np.array(ListDictKey(alldb,'phase')) - self.phase = ListDictKey(alldb,'phase') - - # self.amp= np.array(ListDictKey(alldb,'amp')) - # self.amp_n=np.array(ListDictKey(alldb,'amp_n')) - # self.dc= [] - # self.freq = np.array(ListDictKey(alldb,'k')) - # self.gamma = np.array(ListDictKey(alldb,'gamma')) - - self.amp= ListDictKey(alldb,'amp') - self.amp_n = ListDictKey(alldb,'amp_n') - self.dc= [] - #self.freq = np.array(ListDictKey(alldb,'k')) - self.gamma = np.array(ListDictKey(alldb,'gamma')) - self.gamma_i = np.array(ListDictKey(alldb,'gamma_i')) - - self.freq = np.array(ListDictKey(alldb,'freq')) - - self.IC = np.array(ListDictKey(alldb,'IC')) - self.dz = np.array(ListDictKey(alldb,'dz')) - self.meta['dz'] = np.array(list(set(self.dz).union())) + # self.maxN = findlowpass(self.cxx) #low pass filt from .cxx + + self.nx = np.array(ListDictKey(alldb, "nx"))[0] + self.ny = np.array(ListDictKey(alldb, "ny"))[0] + self.nz = np.array(ListDictKey(alldb, "nz"))[0] + + # self.nt = int(data[0]['meta']['NOUT']['v']+1) + self.Rxy = np.array(ListDictKey(alldb, "Rxy")) + self.Rxynorm = np.array(ListDictKey(alldb, "Rxynorm")) + self.nt = np.array(ListDictKey(alldb, "nt")) + + self.dt = np.array(ListDictKey(alldb, "dt")) + self.nfields = np.array(ListDictKey(alldb, "nfields")) + + self.field = np.array(ListDictKey(alldb, "field")) + + self.k = np.array(ListDictKey(alldb, "k")) + self.k_r = np.array(ListDictKey(alldb, "k_r")) + + self.mn = np.array(ListDictKey(alldb, "mn")) + + # return ListDictKey(alldb,'phase') + + # self.phase = np.array(ListDictKey(alldb,'phase')) + self.phase = ListDictKey(alldb, "phase") + + # self.amp= np.array(ListDictKey(alldb,'amp')) + # self.amp_n=np.array(ListDictKey(alldb,'amp_n')) + # self.dc= [] + # self.freq = np.array(ListDictKey(alldb,'k')) + # self.gamma = np.array(ListDictKey(alldb,'gamma')) + + self.amp = ListDictKey(alldb, "amp") + self.amp_n = ListDictKey(alldb, "amp_n") + self.dc = [] + # self.freq = np.array(ListDictKey(alldb,'k')) + self.gamma = np.array(ListDictKey(alldb, "gamma")) + self.gamma_i = np.array(ListDictKey(alldb, "gamma_i")) + + self.freq = np.array(ListDictKey(alldb, "freq")) + + self.IC = np.array(ListDictKey(alldb, "IC")) + self.dz = np.array(ListDictKey(alldb, "dz")) + self.meta["dz"] = np.array(list(set(self.dz).union())) self.nmodes = self.dz.size - - self.MN = np.array(ListDictKey(alldb,'MN')) - #self.MN = np.float32(self.mn) - #self.MN[:,1] = self.mn[:,1]/self.dz - self.nrun = len(set(self.path).union()) - self.L = np.array(ListDictKey(alldb,'L')) - #self.C_s = - self.modeid = np.array(ListDictKey(alldb,'modeid')) - - self.trans = np.array(ListDictKey(alldb,'transform')) - + + self.MN = np.array(ListDictKey(alldb, "MN")) + # self.MN = np.float32(self.mn) + # self.MN[:,1] = self.mn[:,1]/self.dz + self.nrun = len(set(self.path).union()) + self.L = np.array(ListDictKey(alldb, "L")) + # self.C_s = + self.modeid = np.array(ListDictKey(alldb, "modeid")) + + self.trans = np.array(ListDictKey(alldb, "transform")) + if np.any(self.trans): - self.phase_r = ListDictKey(alldb,'phase_r') - self.gamma_r = np.array(ListDictKey(alldb,'gamma_r')) - self.amp_r = ListDictKey(alldb,'amp_r') - self.freq_r = np.array(ListDictKey(alldb,'freq_r')) - - # try: - # self.model(haswak=False) # - # except: - # self.M = 0 - - #try: - try: #analytic model based on simple matrix - self.models=[] - #self.models.append(_model(self)) #create a list to contain models - self.models.append(_model(self,haswak=True,name='haswak')) #another model - #self.models.append(_model(self,haswak=True,name='haswak_0',m=0)) - # for Ln in range(10): - # Lval = 10**((.2*Ln -1)/10) - # #Lval = 10**(Ln-1) - # #Lval = - # print Lval - # self.models.append(_model(self,varL=True,name='varL'+str(Lval),Lval=Lval,haswak=True)) - + self.phase_r = ListDictKey(alldb, "phase_r") + self.gamma_r = np.array(ListDictKey(alldb, "gamma_r")) + self.amp_r = ListDictKey(alldb, "amp_r") + self.freq_r = np.array(ListDictKey(alldb, "freq_r")) + + # try: + # self.model(haswak=False) # + # except: + # self.M = 0 + + # try: + try: # analytic model based on simple matrix + self.models = [] + # self.models.append(_model(self)) #create a list to contain models + self.models.append( + _model(self, haswak=True, name="haswak") + ) # another model + # self.models.append(_model(self,haswak=True,name='haswak_0',m=0)) + # for Ln in range(10): + # Lval = 10**((.2*Ln -1)/10) + # #Lval = 10**(Ln-1) + # #Lval = + # print Lval + # self.models.append(_model(self,varL=True,name='varL'+str(Lval),Lval=Lval,haswak=True)) except: self.M = 0 - - try: #analytic models based on user defined complex omega - self.ref=[] + + try: # analytic models based on user defined complex omega + self.ref = [] self.ref.append(_ref(self)) - #self.ref.append(_ref(self,haswak=False,name='drift')) - #demand a complex omega to compare - #self.ref.append(_ref(self,haswas=True,name='haswak')) + # self.ref.append(_ref(self,haswak=False,name='drift')) + # demand a complex omega to compare + # self.ref.append(_ref(self,haswas=True,name='haswak')) except: - self.ref =0 - # self.models.append(_model(self,haswak2=True,name='haswak2')) - - # except: - # print 'FAIL' - - def _amp(self,tind,xind): - #first select modes that actually have valid (tind,xind) - #indecies - #s = subset(self.db,'modeid',modelist) - return np.array([self.amp[i][tind,xind] - for i in range(self.nmodes)]) - - - # def model(self,field='Ni',plot=False,haswak=False): - - # #enrich the object - # allk = self.k_r[:,1,self.nx/2] #one location for now - # allkpar = self.k_r[:,0,self.nx/2] #one location for now - - - # self.M = [] - # self.eigsys = [] - # self.gammaA = [] - # self.omegaA = [] - # self.eigvec = [] - # self.gammamax = [] - # self.omegamax = [] - - # #allk = np.arange(0.1,100.0,.1) - # #allk= np.sort(list(set(allk).union())) - - - # for i,k in enumerate(allk): - # #print i - # #M =np.matrix(np.random.rand(3,3),dtype=complex) - # M = np.zeros([3,3],dtype=complex) - # M[0,0] = 0 - # M[0,1] = k/(self.L[i,self.nx/2,self.ny/2]) - # M[1,0] = (2*np.pi/self.meta['lpar'][self.nx/2])**2 * self.meta['sig_par'][0]*complex(0,k**-2) - # M[1,1]= -(2*np.pi/self.meta['lpar'][self.nx/2])**2 * self.meta['sig_par'][0]*complex(0,k**-2) - - # if haswak: - # M[0,0] = M[0,0] + M[1,1]*complex(0,k**2) - # M[0,1] = M[0,1] + M[1,0]*complex(0,k**2) - - # #if rho_conv: - - - # #M[1,0] = (allkpar[i])**2 * self.meta['sig_par'][0]*complex(0,k**-2) - # #M[1,1]= -(allkpar[i])**2 * self.meta['sig_par'][0]*complex(0,k**-2) - - # eigsys= np.linalg.eig(M) - # gamma = (eigsys)[0].imag - # omega =(eigsys)[0].real - # eigvec = eigsys[1] - - # self.M.append(M) - # self.eigsys.append(eigsys) - # self.gammaA.append(gamma) - # self.gammamax.append(max(gamma)) - # where = ((gamma == gamma.max()) & (omega != 0)) - # self.omegamax.append(omega[where[0]]) - # self.eigvec.append(eigvec) - # self.omegaA.append(omega) + self.ref = 0 + + # self.models.append(_model(self,haswak2=True,name='haswak2')) + + # except: + # print 'FAIL' + + def _amp(self, tind, xind): + # first select modes that actually have valid (tind,xind) + # indecies + # s = subset(self.db,'modeid',modelist) + return np.array([self.amp[i][tind, xind] for i in range(self.nmodes)]) + + # def model(self,field='Ni',plot=False,haswak=False): + + # #enrich the object + # allk = self.k_r[:,1,self.nx/2] #one location for now + # allkpar = self.k_r[:,0,self.nx/2] #one location for now + + # self.M = [] + # self.eigsys = [] + # self.gammaA = [] + # self.omegaA = [] + # self.eigvec = [] + # self.gammamax = [] + # self.omegamax = [] + + # #allk = np.arange(0.1,100.0,.1) + # #allk= np.sort(list(set(allk).union())) + + # for i,k in enumerate(allk): + # #print i + # #M =np.matrix(np.random.rand(3,3),dtype=complex) + # M = np.zeros([3,3],dtype=complex) + # M[0,0] = 0 + # M[0,1] = k/(self.L[i,self.nx/2,self.ny/2]) + # M[1,0] = (2*np.pi/self.meta['lpar'][self.nx/2])**2 * self.meta['sig_par'][0]*complex(0,k**-2) + # M[1,1]= -(2*np.pi/self.meta['lpar'][self.nx/2])**2 * self.meta['sig_par'][0]*complex(0,k**-2) + + # if haswak: + # M[0,0] = M[0,0] + M[1,1]*complex(0,k**2) + # M[0,1] = M[0,1] + M[1,0]*complex(0,k**2) + + # #if rho_conv: + + # #M[1,0] = (allkpar[i])**2 * self.meta['sig_par'][0]*complex(0,k**-2) + # #M[1,1]= -(allkpar[i])**2 * self.meta['sig_par'][0]*complex(0,k**-2) + + # eigsys= np.linalg.eig(M) + # gamma = (eigsys)[0].imag + # omega =(eigsys)[0].real + # eigvec = eigsys[1] + + # self.M.append(M) + # self.eigsys.append(eigsys) + # self.gammaA.append(gamma) + # self.gammamax.append(max(gamma)) + # where = ((gamma == gamma.max()) & (omega != 0)) + # self.omegamax.append(omega[where[0]]) + # self.eigvec.append(eigvec) + # self.omegaA.append(omega) class __model__(object): def __init__(self): self.M = 0 - + + class subset(LinRes): - def __init__(self,alldb,key,valuelist,model=False): - selection = ListDictFilt(alldb,key,valuelist) - if len(selection) !=0: - LinRes.__init__(self,selection) - self.skey = key - if model==True: - self.model() - else: - LinRes.__init__(self,alldb) - if model==True: - self.model() + def __init__(self, alldb, key, valuelist, model=False): + selection = ListDictFilt(alldb, key, valuelist) + if len(selection) != 0: + LinRes.__init__(self, selection) + self.skey = key + if model == True: + self.model() + else: + LinRes.__init__(self, alldb) + if model == True: + self.model() + # class subset(originClass): # def __init__(self,alldb,key,valuelist,model=False): @@ -329,10 +329,10 @@ def __init__(self,alldb,key,valuelist,model=False): # if model==True: # self.model() -#not sure if this is the best way . . . +# not sure if this is the best way . . . -# class subset(object): +# class subset(object): # def __init__(self,input_obj,key,valuelist,model=False): # selection = ListDictFilt(input_obj.mode_db,key,valuelist) # if len(selection) !=0: @@ -347,153 +347,198 @@ def __init__(self,alldb,key,valuelist,model=False): # if model==True: # self.model() -class _ref(object): #NOT a derived obj, just takes one as a var - def __init__(self,input_obj,name='haswak',haswak=True): - allk = input_obj.k_r[:,1,old_div(input_obj.nx,2)] #one location for now - allkpar = input_obj.k_r[:,0,old_div(input_obj.nx,2)] #one location for now + +class _ref(object): # NOT a derived obj, just takes one as a var + def __init__(self, input_obj, name="haswak", haswak=True): + allk = input_obj.k_r[:, 1, old_div(input_obj.nx, 2)] # one location for now + allkpar = input_obj.k_r[:, 0, old_div(input_obj.nx, 2)] # one location for now self.name = name - + self.gamma = [] self.omega = [] - self.soln ={} - self.soln['gamma'] = [] - self.soln['freq'] = [] - - for i,k in enumerate(allk): - omega_star = old_div(-(k),(input_obj.L[i,old_div(input_obj.nx,2),old_div(input_obj.ny,2)])) - - - nu = (2*np.pi/input_obj.meta['lpar'][old_div(input_obj.nx,2)])**2 * input_obj.meta['sig_par'][0] - + self.soln = {} + self.soln["gamma"] = [] + self.soln["freq"] = [] + + for i, k in enumerate(allk): + omega_star = old_div( + -(k), + (input_obj.L[i, old_div(input_obj.nx, 2), old_div(input_obj.ny, 2)]), + ) + + nu = ( + 2 * np.pi / input_obj.meta["lpar"][old_div(input_obj.nx, 2)] + ) ** 2 * input_obj.meta["sig_par"][0] + if haswak: - omega = old_div(-omega_star,(1 + (k)**2)) - gamma = old_div(((k**2)*omega_star**2),(nu * (1+k**2)**3)) + omega = old_div(-omega_star, (1 + (k) ** 2)) + gamma = old_div(((k ** 2) * omega_star ** 2), (nu * (1 + k ** 2) ** 3)) else: # omega = -np.sqrt(nu*omega_star)/(np.sqrt(2)*k) + nu**(3/2)/(8*np.sqrt(2*omega_star)*k**3) # gamma = np.sqrt(nu*omega_star)/(np.sqrt(2)*k) - nu/(2* k**2) + nu**(3/2)/(8*np.sqrt(2*omega_star)*k**3) - omega = -omega_star + old_div((2*k**4*omega_star**3),nu**2) - gamma = old_div((k*omega_star)**2,nu) - (5*(k**6*omega_star*4/nu**3)) + omega = -omega_star + old_div((2 * k ** 4 * omega_star ** 3), nu ** 2) + gamma = old_div((k * omega_star) ** 2, nu) - ( + 5 * (k ** 6 * omega_star * 4 / nu ** 3) + ) self.gamma.append(gamma) self.omega.append(omega) - - self.soln['freq'] = np.transpose(np.array(self.omega)) - self.soln['gamma'] = np.transpose(np.array(self.gamma)) - - -class _model(object): #NOT a derived class,but one that takes a class as input - def __init__(self,input_obj,name='drift',haswak=False, - rho_conv=False,haswak2=False,varL=False,Lval=1.0,m=1): - allk = input_obj.k_r[:,1,old_div(input_obj.nx,2)] #one location for now - allkpar = input_obj.k_r[:,0,old_div(input_obj.nx,2)] #one location for now - - #numerical value to compare against - - numgam = input_obj.gamma[:,0,old_div(input_obj.nx,2)] - numfreq =input_obj.freq[:,0,old_div(input_obj.nx,2)] + + self.soln["freq"] = np.transpose(np.array(self.omega)) + self.soln["gamma"] = np.transpose(np.array(self.gamma)) + + +class _model(object): # NOT a derived class,but one that takes a class as input + def __init__( + self, + input_obj, + name="drift", + haswak=False, + rho_conv=False, + haswak2=False, + varL=False, + Lval=1.0, + m=1, + ): + allk = input_obj.k_r[:, 1, old_div(input_obj.nx, 2)] # one location for now + allkpar = input_obj.k_r[:, 0, old_div(input_obj.nx, 2)] # one location for now + + # numerical value to compare against + + numgam = input_obj.gamma[:, 0, old_div(input_obj.nx, 2)] + numfreq = input_obj.freq[:, 0, old_div(input_obj.nx, 2)] self.name = name self.M = [] self.eigsys = [] self.gammaA = [] self.omegaA = [] - self.eigvec = [] + self.eigvec = [] self.gammamax = [] self.omegamax = [] - self.k =[] + self.k = [] self.m = m - - - + self.soln = {} - self.soln['freq'] = [] - self.soln['gamma'] = [] - self.soln['gammamax'] = [] - self.soln['freqmax'] = [] - - self.chi ={} - self.chi['freq']= [] - self.chi['gamma'] = [] - - - for i,k in enumerate(allk): - #print i - #M =np.matrix(np.random.rand(3,3),dtype=complex) - M = np.zeros([4,4],dtype=complex) - M[0,0] = 0 - #k = k/np.sqrt(10) - #L = (input_obj.L)*np.sqrt(10) - + self.soln["freq"] = [] + self.soln["gamma"] = [] + self.soln["gammamax"] = [] + self.soln["freqmax"] = [] + + self.chi = {} + self.chi["freq"] = [] + self.chi["gamma"] = [] + + for i, k in enumerate(allk): + # print i + # M =np.matrix(np.random.rand(3,3),dtype=complex) + M = np.zeros([4, 4], dtype=complex) + M[0, 0] = 0 + # k = k/np.sqrt(10) + # L = (input_obj.L)*np.sqrt(10) + if k == 0: - k= 1e-5 - - #print k {n,phi,v,ajpar} - M[0,1] = old_div(k,(input_obj.L[i,old_div(input_obj.nx,2),old_div(input_obj.ny,2)])) - M[1,0] = (2*m*np.pi/input_obj.meta['lpar'][old_div(input_obj.nx,2)])**2 * input_obj.meta['sig_par'][0]*complex(0,(k)**-2) - M[1,1]= -(2*m*np.pi/input_obj.meta['lpar'][old_div(input_obj.nx,2)])**2 * input_obj.meta['sig_par'][0]*complex(0,(k)**-2) - - #parallel dynamics - #M[2,2] = k/(input_obj.L[i,input_obj.nx/2,input_obj.ny/2]) - #M[2,0] = -(2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2]) - #M[0,2] = -(2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2]) - -#M[1,0] = (2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2])**2 * input_obj.meta['sig_par'][0] - #M[1,1]= -(2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2])**2 * input_obj.meta['sig_par'][0] - - #ajpar dynamics - effectively parallel electron dynamics instead of + k = 1e-5 + + # print k {n,phi,v,ajpar} + M[0, 1] = old_div( + k, (input_obj.L[i, old_div(input_obj.nx, 2), old_div(input_obj.ny, 2)]) + ) + M[1, 0] = ( + (2 * m * np.pi / input_obj.meta["lpar"][old_div(input_obj.nx, 2)]) ** 2 + * input_obj.meta["sig_par"][0] + * complex(0, (k) ** -2) + ) + M[1, 1] = ( + -( + (2 * m * np.pi / input_obj.meta["lpar"][old_div(input_obj.nx, 2)]) + ** 2 + ) + * input_obj.meta["sig_par"][0] + * complex(0, (k) ** -2) + ) + + # parallel dynamics + # M[2,2] = k/(input_obj.L[i,input_obj.nx/2,input_obj.ny/2]) + # M[2,0] = -(2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2]) + # M[0,2] = -(2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2]) + + # M[1,0] = (2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2])**2 * input_obj.meta['sig_par'][0] + # M[1,1]= -(2*m*np.pi/input_obj.meta['lpar'][input_obj.nx/2])**2 * input_obj.meta['sig_par'][0] + + # ajpar dynamics - effectively parallel electron dynamics instead of if haswak: - M[0,0] = -(2*m*np.pi/input_obj.meta['lpar'][old_div(input_obj.nx,2)])**2 * input_obj.meta['sig_par'][0]*complex(0,1) - M[0,1] = ((2*m*np.pi/input_obj.meta['lpar'][old_div(input_obj.nx,2)])**2 * input_obj.meta['sig_par'][0]*complex(0,1) + M[0,1]) - + M[0, 0] = ( + -( + ( + 2 + * m + * np.pi + / input_obj.meta["lpar"][old_div(input_obj.nx, 2)] + ) + ** 2 + ) + * input_obj.meta["sig_par"][0] + * complex(0, 1) + ) + M[0, 1] = ( + 2 * m * np.pi / input_obj.meta["lpar"][old_div(input_obj.nx, 2)] + ) ** 2 * input_obj.meta["sig_par"][0] * complex(0, 1) + M[0, 1] + if varL: - M[0,1] = Lval*M[0,1] - - if rho_conv: #not used - M[1,0] = (allkpar[i])**2 * input_obj.meta['sig_par'][0]*complex(0,(k)**-2) - M[1,1]= -(allkpar[i])**2 * input_obj.meta['sig_par'][0]*complex(0,(k)**-2) - - eigsys= np.linalg.eig(M) + M[0, 1] = Lval * M[0, 1] + + if rho_conv: # not used + M[1, 0] = ( + (allkpar[i]) ** 2 + * input_obj.meta["sig_par"][0] + * complex(0, (k) ** -2) + ) + M[1, 1] = ( + -((allkpar[i]) ** 2) + * input_obj.meta["sig_par"][0] + * complex(0, (k) ** -2) + ) + + eigsys = np.linalg.eig(M) gamma = (eigsys)[0].imag - omega =(eigsys)[0].real + omega = (eigsys)[0].real eigvec = eigsys[1] self.k.append(k) - + self.M.append(M) self.eigsys.append(eigsys) self.gammaA.append(gamma) - self.soln['gamma'].append(gamma) + self.soln["gamma"].append(gamma) self.gammamax.append(max(gamma)) - self.soln['gammamax'].append(max(gamma)) - - where = ((gamma == gamma.max()) & (omega != 0)) + self.soln["gammamax"].append(max(gamma)) + + where = (gamma == gamma.max()) & (omega != 0) # if len(where) > 1: # where = where[0] self.omegamax.append(omega[where]) - self.soln['freqmax'].append(omega[where]) - + self.soln["freqmax"].append(omega[where]) - #print k,gamma,where,M,omega - chigam = old_div(((numgam - max(gamma))**2),max(gamma)) - chifreq =old_div(((numfreq - omega[where])**2),omega[where]) + # print k,gamma,where,M,omega + chigam = old_div(((numgam - max(gamma)) ** 2), max(gamma)) + chifreq = old_div(((numfreq - omega[where]) ** 2), omega[where]) self.eigvec.append(eigvec) self.omegaA.append(omega) - self.soln['freq'].append(omega) - - self.chi['freq'].append(chifreq[i]) - - self.chi['gamma'].append(chigam[i]) - + self.soln["freq"].append(omega) + + self.chi["freq"].append(chifreq[i]) + + self.chi["gamma"].append(chigam[i]) + self.dim = M.shape[0] - self.soln['freq'] = np.transpose(np.array(self.soln['freq'])) - self.soln['gamma'] = np.transpose(np.array(self.soln['gamma'])) - self.chi['freq']= np.transpose(np.array(self.chi['freq'])) - self.chi['gamma']=np.transpose(np.array(self.chi['gamma'])) - + self.soln["freq"] = np.transpose(np.array(self.soln["freq"])) + self.soln["gamma"] = np.transpose(np.array(self.soln["gamma"])) + self.chi["freq"] = np.transpose(np.array(self.chi["freq"])) + self.chi["gamma"] = np.transpose(np.array(self.chi["gamma"])) + # self.soln = {} # self.soln['freq'] = self.omegaA # self.soln['gamma'] = self.gammaA - - diff --git a/tools/pylib/post_bout/pb_draw.py b/tools/pylib/post_bout/pb_draw.py index 9f615e77a9..57ea8835fb 100644 --- a/tools/pylib/post_bout/pb_draw.py +++ b/tools/pylib/post_bout/pb_draw.py @@ -4,14 +4,15 @@ from builtins import str from builtins import range from past.utils import old_div -#some standard analytic stuff to plot, if appending just overplot gam or omeg + +# some standard analytic stuff to plot, if appending just overplot gam or omeg from .pb_corral import LinRes from .ListDict import ListDictKey, ListDictFilt import numpy as np import matplotlib.pyplot as plt from matplotlib import cm -import matplotlib.artist as artist +import matplotlib.artist as artist import matplotlib.ticker as ticker import matplotlib.pyplot as plt import matplotlib.patches as patches @@ -34,1255 +35,1554 @@ class LinResDraw(LinRes): - def __init__(self,alldb): - LinRes.__init__(self,alldb) - - - - - def plottheory(self,pp,m=1,canvas=None,comp='gamma', - field='Ni',allroots=False): + def __init__(self, alldb): + LinRes.__init__(self, alldb) + + def plottheory( + self, pp, m=1, canvas=None, comp="gamma", field="Ni", allroots=False + ): if len(self.models) == 0: try: - self.models=[] - self.models.append(_model(self)) #create a list to contain models - self.models.append(_model(self,haswak=True,name='haswak')) #another model + self.models = [] + self.models.append(_model(self)) # create a list to contain models + self.models.append( + _model(self, haswak=True, name="haswak") + ) # another model except: return 0 - + s = subset(self.db, "field", [field]) - - s = subset(self.db,'field',[field]) - modelist = [] - - [modelist.append([m,n+1]) for n in range(min(s.maxN)-1)] - - s = subset(s.db,'mn',modelist) - - allk = s.k[:,1,old_div(s.nx,2)] + + [modelist.append([m, n + 1]) for n in range(min(s.maxN) - 1)] + + s = subset(s.db, "mn", modelist) + + allk = s.k[:, 1, old_div(s.nx, 2)] ki = np.argsort(allk) - + ownpage = False if canvas is None: ownpage = True - - if ownpage: #if not an overplot + if ownpage: # if not an overplot fig1 = plt.figure() - canvas = fig1.add_subplot(1,1,1) - - label ='gamma analytic' + canvas = fig1.add_subplot(1, 1, 1) - #if comp=='gamma': + label = "gamma analytic" + + # if comp=='gamma': # y = np.array(s.gammamax)[ki] # else: # y = np.array(s.omegamax)[ki] - + for m in s.models: print(m.name) - for i,m in enumerate(s.models): - print(m.name,comp,m.soln[comp].shape) - + for i, m in enumerate(s.models): + print(m.name, comp, m.soln[comp].shape) + if allroots: for elem in m.soln[comp]: - #y = [] - #elem has 2 or more elements - y = (np.array(elem)[ki]).flatten() #n values - #y = y.astype('float') + # y = [] + # elem has 2 or more elements + y = (np.array(elem)[ki]).flatten() # n values + # y = y.astype('float') print(y.shape) - canvas.plot((allk[ki]).flatten(),y,',', - label=label,c=cm.jet(.2*i)) - try: - ymax = (np.array(m.soln[comp+'max'])[ki]).flatten() - #ymax = (np.array(m.gammamax)[ki]).flatten() - ymax = ymax.astype('float') - print(comp,' ymax:', ymax) - canvas.plot((allk[ki]).flatten(),ymax,'-', - label=label,c=cm.jet(.2*i)) + canvas.plot( + (allk[ki]).flatten(), y, ",", label=label, c=cm.jet(0.2 * i) + ) + try: + ymax = (np.array(m.soln[comp + "max"])[ki]).flatten() + # ymax = (np.array(m.gammamax)[ki]).flatten() + ymax = ymax.astype("float") + print(comp, " ymax:", ymax) + canvas.plot( + (allk[ki]).flatten(), ymax, "-", label=label, c=cm.jet(0.2 * i) + ) # if comp=='gamma': # y = (np.array(m.gammamax)[ki]).flatten() - + # else: # y = (np.array(m.omegamax)[ki]).flatten() - - #print m.name, ':' ,y.astype('float') - - - + # print m.name, ':' ,y.astype('float') + except: - print('fail to add theory curve') + print("fail to add theory curve") + + canvas.annotate(m.name, (allk[ki[0]], 1.1 * ymax[0]), fontsize=8) + canvas.annotate(m.name, (1.1 * allk[ki[-1]], 1.1 * ymax[-1]), fontsize=8) - canvas.annotate(m.name,(allk[ki[0]],1.1*ymax[0]),fontsize = 8) - canvas.annotate(m.name,(1.1*allk[ki[-1]],1.1*ymax[-1]),fontsize = 8) - try: - for i,m in enumerate(s.ref): + for i, m in enumerate(s.ref): if not allroots: - y = (np.array(m.soln[comp])[ki]).flatten() - y = y.astype('float') - canvas.plot((allk[ki]).flatten(),y,'--', - label=label,c=cm.jet(.2*i)) + y = (np.array(m.soln[comp])[ki]).flatten() + y = y.astype("float") + canvas.plot( + (allk[ki]).flatten(), + y, + "--", + label=label, + c=cm.jet(0.2 * i), + ) except: - print('no reference curve') + print("no reference curve") - - if ownpage: #set scales if this is its own plot + if ownpage: # set scales if this is its own plot # canvas.set_yscale('symlog',linthreshy=1e-13) # canvas.set_xscale('log') - - canvas.axis('tight') - canvas.set_xscale('log') - canvas.set_yscale('symlog') - fig1.savefig(pp, format='pdf') + + canvas.axis("tight") + canvas.set_xscale("log") + canvas.set_yscale("symlog") + fig1.savefig(pp, format="pdf") plt.close(fig1) - else: #if not plot its probably plotted iwth sim data, print chi somewhere - - for i,m in enumerate(s.models): - textstr = r'$\chi^2$'+ '$=%.2f$'%(m.chi[comp].sum()) + else: # if not plot its probably plotted iwth sim data, print chi somewhere + + for i, m in enumerate(s.models): + textstr = r"$\chi^2$" + "$=%.2f$" % (m.chi[comp].sum()) print(textstr) - #textstr = '$\L=%.2f$'%(m.chi[comp].sum()) - props = dict(boxstyle='square', facecolor='white', alpha=0.3) - textbox = canvas.text(0.1, 0.1, textstr, transform=canvas.transAxes, fontsize=10, - verticalalignment='top', bbox=props) - - def plotomega(self,pp,canvas=None,field='Ni',yscale='linear',clip=0, - xaxis='t',xscale='linear',xrange=1,comp='gamma', - pltlegend='both',overplot=False,gridON=True,trans=False, - infobox=True): - - colors = ['b.','r.','k.','c.','g.','y.','m.','b.','r.','k.','c.','g.','y.','m.'] - colordash = ['b','r','k','c','g','y','m','b','r','k','c','g','y','m'] - - + # textstr = '$\L=%.2f$'%(m.chi[comp].sum()) + props = dict(boxstyle="square", facecolor="white", alpha=0.3) + textbox = canvas.text( + 0.1, + 0.1, + textstr, + transform=canvas.transAxes, + fontsize=10, + verticalalignment="top", + bbox=props, + ) + + def plotomega( + self, + pp, + canvas=None, + field="Ni", + yscale="linear", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + comp="gamma", + pltlegend="both", + overplot=False, + gridON=True, + trans=False, + infobox=True, + ): + + colors = [ + "b.", + "r.", + "k.", + "c.", + "g.", + "y.", + "m.", + "b.", + "r.", + "k.", + "c.", + "g.", + "y.", + "m.", + ] + colordash = [ + "b", + "r", + "k", + "c", + "g", + "y", + "m", + "b", + "r", + "k", + "c", + "g", + "y", + "m", + ] + if canvas is None: ownpage = True else: ownpage = False - - if ownpage: + + if ownpage: fig1 = plt.figure() fig1.subplots_adjust(bottom=0.12) fig1.subplots_adjust(top=0.80) fig1.subplots_adjust(right=0.83) fig1.subplots_adjust(left=0.17) - canvas = fig1.add_subplot(1,1,1) + canvas = fig1.add_subplot(1, 1, 1) clonex = canvas.twinx() # if trans: # cloney = canvas.twiny() - - dzhandles = [] - parhandles =[] - parlabels =[] - dzlabels=[] - + parhandles = [] + parlabels = [] + dzlabels = [] + m_shift = 1 - for q in np.array(list(range(1)))+m_shift: - s = subset(self.db,'field',[field]) #pick field + for q in np.array(list(range(1))) + m_shift: + s = subset(self.db, "field", [field]) # pick field maxZ = min(s.maxN) modelist = [] - [modelist.append([q,p+1]) for p in range(maxZ-1)] + [modelist.append([q, p + 1]) for p in range(maxZ - 1)] print(modelist) - print(q,'in plotgamma') - - s = subset(s.db,'mn',modelist) - - xrange = old_div(s.nx,2)-2 - - xrange = [old_div(s.nx,2),old_div(s.nx,2)+xrange] - - - y = np.array(ListDictKey(s.db,comp)) - - #y = s.gamma #nmodes x 2 x nx ndarray - k = s.k ##nmodes x 2 x nx ndarray k_zeta - - kfactor = np.mean(old_div(s.k_r[:,1,old_div(s.nx,2)],s.k[:,1,old_div(s.nx,2)])) #good enough for now - - print(k[:,1,old_div(s.nx,2)].shape, y[:,0,old_div(s.nx,2)].shape, len(colors), ownpage)#,k[:,1,s.nx/2],y[:,0,s.nx/2] - - parhandles.append(canvas.errorbar(np.squeeze(k[:,1,old_div(s.nx,2)]), - np.squeeze(y[:,0,old_div(s.nx,2)]), - yerr= np.squeeze(y[:,1,old_div(s.nx,2)]), - fmt=colors[q])) - - - - - parlabels.append("m "+str(q)) - - #loop over dz sets and connect with dotted line . . . - jj=0 - - ymin_data =np.max(np.array(ListDictKey(s.db,comp))) - ymax_data = 0 #for bookeeping + print(q, "in plotgamma") + + s = subset(s.db, "mn", modelist) + + xrange = old_div(s.nx, 2) - 2 + + xrange = [old_div(s.nx, 2), old_div(s.nx, 2) + xrange] + + y = np.array(ListDictKey(s.db, comp)) + + # y = s.gamma #nmodes x 2 x nx ndarray + k = s.k ##nmodes x 2 x nx ndarray k_zeta + + kfactor = np.mean( + old_div(s.k_r[:, 1, old_div(s.nx, 2)], s.k[:, 1, old_div(s.nx, 2)]) + ) # good enough for now + + print( + k[:, 1, old_div(s.nx, 2)].shape, + y[:, 0, old_div(s.nx, 2)].shape, + len(colors), + ownpage, + ) # ,k[:,1,s.nx/2],y[:,0,s.nx/2] + + parhandles.append( + canvas.errorbar( + np.squeeze(k[:, 1, old_div(s.nx, 2)]), + np.squeeze(y[:, 0, old_div(s.nx, 2)]), + yerr=np.squeeze(y[:, 1, old_div(s.nx, 2)]), + fmt=colors[q], + ) + ) + + parlabels.append("m " + str(q)) + + # loop over dz sets and connect with dotted line . . . + jj = 0 + + ymin_data = np.max(np.array(ListDictKey(s.db, comp))) + ymax_data = 0 # for bookeeping for p in list(set(s.path).union()): - print(p, 'in plotomega') - - sub_s = subset(s.db,'path',[p]) + print(p, "in plotomega") + + sub_s = subset(s.db, "path", [p]) j = sub_s.dz[0] - #print sub_s.amp.shape - s_i = np.argsort(sub_s.mn[:,1]) #sort by 'local' m, global m is ok also - #print s_i, sub_s.mn, sub_s.nx, jj - y = np.array(ListDictKey(sub_s.db,comp)) - y_alt = 2.0*np.array(ListDictKey(sub_s.db,comp)) - - k = sub_s.k ## - if q == m_shift: #fix the parallel mode - dzhandles.append(canvas.plot(k[s_i,1,old_div(sub_s.nx,2)], - y[s_i,0,old_div(sub_s.nx,2)],color=colordash[jj],alpha=.5)) - #clonex.plot(k[s_i,1,sub_s.nx/2], - #y_alt[s_i,0,sub_s.nx/2],color=colordash[jj],alpha=.5) - # if np.any(sub_s.trans) and trans: - # comp_r = comp+'_r' - # k_r = sub_s.k_r - # y2 = np.array(ListDictKey(sub_s.db,comp_r)) - # cloney.plot(k[s_i,1,sub_s.nx/2], - # y2[s_i,0,sub_s.nx/2],'k.',ms = 3) - - ymin_data = np.min([np.min(y[s_i,0,old_div(sub_s.nx,2)]),ymin_data]) - ymax_data = np.max([np.max(y[s_i,0,old_div(sub_s.nx,2)]),ymax_data]) - - - - - print('dzhandle color', jj) - #dzlabels.append("DZ: "+ str(2*j)+r'$\pi$') - dzlabels.append(j) - - if yscale=='log': - factor = 10 - else: - factor = 2 - print('annotating') - canvas.annotate(str(j),(k[s_i[0],1,old_div(sub_s.nx,2)],y[s_i[0],0,old_div(sub_s.nx,2)]),fontsize = 8) - p = canvas.axvspan(k[s_i[0],1,old_div(sub_s.nx,2)], k[s_i[-1],1,old_div(sub_s.nx,2)], - facecolor=colordash[jj], alpha=0.01) - print('done annotating') + # print sub_s.amp.shape + s_i = np.argsort(sub_s.mn[:, 1]) # sort by 'local' m, global m is ok also + # print s_i, sub_s.mn, sub_s.nx, jj + y = np.array(ListDictKey(sub_s.db, comp)) + y_alt = 2.0 * np.array(ListDictKey(sub_s.db, comp)) + + k = sub_s.k ## + if q == m_shift: # fix the parallel mode + dzhandles.append( + canvas.plot( + k[s_i, 1, old_div(sub_s.nx, 2)], + y[s_i, 0, old_div(sub_s.nx, 2)], + color=colordash[jj], + alpha=0.5, + ) + ) + # clonex.plot(k[s_i,1,sub_s.nx/2], + # y_alt[s_i,0,sub_s.nx/2],color=colordash[jj],alpha=.5) + # if np.any(sub_s.trans) and trans: + # comp_r = comp+'_r' + # k_r = sub_s.k_r + # y2 = np.array(ListDictKey(sub_s.db,comp_r)) + # cloney.plot(k[s_i,1,sub_s.nx/2], + # y2[s_i,0,sub_s.nx/2],'k.',ms = 3) + + ymin_data = np.min([np.min(y[s_i, 0, old_div(sub_s.nx, 2)]), ymin_data]) + ymax_data = np.max([np.max(y[s_i, 0, old_div(sub_s.nx, 2)]), ymax_data]) + + print("dzhandle color", jj) + # dzlabels.append("DZ: "+ str(2*j)+r'$\pi$') + dzlabels.append(j) + + if yscale == "log": + factor = 10 + else: + factor = 2 + print("annotating") + canvas.annotate( + str(j), + ( + k[s_i[0], 1, old_div(sub_s.nx, 2)], + y[s_i[0], 0, old_div(sub_s.nx, 2)], + ), + fontsize=8, + ) + p = canvas.axvspan( + k[s_i[0], 1, old_div(sub_s.nx, 2)], + k[s_i[-1], 1, old_div(sub_s.nx, 2)], + facecolor=colordash[jj], + alpha=0.01, + ) + print("done annotating") else: - canvas.plot(k[s_i,1,old_div(sub_s.nx,2)], - y[s_i,0,old_div(sub_s.nx,2)],color=colordash[jj],alpha=.3) + canvas.plot( + k[s_i, 1, old_div(sub_s.nx, 2)], + y[s_i, 0, old_div(sub_s.nx, 2)], + color=colordash[jj], + alpha=0.3, + ) + + jj = jj + 1 - jj=jj+1 - dzhandles = np.array(dzhandles).flatten() dzlabels = np.array(dzlabels).flatten() - + dzlabels = list(set(dzlabels).union()) - + dz_i = np.argsort(dzlabels) - + dzhandles = dzhandles[dz_i] dzlabels_cp = np.array(dzlabels)[dz_i] - + print(type(dzlabels), np.size(dzlabels)) for i in range(np.size(dzlabels)): - dzlabels[i] = "DZ: "+ str(dzlabels_cp[i])#+r"$\pi$" - + dzlabels[i] = "DZ: " + str(dzlabels_cp[i]) # +r"$\pi$" parlabels = np.array(parlabels).flatten() - - #if pltlegend =='both': # - - print('legends') - - #l1 = legend(parhandles,parlabels,loc = 3,prop={'size':6}) - #l2 = legend(dzhandles,dzlabels,loc = 1,prop={'size':6}) - #plt.gca().add_artist(l1) - - # else: - # legend(dzhandles,dzlabels,loc=3,prop={'size':6}) - if overplot==True: + + # if pltlegend =='both': # + + print("legends") + + # l1 = legend(parhandles,parlabels,loc = 3,prop={'size':6}) + # l2 = legend(dzhandles,dzlabels,loc = 1,prop={'size':6}) + # plt.gca().add_artist(l1) + + # else: + # legend(dzhandles,dzlabels,loc=3,prop={'size':6}) + if overplot == True: try: - self.plottheory(pp,canvas=canvas,comp=comp,field=field) - #self.plottheory(pp,comp=comp) + self.plottheory(pp, canvas=canvas, comp=comp, field=field) + # self.plottheory(pp,comp=comp) except: - print('no theory plot') + print("no theory plot") if infobox: - textstr = '$\L_{\parallel}=%.2f$\n$\L_{\partial_r n}=%.2f$\n$B=%.2f$'%(s.meta['lpar'][old_div(s.nx,2)], - s.meta['L'][old_div(s.nx,2),old_div(s.ny,2)], - s.meta['Bpxy']['v'][old_div(s.nx,2),old_div(s.ny,2)]) - props = dict(boxstyle='square', facecolor='white', alpha=0.3) - textbox = canvas.text(0.82, 0.95, textstr, transform=canvas.transAxes, fontsize=10, - verticalalignment='top', bbox=props) - # leg = canvas.legend(handles,labels,ncol=2,loc='best',prop={'size':4},fancybox=True) - #textbox.get_frame().set_alpha(0.3) - #matplotlib.patches.Rectangle + textstr = "$\L_{\parallel}=%.2f$\n$\L_{\partial_r n}=%.2f$\n$B=%.2f$" % ( + s.meta["lpar"][old_div(s.nx, 2)], + s.meta["L"][old_div(s.nx, 2), old_div(s.ny, 2)], + s.meta["Bpxy"]["v"][old_div(s.nx, 2), old_div(s.ny, 2)], + ) + props = dict(boxstyle="square", facecolor="white", alpha=0.3) + textbox = canvas.text( + 0.82, + 0.95, + textstr, + transform=canvas.transAxes, + fontsize=10, + verticalalignment="top", + bbox=props, + ) + # leg = canvas.legend(handles,labels,ncol=2,loc='best',prop={'size':4},fancybox=True) + # textbox.get_frame().set_alpha(0.3) + # matplotlib.patches.Rectangle # p = patches.Rectangle((0, 0), 1, 1, fc="r") # p = str('L_par') # leg = canvas.legend([p], ["Red Rectangle"],loc='best',prop={'size':4}) # leg.get_frame().set_alpha(0.3) - #cloney.set_xlim(xmin,xmax) + # cloney.set_xlim(xmin,xmax) try: canvas.set_yscale(yscale) canvas.set_xscale(xscale) - - if yscale =='symlog': - canvas.set_yscale(yscale,linthreshy=1e-13) - if xscale =='symlog': - canvas.set_xscale(xscale,linthreshy=1e-13) - + + if yscale == "symlog": + canvas.set_yscale(yscale, linthreshy=1e-13) + if xscale == "symlog": + canvas.set_xscale(xscale, linthreshy=1e-13) + if gridON: canvas.grid() except: try: - canvas.set_yscale('symlog') + canvas.set_yscale("symlog") except: - print('scaling failed completely') - - - #print '[xmin, xmax, ymin, ymax]: ',[xmin, xmax, ymin, ymax] - - - clonex.set_yscale(yscale) #must be called before limits are set - + print("scaling failed completely") + + # print '[xmin, xmax, ymin, ymax]: ',[xmin, xmax, ymin, ymax] + + clonex.set_yscale(yscale) # must be called before limits are set + try: - if yscale == 'linear': + if yscale == "linear": formatter = ticker.ScalarFormatter() - formatter.set_powerlimits((-2, 2)) #force scientific notation + formatter.set_powerlimits((-2, 2)) # force scientific notation canvas.yaxis.set_major_formatter(formatter) clonex.yaxis.set_major_formatter(formatter) - #canvas.useOffset=False + # canvas.useOffset=False except: - print('fail 1') - [xmin, xmax, ymin, ymax] = canvas.axis() - - - if yscale =='symlog': - clonex.set_yscale(yscale,linthreshy=1e-9) - if xscale =='symlog': - clonex.set_xscale(xscale,linthreshy=1e-9) - #if np.any(s.trans) and trans: - [xmin1, xmax1, ymin1, ymax1] = canvas.axis() + print("fail 1") + [xmin, xmax, ymin, ymax] = canvas.axis() + + if yscale == "symlog": + clonex.set_yscale(yscale, linthreshy=1e-9) + if xscale == "symlog": + clonex.set_xscale(xscale, linthreshy=1e-9) + # if np.any(s.trans) and trans: + [xmin1, xmax1, ymin1, ymax1] = canvas.axis() if trans: try: cloney = canvas.twiny() - #cloney.set_yscale(yscale) + # cloney.set_yscale(yscale) cloney.set_xscale(xscale) [xmin1, xmax1, ymin2, ymax2] = canvas.axis() - if xscale =='symlog': - cloney.set_xscale(xscale,linthreshy=1e-9) - if yscale =='symlog': - cloney.set_yscale(yscale,linthreshy=1e-9) - if yscale =='linear': + if xscale == "symlog": + cloney.set_xscale(xscale, linthreshy=1e-9) + if yscale == "symlog": + cloney.set_yscale(yscale, linthreshy=1e-9) + if yscale == "linear": cloney.yaxis.set_major_formatter(formatter) except: - print('fail trans') + print("fail trans") # cloney.useOffset=False - - + # if xscale =='symlog' and trans: # cloney.set_yscale(yscale,linthreshy=1e-9) # cloney.set_xscale(xscale,linthreshy=1e-9) - - Ln_drive_scale = s.meta['w_Ln'][0]**-1 - #Ln_drive_scale = 2.1e3 - clonex.set_ylim(Ln_drive_scale*ymin, Ln_drive_scale*ymax) - + + Ln_drive_scale = s.meta["w_Ln"][0] ** -1 + # Ln_drive_scale = 2.1e3 + clonex.set_ylim(Ln_drive_scale * ymin, Ln_drive_scale * ymax) + try: if trans: - #k_factor = #scales from k_zeta to k_perp - cloney.set_xlim(kfactor*xmin, kfactor*xmax) + # k_factor = #scales from k_zeta to k_perp + cloney.set_xlim(kfactor * xmin, kfactor * xmax) # if np.any(sub_s.trans) and trans: # comp_r = comp+'_r' # y2 = np.array(ListDictKey(sub_s.db,comp_r)) # #canvas.plot(k[s_i,1,sub_s.nx/2], # # y2[s_i,0,sub_s.nx/2],'k.',ms = 3) - + # cloney.plot(k_r[s_i,1,sub_s.nx/2], # y2[s_i,0,sub_s.nx/2],'k.',ms = 3) # print 'np.sum(np.abs(y-y2)): ',np.sum(np.abs(y-y2)),comp_r - #kfactor =1.0 - #cloney.set_xlim(xmin,xmax) - cloney.set_ylim(ymin,ymax) #because cloney shares the yaxis with canvas it may overide them, this fixes that - cloney.set_xlabel(r'$k_{\perp} \rho_{ci}$',fontsize=18) + # kfactor =1.0 + # cloney.set_xlim(xmin,xmax) + cloney.set_ylim( + ymin, ymax + ) # because cloney shares the yaxis with canvas it may overide them, this fixes that + cloney.set_xlabel(r"$k_{\perp} \rho_{ci}$", fontsize=18) except: - print('moar fail') - #clonex.set_xscale(xscale) - + print("moar fail") + # clonex.set_xscale(xscale) + # except: - # #canvas.set_xscale('symlog', linthreshx=0.1) + # #canvas.set_xscale('symlog', linthreshx=0.1) # print 'extra axis FAIL' - - - #if yscale == 'linear': - #canvas.yaxis.set_major_locator(ticker.LinearLocator(numticks=8)) - - + # if yscale == 'linear': + # canvas.yaxis.set_major_locator(ticker.LinearLocator(numticks=8)) + # minorLocator = MultipleLocator(.005) # canvas.yaxis.set_minor_locator(minorLocator) - #spawn another y label - - - - #clone = canvas.twinx() - #s2 = np.sin(2*np.pi*t) - #ax2.plot(x, s2, 'r.') - - - #ion_acoust_str = r"$\frac{c_s}{L_{\partial_r n}}}$" - - if comp=='gamma': - canvas.set_ylabel(r'$\frac{\gamma}{\omega_{ci}}$',fontsize=18,rotation='horizontal') - clonex.set_ylabel(r'$\frac{\gamma}{\frac{c_s}{L_n}}$', color='k',fontsize=18,rotation='horizontal') - if comp=='freq': - canvas.set_ylabel(r'$\frac{\omega}{\omega_{ci}}$',fontsize=18,rotation='horizontal') - clonex.set_ylabel(r'$\frac{\omega}{\frac{c_s}{L_n}}$', color='k',fontsize=18,rotation='horizontal') - - if comp=='amp': - canvas.set_ylabel(r'$A_k$',fontsize=18,rotation='horizontal') - clonex.set_ylabel(r'$\frac{A_k}{A_{max}}$', color='k',fontsize=18,rotation='horizontal') - - canvas.set_xlabel(r'$k_{\zeta} \rho_{ci}$',fontsize=18) - - - title = comp+ ' computed from ' +field - #canvas.set_title(title,fontsize=14) - fig1.suptitle(title,fontsize=14) - + # spawn another y label + + # clone = canvas.twinx() + # s2 = np.sin(2*np.pi*t) + # ax2.plot(x, s2, 'r.') + + # ion_acoust_str = r"$\frac{c_s}{L_{\partial_r n}}}$" + + if comp == "gamma": + canvas.set_ylabel( + r"$\frac{\gamma}{\omega_{ci}}$", fontsize=18, rotation="horizontal" + ) + clonex.set_ylabel( + r"$\frac{\gamma}{\frac{c_s}{L_n}}$", + color="k", + fontsize=18, + rotation="horizontal", + ) + if comp == "freq": + canvas.set_ylabel( + r"$\frac{\omega}{\omega_{ci}}$", fontsize=18, rotation="horizontal" + ) + clonex.set_ylabel( + r"$\frac{\omega}{\frac{c_s}{L_n}}$", + color="k", + fontsize=18, + rotation="horizontal", + ) + + if comp == "amp": + canvas.set_ylabel(r"$A_k$", fontsize=18, rotation="horizontal") + clonex.set_ylabel( + r"$\frac{A_k}{A_{max}}$", color="k", fontsize=18, rotation="horizontal" + ) + + canvas.set_xlabel(r"$k_{\zeta} \rho_{ci}$", fontsize=18) + + title = comp + " computed from " + field + # canvas.set_title(title,fontsize=14) + fig1.suptitle(title, fontsize=14) + if ownpage: try: - fig1.savefig(pp, format='pdf') + fig1.savefig(pp, format="pdf") except: - print('pyplt doesnt like you') + print("pyplt doesnt like you") plt.close(fig1) - def plotfreq(self,pp,field='Ni',clip=0, - xaxis='t',xscale='linear',yscale='linear'): - #colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] - colors = ['b.','g.','r.','c.','m.','y.','k.','b.','g.','r.','c.','m.','y','k'] + def plotfreq( + self, pp, field="Ni", clip=0, xaxis="t", xscale="linear", yscale="linear" + ): + # colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] + colors = [ + "b.", + "g.", + "r.", + "c.", + "m.", + "y.", + "k.", + "b.", + "g.", + "r.", + "c.", + "m.", + "y", + "k", + ] plt.figure() - - #s = subset(self.db,'field',[field]) #pick field - - + # s = subset(self.db,'field',[field]) #pick field + for q in range(4): - s = subset(self.db,'field',[field]) #pick field across all dz sets + s = subset(self.db, "field", [field]) # pick field across all dz sets modelist = [] - [modelist.append([q+1,p+1]) for p in range(5)] - print(q,'in plotgamma') - s = subset(s.db,'mn',modelist) - - - gamma = s.freq #nmodes x 2 x nx ndarray - k = s.k ##nmodes x 2 x nx ndarray - - plt.errorbar(k[:,1,old_div(s.nx,2)],gamma[:,0,old_div(s.nx,2)], - yerr=gamma[:,1,old_div(s.nx,2)],fmt=colors[q]) - plt.plot(k[:,1,old_div(s.nx,2)], - gamma[:,0,old_div(s.nx,2)],'k:',alpha=.3) - -#loop over dz sets and connect with dotted line . . . + [modelist.append([q + 1, p + 1]) for p in range(5)] + print(q, "in plotgamma") + s = subset(s.db, "mn", modelist) + + gamma = s.freq # nmodes x 2 x nx ndarray + k = s.k ##nmodes x 2 x nx ndarray + + plt.errorbar( + k[:, 1, old_div(s.nx, 2)], + gamma[:, 0, old_div(s.nx, 2)], + yerr=gamma[:, 1, old_div(s.nx, 2)], + fmt=colors[q], + ) + plt.plot( + k[:, 1, old_div(s.nx, 2)], + gamma[:, 0, old_div(s.nx, 2)], + "k:", + alpha=0.3, + ) + + # loop over dz sets and connect with dotted line . . . for j in list(set(s.dz).union()): - # print j,len(s.mn) - sub_s = subset(s.db,'dz',[j]) - gamma = sub_s.gamma - k = sub_s.k ## - plt.plot(k[:,1,old_div(sub_s.nx,2)], - gamma[:,0,old_div(sub_s.nx,2)],'k:',alpha=.1) + # print j,len(s.mn) + sub_s = subset(s.db, "dz", [j]) + gamma = sub_s.gamma + k = sub_s.k ## + plt.plot( + k[:, 1, old_div(sub_s.nx, 2)], + gamma[:, 0, old_div(sub_s.nx, 2)], + "k:", + alpha=0.1, + ) try: plt.yscale(yscale) except: - print('yscale fail') + print("yscale fail") - try: plt.xscale(yscale) except: - plt.xscale('symlog') - plt.xlabel(r'$k \rho_{ci}$',fontsize=14) - plt.ylabel(r'$\frac{\omega}{\omega_{ci}}$',fontsize=14) - #plt.title(r'$\frac{\omega}\{\omega_{ci}}$ '+ 'computed from'+field+ 'field',fontsize=10) - - plt.savefig(pp, format='pdf') + plt.xscale("symlog") + plt.xlabel(r"$k \rho_{ci}$", fontsize=14) + plt.ylabel(r"$\frac{\omega}{\omega_{ci}}$", fontsize=14) + # plt.title(r'$\frac{\omega}\{\omega_{ci}}$ '+ 'computed from'+field+ 'field',fontsize=10) + + plt.savefig(pp, format="pdf") plt.close() - - def plotgamma(self,pp,field='Ni',yscale='symlog',clip=0, - xaxis='t',xscale='linear',xrange=1,comp='gamma', - overplot=False,trans=True): - self.plotomega(pp,field=field,yscale=yscale,clip=clip, - xaxis=xaxis,xscale=xscale,xrange=xrange,comp=comp, - overplot=overplot,trans=trans) - - def plotfreq2(self,pp,field='Ni',yscale='symlog',clip=0, - xaxis='t',xscale='linear',xrange=1,comp='freq', - overplot=False,trans=True): - self.plotomega(pp,field=field,yscale=yscale,clip=clip, - xaxis=xaxis,xscale=xscale,xrange=xrange,comp=comp, - overplot=overplot,trans=trans) - - - def plotvsK(self,pp,rootfig=None,field='Ni',yscale='log',clip=0, - xaxis='t',xscale='linear',xrange=1,comp='amp', - pltlegend='both',overplot=False,gridON=True,trans=False, - infobox=True,m=1,t=[0],file=None,save=True): - colors = ['b.','r.','k.','c.','g.','y.','m.','b.','r.','k.','c.','g.','y.','m.'] - colordash = ['b','r','k','c','g','y','m','b','r','k','c','g','y','m'] - + + def plotgamma( + self, + pp, + field="Ni", + yscale="symlog", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + comp="gamma", + overplot=False, + trans=True, + ): + self.plotomega( + pp, + field=field, + yscale=yscale, + clip=clip, + xaxis=xaxis, + xscale=xscale, + xrange=xrange, + comp=comp, + overplot=overplot, + trans=trans, + ) + + def plotfreq2( + self, + pp, + field="Ni", + yscale="symlog", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + comp="freq", + overplot=False, + trans=True, + ): + self.plotomega( + pp, + field=field, + yscale=yscale, + clip=clip, + xaxis=xaxis, + xscale=xscale, + xrange=xrange, + comp=comp, + overplot=overplot, + trans=trans, + ) + + def plotvsK( + self, + pp, + rootfig=None, + field="Ni", + yscale="log", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + comp="amp", + pltlegend="both", + overplot=False, + gridON=True, + trans=False, + infobox=True, + m=1, + t=[0], + file=None, + save=True, + ): + colors = [ + "b.", + "r.", + "k.", + "c.", + "g.", + "y.", + "m.", + "b.", + "r.", + "k.", + "c.", + "g.", + "y.", + "m.", + ] + colordash = [ + "b", + "r", + "k", + "c", + "g", + "y", + "m", + "b", + "r", + "k", + "c", + "g", + "y", + "m", + ] + if rootfig is None: ownpage = True else: ownpage = False - - if ownpage: + + if ownpage: fig1 = plt.figure() fig1.subplots_adjust(bottom=0.12) fig1.subplots_adjust(top=0.80) fig1.subplots_adjust(right=0.83) fig1.subplots_adjust(left=0.17) - canvas = fig1.add_subplot(1,1,1) + canvas = fig1.add_subplot(1, 1, 1) clonex = canvas.twinx() # if trans: # cloney = canvas.twiny() else: - canvas = rootfig.add_subplot(1,1,1) + canvas = rootfig.add_subplot(1, 1, 1) dzhandles = [] - parhandles =[] - parlabels =[] - dzlabels=[] - - #pick the modes + parhandles = [] + parlabels = [] + dzlabels = [] + + # pick the modes m_shift = m - for q in np.array(list(range(1)))+m_shift: - s = subset(self.db,'field',[field]) #pick field + for q in np.array(list(range(1))) + m_shift: + s = subset(self.db, "field", [field]) # pick field maxZ = min(s.maxN) modelist = [] - [modelist.append([q,p+1]) for p in range(maxZ-1)] - #print q,'in plotgamma' - s = subset(s.db,'mn',modelist) - - #set x-range - xrange = old_div(s.nx,2)-2 - xrange = [old_div(s.nx,2),old_div(s.nx,2)+xrange] - - - #pull up the data - y = np.array(ListDictKey(s.db,comp)) - print('y.shape', y.shape) - - #in case multiple timesteps are indicated + [modelist.append([q, p + 1]) for p in range(maxZ - 1)] + # print q,'in plotgamma' + s = subset(s.db, "mn", modelist) + + # set x-range + xrange = old_div(s.nx, 2) - 2 + xrange = [old_div(s.nx, 2), old_div(s.nx, 2) + xrange] + + # pull up the data + y = np.array(ListDictKey(s.db, comp)) + print("y.shape", y.shape) + + # in case multiple timesteps are indicated all_y = [] all_yerr = [] - if comp=='amp': + if comp == "amp": for elem in t: - all_y.append(np.squeeze(y[:,elem,:])) - all_yerr.append(np.squeeze(0*y[:,elem,:])) + all_y.append(np.squeeze(y[:, elem, :])) + all_yerr.append(np.squeeze(0 * y[:, elem, :])) ynorm = np.max(all_y) - #all_y = np.array(np.squeeze(all_y)) - #all_yerr = np.array(np.squeeze(all_yerr)) + # all_y = np.array(np.squeeze(all_y)) + # all_yerr = np.array(np.squeeze(all_yerr)) else: - all_y.append(np.squeeze(y[:,0,:])) - all_yerr.append(np.squeeze(y[:,1,:])) - ynorm = s.meta['w_Ln'][0] - + all_y.append(np.squeeze(y[:, 0, :])) + all_yerr.append(np.squeeze(y[:, 1, :])) + ynorm = s.meta["w_Ln"][0] + + k = s.k ##nmodes x 2 x nx ndarray k_zeta + kfactor = np.mean( + old_div(s.k_r[:, 1, old_div(s.nx, 2)], s.k[:, 1, old_div(s.nx, 2)]) + ) # good enough for now - k = s.k ##nmodes x 2 x nx ndarray k_zeta - - kfactor = np.mean(old_div(s.k_r[:,1,old_div(s.nx,2)],s.k[:,1,old_div(s.nx,2)])) #good enough for now - - for elem in range(np.size(t)): - #print 'printing line' , elem - errorline = parhandles.append(canvas.errorbar(k[:,1,old_div(s.nx,2)], - all_y[elem][:,old_div(s.nx,2)], - yerr=all_yerr[elem][:,old_div(s.nx,2)], - fmt=colors[q])) - - - parlabels.append("m "+str(q)) - - #loop over dz sets and connect with dotted line . . . - jj=0 #will reference dz color - - ymin_data =np.max(np.array(ListDictKey(s.db,comp))) - ymax_data = 0 #for bookeeping + # print 'printing line' , elem + errorline = parhandles.append( + canvas.errorbar( + k[:, 1, old_div(s.nx, 2)], + all_y[elem][:, old_div(s.nx, 2)], + yerr=all_yerr[elem][:, old_div(s.nx, 2)], + fmt=colors[q], + ) + ) + + parlabels.append("m " + str(q)) + + # loop over dz sets and connect with dotted line . . . + jj = 0 # will reference dz color + + ymin_data = np.max(np.array(ListDictKey(s.db, comp))) + ymax_data = 0 # for bookeeping for p in list(set(s.path).union()): - sub_s = subset(s.db,'path',[p]) + sub_s = subset(s.db, "path", [p]) j = sub_s.dz[0] - #print sub_s.amp.shape - s_i = np.argsort(sub_s.mn[:,1]) #sort by 'local' m, global m is ok also - #print s_i, sub_s.mn, sub_s.nx, jj - y = np.array(ListDictKey(sub_s.db,comp)) - y_alt = 2.0*np.array(ListDictKey(sub_s.db,comp)) + # print sub_s.amp.shape + s_i = np.argsort(sub_s.mn[:, 1]) # sort by 'local' m, global m is ok also + # print s_i, sub_s.mn, sub_s.nx, jj + y = np.array(ListDictKey(sub_s.db, comp)) + y_alt = 2.0 * np.array(ListDictKey(sub_s.db, comp)) all_y = [] all_yerr = [] - if comp=='amp': - for elem in t: - all_y.append(np.squeeze(y[:,elem,:])) - all_yerr.append(np.squeeze(0*y[:,elem,:])) + if comp == "amp": + for elem in t: + all_y.append(np.squeeze(y[:, elem, :])) + all_yerr.append(np.squeeze(0 * y[:, elem, :])) else: - all_y.append(np.squeeze(y[:,0,:])) - all_yerr.append(np.squeeze(y[:,1,:])) - + all_y.append(np.squeeze(y[:, 0, :])) + all_yerr.append(np.squeeze(y[:, 1, :])) + + k = sub_s.k ## - k = sub_s.k ## - for elem in range(np.size(t)): - if q == m_shift: #fix the parallel mode - dzhandles.append(canvas.plot(k[s_i,1,old_div(sub_s.nx,2)], - all_y[elem][s_i,old_div(sub_s.nx,2)],color=colordash[jj],alpha=.5)) - - - ymin_data = np.min([np.min(y[s_i,old_div(sub_s.nx,2)]),ymin_data]) - ymax_data = np.max([np.max(y[s_i,old_div(sub_s.nx,2)]),ymax_data]) - - - dzlabels.append(j) - - if yscale=='log': + if q == m_shift: # fix the parallel mode + dzhandles.append( + canvas.plot( + k[s_i, 1, old_div(sub_s.nx, 2)], + all_y[elem][s_i, old_div(sub_s.nx, 2)], + color=colordash[jj], + alpha=0.5, + ) + ) + + ymin_data = np.min( + [np.min(y[s_i, old_div(sub_s.nx, 2)]), ymin_data] + ) + ymax_data = np.max( + [np.max(y[s_i, old_div(sub_s.nx, 2)]), ymax_data] + ) + + dzlabels.append(j) + + if yscale == "log": factor = 10 else: factor = 2 - #print 'annotating' - canvas.annotate(str(j),(k[s_i[0],1,old_div(sub_s.nx,2)],y[elem][s_i[0],old_div(sub_s.nx,2)]),fontsize = 8) - #p = canvas.axvspan(k[s_i[0],1,sub_s.nx/2], k[s_i[-1],1,sub_s.nx/2], - # facecolor=colordash[jj], alpha=0.01) - print('done annotating') + # print 'annotating' + canvas.annotate( + str(j), + ( + k[s_i[0], 1, old_div(sub_s.nx, 2)], + y[elem][s_i[0], old_div(sub_s.nx, 2)], + ), + fontsize=8, + ) + # p = canvas.axvspan(k[s_i[0],1,sub_s.nx/2], k[s_i[-1],1,sub_s.nx/2], + # facecolor=colordash[jj], alpha=0.01) + print("done annotating") else: - canvas.plot(k[s_i,1,old_div(sub_s.nx,2)], - y[elem][s_i,old_div(sub_s.nx,2)],color=colordash[jj],alpha=.3) + canvas.plot( + k[s_i, 1, old_div(sub_s.nx, 2)], + y[elem][s_i, old_div(sub_s.nx, 2)], + color=colordash[jj], + alpha=0.3, + ) + + jj = jj + 1 - jj=jj+1 - dzhandles = np.array(dzhandles).flatten() dzlabels = np.array(dzlabels).flatten() - + dzlabels = list(set(dzlabels).union()) - + dz_i = np.argsort(dzlabels) - + dzhandles = dzhandles[dz_i] dzlabels_cp = np.array(dzlabels)[dz_i] - - #print type(dzlabels), np.size(dzlabels) + + # print type(dzlabels), np.size(dzlabels) for i in range(np.size(dzlabels)): - dzlabels[i] = "DZ: "+ str(dzlabels_cp[i])#+r"$\pi$" - + dzlabels[i] = "DZ: " + str(dzlabels_cp[i]) # +r"$\pi$" parlabels = np.array(parlabels).flatten() - - if overplot==True: + + if overplot == True: try: - self.plottheory(pp,canvas=canvas,comp=comp,field=field) - #self.plottheory(pp,comp=comp) + self.plottheory(pp, canvas=canvas, comp=comp, field=field) + # self.plottheory(pp,comp=comp) except: - print('no theory plot') + print("no theory plot") if infobox: - textstr = '$\L_{\parallel}=%.2f$\n$\L_{\partial_r n}=%.2f$\n$B=%.2f$'%(s.meta['lpar'][old_div(s.nx,2)], - s.meta['L'][old_div(s.nx,2),old_div(s.ny,2)], - s.meta['Bpxy']['v'][old_div(s.nx,2),old_div(s.ny,2)]) - props = dict(boxstyle='square', facecolor='white', alpha=0.3) - textbox = canvas.text(0.82, 0.95, textstr, transform=canvas.transAxes, fontsize=10, - verticalalignment='top', bbox=props) - # leg = canvas.legend(handles,labels,ncol=2,loc='best',prop={'size':4},fancybox=True) - - - #cloney.set_xlim(xmin,xmax) + textstr = "$\L_{\parallel}=%.2f$\n$\L_{\partial_r n}=%.2f$\n$B=%.2f$" % ( + s.meta["lpar"][old_div(s.nx, 2)], + s.meta["L"][old_div(s.nx, 2), old_div(s.ny, 2)], + s.meta["Bpxy"]["v"][old_div(s.nx, 2), old_div(s.ny, 2)], + ) + props = dict(boxstyle="square", facecolor="white", alpha=0.3) + textbox = canvas.text( + 0.82, + 0.95, + textstr, + transform=canvas.transAxes, + fontsize=10, + verticalalignment="top", + bbox=props, + ) + # leg = canvas.legend(handles,labels,ncol=2,loc='best',prop={'size':4},fancybox=True) + + # cloney.set_xlim(xmin,xmax) try: canvas.set_yscale(yscale) canvas.set_xscale(xscale) - - if yscale =='symlog': - canvas.set_yscale(yscale,linthreshy=1e-13) - if xscale =='symlog': - canvas.set_xscale(xscale,linthreshy=1e-13) - + + if yscale == "symlog": + canvas.set_yscale(yscale, linthreshy=1e-13) + if xscale == "symlog": + canvas.set_xscale(xscale, linthreshy=1e-13) + if gridON: canvas.grid() except: try: - canvas.set_yscale('symlog') + canvas.set_yscale("symlog") except: - print('scaling failed completely') - - ################################################################## - + print("scaling failed completely") + + ################################################################## + if ownpage and rootfig is None: - clonex.set_yscale(yscale) #must be called before limits are set - + clonex.set_yscale(yscale) # must be called before limits are set + try: - if yscale == 'linear': + if yscale == "linear": formatter = ticker.ScalarFormatter() - formatter.set_powerlimits((-2, 2)) #force scientific notation + formatter.set_powerlimits((-2, 2)) # force scientific notation canvas.yaxis.set_major_formatter(formatter) clonex.yaxis.set_major_formatter(formatter) - #canvas.useOffset=False + # canvas.useOffset=False except: - print('fail 1') - [xmin, xmax, ymin, ymax] = canvas.axis() - - - if yscale =='symlog': - clonex.set_yscale(yscale,linthreshy=1e-9) - if xscale =='symlog': - clonex.set_xscale(xscale,linthreshy=1e-9) - #if np.any(s.trans) and trans: - [xmin1, xmax1, ymin1, ymax1] = canvas.axis() + print("fail 1") + [xmin, xmax, ymin, ymax] = canvas.axis() + + if yscale == "symlog": + clonex.set_yscale(yscale, linthreshy=1e-9) + if xscale == "symlog": + clonex.set_xscale(xscale, linthreshy=1e-9) + # if np.any(s.trans) and trans: + [xmin1, xmax1, ymin1, ymax1] = canvas.axis() if trans: try: cloney = canvas.twiny() - #cloney.set_yscale(yscale) + # cloney.set_yscale(yscale) cloney.set_xscale(xscale) [xmin1, xmax1, ymin2, ymax2] = canvas.axis() - if xscale =='symlog': - cloney.set_xscale(xscale,linthreshy=1e-9) - if yscale =='symlog': - cloney.set_yscale(yscale,linthreshy=1e-9) - if yscale =='linear': + if xscale == "symlog": + cloney.set_xscale(xscale, linthreshy=1e-9) + if yscale == "symlog": + cloney.set_yscale(yscale, linthreshy=1e-9) + if yscale == "linear": cloney.yaxis.set_major_formatter(formatter) except: - print('fail trans') - - Ln_drive_scale = s.meta['w_Ln'][0]**-1 - #Ln_drive_scale = 2.1e3 - #clonex.set_ylim(Ln_drive_scale*ymin, Ln_drive_scale*ymax) - clonex.set_ylim(ynorm**-1*ymin, ynorm**-1*ymax) - + print("fail trans") + + Ln_drive_scale = s.meta["w_Ln"][0] ** -1 + # Ln_drive_scale = 2.1e3 + # clonex.set_ylim(Ln_drive_scale*ymin, Ln_drive_scale*ymax) + clonex.set_ylim(ynorm ** -1 * ymin, ynorm ** -1 * ymax) + try: if trans: - #k_factor = #scales from k_zeta to k_perp - cloney.set_xlim(kfactor*xmin, kfactor*xmax) - - cloney.set_ylim(ymin,ymax) #because cloney shares the yaxis with canvas it may overide them, this fixes that - cloney.set_xlabel(r'$k_{\perp} \rho_{ci}$',fontsize=18) + # k_factor = #scales from k_zeta to k_perp + cloney.set_xlim(kfactor * xmin, kfactor * xmax) + + cloney.set_ylim( + ymin, ymax + ) # because cloney shares the yaxis with canvas it may overide them, this fixes that + cloney.set_xlabel(r"$k_{\perp} \rho_{ci}$", fontsize=18) except: - print('moar fail') - #clonex.set_xscale(xscale) - - - - #ion_acoust_str = r"$\frac{c_s}{L_{\partial_r n}}}$" - - if comp=='gamma': - canvas.set_ylabel(r'$\frac{\gamma}{\omega_{ci}}$',fontsize=18,rotation='horizontal') - clonex.set_ylabel(r'$\frac{\gamma}{\frac{c_s}{L_n}}$', color='k',fontsize=18,rotation='horizontal') - if comp=='freq': - canvas.set_ylabel(r'$\frac{\omega}{\omega_{ci}}$',fontsize=18,rotation='horizontal') - clonex.set_ylabel(r'$\frac{\omega}{\frac{c_s}{L_n}}$', color='k',fontsize=18,rotation='horizontal') - - if comp=='amp': - canvas.set_ylabel(r'$A_k$',fontsize=18,rotation='horizontal') - clonex.set_ylabel(r'$\frac{A_k}{A_{max}}$', color='k',fontsize=18,rotation='horizontal') - - canvas.set_xlabel(r'$k_{\zeta} \rho_{ci}$',fontsize=18) - - - title = comp+ ' computed from ' +field - #canvas.set_title(title,fontsize=14) - fig1.suptitle(title,fontsize=14) - - - - + print("moar fail") + # clonex.set_xscale(xscale) + + # ion_acoust_str = r"$\frac{c_s}{L_{\partial_r n}}}$" + + if comp == "gamma": + canvas.set_ylabel( + r"$\frac{\gamma}{\omega_{ci}}$", fontsize=18, rotation="horizontal" + ) + clonex.set_ylabel( + r"$\frac{\gamma}{\frac{c_s}{L_n}}$", + color="k", + fontsize=18, + rotation="horizontal", + ) + if comp == "freq": + canvas.set_ylabel( + r"$\frac{\omega}{\omega_{ci}}$", fontsize=18, rotation="horizontal" + ) + clonex.set_ylabel( + r"$\frac{\omega}{\frac{c_s}{L_n}}$", + color="k", + fontsize=18, + rotation="horizontal", + ) + + if comp == "amp": + canvas.set_ylabel(r"$A_k$", fontsize=18, rotation="horizontal") + clonex.set_ylabel( + r"$\frac{A_k}{A_{max}}$", + color="k", + fontsize=18, + rotation="horizontal", + ) + + canvas.set_xlabel(r"$k_{\zeta} \rho_{ci}$", fontsize=18) + + title = comp + " computed from " + field + # canvas.set_title(title,fontsize=14) + fig1.suptitle(title, fontsize=14) + if not ownpage: - print('probably for a movie') + print("probably for a movie") fig1 = rootfig - # canvasjunk = fig1.add_subplot(1,1,1) + # canvasjunk = fig1.add_subplot(1,1,1) # canvasjunk = canvas - if save: if file is None: try: - fig1.savefig(pp,format='pdf') + fig1.savefig(pp, format="pdf") except: - print('pyplt doesnt like you') - else: + print("pyplt doesnt like you") + else: try: - fig1.savefig(file,dpi=200) + fig1.savefig(file, dpi=200) except: - print('no movie for you ;(') + print("no movie for you ;(") if ownpage: - #fig1.close() + # fig1.close() plt.close(fig1) - - + def plotmodes( + self, + pp, + field="Ni", + comp="amp", + math="1", + ylim=1, + yscale="symlog", + clip=False, + xaxis="t", + xscale="linear", + xrange=1, + debug=False, + yaxis=r"$\frac{Ni}{Ni_0}$", + linestyle="-", + summary=True, + ): - def plotmodes(self,pp,field='Ni',comp='amp',math='1',ylim=1, - yscale='symlog',clip=False,xaxis='t',xscale='linear', - xrange=1,debug=False,yaxis=r'$\frac{Ni}{Ni_0}$', - linestyle='-',summary=True): - Nplots = self.nrun - colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] - styles = ['^','s'] - + colors = ["b", "g", "r", "c", "m", "y", "k", "b", "g", "r", "c", "m", "y", "k"] + styles = ["^", "s"] + fig1 = plt.figure() - + fig2 = plt.figure() - - - Modes = subset(self.db,'field',[field]) #pick field - - - adj = fig2.subplots_adjust(hspace=0.4,wspace=0.4) - fig2.suptitle('Dominant mode '+ comp+' for '+ field) - props = dict( alpha=0.8, edgecolors='none') - - - allcurves = fig1.add_subplot(1,1,1) - fig1.suptitle('Dominant mode behavior for '+ field) - + + Modes = subset(self.db, "field", [field]) # pick field + + adj = fig2.subplots_adjust(hspace=0.4, wspace=0.4) + fig2.suptitle("Dominant mode " + comp + " for " + field) + props = dict(alpha=0.8, edgecolors="none") + + allcurves = fig1.add_subplot(1, 1, 1) + fig1.suptitle("Dominant mode behavior for " + field) + modenames = [] k = 0 - + for j in list(set(Modes.path).union()): # - s = subset(Modes.db,'path',[j]) #pick run + s = subset(Modes.db, "path", [j]) # pick run dz = s.dz[0] - xr = list(range(old_div(s.nx,2)-old_div(xrange,2),old_div(s.nx,2)+old_div(xrange,2)+1)) - data = np.array(ListDictKey(s.db,comp)) #pick component should be ok for a fixed dz key - - data = data #+ 1e-32 #hacky way to deal with buggy scaling - ax =fig2.add_subplot(round(old_div(Nplots,3.0) + 1.0),3,k+1) - - ax.grid(True,linestyle='-',color='.75') - handles=[] - #modenames.append(str(j)) - - #find the "biggest" mode for this dz - d = data[:,s.nt[0]-1,:] #nmode X nx array - #d = s.gamma[:,2,:] + xr = list( + range( + old_div(s.nx, 2) - old_div(xrange, 2), + old_div(s.nx, 2) + old_div(xrange, 2) + 1, + ) + ) + data = np.array( + ListDictKey(s.db, comp) + ) # pick component should be ok for a fixed dz key + + data = data # + 1e-32 #hacky way to deal with buggy scaling + ax = fig2.add_subplot(round(old_div(Nplots, 3.0) + 1.0), 3, k + 1) + + ax.grid(True, linestyle="-", color=".75") + handles = [] + # modenames.append(str(j)) + + # find the "biggest" mode for this dz + d = data[:, s.nt[0] - 1, :] # nmode X nx array + # d = s.gamma[:,2,:] where = d == np.nanmax(d) - z = where.nonzero() #mode index and n index + z = where.nonzero() # mode index and n index imax = z[0][0] - #xi_max = z[1][0] - xi_max = old_div(s.nx,2) + # xi_max = z[1][0] + xi_max = old_div(s.nx, 2) + + if debug and yscale == "log": + gamma = np.array(ListDictKey(s.db, "gamma")) # nmodes x 2 x nx - if debug and yscale=='log': - gamma = np.array(ListDictKey(s.db,'gamma')) #nmodes x 2 x nx - for i in range(s.nmodes): - if math=='gamma': - out = old_div(np.gradient(data[i,:,xr])[1],data[i,:,xr]) + if math == "gamma": + out = old_div(np.gradient(data[i, :, xr])[1], data[i, :, xr]) else: - out = data[i,2:,xi_max] #skip the first 2 points - - if xaxis=='t': - #print 'out.size', out.size, out.shape + out = data[i, 2:, xi_max] # skip the first 2 points + + if xaxis == "t": + # print 'out.size', out.size, out.shape x = np.array(list(range(out.size))) - #plt.plot(x,out.flatten(),c=colors[k]) + # plt.plot(x,out.flatten(),c=colors[k]) label = str(s.mn[i]) - #handles.append(ax.plot(x,out.flatten(), - # c=cm.jet(1.*k),label = label)) - ax.plot(x,out.flatten(), - c=cm.jet(.2*i),label = label,linestyle='-') - + # handles.append(ax.plot(x,out.flatten(), + # c=cm.jet(1.*k),label = label)) + ax.plot( + x, out.flatten(), c=cm.jet(0.2 * i), label=label, linestyle="-" + ) + else: - x = np.array(ListDictKey(s.db,xaxis))[i,:,xr] - #x #an N? by nx array - print(x[:,1], out[:,0]) - plt.scatter(x[:,1],out[:,0])#,c=colors[k]) - ax.scatter(x[:,1],out[:,0])#,c=colors[k])#,alpha = (1 +i)/s.nmodes) - - #detect error (bar data - print('error bars:',x,out) - - - #ax.legend(handles,labels,loc='best',prop={'size':6}) - + x = np.array(ListDictKey(s.db, xaxis))[i, :, xr] + # x #an N? by nx array + print(x[:, 1], out[:, 0]) + plt.scatter(x[:, 1], out[:, 0]) # ,c=colors[k]) + ax.scatter( + x[:, 1], out[:, 0] + ) # ,c=colors[k])#,alpha = (1 +i)/s.nmodes) + + # detect error (bar data + print("error bars:", x, out) + + # ax.legend(handles,labels,loc='best',prop={'size':6}) + formatter = ticker.ScalarFormatter() - formatter.set_powerlimits((0, 0)) - ax.xaxis.set_major_formatter(formatter) - #ax.axis('tight') - if yscale=='linear': + formatter.set_powerlimits((0, 0)) + ax.xaxis.set_major_formatter(formatter) + # ax.axis('tight') + if yscale == "linear": ax.yaxis.set_major_formatter(formatter) - if yscale=='symlog': - ax.set_yscale('symlog',linthreshy=1e-13) + if yscale == "symlog": + ax.set_yscale("symlog", linthreshy=1e-13) else: try: - ax.set_yscale(yscale) + ax.set_yscale(yscale) except: - print('may get weird axis') - ax.set_yscale('symlog') + print("may get weird axis") + ax.set_yscale("symlog") # if comp=='phase' or yscale=='linear': # ax.set_xscale('symlog',linthreshx=1.0) - + ax.set_xscale(xscale) - ax.axis('tight') + ax.axis("tight") artist.setp(ax.axes.get_xticklabels(), fontsize=6) artist.setp(ax.axes.get_yticklabels(), fontsize=8) - #artist.setp(ax.axes.get_yscale(), fontsize=8) - ax.set_title(str(dz),fontsize=10) + # artist.setp(ax.axes.get_yscale(), fontsize=8) + ax.set_title(str(dz), fontsize=10) ax.set_xlabel(xaxis) handles, labels = ax.get_legend_handles_labels() - leg = ax.legend(handles,labels,ncol=2,loc='best',prop={'size':4},fancybox=True) + leg = ax.legend( + handles, labels, ncol=2, loc="best", prop={"size": 4}, fancybox=True + ) leg.get_frame().set_alpha(0.3) - #x = s.Rxy[imax,:,s.ny/2] - - t0=2 - if clip == True: - t0 = round(old_div(s.nt[0],3)) - y = np.squeeze(data[imax,t0:,xi_max]) + # x = s.Rxy[imax,:,s.ny/2] + + t0 = 2 + if clip == True: + t0 = round(old_div(s.nt[0], 3)) + y = np.squeeze(data[imax, t0:, xi_max]) x = np.array(list(range(y.size))) - - - print(imax,xi_max) - - label = str([round(elem,3) for elem in s.MN[imax]])+ str(s.mn[imax])+' at x= '+str(xi_max)+' ,'+str(round(old_div(s.gamma[imax,2,xi_max],s.gamma[imax,0,xi_max]),3))+'% '+str(round(s.gamma[imax,0,xi_max],4)) + + print(imax, xi_max) + + label = ( + str([round(elem, 3) for elem in s.MN[imax]]) + + str(s.mn[imax]) + + " at x= " + + str(xi_max) + + " ," + + str( + round( + old_div(s.gamma[imax, 2, xi_max], s.gamma[imax, 0, xi_max]), 3 + ) + ) + + "% " + + str(round(s.gamma[imax, 0, xi_max], 4)) + ) short_label = str(dz) - print(short_label,x.shape,y.shape) - allcurves.plot(x,y,'.',c=cm.jet(1.*k/len(x)), - label=label) - #print len(x), k*len(x)/(Nplots+2),s.nrun - allcurves.annotate(short_label,(x[k*len(x)/(Nplots+1)], - y[k*len(x)/(Nplots+1)]),fontsize = 8) - - - #modenames.append(str([round(elem,3) for elem in s.MN[imax]]) - # +str(s.mn[imax])+' at x= '+str(xi_max)+' ,'+str(s.gamma[imax,2,xi_max])) - - if debug and yscale=='log': - gam = gamma[imax,0,xi_max] - f0 = gamma[imax,1,xi_max] - allcurves.plot(x,f0*np.exp(gam*s.dt[imax]*x),'k:') - - - k+=1 - - # if ylim: - # allcurves.set_ylim(data[,xi_max].min(),5*data[:,xi_max].max()) - - fig2.savefig(pp, format='pdf') - + print(short_label, x.shape, y.shape) + allcurves.plot(x, y, ".", c=cm.jet(1.0 * k / len(x)), label=label) + # print len(x), k*len(x)/(Nplots+2),s.nrun + allcurves.annotate( + short_label, + (x[k * len(x) / (Nplots + 1)], y[k * len(x) / (Nplots + 1)]), + fontsize=8, + ) + + # modenames.append(str([round(elem,3) for elem in s.MN[imax]]) + # +str(s.mn[imax])+' at x= '+str(xi_max)+' ,'+str(s.gamma[imax,2,xi_max])) + + if debug and yscale == "log": + gam = gamma[imax, 0, xi_max] + f0 = gamma[imax, 1, xi_max] + allcurves.plot(x, f0 * np.exp(gam * s.dt[imax] * x), "k:") + + k += 1 + + # if ylim: + # allcurves.set_ylim(data[,xi_max].min(),5*data[:,xi_max].max()) + + fig2.savefig(pp, format="pdf") + handles, labels = allcurves.get_legend_handles_labels() - allcurves.legend(handles,labels,loc='best',prop={'size':6}) -#allcurves.legend(modenames,loc='best',prop={'size':6}) - allcurves.set_title(field+ ' '+comp+', all runs, '+yscale+' yscale',fontsize=10) + allcurves.legend(handles, labels, loc="best", prop={"size": 6}) + # allcurves.legend(modenames,loc='best',prop={'size':6}) + allcurves.set_title( + field + " " + comp + ", all runs, " + yscale + " yscale", fontsize=10 + ) allcurves.set_ylabel(yaxis) allcurves.set_xlabel(xaxis) - - - if yscale=='linear': + + if yscale == "linear": allcurves.yaxis.set_major_formatter(formatter) else: try: - allcurves.set_yscale(yscale) + allcurves.set_yscale(yscale) except: - print('may get weird axis scaling') - if yscale=='log': - allcurves.axis('tight') - #allcurves.set_ylim(data.min(),data.max()) - #allcurves.set_yscale(yscale,nonposy='mask') - - #plt.xscale(xscale) - - - #plt.legend(modenames,loc='best') - if summary: - fig1.savefig(pp, format='pdf') + print("may get weird axis scaling") + if yscale == "log": + allcurves.axis("tight") + # allcurves.set_ylim(data.min(),data.max()) + # allcurves.set_yscale(yscale,nonposy='mask') + + # plt.xscale(xscale) + + # plt.legend(modenames,loc='best') + if summary: + fig1.savefig(pp, format="pdf") plt.close(fig1) plt.close(fig2) - - #except: - # print "Sorry you fail" - - - def plotradeigen(self,pp,field='Ni',comp='amp', - yscale='linear',xscale = 'linear'): - - Nplots = self.nrun - colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] + + # except: + # print "Sorry you fail" + + def plotradeigen( + self, pp, field="Ni", comp="amp", yscale="linear", xscale="linear" + ): + + Nplots = self.nrun + colors = ["b", "g", "r", "c", "m", "y", "k", "b", "g", "r", "c", "m", "y", "k"] fig1 = plt.figure() - + fig2 = plt.figure() - adj = fig2.subplots_adjust(hspace=0.4,wspace=0.4) - - #canvas = FigureCanvas(fig) - - Modes = subset(self.db,'field',[field]) - + adj = fig2.subplots_adjust(hspace=0.4, wspace=0.4) + + # canvas = FigureCanvas(fig) + + Modes = subset(self.db, "field", [field]) + k = 0 - fig2.suptitle('Dominant mode behavior for '+ field) - props = dict( alpha=0.8, edgecolors='none' ) - - allcurves = fig1.add_subplot(1,1,1) - fig1.suptitle('Dominant mode behavior for '+ field) - - modeleg = [] + fig2.suptitle("Dominant mode behavior for " + field) + props = dict(alpha=0.8, edgecolors="none") + + allcurves = fig1.add_subplot(1, 1, 1) + fig1.suptitle("Dominant mode behavior for " + field) + modeleg = [] for p in list(set(Modes.path).union()): print(p) - s = subset(Modes.db,'path',[p]) #pick run - #data = np.array(ListDictKey(s.db,comp)) #pick component - j = s.dz[0] - ax =fig2.add_subplot(round(old_div(Nplots,3.0) + 1.0),3,k+1) - ax.grid(True,linestyle='-',color='.75') - data = np.array(ListDictKey(s.db,comp)) #pick component - handles=[] - - #find the "biggest" mode for this dz - d = data[:,s.nt[0]-1,:] #nmode X nx array + s = subset(Modes.db, "path", [p]) # pick run + # data = np.array(ListDictKey(s.db,comp)) #pick component + j = s.dz[0] + ax = fig2.add_subplot(round(old_div(Nplots, 3.0) + 1.0), 3, k + 1) + ax.grid(True, linestyle="-", color=".75") + data = np.array(ListDictKey(s.db, comp)) # pick component + handles = [] + + # find the "biggest" mode for this dz + d = data[:, s.nt[0] - 1, :] # nmode X nx array where = d == d.max() - z = where.nonzero() #mode index and n index + z = where.nonzero() # mode index and n index imax = z[0][0] - modeleg.append(str([round(elem,3) for elem in s.MN[imax]])+str(s.mn[imax])) - - #str(s.k[:,1,:][z]) - - - for i in range(s.nmodes): - #out = mode[mode.ny/2,:] - #print i,s.Rxynorm.shape,s.ny - x = np.squeeze(s.Rxynorm[i,:,old_div(s.ny,2)]) - y = data[i,s.nt[0]-1,:] - - handles.append(ax.plot(x,y,c=cm.jet(1.*k/len(x)))) + modeleg.append( + str([round(elem, 3) for elem in s.MN[imax]]) + str(s.mn[imax]) + ) + + # str(s.k[:,1,:][z]) + + for i in range(s.nmodes): + # out = mode[mode.ny/2,:] + # print i,s.Rxynorm.shape,s.ny + x = np.squeeze(s.Rxynorm[i, :, old_div(s.ny, 2)]) + y = data[i, s.nt[0] - 1, :] + + handles.append(ax.plot(x, y, c=cm.jet(1.0 * k / len(x)))) formatter = ticker.ScalarFormatter() - formatter.set_powerlimits((0, 0)) - ax.xaxis.set_major_formatter(formatter) + formatter.set_powerlimits((0, 0)) + ax.xaxis.set_major_formatter(formatter) - if yscale=='linear': + if yscale == "linear": ax.yaxis.set_major_formatter(formatter) else: ax.set_yscale(yscale) - + artist.setp(ax.axes.get_xticklabels(), fontsize=6) artist.setp(ax.axes.get_yticklabels(), fontsize=8) - #artist.setp(ax.axes.get_yscale(), fontsize=8) - ax.set_title(str(j),fontsize=10) - - - x = np.squeeze(s.Rxynorm[imax,:,old_div(s.ny,2)]) - y = data[imax,s.nt[0]-1,:] - #allcurves.plot(x,y,c= colors[k]) - allcurves.plot(x,y,c=cm.jet(.1*k/len(x))) + # artist.setp(ax.axes.get_yscale(), fontsize=8) + ax.set_title(str(j), fontsize=10) + + x = np.squeeze(s.Rxynorm[imax, :, old_div(s.ny, 2)]) + y = data[imax, s.nt[0] - 1, :] + # allcurves.plot(x,y,c= colors[k]) + allcurves.plot(x, y, c=cm.jet(0.1 * k / len(x))) print(k) - k= k+1 - - fig2.savefig(pp, format='pdf') - if yscale=='linear': + k = k + 1 + + fig2.savefig(pp, format="pdf") + if yscale == "linear": allcurves.yaxis.set_major_formatter(formatter) else: allcurves.set_yscale(yscale) try: allcurves.set_xscale(xscale) except: - allcurves.set_xscale('symlog') + allcurves.set_xscale("symlog") - #allcurves.xaxis.set_major_formatter(ticker.NullFormatter()) - allcurves.legend(modeleg,loc='best',prop={'size':6}) - allcurves.set_xlabel(r'$\frac{x}{\rho_{ci}}$') - allcurves.set_ylabel(r'$\frac{Ni}{Ni_0}$') - fig1.savefig(pp, format='pdf') + # allcurves.xaxis.set_major_formatter(ticker.NullFormatter()) + allcurves.legend(modeleg, loc="best", prop={"size": 6}) + allcurves.set_xlabel(r"$\frac{x}{\rho_{ci}}$") + allcurves.set_ylabel(r"$\frac{Ni}{Ni_0}$") + fig1.savefig(pp, format="pdf") plt.close(fig1) plt.close(fig2) - - - def plotmodes2(self,pp,field='Ni',comp='amp',math='1',ylim=1, - yscale='symlog',clip=0,xaxis='t',xscale='linear', - xrange=1,debug=False): - - Nplots = self.nrun - Modes = subset(self.db,'field',[field]) #pick field - colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] - - fig = Figure() - plt.figure() - - canvas = FigureCanvas(fig) - k = 0 - nrow = round(old_div(Nplots,3.0) + 1.0) - ncol = 3 - #nrow = round(Nplots/3.0 + 1.0) - #ncol = round(Nplots/3.0 + 1.0) - f, axarr = plt.subplots(int(nrow),int(ncol)) - - for p in list(set(Modes.path).union()): # - s = subset(Modes.db,'path',[p]) #pick run - j= s.dz[0] - xr = list(range(old_div(s.nx,2)-old_div(xrange,2),old_div(s.nx,2)+old_div(xrange,2)+1)) - data = np.array(ListDictKey(s.db,comp)) #pick component - #ax =fig.add_subplot(round(Nplots/3.0 + 1.0),3,k+1) - - for i in range(s.nmodes): - out = data[i,:,xr] - - print(j,i) - if xaxis=='t': - x = list(range(out.size)) - #plt.scatter(x,out.flatten(),c=colors[k]) - plt.scatter(x,out.flatten(), - c=cm.jet(1.*k/len(x))) - #axarr[j%(ncol),j/ncol].scatter(x,out.flatten(),c=colors[k])#,alpha = (1 +i)/s.nmodes) - axarr[old_div(j,ncol),j%(ncol)].scatter(x,out.flatten(),c=cm.jet(1.*k/len(x)))# - - else: - x = np.array(ListDictKey(s.db,xaxis))[i,:,xr] - #x #an N? by nx array - print(x[:,1], out[:,0]) - plt.scatter(x[:,1],out[:,0])#,c=colors[k]) - axarr[j%(col),old_div(j,col)].scatter(x[:,1],out[:,0])#,c=colors[k])#,alpha = (1 +i)/s.nmodes) - - #detect error (bar data - print('error bars:',x,out) - - - - axarr[old_div(j,ncol),j%(ncol)].set_yscale(yscale) - axarr[old_div(j,ncol),j%(ncol)].set_xscale(xscale) - axarr[old_div(j,ncol),j%(ncol)].set_title(str(j),fontsize=10) - axarr[old_div(j,ncol),j%(ncol)].set_xlabel(xaxis) - - plt.setp([a.get_xticklabels() for a in axarr[0,:]], visible=False) - plt.setp([a.get_yticklabels() for a in axarr[:,ncol-1]], visible=False) - - if ylim: - axarr[j%(ncol),old_div(j,ncol)].set_ylim(data.min(),5*data.max()) - k+=1 - - plt.title(field+ ' '+comp+', all runs, '+yscale+' yscale',fontsize=10) - plt.xlabel(xaxis) - if ylim: - plt.ylim(data.min(),10*data.max()) - - - plt.yscale(yscale,nonposy='mask') - plt.xscale(xscale) - - fig.savefig(pp, format='pdf') - plt.savefig(pp, format='pdf') - - plt.close() - - return 0 - - def plotMacroDep(self,pp,field='Ni',yscale='symlog',clip=0, - xaxis='t',xscale='linear',xrange=1): - colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] + + def plotmodes2( + self, + pp, + field="Ni", + comp="amp", + math="1", + ylim=1, + yscale="symlog", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + debug=False, + ): + + Nplots = self.nrun + Modes = subset(self.db, "field", [field]) # pick field + colors = ["b", "g", "r", "c", "m", "y", "k", "b", "g", "r", "c", "m", "y", "k"] + + fig = Figure() plt.figure() - - def savemovie(self,field='Ni',yscale='log',xscale='log',moviename='spectrum.avi'): - - print('Making movie animation.mpg - this make take a while') + + canvas = FigureCanvas(fig) + k = 0 + nrow = round(old_div(Nplots, 3.0) + 1.0) + ncol = 3 + # nrow = round(Nplots/3.0 + 1.0) + # ncol = round(Nplots/3.0 + 1.0) + f, axarr = plt.subplots(int(nrow), int(ncol)) + + for p in list(set(Modes.path).union()): # + s = subset(Modes.db, "path", [p]) # pick run + j = s.dz[0] + xr = list( + range( + old_div(s.nx, 2) - old_div(xrange, 2), + old_div(s.nx, 2) + old_div(xrange, 2) + 1, + ) + ) + data = np.array(ListDictKey(s.db, comp)) # pick component + # ax =fig.add_subplot(round(Nplots/3.0 + 1.0),3,k+1) + + for i in range(s.nmodes): + out = data[i, :, xr] + + print(j, i) + if xaxis == "t": + x = list(range(out.size)) + # plt.scatter(x,out.flatten(),c=colors[k]) + plt.scatter(x, out.flatten(), c=cm.jet(1.0 * k / len(x))) + # axarr[j%(ncol),j/ncol].scatter(x,out.flatten(),c=colors[k])#,alpha = (1 +i)/s.nmodes) + axarr[old_div(j, ncol), j % (ncol)].scatter( + x, out.flatten(), c=cm.jet(1.0 * k / len(x)) + ) # + + else: + x = np.array(ListDictKey(s.db, xaxis))[i, :, xr] + # x #an N? by nx array + print(x[:, 1], out[:, 0]) + plt.scatter(x[:, 1], out[:, 0]) # ,c=colors[k]) + axarr[j % (col), old_div(j, col)].scatter( + x[:, 1], out[:, 0] + ) # ,c=colors[k])#,alpha = (1 +i)/s.nmodes) + + # detect error (bar data + print("error bars:", x, out) + + axarr[old_div(j, ncol), j % (ncol)].set_yscale(yscale) + axarr[old_div(j, ncol), j % (ncol)].set_xscale(xscale) + axarr[old_div(j, ncol), j % (ncol)].set_title(str(j), fontsize=10) + axarr[old_div(j, ncol), j % (ncol)].set_xlabel(xaxis) + + plt.setp([a.get_xticklabels() for a in axarr[0, :]], visible=False) + plt.setp([a.get_yticklabels() for a in axarr[:, ncol - 1]], visible=False) + + if ylim: + axarr[j % (ncol), old_div(j, ncol)].set_ylim(data.min(), 5 * data.max()) + k += 1 + + plt.title(field + " " + comp + ", all runs, " + yscale + " yscale", fontsize=10) + plt.xlabel(xaxis) + if ylim: + plt.ylim(data.min(), 10 * data.max()) + + plt.yscale(yscale, nonposy="mask") + plt.xscale(xscale) + + fig.savefig(pp, format="pdf") + plt.savefig(pp, format="pdf") + + plt.close() + + return 0 + + def plotMacroDep( + self, + pp, + field="Ni", + yscale="symlog", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + ): + colors = ["b", "g", "r", "c", "m", "y", "k", "b", "g", "r", "c", "m", "y", "k"] + plt.figure() + + def savemovie( + self, field="Ni", yscale="log", xscale="log", moviename="spectrum.avi" + ): + + print("Making movie animation.mpg - this make take a while") files = [] - - for t in range(self.nt[0]-3): - print(t) - filename = str('%03d' %(t+1) + '.png') - self.plotvsK('dont need pp',yscale='log',t=[1,t+2],xscale='log', - overplot=False,comp='amp',trans=True,file=filename) - files.append(filename) - - command = ('mencoder', - 'mf://*.png', - '-mf', - 'type=png:w=800:h=600:fps=10', - '-ovc', - 'lavc', - '-lavcopts', - 'vcodec=mpeg4', - '-oac', - 'copy', - '-o', - moviename) - - import subprocess,os + + for t in range(self.nt[0] - 3): + print(t) + filename = str("%03d" % (t + 1) + ".png") + self.plotvsK( + "dont need pp", + yscale="log", + t=[1, t + 2], + xscale="log", + overplot=False, + comp="amp", + trans=True, + file=filename, + ) + files.append(filename) + + command = ( + "mencoder", + "mf://*.png", + "-mf", + "type=png:w=800:h=600:fps=10", + "-ovc", + "lavc", + "-lavcopts", + "vcodec=mpeg4", + "-oac", + "copy", + "-o", + moviename, + ) + + import subprocess, os subprocess.check_call(command) - os.system("rm *png") + os.system("rm *png") - def printmeta(self,pp,filename='output2.pdf',debug=False): + def printmeta(self, pp, filename="output2.pdf", debug=False): import os from pyPdf import PdfFileWriter, PdfFileReader - - PAGE_HEIGHT=defaultPageSize[1] + + PAGE_HEIGHT = defaultPageSize[1] styles = getSampleStyleSheet() Title = "BOUT++ Results" Author = "Dmitry Meyerson" URL = "" email = "dmitry.meyerson@gmail.com" Abstract = """This document highlights some results from BOUT++ simulation""" - Elements=[] + Elements = [] HeaderStyle = styles["Heading1"] ParaStyle = styles["Normal"] PreStyle = styles["Code"] - - def header(txt, style=HeaderStyle, klass=Paragraph, sep=0.3): #return styled text with a space - s = Spacer(0.2*inch, sep*inch) + + def header( + txt, style=HeaderStyle, klass=Paragraph, sep=0.3 + ): # return styled text with a space + s = Spacer(0.2 * inch, sep * inch) para = klass(txt, style) sect = [s, para] result = KeepTogether(sect) return result - - def p(txt): #wrapper for header + + def p(txt): # wrapper for header return header(txt, style=ParaStyle, sep=0.1) - - def pre(txt): #return styled text with a space - s = Spacer(0.1*inch, 0.1*inch) + + def pre(txt): # return styled text with a space + s = Spacer(0.1 * inch, 0.1 * inch) p = Preformatted(txt, PreStyle) - precomps = [s,p] + precomps = [s, p] result = KeepTogether(precomps) return result - - def graphout(name, datain,xaxis=None): + + def graphout(name, datain, xaxis=None): if xaxis is None: - xaxis=list(range(datain.size)) + xaxis = list(range(datain.size)) if xlabel is None: - xlabel = '' + xlabel = "" if ylabel is None: - ylabel = '' - + ylabel = "" + drawing = Drawing(400, 200) - # data = [ - # ((1,1), (2,2), (2.5,1), (3,3), (4,5)), - # ((1,2), (2,3), (2.5,2), (3.5,5), (4,6)) - # ] - dataview = [tuple([(xaxis[i],datain[i]) for i in range(datain.size)])] + # data = [ + # ((1,1), (2,2), (2.5,1), (3,3), (4,5)), + # ((1,2), (2,3), (2.5,2), (3.5,5), (4,6)) + # ] + dataview = [tuple([(xaxis[i], datain[i]) for i in range(datain.size)])] lp = LinePlot() lp.x = 50 lp.y = 50 lp.height = 125 lp.width = 300 lp.data = dataview - lp.xValueAxis.xLabelFormat = '{mmm} {yy}' - lp.lineLabels.fontSize = 6 - lp.lineLabels.boxStrokeWidth = 0.5 - lp.lineLabels.visible = 1 - lp.lineLabels.boxAnchor = 'c' - # lp.joinedLines = 1 - # lp.lines[0].symbol = makeMarker('FilledCircle') - # lp.lines[1].symbol = makeMarker('Circle') - # lp.lineLabelFormat = '%2.0f' - # lp.strokeColor = colors.black - # lp.xValueAxis.valueMin = min(xaxis) - # lp.xValueAxis.valueMax = max(xaxis) - # lp.xValueAxis.valueSteps = xaxis - # lp.xValueAxis.labelTextFormat = '%2.1f' - # lp.yValueAxis.valueMin = min(datain) - # lp.yValueAxis.valueMax = max(datain) - # lp.yValueAxis.valueSteps = [1, 2, 3, 5, 6] + lp.xValueAxis.xLabelFormat = "{mmm} {yy}" + lp.lineLabels.fontSize = 6 + lp.lineLabels.boxStrokeWidth = 0.5 + lp.lineLabels.visible = 1 + lp.lineLabels.boxAnchor = "c" + # lp.joinedLines = 1 + # lp.lines[0].symbol = makeMarker('FilledCircle') + # lp.lines[1].symbol = makeMarker('Circle') + # lp.lineLabelFormat = '%2.0f' + # lp.strokeColor = colors.black + # lp.xValueAxis.valueMin = min(xaxis) + # lp.xValueAxis.valueMax = max(xaxis) + # lp.xValueAxis.valueSteps = xaxis + # lp.xValueAxis.labelTextFormat = '%2.1f' + # lp.yValueAxis.valueMin = min(datain) + # lp.yValueAxis.valueMax = max(datain) + # lp.yValueAxis.valueSteps = [1, 2, 3, 5, 6] drawing.add(lp) return drawing - + def go(): - doc = SimpleDocTemplate('meta.pdf') + doc = SimpleDocTemplate("meta.pdf") doc.build(Elements) - + mytitle = header(Title) myname = header(Author, sep=0.1, style=ParaStyle) mysite = header(URL, sep=0.1, style=ParaStyle) @@ -1291,85 +1591,92 @@ def go(): myabstract = p(Abstract) head_info = [mytitle, myname, mysite, mymail, abstract_title, myabstract] Elements.extend(head_info) - + meta_title = header("metadata", sep=0) metasection = [] metasection.append(meta_title) - - for i,elem in enumerate(self.meta): - #if type(self.meta[elem]) != type(np.array([])): - + + for i, elem in enumerate(self.meta): + # if type(self.meta[elem]) != type(np.array([])): + print(elem, type(self.meta[elem])) - - if type(self.meta[elem])== type({}): - print('{}') - data = np.array(self.meta[elem]['v']) - unit_label = str(self.meta[elem]['u']) + if type(self.meta[elem]) == type({}): + print("{}") + data = np.array(self.meta[elem]["v"]) + unit_label = str(self.meta[elem]["u"]) else: data = np.array(self.meta[elem]) - unit_label = '' - - xaxis = np.squeeze(self.meta['Rxy']['v'][:,old_div(self.ny,2)]) - - if data.shape == (self.nx,self.ny): - datastr = np.squeeze(data[:,old_div(self.ny,2)]) - #metasection.append(graphout('stuff',datastr,xaxis=xaxis)) - #metasection.append(RL_Plot(datastr,xaxis)) - - metasection.append(RL_Plot(datastr,xaxis,linelabel=str(elem))) - #metasection.append(RL_Plot(datastr,xaxis,xlabel='xlabel')) + unit_label = "" + + xaxis = np.squeeze(self.meta["Rxy"]["v"][:, old_div(self.ny, 2)]) + + if data.shape == (self.nx, self.ny): + datastr = np.squeeze(data[:, old_div(self.ny, 2)]) + # metasection.append(graphout('stuff',datastr,xaxis=xaxis)) + # metasection.append(RL_Plot(datastr,xaxis)) + + metasection.append(RL_Plot(datastr, xaxis, linelabel=str(elem))) + # metasection.append(RL_Plot(datastr,xaxis,xlabel='xlabel')) elif data.shape == self.nx: datastr = data - #metasection.append(graphout('stuff',datastr,xaxis=xaxis)) - #metasection.append(RL_Plot(datastr,xaxis,linelabel=str(elem))) + # metasection.append(graphout('stuff',datastr,xaxis=xaxis)) + # metasection.append(RL_Plot(datastr,xaxis,linelabel=str(elem))) elif data.shape == (1,): data = data[0] - metasection.append(header(str(elem)+': '+str(data)+ ' '+ unit_label, - sep=0.1, style=ParaStyle)) + metasection.append( + header( + str(elem) + ": " + str(data) + " " + unit_label, + sep=0.1, + style=ParaStyle, + ) + ) else: - print(elem, data,data.shape) - metasection.append(header(str(elem)+': '+str(data)+ ' '+ unit_label, - sep=0.1, style=ParaStyle)) - - + print(elem, data, data.shape) + metasection.append( + header( + str(elem) + ": " + str(data) + " " + unit_label, + sep=0.1, + style=ParaStyle, + ) + ) + src = KeepTogether(metasection) Elements.append(src) cxxtitle = header("Equations in CXX") cxxsection = [] - #print self.cxx + # print self.cxx cxxsection.append(header(self.cxx[0], sep=0.1, style=ParaStyle)) cxxsrc = KeepTogether(cxxsection) - + Elements.append(cxxsrc) - # for i,elem in enumerate(self.cxx): - # if type(self.meta[elem])== type({}): - # print elem #np.array(self.meta[elem]['v']).shape() - # if np.array(self.meta[elem]['v']).shape == (self.nx,self.ny): - # datastr = str(self.meta[elem]['v'][:,self.ny/2]) - # metasection.append(graphout('stuff', - # self.meta[elem]['v'][:,self.ny/2])) - # else: - # datastr = str(self.meta[elem]['v']) - # metasection.append(header(str(elem)+': '+datastr - # + ' '+ str(self.meta[elem]['u']), - # sep=0.1, style=ParaStyle)) - - + # for i,elem in enumerate(self.cxx): + # if type(self.meta[elem])== type({}): + # print elem #np.array(self.meta[elem]['v']).shape() + # if np.array(self.meta[elem]['v']).shape == (self.nx,self.ny): + # datastr = str(self.meta[elem]['v'][:,self.ny/2]) + # metasection.append(graphout('stuff', + # self.meta[elem]['v'][:,self.ny/2])) + # else: + # datastr = str(self.meta[elem]['v']) + # metasection.append(header(str(elem)+': '+datastr + # + ' '+ str(self.meta[elem]['u']), + # sep=0.1, style=ParaStyle)) + if debug: return Elements go() - + output = PdfFileWriter() metapdf = PdfFileReader(file("meta.pdf", "rb")) mainpdf = PdfFileReader(file("output.pdf", "rb")) - for i in range (0, metapdf.getNumPages() ): + for i in range(0, metapdf.getNumPages()): output.addPage(metapdf.getPage(i)) - - for i in range (0, mainpdf.getNumPages() ): - output.addPage(mainpdf.getPage(i)) + + for i in range(0, mainpdf.getNumPages()): + output.addPage(mainpdf.getPage(i)) outputFile = filename outputStream = file(outputFile, "wb") @@ -1379,16 +1686,14 @@ def go(): class subset(LinResDraw): - def __init__(self,alldb,key,valuelist,model=False): - selection = ListDictFilt(alldb,key,valuelist) - if len(selection) !=0: - LinRes.__init__(self,selection) - self.skey = key - if model==True: - self.model() - else: - LinRes.__init__(self,alldb) - if model==True: - self.model() - - + def __init__(self, alldb, key, valuelist, model=False): + selection = ListDictFilt(alldb, key, valuelist) + if len(selection) != 0: + LinRes.__init__(self, selection) + self.skey = key + if model == True: + self.model() + else: + LinRes.__init__(self, alldb) + if model == True: + self.model() diff --git a/tools/pylib/post_bout/pb_nonlinear.py b/tools/pylib/post_bout/pb_nonlinear.py index 3497b27ce4..c14072cff5 100644 --- a/tools/pylib/post_bout/pb_nonlinear.py +++ b/tools/pylib/post_bout/pb_nonlinear.py @@ -2,14 +2,15 @@ from __future__ import division from builtins import range from past.utils import old_div -#some function to plot nonlinear stuff + +# some function to plot nonlinear stuff from .pb_corral import LinRes from .ListDict import ListDictKey, ListDictFilt import numpy as np import matplotlib.pyplot as plt from matplotlib import cm -import matplotlib.artist as artist +import matplotlib.artist as artist import matplotlib.ticker as ticker import matplotlib.pyplot as plt import matplotlib.patches as patches @@ -32,59 +33,68 @@ class NLinResDraw(LinRes): - def __init__(self,alldb): - LinRes.__init__(self,alldb) + def __init__(self, alldb): + LinRes.__init__(self, alldb) + + def plotnlrhs( + self, + pp, + field="Ni", + yscale="linear", + clip=0, + xaxis="t", + xscale="linear", + xrange=1, + ): + + colors = ["b", "g", "r", "c", "m", "y", "k", "b", "g", "r", "c", "m", "y", "k"] - def plotnlrhs(self,pp,field='Ni',yscale='linear',clip=0, - xaxis='t',xscale='linear',xrange=1): - - colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] - - Modes = subset(self.db,'field',[field]) #pick field - comp ='ave' + Modes = subset(self.db, "field", [field]) # pick field + comp = "ave" fig1 = plt.figure() - adj = fig1.subplots_adjust(hspace=0.4,wspace=0.4) - fig1.suptitle('Nonlinear contribution for ' + field) - props = dict( alpha=0.8, edgecolors='none') + adj = fig1.subplots_adjust(hspace=0.4, wspace=0.4) + fig1.suptitle("Nonlinear contribution for " + field) + props = dict(alpha=0.8, edgecolors="none") Nplots = self.nrun - - k=0 + + k = 0 for j in list(set(Modes.path).union()): - s = subset(Modes.db,'path',[j]) #pick a run folder - many modes + s = subset(Modes.db, "path", [j]) # pick a run folder - many modes dz = s.dz[0] - data = s.ave[0]['nl'] + data = s.ave[0]["nl"] x = np.array(list(range(data.size))) - ax =fig1.add_subplot(round(old_div(Nplots,2.0) + 1.0),2,k+1) - ax.set_ylabel(r'$\frac{ddt_N}{ddt}$',fontsize=12,rotation='horizontal') - k+=1 - ax.grid(True,linestyle='-',color='.75') + ax = fig1.add_subplot(round(old_div(Nplots, 2.0) + 1.0), 2, k + 1) + ax.set_ylabel(r"$\frac{ddt_N}{ddt}$", fontsize=12, rotation="horizontal") + k += 1 + ax.grid(True, linestyle="-", color=".75") try: - ax.set_yscale(yscale,linthreshy=1e-13) + ax.set_yscale(yscale, linthreshy=1e-13) except: - ax.set_yscale('linear') - i=1 - ax.plot(x,data.flatten(), - c=cm.jet(.2*i),linestyle='-') + ax.set_yscale("linear") + i = 1 + ax.plot(x, data.flatten(), c=cm.jet(0.2 * i), linestyle="-") + + # data = np.array(ListDictKey(s.db,comp)) #pick component should be ok for a fixed dz key - #data = np.array(ListDictKey(s.db,comp)) #pick component should be ok for a fixed dz key - # we are not interested in looping over all modes - - fig1.savefig(pp,format='pdf') + + fig1.savefig(pp, format="pdf") plt.close(fig1) - - #return 0 + + # return 0 + + class subset(NLinResDraw): - def __init__(self,alldb,key,valuelist,model=False): - selection = ListDictFilt(alldb,key,valuelist) - if len(selection) !=0: - LinRes.__init__(self,selection) - self.skey = key - if model==True: - self.model() - else: - LinRes.__init__(self,alldb) - if model==True: - self.model() + def __init__(self, alldb, key, valuelist, model=False): + selection = ListDictFilt(alldb, key, valuelist) + if len(selection) != 0: + LinRes.__init__(self, selection) + self.skey = key + if model == True: + self.model() + else: + LinRes.__init__(self, alldb) + if model == True: + self.model() diff --git a/tools/pylib/post_bout/pb_present.py b/tools/pylib/post_bout/pb_present.py index d7289c51f6..e1fc92ea6d 100644 --- a/tools/pylib/post_bout/pb_present.py +++ b/tools/pylib/post_bout/pb_present.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from builtins import str from builtins import range -from .pb_draw import LinResDraw,subset +from .pb_draw import LinResDraw, subset from .pb_corral import LinRes from .pb_nonlinear import NLinResDraw from pb_transport import Transport @@ -14,10 +14,11 @@ from matplotlib.figure import Figure from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas from matplotlib.backends.backend_pdf import PdfPages -import matplotlib.artist as artist +import matplotlib.artist as artist import matplotlib.ticker as ticker -#from matplotlib.ticker import FuncFormatter -#from matplotlib.ticker import ScalarFormatter + +# from matplotlib.ticker import FuncFormatter +# from matplotlib.ticker import ScalarFormatter from reportlab.platypus import * from reportlab.lib.styles import getSampleStyleSheet @@ -30,152 +31,184 @@ from reportlab.lib import colors from replab_x_vs_y import RL_Plot -#for movie making -from multiprocessing import Queue,Pool + +# for movie making +from multiprocessing import Queue, Pool import multiprocessing -import subprocess -#uses LinResDraw to make a pdf - -class LinResPresent(LinResDraw,NLinResDraw,Transport): - def __init__(self,alldb): - LinResDraw.__init__(self,alldb) - NLinResDraw.__init__(self,alldb) - Transport.__init__(self,alldb) - - def show(self,filter =True,quick=False,pdfname='output2.pdf',debug=False,spectrum_movie=False): - colors = ['b','g','r','c','m','y','k','b','g','r','c','m','y','k'] - pp = PdfPages('output.pdf') - - #start by removing modes above the maxN threshold - modelist =[] - [modelist.append(list(self.modeid[p])) for p in range(self.nmodes) if self.mn[p][1] <= self.maxN[p] ] - - s = subset(self.db,'modeid',modelist) - - try: - #fig = Figure(figsize=(6,6)) - # fig = plt.figure() - dz0 = list(set(s.dz).union())[0] - ss = subset(s.db,'dz',[dz0]) - - # show initial condition and the first step after - s.plotvsK(pp,yscale='log',xscale='log',t=[0,1,-1],overplot=False,comp='amp',trans=True) - - - - if spectrum_movie: - ss.savemovie() - - - except: - print('no scatter') - #2D true NM spectrum with color code and boxes around spectral res regions log scale - - - - plt.figure() - i = 0 - for j in list(set(s.dz).union()): #looping over runs, over unique 'dz' key values - - ss = subset(s.db,'dz',[j]) #subset where dz = j - plt.scatter(ss.MN[:,1],ss.MN[:,0],c=colors[i]) - plt.annotate(str(j),(ss.MN[0,1],ss.MN[0,0])) - i+=1 - - plt.title(' Ni spectrum at t=0, all x') - plt.ylabel('M -parallel') - plt.xlabel('N - axisymmteric') - plt.xscale('log') - plt.grid(True,linestyle='-',color='.75') - - try: - plt.savefig(pp, format='pdf') - except: - print('FAILED TO save 1st part') - - plt.close() - - # for elem in self.meta['evolved']['v']: - # s.plotnl(pp - - if self.meta['nonlinear']['v'] == 'true': - self.plotnlrhs(pp) - - if self.meta['transport'] == 'true': - self.plotnlrms(pp) - - for elem in self.meta['evolved']: - s.plotmodes(pp,yscale='symlog',comp='phase',linestyle='.',field=elem,summary=False) - s.plotmodes(pp,yscale='symlog',field=elem,summary=False) - print(elem) - try: - s.plotmodes(pp,yscale='symlog',field=elem,comp='gamma_i',summary=False) - except: - print('gamma_i plot for '+elem+' failed') - - #s.plotmodes(pp,yscale='symlog',summary=False) - - modelist = [] - # maxZ = - #[modelist.append([1,p+1]) for p in range(maxZ-1)] - [modelist.append(list(self.modeid[p])) for p in range(self.nmodes) if self.mn[p][1] <= self.maxN[p] ] - ss = subset(s.db,'mn',modelist) - - if debug: #just a few problematic slides - fig1 = plt.figure() - pp_bug = PdfPages('debug.pdf') - #ss.plotmodes(pp_bug,yscale='symlog',comp='phase',summary=False) - s.plotfreq2(pp_bug,xscale='log',yscale='symlog',overplot=True) - ss.plotgamma(pp_bug,xscale='log',yscale='symlog',overplot=True) - ss.plottheory(pp_bug) - ss.plottheory(pp_bug,comp='freq') - fig1.savefig(pp_bug, format='pdf') - pp_bug.close() - pp.close() - return 0 - - dir(ss) - ss.plotmodes(pp,yscale='log',debug=True,summary=False) - ss.plotmodes(pp,yscale='symlog',comp='phase',summary=False) - ss.plotmodes(pp,yscale='symlog',comp='phase',field='rho',summary=False) - print(dir(ss)) - - #ss.plotmodes(pp,yscale='log',comp='phase',clip=True) - - #ss.plotfreq2(pp,xscale='log',yscale='linear',overplot=False) - for elem in self.meta['evolved']: - ss.plotfreq2(pp,xscale='log',yscale='symlog',field=elem, - overplot=True,trans=True) - - - #ss.plotfreq2(pp,xscale='log',yscale='symlog',field='rho',overplot=True) - - if quick==True: - pp.close() - s.printmeta(pp) - - #plt.savefig(pp, format='pdf') - return 0 - - all_fields = list(set(s.field).union()) - - s.plotgamma(pp,xscale='log',yscale='linear',overplot=True,trans=True) - - s.plotgamma(pp,yscale='symlog',xscale='log',overplot=True) - s.plotgamma(pp,yscale='symlog',xscale='log',field='rho',overplot=True) - - try: - s.plotfreq2(pp,xscale='log',yscale='linear',overplot=True) - #s.plotfreq2(pp,xscale='log',yscale='symlog',overplot=False) - s.plotfreq2(pp,xscale='log',yscale='symlog',field='rho',overplot=True) - - #s.plotfreq2(pp,xscale='log',yscale='linear') - except: - print('something terrible') - - s.plotradeigen(pp,yscale='linear') - #s.plotradeigen(pp,field ='Vi',yscale='linear') - s.plotradeigen(pp,field='rho',yscale='log') - - pp.close() - s.printmeta(pp,filename=pdfname) #append a metadata header +import subprocess + +# uses LinResDraw to make a pdf + + +class LinResPresent(LinResDraw, NLinResDraw, Transport): + def __init__(self, alldb): + LinResDraw.__init__(self, alldb) + NLinResDraw.__init__(self, alldb) + Transport.__init__(self, alldb) + + def show( + self, + filter=True, + quick=False, + pdfname="output2.pdf", + debug=False, + spectrum_movie=False, + ): + colors = ["b", "g", "r", "c", "m", "y", "k", "b", "g", "r", "c", "m", "y", "k"] + pp = PdfPages("output.pdf") + + # start by removing modes above the maxN threshold + modelist = [] + [ + modelist.append(list(self.modeid[p])) + for p in range(self.nmodes) + if self.mn[p][1] <= self.maxN[p] + ] + + s = subset(self.db, "modeid", modelist) + + try: + # fig = Figure(figsize=(6,6)) + # fig = plt.figure() + dz0 = list(set(s.dz).union())[0] + ss = subset(s.db, "dz", [dz0]) + + # show initial condition and the first step after + s.plotvsK( + pp, + yscale="log", + xscale="log", + t=[0, 1, -1], + overplot=False, + comp="amp", + trans=True, + ) + + if spectrum_movie: + ss.savemovie() + + except: + print("no scatter") + # 2D true NM spectrum with color code and boxes around spectral res regions log scale + + plt.figure() + i = 0 + for j in list( + set(s.dz).union() + ): # looping over runs, over unique 'dz' key values + + ss = subset(s.db, "dz", [j]) # subset where dz = j + plt.scatter(ss.MN[:, 1], ss.MN[:, 0], c=colors[i]) + plt.annotate(str(j), (ss.MN[0, 1], ss.MN[0, 0])) + i += 1 + + plt.title(" Ni spectrum at t=0, all x") + plt.ylabel("M -parallel") + plt.xlabel("N - axisymmteric") + plt.xscale("log") + plt.grid(True, linestyle="-", color=".75") + + try: + plt.savefig(pp, format="pdf") + except: + print("FAILED TO save 1st part") + + plt.close() + + # for elem in self.meta['evolved']['v']: + # s.plotnl(pp + + if self.meta["nonlinear"]["v"] == "true": + self.plotnlrhs(pp) + + if self.meta["transport"] == "true": + self.plotnlrms(pp) + + for elem in self.meta["evolved"]: + s.plotmodes( + pp, + yscale="symlog", + comp="phase", + linestyle=".", + field=elem, + summary=False, + ) + s.plotmodes(pp, yscale="symlog", field=elem, summary=False) + print(elem) + try: + s.plotmodes( + pp, yscale="symlog", field=elem, comp="gamma_i", summary=False + ) + except: + print("gamma_i plot for " + elem + " failed") + + # s.plotmodes(pp,yscale='symlog',summary=False) + + modelist = [] + # maxZ = + # [modelist.append([1,p+1]) for p in range(maxZ-1)] + [ + modelist.append(list(self.modeid[p])) + for p in range(self.nmodes) + if self.mn[p][1] <= self.maxN[p] + ] + ss = subset(s.db, "mn", modelist) + + if debug: # just a few problematic slides + fig1 = plt.figure() + pp_bug = PdfPages("debug.pdf") + # ss.plotmodes(pp_bug,yscale='symlog',comp='phase',summary=False) + s.plotfreq2(pp_bug, xscale="log", yscale="symlog", overplot=True) + ss.plotgamma(pp_bug, xscale="log", yscale="symlog", overplot=True) + ss.plottheory(pp_bug) + ss.plottheory(pp_bug, comp="freq") + fig1.savefig(pp_bug, format="pdf") + pp_bug.close() + pp.close() + return 0 + + dir(ss) + ss.plotmodes(pp, yscale="log", debug=True, summary=False) + ss.plotmodes(pp, yscale="symlog", comp="phase", summary=False) + ss.plotmodes(pp, yscale="symlog", comp="phase", field="rho", summary=False) + print(dir(ss)) + + # ss.plotmodes(pp,yscale='log',comp='phase',clip=True) + + # ss.plotfreq2(pp,xscale='log',yscale='linear',overplot=False) + for elem in self.meta["evolved"]: + ss.plotfreq2( + pp, xscale="log", yscale="symlog", field=elem, overplot=True, trans=True + ) + + # ss.plotfreq2(pp,xscale='log',yscale='symlog',field='rho',overplot=True) + + if quick == True: + pp.close() + s.printmeta(pp) + + # plt.savefig(pp, format='pdf') + return 0 + + all_fields = list(set(s.field).union()) + + s.plotgamma(pp, xscale="log", yscale="linear", overplot=True, trans=True) + + s.plotgamma(pp, yscale="symlog", xscale="log", overplot=True) + s.plotgamma(pp, yscale="symlog", xscale="log", field="rho", overplot=True) + + try: + s.plotfreq2(pp, xscale="log", yscale="linear", overplot=True) + # s.plotfreq2(pp,xscale='log',yscale='symlog',overplot=False) + s.plotfreq2(pp, xscale="log", yscale="symlog", field="rho", overplot=True) + + # s.plotfreq2(pp,xscale='log',yscale='linear') + except: + print("something terrible") + + s.plotradeigen(pp, yscale="linear") + # s.plotradeigen(pp,field ='Vi',yscale='linear') + s.plotradeigen(pp, field="rho", yscale="log") + + pp.close() + s.printmeta(pp, filename=pdfname) # append a metadata header diff --git a/tools/pylib/post_bout/read_cxx.py b/tools/pylib/post_bout/read_cxx.py index f60ae7ce7c..907edc48a7 100644 --- a/tools/pylib/post_bout/read_cxx.py +++ b/tools/pylib/post_bout/read_cxx.py @@ -8,138 +8,133 @@ def findlowpass(cxxstring): ##p1="lowPass\(.*\)" - p1="lowPass\(.*\,(.*)\)" - maxN = np.array(re.findall(p1, cxxstring)) - #print substrings + p1 = "lowPass\(.*\,(.*)\)" + maxN = np.array(re.findall(p1, cxxstring)) + # print substrings - #p2=("[0-9]") + # p2=("[0-9]") + + # maxN = np.array([re.findall(p2,elem) for elem in substrings]).flatten() - #maxN = np.array([re.findall(p2,elem) for elem in substrings]).flatten() - if maxN.size == 0: return 100 else: - output = int(min(maxN)) - if output ==0: + output = int(min(maxN)) + if output == 0: return 20 else: return output -def no_comment_cxx(path='.',boutcxx='physics_code.cxx.ref'): - #print 'no_comment' - boutcxx = path+'/'+boutcxx - #boutcxx = open(boutcxx,'r').readlines() - f = open(boutcxx,'r') + +def no_comment_cxx(path=".", boutcxx="physics_code.cxx.ref"): + # print 'no_comment' + boutcxx = path + "/" + boutcxx + # boutcxx = open(boutcxx,'r').readlines() + f = open(boutcxx, "r") boutcxx = f.read() f.close() - start =string.find(boutcxx,'/*') - end =string.find(boutcxx,'*/')+2 + start = string.find(boutcxx, "/*") + end = string.find(boutcxx, "*/") + 2 s = boutcxx[0:start] - for i in range(string.count(boutcxx,'/*')): - start =string.find(boutcxx,'/*',end) - s=s+boutcxx[end+1:start-1] - - end =string.find(boutcxx,'*/',end)+2 - - s=s+boutcxx[end+1:] - - #pattern = "\n \s* \(//)* .* \n" #pattern for a section start [All],[Ni], etc - pattern = "\n+.*;" #everythin - pattern = re.compile(pattern) - result = re.findall(pattern,s) - - #print result + for i in range(string.count(boutcxx, "/*")): + start = string.find(boutcxx, "/*", end) + s = s + boutcxx[end + 1 : start - 1] + + end = string.find(boutcxx, "*/", end) + 2 + + s = s + boutcxx[end + 1 :] + + # pattern = "\n \s* \(//)* .* \n" #pattern for a section start [All],[Ni], etc + pattern = "\n+.*;" # everythin + pattern = re.compile(pattern) + result = re.findall(pattern, s) + + # print result nocomment = [] for elem in result: - #print elem + # print elem elem = elem.lstrip() - stop = elem.find('//') - #print start,stop - - if stop >0: + stop = elem.find("//") + # print start,stop + + if stop > 0: nocomment.append(elem[0:stop]) elif stop == -1: nocomment.append(elem) - - - #result = pattern.match(val) + # result = pattern.match(val) # start = string.find(z,'\n //') # end =string.find(boutcxx,'*/')+2 - #print nocomment - + # print nocomment + return nocomment - + + def get_evolved_cxx(cxxfile=None): if cxxfile is None: cxxfile = no_comment_cxx() - - + # s = cxxfile # section_0 = string.find(s,'int physics_run(BoutReal t)') # section_1 = string.find(s,'return',section_0) # s = s[section_0:section_1] - temp =[] + temp = [] for x in cxxfile: i = x.find("bout_solve(") - #print i,x + # print i,x if i != -1: comma_i = x[i::].find('"') - comma_j = x[i::].rfind('"') - #print x[i+comma_i:i+comma_j+1] - temp.append(x[i+comma_i+1:i+comma_j]) - - evolved=[] - [evolved.append(x) for x in set(temp) ] + comma_j = x[i::].rfind('"') + # print x[i+comma_i:i+comma_j+1] + temp.append(x[i + comma_i + 1 : i + comma_j]) + + evolved = [] + [evolved.append(x) for x in set(temp)] return np.array(evolved) -def read_cxx(path='.',boutcxx='physics_code.cxx.ref',evolved=''): - - - #print path, boutcxx - boutcxx = path+'/'+boutcxx - #boutcxx = open(boutcxx,'r').readlines() - f = open(boutcxx,'r') +def read_cxx(path=".", boutcxx="physics_code.cxx.ref", evolved=""): + + # print path, boutcxx + boutcxx = path + "/" + boutcxx + # boutcxx = open(boutcxx,'r').readlines() + f = open(boutcxx, "r") boutcxx = f.read() f.close() - - - # start by stripping out all comments - # look at the 1st character of all list elements - # for now use a gross loop, vectorize later + # start by stripping out all comments + # look at the 1st character of all list elements + # for now use a gross loop, vectorize later - start =string.find(boutcxx,'/*') - end =string.find(boutcxx,'*/')+2 + start = string.find(boutcxx, "/*") + end = string.find(boutcxx, "*/") + 2 s = boutcxx[0:start] - for i in range(string.count(boutcxx,'/*')): - start =string.find(boutcxx,'/*',end) - s=s+boutcxx[end+1:start-1] - - end =string.find(boutcxx,'*/',end)+2 - - s=s+boutcxx[end+1:] - - section_0 = string.find(s,'int physics_run(BoutReal t)') - section_1 = string.find(s,'return',section_0) - s = s[section_0:section_1] - - - tmp = open('./read_cxx.tmp','w') + for i in range(string.count(boutcxx, "/*")): + start = string.find(boutcxx, "/*", end) + s = s + boutcxx[end + 1 : start - 1] + + end = string.find(boutcxx, "*/", end) + 2 + + s = s + boutcxx[end + 1 :] + + section_0 = string.find(s, "int physics_run(BoutReal t)") + section_1 = string.find(s, "return", section_0) + s = s[section_0:section_1] + + tmp = open("./read_cxx.tmp", "w") tmp.write(s) tmp.close() - tmp = open('./read_cxx.tmp','r') - - cxxlist = '' + tmp = open("./read_cxx.tmp", "r") + + cxxlist = "" for line in tmp: - if line[0] != '//' and line.isspace()==False: - cxxlist=cxxlist+line.split("//")[0] - + if line[0] != "//" and line.isspace() == False: + cxxlist = cxxlist + line.split("//")[0] + return cxxlist diff --git a/tools/pylib/post_bout/read_inp.py b/tools/pylib/post_bout/read_inp.py index 71edec7515..40a60774af 100644 --- a/tools/pylib/post_bout/read_inp.py +++ b/tools/pylib/post_bout/read_inp.py @@ -9,379 +9,416 @@ import numpy as np from boututils.file_import import file_import from .read_cxx import * -def read_inp(path='',boutinp='BOUT.inp'): - - - boutfile = path+'/'+boutinp - boutinp = open(boutfile,'r').readlines() - - - # start by stripping out all comments - # look at the 1st character of all list elements - # for now use a gross loop, vectorize later - boutlist = [] - - for i,val in enumerate(boutinp): - if val[0] != '#' and val.isspace() == False: - boutlist.append(val.split("#")[0]) - - return boutlist + + +def read_inp(path="", boutinp="BOUT.inp"): + + boutfile = path + "/" + boutinp + boutinp = open(boutfile, "r").readlines() + + # start by stripping out all comments + # look at the 1st character of all list elements + # for now use a gross loop, vectorize later + boutlist = [] + + for i, val in enumerate(boutinp): + if val[0] != "#" and val.isspace() == False: + boutlist.append(val.split("#")[0]) + + return boutlist + def parse_inp(boutlist): - import re - from ordereddict import OrderedDict - - if not boutlist: - return 0 - - - - #boutdic={} unordered standard dict - boutdic = OrderedDict() - - #regex is messy see http://docs.python.org/howto/regex.html#regex-howto - pattern = "\[\S*\]" #pattern for a section start [All],[Ni], etc - - pattern = re.compile(pattern) - - boutdic['[main]'] = {} - current='[main]' - - for i,val in enumerate(boutlist): - #print i,val - result =pattern.match(val) - #while the current value is not a new section name add everything to the current section - - if result is None: - #print val - key,value = val.split("=") - value = value.replace('\"','') - #print current, key,value - - - boutdic[current][key.strip()] = value.strip() - else: - boutdic[result.group()] = {} - current = result.group() - - return boutdic - -def read_log(path='.',logname='status.log'): - - print('in read_log') - import re - from ordereddict import OrderedDict - - #logfile = path+'/'+logname - logfile = logname - print(logfile) - logcase = open(logfile,'r').readlines() - - # start by stripping out all comments - # look at the 1st character of all list elements - # for now use a gross loop, vectorize later - loglist = [] - - for i,val in enumerate(logcase): - if val[0] != '#' and val.isspace() == False: - loglist.append(val.split("#")[0]) - - if not loglist: - return 0 - - logdict = OrderedDict() - logdict['runs'] = [] - #print len(loglist) - print(loglist) - #print loglist[len(loglist)-1] == 'last one\n' - - # last = loglist.pop().rstrip() - - # logdict['done'] = last == 'done' - - - logdict['current'] = loglist.pop().rstrip() - for i,val in enumerate(loglist): - print(val) - logdict['runs'].append(val.rstrip()) - - logdict['runs'].append(logdict['current']) - - - #print logdict - return logdict - -def metadata(inpfile='BOUT.inp',path ='.',v=False): - filepath = path+'/'+inpfile + import re + from ordereddict import OrderedDict + + if not boutlist: + return 0 + + # boutdic={} unordered standard dict + boutdic = OrderedDict() + + # regex is messy see http://docs.python.org/howto/regex.html#regex-howto + pattern = "\[\S*\]" # pattern for a section start [All],[Ni], etc + + pattern = re.compile(pattern) + + boutdic["[main]"] = {} + current = "[main]" + + for i, val in enumerate(boutlist): + # print i,val + result = pattern.match(val) + # while the current value is not a new section name add everything to the current section + + if result is None: + # print val + key, value = val.split("=") + value = value.replace('"', "") + # print current, key,value + + boutdic[current][key.strip()] = value.strip() + else: + boutdic[result.group()] = {} + current = result.group() + + return boutdic + + +def read_log(path=".", logname="status.log"): + + print("in read_log") + import re + from ordereddict import OrderedDict + + # logfile = path+'/'+logname + logfile = logname + print(logfile) + logcase = open(logfile, "r").readlines() + + # start by stripping out all comments + # look at the 1st character of all list elements + # for now use a gross loop, vectorize later + loglist = [] + + for i, val in enumerate(logcase): + if val[0] != "#" and val.isspace() == False: + loglist.append(val.split("#")[0]) + + if not loglist: + return 0 + + logdict = OrderedDict() + logdict["runs"] = [] + # print len(loglist) + print(loglist) + # print loglist[len(loglist)-1] == 'last one\n' + + # last = loglist.pop().rstrip() + + # logdict['done'] = last == 'done' + + logdict["current"] = loglist.pop().rstrip() + for i, val in enumerate(loglist): + print(val) + logdict["runs"].append(val.rstrip()) + + logdict["runs"].append(logdict["current"]) + + # print logdict + return logdict + + +def metadata(inpfile="BOUT.inp", path=".", v=False): + filepath = path + "/" + inpfile print(filepath) - inp = read_inp(path=path,boutinp=inpfile) - inp = parse_inp(inp) #inp file + inp = read_inp(path=path, boutinp=inpfile) + inp = parse_inp(inp) # inp file print(path) - outinfo = file_import(path+'/BOUT.dmp.0.nc') #output data - + outinfo = file_import(path + "/BOUT.dmp.0.nc") # output data + try: - print(path) - cxxinfo = no_comment_cxx(path=path,boutcxx='physics_code.cxx.ref') - #evolved = get_evolved_cxx(cxxinfo) - fieldkeys = get_evolved_cxx(cxxinfo) - fieldkeys = ['['+elem+']' for elem in fieldkeys] + print(path) + cxxinfo = no_comment_cxx(path=path, boutcxx="physics_code.cxx.ref") + # evolved = get_evolved_cxx(cxxinfo) + fieldkeys = get_evolved_cxx(cxxinfo) + fieldkeys = ["[" + elem + "]" for elem in fieldkeys] except: - print('cant find the cxx file') - - - #gridoptions = {'grid':grid,'mesh':mesh} - if '[mesh]' in list(inp.keys()): - #IC = outinfo - IC = read_grid(path+'/BOUT.dmp.0.nc') #output data again - elif 'grid' in inp['[main]']: - gridname = inp['[main]']['grid'] - try: - IC = read_grid(gridname) #have to be an ansoulte file path for now - print('IC: ',type(IC)) - # print IC.variables - # print gridname - except: - #print gridname - print('Fail to load the grid file') - #print IC - - #print gridname - #print len(IC) - #print IC - + print("cant find the cxx file") + + # gridoptions = {'grid':grid,'mesh':mesh} + if "[mesh]" in list(inp.keys()): + # IC = outinfo + IC = read_grid(path + "/BOUT.dmp.0.nc") # output data again + elif "grid" in inp["[main]"]: + gridname = inp["[main]"]["grid"] + try: + IC = read_grid(gridname) # have to be an ansoulte file path for now + print("IC: ", type(IC)) + # print IC.variables + # print gridname + except: + # print gridname + print("Fail to load the grid file") + # print IC + + # print gridname + # print len(IC) + # print IC + evolved = [] - collected =[] + collected = [] ICscale = [] - + # fieldkeys = ['[Ni]','[Te]','[Ti]','[Vi]','[rho]', # '[Ajpar]','[Apar]','[vEBx]','[vEBy]','[vEBz]', # '[jpar]','[phi]'] - - #construct fieldkeys from cxx info - #fieldkeys = ['['+x+']' for x in evolved] - #fieldkeys = evolved - #just look ahead and see what 3D fields have been output + # construct fieldkeys from cxx info + # fieldkeys = ['['+x+']' for x in evolved] + # fieldkeys = evolved + + # just look ahead and see what 3D fields have been output available = np.array([str(x) for x in outinfo]) - a = np.array([(len(outinfo[x].shape) ==4) for x in available]) + a = np.array([(len(outinfo[x].shape) == 4) for x in available]) available = available[a] - - - - defaultIC = float(inp['[All]'].get('scale',0.0)) + + defaultIC = float(inp["[All]"].get("scale", 0.0)) # print inp.keys() - - #figure out which fields are evolved + + # figure out which fields are evolved print(fieldkeys) - - for section in list(inp.keys()): #loop over section keys - print('section: ', section) - if section in fieldkeys: #pick the relevant sections - print(section) - #print inp[section].get('evolve','True') - #rint (inp[section].get('evolve','True')).lower().strip() - if (inp[section].get('evolve','True').lower().strip() == 'true'):# and section[1:-1] in available : - print('ok reading') - evolved.append(section.strip('[]')) - ICscale.append(float(inp[section].get('scale',defaultIC))) - - if inp[section].get('collect','False').lower().strip() == 'true': - collected.append(section.strip('[]')) - - - - - try: - if inp['[physics]'].get('transport','False').lower().strip() == 'true': - vEBstr = ['vEBx','vEBy','vEBz','vEBrms'] - [collected.append(item) for item in vEBstr] + + for section in list(inp.keys()): # loop over section keys + print("section: ", section) + if section in fieldkeys: # pick the relevant sections + print(section) + # print inp[section].get('evolve','True') + # rint (inp[section].get('evolve','True')).lower().strip() + if ( + inp[section].get("evolve", "True").lower().strip() == "true" + ): # and section[1:-1] in available : + print("ok reading") + evolved.append(section.strip("[]")) + ICscale.append(float(inp[section].get("scale", defaultIC))) + + if inp[section].get("collect", "False").lower().strip() == "true": + collected.append(section.strip("[]")) + + try: + if inp["[physics]"].get("transport", "False").lower().strip() == "true": + vEBstr = ["vEBx", "vEBy", "vEBz", "vEBrms"] + [collected.append(item) for item in vEBstr] except: - print('no [physics] key') - + print("no [physics] key") + meta = OrderedDict() - + class ValUnit(object): - def __init__(self,value=0,units=''): - self.u = units - self.v = value - def todict(self): - return {'u':self.u,'v':self.v} + def __init__(self, value=0, units=""): + self.u = units + self.v = value - + def todict(self): + return {"u": self.u, "v": self.v} + + # def decode_valunit(d): - #def decode_valunit(d): - - def ToFloat(metaString): - try: - return float(metaString) - except ValueError: - return metaString - - #meta['evolved'] = ValUnit(evolved,'') - meta['evolved'] = evolved - meta['collected'] = collected - meta['IC']= np.array(ICscale) + try: + return float(metaString) + except ValueError: + return metaString + + # meta['evolved'] = ValUnit(evolved,'') + meta["evolved"] = evolved + meta["collected"] = collected + meta["IC"] = np.array(ICscale) d = {} - print('evolved: ',evolved) + print("evolved: ", evolved) # read meta data from .inp file, this is whre most metadata get written for section in list(inp.keys()): - if (('evolve' not in inp[section]) and ('first' not in inp[section])): #hacky way to exclude some less relevant metadata - for elem in list(inp[section].keys()): - meta[elem] = ValUnit(ToFloat(inp[section][elem])) - d[elem] = np.array(ToFloat(inp[section][elem])) - - #read in some values from the grid(IC) and scale them as needed - norms = {'Ni0':ValUnit(1.e14,'cm^-3'),'bmag':ValUnit(1.0e4,'gauss'), - 'Ni_x':ValUnit(1.e14,'cm^-3'), - 'Te_x':ValUnit(1.0,'eV'),'Ti_x':ValUnit(1.0,'eV'),'Rxy':ValUnit(1,'m'), - 'Bxy':ValUnit(1.0e4,'gauss'),'Bpxy':ValUnit(1.0e4,'gauss'), - 'Btxy':ValUnit(1.0e4,'gauss'),'Zxy':ValUnit(1,'m'), - 'dlthe':ValUnit(1,'m'),'dx':ValUnit(1,'m'),'hthe0':ValUnit(1,'m')} + if ("evolve" not in inp[section]) and ( + "first" not in inp[section] + ): # hacky way to exclude some less relevant metadata + for elem in list(inp[section].keys()): + meta[elem] = ValUnit(ToFloat(inp[section][elem])) + d[elem] = np.array(ToFloat(inp[section][elem])) + + # read in some values from the grid(IC) and scale them as needed + norms = { + "Ni0": ValUnit(1.0e14, "cm^-3"), + "bmag": ValUnit(1.0e4, "gauss"), + "Ni_x": ValUnit(1.0e14, "cm^-3"), + "Te_x": ValUnit(1.0, "eV"), + "Ti_x": ValUnit(1.0, "eV"), + "Rxy": ValUnit(1, "m"), + "Bxy": ValUnit(1.0e4, "gauss"), + "Bpxy": ValUnit(1.0e4, "gauss"), + "Btxy": ValUnit(1.0e4, "gauss"), + "Zxy": ValUnit(1, "m"), + "dlthe": ValUnit(1, "m"), + "dx": ValUnit(1, "m"), + "hthe0": ValUnit(1, "m"), + } availkeys = np.array([str(x) for x in outinfo]) tmp1 = np.array([x for x in availkeys]) - #b = np.array([x if x not in available for x in a]) + # b = np.array([x if x not in available for x in a]) tmp2 = np.array([x for x in tmp1 if x not in available]) static_fields = np.array([x for x in tmp2 if x in list(norms.keys())]) - #static_fields = tmp2 - - #print availkeys + # static_fields = tmp2 + + # print availkeys # print meta.keys() - #print IC.variables.keys() + # print IC.variables.keys() # print tmp1 # print tmp2 - for elem in static_fields: - print('elem: ',elem) - meta[elem] = ValUnit(IC.variables[elem][:]*norms[elem].v,norms[elem].u) - d[elem] = np.array(IC.variables[elem][:]*norms[elem].v) - + print("elem: ", elem) + meta[elem] = ValUnit(IC.variables[elem][:] * norms[elem].v, norms[elem].u) + d[elem] = np.array(IC.variables[elem][:] * norms[elem].v) + for elem in IC.variables: - if elem not in meta: - if elem in list(norms.keys()): - meta[elem] = ValUnit(IC.variables[elem][:]*norms[elem].v,norms[elem].u) - d[elem] = np.array(IC.variables[elem][:]*norms[elem].v) - else: - meta[elem] = IC.variables[elem][:] - d[elem] = IC.variables[elem][:] - - #print d.keys() - - #if case some values are missing - default = {'bmag':1,'Ni_x':1,'NOUT':100,'TIMESTEP':1, - 'MZ':32,'AA':1,'Zeff':ValUnit(1,''),'ZZ':1, - 'zlowpass':0.0,'transport':False} + if elem not in meta: + if elem in list(norms.keys()): + meta[elem] = ValUnit( + IC.variables[elem][:] * norms[elem].v, norms[elem].u + ) + d[elem] = np.array(IC.variables[elem][:] * norms[elem].v) + else: + meta[elem] = IC.variables[elem][:] + d[elem] = IC.variables[elem][:] + + # print d.keys() + + # if case some values are missing + default = { + "bmag": 1, + "Ni_x": 1, + "NOUT": 100, + "TIMESTEP": 1, + "MZ": 32, + "AA": 1, + "Zeff": ValUnit(1, ""), + "ZZ": 1, + "zlowpass": 0.0, + "transport": False, + } diff = set(default.keys()).difference(set(d.keys())) - + for elem in diff: - #print 'diff: ',elem - meta[elem] = default[elem] - d[elem] = np.array(default[elem]) - - #print meta.keys() - #print d.keys() - - #print meta['zlowpass'] - - - if meta['zlowpass'] != 0: - print(meta['MZ'].v, meta['zlowpass'].v) - meta['maxZ'] = int(np.floor(meta['MZ'].v*meta['zlowpass'].v)) + # print 'diff: ',elem + meta[elem] = default[elem] + d[elem] = np.array(default[elem]) + + # print meta.keys() + # print d.keys() + + # print meta['zlowpass'] + + if meta["zlowpass"] != 0: + print(meta["MZ"].v, meta["zlowpass"].v) + meta["maxZ"] = int(np.floor(meta["MZ"].v * meta["zlowpass"].v)) else: - meta['maxZ'] = 5 - - #meta['nx'] = nx - #meta['ny']= ny - meta['dt'] = meta['TIMESTEP'] - - - #nx,ny = d['Rxy'].shape - - - #print meta['AA'].v - - meta['rho_s'] = ValUnit(1.02e2*np.sqrt(d['AA']*d['Te_x'])/(d['ZZ']* d['bmag']),'cm') # ion gyrorad at T_e, in cm - meta['rho_i'] = ValUnit(1.02e2*np.sqrt(d['AA']*d['Ti_x'])/(d['ZZ']* d['bmag']),'cm') - meta['rho_e'] = ValUnit(2.38*np.sqrt(d['Te_x'])/(d['bmag']),'cm') - - meta['fmei'] = ValUnit(1./1836.2/d['AA']) - - meta['lambda_ei'] = 24.-np.log(old_div(np.sqrt(d['Ni_x']),d['Te_x'])) ; - meta['lambda_ii'] = 23.-np.log(d['ZZ']**3 * np.sqrt(2.*d['Ni_x'])/(d['Ti_x']**1.5)) # - - meta['wci'] = 1.0*9.58e3*d['ZZ']*d['bmag']/d['AA'] # ion gyrofrteq - meta['wpi'] = 1.32e3*d['ZZ']*np.sqrt(old_div(d['Ni_x'],d['AA'])) # ion plasma freq - - meta['wce'] = 1.78e7*d['bmag'] #electron gyrofreq - meta['wpe'] = 5.64e4*np.sqrt(d['Ni_x'])#electron plasma freq - - meta['v_the'] = 4.19e7*np.sqrt(d['Te_x'])#cm/s - meta['v_thi'] = 9.79e5*np.sqrt(old_div(d['Ti_x'],d['AA'])) #cm/s - meta['c_s'] = 9.79e5*np.sqrt(5.0/3.0 * d['ZZ'] * d['Te_x']/d['AA'])# - meta['v_A'] = 2.18e11*np.sqrt(old_div(1.0,(d['AA'] * d['Ni_x']))) - - meta['nueix'] = 2.91e-6*d['Ni_x']*meta['lambda_ei']/d['Te_x']**1.5 # - meta['nuiix'] = 4.78e-8*d['ZZ']**4.*d['Ni_x']*meta['lambda_ii']/d['Ti_x']**1.5/np.sqrt(d['AA']) # - meta['nu_hat'] = meta['Zeff'].v*meta['nueix']/meta['wci'] - - meta['L_d'] = 7.43e2*np.sqrt(old_div(d['Te_x'],d['Ni_x'])) - meta['L_i_inrt'] = 2.28e7*np.sqrt(old_div(d['AA'],d['Ni_x']))/ d['ZZ'] #ion inertial length in cm - meta['L_e_inrt'] = 5.31e5*np.sqrt(d['Ni_x']) #elec inertial length in cm - - meta['Ve_x'] = 4.19e7*d['Te_x'] - - - meta['R0'] = old_div((d['Rxy'].max()+d['Rxy'].min()),2.0) - - - print(d['Rxy'].mean(1)) - print(d['ZMAX']) - print(d['ZMIN']) - meta['L_z'] = 1e2 * 2*np.pi * d['Rxy'].mean(1) *(d['ZMAX'] - d['ZMIN']) # in cm toroidal range - meta['dz'] = (d['ZMAX'] - d['ZMIN']) - - #meta['lbNorm']=meta['L_z']*(d['Bpxy']/d['Bxy']).mean(1) #-binormal coord range [cm] - meta['lbNorm']=meta['L_z']*(old_div(d['Bxy'],d['Bpxy'])).mean(1) - - #meta['zPerp']=np.array(meta['lbNorm']).mean*np.array(range(d['MZ']))/(d['MZ']-1) - #let's calculate some profile properties - dx = np.gradient(d['Rxy'])[0] - meta['L'] = 1.0*1e2*dx*(meta['Ni0'].v)/np.gradient(meta['Ni0'].v)[0]/meta['rho_s'].v - - meta['w_Ln'] = old_div(meta['c_s'],(np.min(abs(meta['L']))*meta['wci'] *meta['rho_s'].v)) #normed to wci - - AA = meta['AA'].v - ZZ = d['ZZ'] - Te_x = d['Te_x'] - Ti_x = d['Ti_x'] - fmei = meta['fmei'].v - - meta['lpar'] =1e2*((old_div(d['Bxy'],d['Bpxy']))*d['dlthe']).sum(1)/meta['rho_s'].v #-[normed], average over flux surfaces, parallel length - - #yes dlthe is always the vertical displacement - #dlthe = (hthe0*2 pi)/nz - #meta['lpar']=1e2*(d['Bxy']/d['Bpxy']).mean(1)*d['dlthe'].mean(1) #function of x - meta['sig_par'] = old_div(1.0,(fmei*0.51*meta['nu_hat'])) - #meta['heat_nue'] = ((2*np.pi/meta['lpar'])**2)/(fmei*meta['nu_hat']) - #kz_e = kz_i*(rho_e/rho_i) + meta["maxZ"] = 5 + + # meta['nx'] = nx + # meta['ny']= ny + meta["dt"] = meta["TIMESTEP"] + + # nx,ny = d['Rxy'].shape + + # print meta['AA'].v + + meta["rho_s"] = ValUnit( + 1.02e2 * np.sqrt(d["AA"] * d["Te_x"]) / (d["ZZ"] * d["bmag"]), "cm" + ) # ion gyrorad at T_e, in cm + meta["rho_i"] = ValUnit( + 1.02e2 * np.sqrt(d["AA"] * d["Ti_x"]) / (d["ZZ"] * d["bmag"]), "cm" + ) + meta["rho_e"] = ValUnit(2.38 * np.sqrt(d["Te_x"]) / (d["bmag"]), "cm") + + meta["fmei"] = ValUnit(1.0 / 1836.2 / d["AA"]) + + meta["lambda_ei"] = 24.0 - np.log(old_div(np.sqrt(d["Ni_x"]), d["Te_x"])) + meta["lambda_ii"] = 23.0 - np.log( + d["ZZ"] ** 3 * np.sqrt(2.0 * d["Ni_x"]) / (d["Ti_x"] ** 1.5) + ) # + + meta["wci"] = 1.0 * 9.58e3 * d["ZZ"] * d["bmag"] / d["AA"] # ion gyrofrteq + meta["wpi"] = ( + 1.32e3 * d["ZZ"] * np.sqrt(old_div(d["Ni_x"], d["AA"])) + ) # ion plasma freq + + meta["wce"] = 1.78e7 * d["bmag"] # electron gyrofreq + meta["wpe"] = 5.64e4 * np.sqrt(d["Ni_x"]) # electron plasma freq + + meta["v_the"] = 4.19e7 * np.sqrt(d["Te_x"]) # cm/s + meta["v_thi"] = 9.79e5 * np.sqrt(old_div(d["Ti_x"], d["AA"])) # cm/s + meta["c_s"] = 9.79e5 * np.sqrt(5.0 / 3.0 * d["ZZ"] * d["Te_x"] / d["AA"]) # + meta["v_A"] = 2.18e11 * np.sqrt(old_div(1.0, (d["AA"] * d["Ni_x"]))) + + meta["nueix"] = 2.91e-6 * d["Ni_x"] * meta["lambda_ei"] / d["Te_x"] ** 1.5 # + meta["nuiix"] = ( + 4.78e-8 + * d["ZZ"] ** 4.0 + * d["Ni_x"] + * meta["lambda_ii"] + / d["Ti_x"] ** 1.5 + / np.sqrt(d["AA"]) + ) # + meta["nu_hat"] = meta["Zeff"].v * meta["nueix"] / meta["wci"] + + meta["L_d"] = 7.43e2 * np.sqrt(old_div(d["Te_x"], d["Ni_x"])) + meta["L_i_inrt"] = ( + 2.28e7 * np.sqrt(old_div(d["AA"], d["Ni_x"])) / d["ZZ"] + ) # ion inertial length in cm + meta["L_e_inrt"] = 5.31e5 * np.sqrt(d["Ni_x"]) # elec inertial length in cm + + meta["Ve_x"] = 4.19e7 * d["Te_x"] + + meta["R0"] = old_div((d["Rxy"].max() + d["Rxy"].min()), 2.0) + + print(d["Rxy"].mean(1)) + print(d["ZMAX"]) + print(d["ZMIN"]) + meta["L_z"] = ( + 1e2 * 2 * np.pi * d["Rxy"].mean(1) * (d["ZMAX"] - d["ZMIN"]) + ) # in cm toroidal range + meta["dz"] = d["ZMAX"] - d["ZMIN"] + + # meta['lbNorm']=meta['L_z']*(d['Bpxy']/d['Bxy']).mean(1) #-binormal coord range [cm] + meta["lbNorm"] = meta["L_z"] * (old_div(d["Bxy"], d["Bpxy"])).mean(1) + + # meta['zPerp']=np.array(meta['lbNorm']).mean*np.array(range(d['MZ']))/(d['MZ']-1) + # let's calculate some profile properties + dx = np.gradient(d["Rxy"])[0] + meta["L"] = ( + 1.0 + * 1e2 + * dx + * (meta["Ni0"].v) + / np.gradient(meta["Ni0"].v)[0] + / meta["rho_s"].v + ) + + meta["w_Ln"] = old_div( + meta["c_s"], (np.min(abs(meta["L"])) * meta["wci"] * meta["rho_s"].v) + ) # normed to wci + + AA = meta["AA"].v + ZZ = d["ZZ"] + Te_x = d["Te_x"] + Ti_x = d["Ti_x"] + fmei = meta["fmei"].v + + meta["lpar"] = ( + 1e2 * ((old_div(d["Bxy"], d["Bpxy"])) * d["dlthe"]).sum(1) / meta["rho_s"].v + ) # -[normed], average over flux surfaces, parallel length + + # yes dlthe is always the vertical displacement + # dlthe = (hthe0*2 pi)/nz + # meta['lpar']=1e2*(d['Bxy']/d['Bpxy']).mean(1)*d['dlthe'].mean(1) #function of x + meta["sig_par"] = old_div(1.0, (fmei * 0.51 * meta["nu_hat"])) + # meta['heat_nue'] = ((2*np.pi/meta['lpar'])**2)/(fmei*meta['nu_hat']) + # kz_e = kz_i*(rho_e/rho_i) # kz_s = kz_i*(rho_s/rho_i) # kz_i = (TWOPI/L_z)*(indgen((*current_str).fft.nz+1))*rho_i - + # knorm = (TWOPI/lbNorm)*(indgen((*current_str).fft.nz+1))*rho_s # for now just translate for elem in meta: - if type(meta[elem]).__name__ =='ValUnit': - meta[elem] = {'u':meta[elem].u,'v':meta[elem].v} - - - print('meta: ', type(meta)) + if type(meta[elem]).__name__ == "ValUnit": + meta[elem] = {"u": meta[elem].u, "v": meta[elem].v} + + print("meta: ", type(meta)) return meta # meta['DZ'] =inp['[main]']['ZMAX']#-b['[main]']['ZMIN'] @@ -390,13 +427,10 @@ def ToFloat(metaString): # bmag = IC.variables['bmag'][:]*1.e4 #to cgs # Ni_x = IC.variables['Ni_x'][:]*1.e14 # cm^-3 # Te_x - + # rho_s = 1.02e2*sqrt(AA.v*Te_x.v)/ZZ.v/bmag.v # rho_i - # rho_e - - + # rho_e - - #for i,val in enumerate(boutlist): +# for i,val in enumerate(boutlist): diff --git a/tools/pylib/post_bout/rms.py b/tools/pylib/post_bout/rms.py index 586d426ed4..9ec23d9f90 100644 --- a/tools/pylib/post_bout/rms.py +++ b/tools/pylib/post_bout/rms.py @@ -1,55 +1,56 @@ from __future__ import division from builtins import range from past.utils import old_div + ### # rms(f) : compute growth rate vs. time based on rms of bout variable f for all grid points # plot_rms (x,y): plots the graph growth_rate vs. time for grid point x,y ### - import numpy as np from pylab import plot, show, xlabel, ylabel, tight_layout from boutdata.collect import collect - def rms(f): - nt=f.shape[0] + nt = f.shape[0] - ns=f.shape[1] - ne=f.shape[2] - nz=f.shape[3] + ns = f.shape[1] + ne = f.shape[2] + nz = f.shape[3] - ar=np.zeros([nz]) + ar = np.zeros([nz]) - rms=np.zeros([nt,ns,ne]) + rms = np.zeros([nt, ns, ne]) for i in range(nt): for j in range(ns): for k in range(ne): - ar=f[i,j,k,:] - valav=np.sum(ar) - tot=np.sum(old_div(np.power(ar-valav,2),nz)) - rms[i,j,k]=np.sqrt(tot) + ar = f[i, j, k, :] + valav = np.sum(ar) + tot = np.sum(old_div(np.power(ar - valav, 2), nz)) + rms[i, j, k] = np.sqrt(tot) return rms -def plot_rms(x,y): - s=plot(np.gradient(np.log(rmsp[:,x,y]))) - ylabel('$\gamma / \omega_A$',fontsize=25) - xlabel('Time$(\\tau_A)$',fontsize=25) + +def plot_rms(x, y): + s = plot(np.gradient(np.log(rmsp[:, x, y]))) + ylabel("$\gamma / \omega_A$", fontsize=25) + xlabel("Time$(\\tau_A)$", fontsize=25) tight_layout() return s -#test -if __name__ == '__main__': - path='../../../examples/elm-pb/data' + +# test +if __name__ == "__main__": + path = "../../../examples/elm-pb/data" data = collect("P", path=path) - rmsp=rms(data) + rmsp = rms(data) - plot_rms(34,32) + plot_rms(34, 32) tight_layout() show() diff --git a/tools/tokamak_grids/all/grid2bout.py b/tools/tokamak_grids/all/grid2bout.py index ac55360855..da62a37aeb 100644 --- a/tools/tokamak_grids/all/grid2bout.py +++ b/tools/tokamak_grids/all/grid2bout.py @@ -12,16 +12,19 @@ def grid2bout(input, output="bout.grd.nc"): # List variables needed and dimensions - dimensions = {'nx':0, 'ny':0, - 'psi':1, - 'mu0p':1, - 'mu0pprime':1, - 'f':1, - 'ffprime':1, - 'qsafe':1, - 'Rxy':2, - 'Zxy':2} - + dimensions = { + "nx": 0, + "ny": 0, + "psi": 1, + "mu0p": 1, + "mu0pprime": 1, + "f": 1, + "ffprime": 1, + "qsafe": 1, + "Rxy": 2, + "Zxy": 2, + } + # Open the input file infile = Datafile(input) @@ -29,29 +32,27 @@ def grid2bout(input, output="bout.grd.nc"): vars = {} # Check the required variables - for k,v in list(dimensions.items()): + for k, v in list(dimensions.items()): nd = infile.ndims(k) if nd == None: print("ERROR: Variable missing: " + k) return False if v != nd: - print("ERROR: Variable '"+k+"' has wrong number of dimensions") + print("ERROR: Variable '" + k + "' has wrong number of dimensions") return False - + # Read the variables vars[k] = f.read(k) - + # Read the size of the grid - nx = vars['nx'] - ny = vars['ny'] - + nx = vars["nx"] + ny = vars["ny"] + # Location of grid points - Rxy = vars['Rxy'] - Zxy = vars['Zxy'] - + Rxy = vars["Rxy"] + Zxy = vars["Zxy"] + # Check if the last point is the same as the first - dl = (Rxy[:,ny-1] - Rxy[:,0])**2 + (Zxy[:,ny-1] - Zxy[:,0])**2 - if dl.max() < 1.e-4: + dl = (Rxy[:, ny - 1] - Rxy[:, 0]) ** 2 + (Zxy[:, ny - 1] - Zxy[:, 0]) ** 2 + if dl.max() < 1.0e-4: print("**Last poloidal point duplicates the first. Removing...") - - diff --git a/tools/tokamak_grids/cyclone/cyclone.py b/tools/tokamak_grids/cyclone/cyclone.py index 519b93dae8..b6496d9bc6 100755 --- a/tools/tokamak_grids/cyclone/cyclone.py +++ b/tools/tokamak_grids/cyclone/cyclone.py @@ -12,104 +12,110 @@ ###################################################### -nx = 68 # Number of radial grid points -ny = 32 # Number of poloidal (parallel) grid points +nx = 68 # Number of radial grid points +ny = 32 # Number of poloidal (parallel) grid points varyBp = False -output = "cyclone_"+str(nx)+"x"+str(ny)+".nc" +output = "cyclone_" + str(nx) + "x" + str(ny) + ".nc" ###################################################### -Ni = 1. # Ion density in 10^20 m^-3 -Ti = 1000 # Temperature in eV (Te = Ti) +Ni = 1.0 # Ion density in 10^20 m^-3 +Ti = 1000 # Temperature in eV (Te = Ti) Rmaj = 4 # Major radius [meters] -q = 1.4 # Safety factor q = r*Bt/(R*Bp) -s = 0.776 # Magnetic shear s = (r/q) dq/dr -eta_i = 3.114 # Ratio of density to temp. length scales eta = L_n / L_T +q = 1.4 # Safety factor q = r*Bt/(R*Bp) +s = 0.776 # Magnetic shear s = (r/q) dq/dr +eta_i = 3.114 # Ratio of density to temp. length scales eta = L_n / L_T epsilon = 0.18 # Inverse aspect ratio epsilon = r / R -Rnorm = 6.92 # Ratio of major radius to L_T Rnorm = R / L_T -rho_norm = 0.01 # Normalised ion gyro-radius rho_norm = rho_i / L_T -r_wid = 100 # Radial extent, normalised to gyro-radius r_wid = dr / rho_i +Rnorm = 6.92 # Ratio of major radius to L_T Rnorm = R / L_T +rho_norm = 0.01 # Normalised ion gyro-radius rho_norm = rho_i / L_T +r_wid = 100 # Radial extent, normalised to gyro-radius r_wid = dr / rho_i -Mi = 2.*1.67262158e-27 # Ion mass [kg]. Deuterium +Mi = 2.0 * 1.67262158e-27 # Ion mass [kg]. Deuterium ###################################################### + def eps_integral(eps, theta=None): if theta == None: - theta = 2.*pi - return (quad(lambda t: 1./((1. - eps*cos(t))**2), 0., theta))[0] + theta = 2.0 * pi + return (quad(lambda t: 1.0 / ((1.0 - eps * cos(t)) ** 2), 0.0, theta))[0] + rminor = Rmaj * epsilon # Minor radius [m] -L_T = Rmaj / Rnorm # Temp. length scale [m] -L_n = eta_i * L_T # Density length scale [m] -rho_i = rho_norm * L_T # Ion Larmor radius [m] -Bt0 = sqrt(2.*Ti*Mi / 1.602e-19)/rho_i # Toroidal field from rho_i [T] -Bp = rminor * Bt0 * eps_integral(epsilon)/ (2.*pi * q * Rmaj) # Poloidal field [T] +L_T = Rmaj / Rnorm # Temp. length scale [m] +L_n = eta_i * L_T # Density length scale [m] +rho_i = rho_norm * L_T # Ion Larmor radius [m] +Bt0 = sqrt(2.0 * Ti * Mi / 1.602e-19) / rho_i # Toroidal field from rho_i [T] +Bp = rminor * Bt0 * eps_integral(epsilon) / (2.0 * pi * q * Rmaj) # Poloidal field [T] -dr = r_wid * rho_i # Width of domain [m] +dr = r_wid * rho_i # Width of domain [m] -theta = 2.*pi * arange(0,float(ny)) / float(ny) +theta = 2.0 * pi * arange(0, float(ny)) / float(ny) Rxy = zeros([nx, ny]) Zxy = Rxy.copy() for i in range(ny): - Rxy[:,i] = Rmaj - rminor*cos(theta[i]) - Zxy[:,i] = rminor * sin(theta[i]) + Rxy[:, i] = Rmaj - rminor * cos(theta[i]) + Zxy[:, i] = rminor * sin(theta[i]) -dy = zeros([nx,ny]) + 2.*pi / float(ny) -hthe = zeros([nx,ny]) + rminor +dy = zeros([nx, ny]) + 2.0 * pi / float(ny) +hthe = zeros([nx, ny]) + rminor Btxy = Bt0 * Rmaj / Rxy -print("Toroidal field varies from "+str(Bt0*Rmaj/(Rmaj + rminor)) + \ - " to "+str(Bt0*Rmaj/(Rmaj - rminor))) +print( + "Toroidal field varies from " + + str(Bt0 * Rmaj / (Rmaj + rminor)) + + " to " + + str(Bt0 * Rmaj / (Rmaj - rminor)) +) # Minor radius offset -drprof = dr*((arange(nx)/float(nx-1)) - 0.5) +drprof = dr * ((arange(nx) / float(nx - 1)) - 0.5) # q profile -qprof = q + (s*q/rminor) * drprof +qprof = q + (s * q / rminor) * drprof -print("q varies from "+str(min(qprof))+" to "+str(max(qprof))) +print("q varies from " + str(min(qprof)) + " to " + str(max(qprof))) -ShiftAngle = qprof * 2.*pi +ShiftAngle = qprof * 2.0 * pi -Bpxy = zeros([nx,ny]) +Bpxy = zeros([nx, ny]) if varyBp: # Vary Bp to get shear for y in range(ny): - Bpxy[:,y] = Bp * q / qprof - print("Poloidal field varies from "+str(amin(Bpxy))+" to "+str(amax(Bpxy))) + Bpxy[:, y] = Bp * q / qprof + print("Poloidal field varies from " + str(amin(Bpxy)) + " to " + str(amax(Bpxy))) else: # Constant Bp, but shift angle varies Bpxy += Bp -dx = Bp * (dr/float(nx-1)) * Rxy +dx = Bp * (dr / float(nx - 1)) * Rxy -Bxy = sqrt(Btxy**2 + Bpxy**2) +Bxy = sqrt(Btxy ** 2 + Bpxy ** 2) zShift = zeros([nx, ny]) qint = eps_integral(epsilon) -for i in range(1,ny): - zShift[:,i] = ShiftAngle * eps_integral(epsilon, theta=theta[i]) / qint +for i in range(1, ny): + zShift[:, i] = ShiftAngle * eps_integral(epsilon, theta=theta[i]) / qint # Make zShift = 0 on outboard midplane (for plotting mainly) -y0 = int(ny/2) -zs0 = zShift[:,y0] +y0 = int(ny / 2) +zs0 = zShift[:, y0] for i in range(ny): - zShift[:,i] -= zs0 + zShift[:, i] -= zs0 Ni0 = zeros([nx, ny]) Ti0 = Ni0 for i in range(ny): - Ni0[:,i] = Ni * exp(-drprof / L_n) - Ti0[:,i] = Ti * exp(-drprof / L_T) + Ni0[:, i] = Ni * exp(-drprof / L_n) + Ti0[:, i] = Ti * exp(-drprof / L_T) Te0 = Ti0 -pressure = Ni0 * (Ti0 + Te0) * 1.602e-19*1.0e20 # In Pascals +pressure = Ni0 * (Ti0 + Te0) * 1.602e-19 * 1.0e20 # In Pascals Jpar0 = zeros([nx, ny]) @@ -128,10 +134,10 @@ def eps_integral(eps, theta=None): for x in range(nx): for y in range(ny): - rpos = (float(x)/float(nx-1) - 0.5) * dr - R = Rmaj - (rminor + rpos)*cos(theta[y]) + rpos = (float(x) / float(nx - 1) - 0.5) * dr + R = Rmaj - (rminor + rpos) * cos(theta[y]) Bt = Bt0 * Rmaj / R - logB[x,y] = log(sqrt(Bt**2 + Bp**2)) + logB[x, y] = log(sqrt(Bt ** 2 + Bp ** 2)) ###################################################### # Topology: Just in the core @@ -139,13 +145,13 @@ def eps_integral(eps, theta=None): ixseps1 = nx ixseps2 = nx jyseps1_1 = -1 -jyseps1_2 = int(ny/2) +jyseps1_2 = int(ny / 2) jyseps2_1 = jyseps1_2 -jyseps2_2 = ny-1 +jyseps2_2 = ny - 1 ny_inner = jyseps1_2 # Only one region -yup_xsplit = [nx] +yup_xsplit = [nx] ydown_xsplit = [nx] yup_xin = [0] yup_xout = [-1] @@ -156,7 +162,7 @@ def eps_integral(eps, theta=None): ###################################################### -print("Writing grid to file "+output) +print("Writing grid to file " + output) of = DataFile() of.open(output, create=True) diff --git a/tools/tokamak_grids/elite/elite2nc b/tools/tokamak_grids/elite/elite2nc index aa181877fb..eb17c13bd9 100755 --- a/tools/tokamak_grids/elite/elite2nc +++ b/tools/tokamak_grids/elite/elite2nc @@ -62,11 +62,13 @@ def file_tokens(fp): toklist = [] while True: line = fp.readline() - if not line: break + if not line: + break toklist = line.split() for tok in toklist: yield tok + token = file_tokens(f) try: @@ -82,7 +84,7 @@ except ValueError: print("Size of grid: %d by %d\n" % (npsi, npol)) # var will be a dictionary of variables -var=dict() +var = dict() while True: try: @@ -90,13 +92,13 @@ while True: except: break - if (varname == 'R') or (varname == 'Z') or (varname[0] == 'B'): + if (varname == "R") or (varname == "Z") or (varname[0] == "B"): # A 2D variable try: data = np.zeros([npsi, npol]) for j in np.arange(npol): for i in np.arange(npsi): - data[i,j] = float(next(token)) + data[i, j] = float(next(token)) except StopIteration: print("ERROR: Unexpected end of file while reading " + varname) raise SystemExit @@ -142,31 +144,33 @@ f.close() try: Bt = np.zeros([npsi, npol]) - f = var['f(psi)'] - R = var['R'] + f = var["f(psi)"] + R = var["R"] for i in np.arange(npsi): - Bt[i,:] = f[i] * R[i,:] - var['Bt'] = Bt + Bt[i, :] = f[i] * R[i, :] + var["Bt"] = Bt except KeyError: print("ERROR: Need f(psi) and R to calculate Bt") raise SystemExit # Temperatures: If only have one, set equal -if 'Te' in var and 'Ti' not in var: - var['Ti'] = var['Te'] +if "Te" in var and "Ti" not in var: + var["Ti"] = var["Te"] -if 'Ti' in var and 'Te' not in var: - var['Te'] = var['Ti'] +if "Ti" in var and "Te" not in var: + var["Te"] = var["Ti"] # Calculate pressure -if 'p' not in var: - if 'ne' in var and 'Te' in var: +if "p" not in var: + if "ne" in var and "Te" in var: # Calculate using Ni, Te and Ti print("Calculating pressure from ne, Te, Ti") - var['p'] = var['ne'] * (var['Te'] + var['Ti']) * 1.602e-19 * (4.0*3.14159*1e-7) + var["p"] = ( + var["ne"] * (var["Te"] + var["Ti"]) * 1.602e-19 * (4.0 * 3.14159 * 1e-7) + ) # Could check against pprime else: # No plasma quantities to use, so integrate pprime @@ -186,19 +190,21 @@ except: # Write data # Map between input and output variable names -vnames = {'psi':'psi', - 'f':'f(psi)', - 'ffprime':'ffprime', - 'mu0p':'p', - 'mu0pprime':'pprime', - 'qsafe':'q', - 'Ni':'ne', - 'Te':'Te', - 'Ti':'Ti', - 'Rxy':'R', - 'Zxy':'Z', - 'Bpxy':'Bp', - 'Btxy':'Bt'} +vnames = { + "psi": "psi", + "f": "f(psi)", + "ffprime": "ffprime", + "mu0p": "p", + "mu0pprime": "pprime", + "qsafe": "q", + "Ni": "ne", + "Te": "Te", + "Ti": "Ti", + "Rxy": "R", + "Zxy": "Z", + "Bpxy": "Bp", + "Btxy": "Bt", +} try: of.write("nx", npsi) diff --git a/tools/tokamak_grids/gato/gato2nc b/tools/tokamak_grids/gato/gato2nc index f7b40cf378..81af8ccc3d 100755 --- a/tools/tokamak_grids/gato/gato2nc +++ b/tools/tokamak_grids/gato/gato2nc @@ -59,8 +59,8 @@ f = open(infile) # First line contains the date date = f.readline() if not date: - print("ERROR: Cannot read from input file") - raise SystemExit + print("ERROR: Cannot read from input file") + raise SystemExit print("Date: " + date) @@ -74,13 +74,15 @@ def file_tokens(fp): toklist = [] while True: line = fp.readline() - if not line: break + if not line: + break # Match numbers in the line using regular expression - pattern = r'[+-]?\d*[\.]?\d+(?:[Ee][+-]?\d+)?' + pattern = r"[+-]?\d*[\.]?\d+(?:[Ee][+-]?\d+)?" toklist = re.findall(pattern, line) for tok in toklist: yield tok + token = file_tokens(f) # Third contains number of mesh points @@ -108,8 +110,8 @@ if (npsi < 1) or (ntheta < 1): try: rcnt = float(next(token)) - xma = float(next(token)) - zma = float(next(token)) + xma = float(next(token)) + zma = float(next(token)) btor = float(next(token)) except: print("ERROR: Couldn't read normalisation factors") @@ -119,39 +121,42 @@ print("rcnt = %e, xma = %e, zma = %e, btor = %e" % (rcnt, xma, zma, btor)) try: curtot = float(next(token)) - eaxe = float(next(token)) - dnorm = float(next(token)) + eaxe = float(next(token)) + dnorm = float(next(token)) except: print("ERROR: Couldn't read normalisation factors") raise SystemExit print("curtot = %e, eaxe = %e, dnorm = %e\n" % (curtot, eaxe, dnorm)) + def read_array(n, name="Unknown"): data = np.zeros([n]) try: for i in np.arange(n): data[i] = float(next(token)) except: - print("ERROR: Failed reading array '"+name+"' of size ", n) + print("ERROR: Failed reading array '" + name + "' of size ", n) raise SystemExit return data + def read_2d(nx, ny, name="Unknown"): data = np.zeros([nx, ny]) print("Reading 2D variable " + name) for i in np.arange(nx): - data[i,:] = read_array(ny, name+"["+str(i)+"]") + data[i, :] = read_array(ny, name + "[" + str(i) + "]") return data + # Read 1D arrays psiflux = read_array(npsi, "psiflux") -fnorm = read_array(npsi, "fnorm") +fnorm = read_array(npsi, "fnorm") ffpnorm = read_array(npsi, "ffpnorm") -ponly = read_array(npsi, "ponly") -pponly = read_array(npsi, "pponly") -qsf = read_array(npsi, "qsf") -d = read_array(npsi, "d") +ponly = read_array(npsi, "ponly") +pponly = read_array(npsi, "pponly") +qsf = read_array(npsi, "qsf") +d = read_array(npsi, "d") dpdz = read_array(ntheta, "dpdz") dpdr = read_array(ntheta, "dpdr") @@ -174,27 +179,27 @@ ny = ntheta if isym == 1: # Fill in values for up-down symmetric case print("Grid is up-down symmetric. Reflecting grid about midplane") - ny = tsize = 2*(ntheta - 1) + 1 + ny = tsize = 2 * (ntheta - 1) + 1 - def reflect(data, mapfunc = lambda x:x): - """ Reflect a variable about midplane + def reflect(data, mapfunc=lambda x: x): + """Reflect a variable about midplane Optionally supply a mapping function""" data2 = np.zeros([tsize, npsi]) # Copy the original data for i in np.arange(ntheta): - data2[i,:] = data[i,:] + data2[i, :] = data[i, :] # Now fill in the remainder for i in np.arange(ntheta, tsize): t0 = tsize - 1 - i - data2[i,:] = mapfunc(data[t0,:]) + data2[i, :] = mapfunc(data[t0, :]) return data2 xnorm = reflect(xnorm) - znorm = reflect(znorm, lambda x: 2.*zma - x) # Reflect about zma + znorm = reflect(znorm, lambda x: 2.0 * zma - x) # Reflect about zma if Br != None: - Br = reflect(Br, lambda x:-x) # Br reverses + Br = reflect(Br, lambda x: -x) # Br reverses if Bz != None: - Bz = reflect(Bz) # Bz remains the same + Bz = reflect(Bz) # Bz remains the same theta = tsize # Make sure we have Br, Bz and Bpol @@ -204,13 +209,13 @@ if (Br == None) or (Bz == None): # Use dpsi = 2*PI*R*Bp dx (for now) Bpol = None else: - Bpol = np.sqrt(Br**2 + Bz**2) + Bpol = np.sqrt(Br ** 2 + Bz ** 2) # Calculate toroidal field Btor = old_div(fnorm, xnorm) # Output file -print("Writing data to '"+outfile+"'") +print("Writing data to '" + outfile + "'") of = DataFile() of.open(outfile, create=True) @@ -218,12 +223,12 @@ of.write("nx", npsi) of.write("ny", ny) # Write 1D flux functions -mu0 = 4.e-7*np.pi +mu0 = 4.0e-7 * np.pi of.write("psi", psiflux) of.write("f", fnorm) of.write("ffprime", ffpnorm) -of.write("mu0p", ponly*mu0) -of.write("mu0pprime", pponly*mu0) +of.write("mu0p", ponly * mu0) +of.write("mu0pprime", pponly * mu0) of.write("qsafe", qsf) of.write("Ni", d) @@ -232,9 +237,9 @@ of.write("Rxy", np.transpose(xnorm)) of.write("Zxy", np.transpose(znorm)) # Write 2D field components -#of.write("Br", np.transpose(Br)) -#of.write("Bz", np.transpose(Bz)) -#of.write("Bpol", np.transpose(Bpol)) +# of.write("Br", np.transpose(Br)) +# of.write("Bz", np.transpose(Bz)) +# of.write("Bpol", np.transpose(Bpol)) of.write("Btor", np.transpose(Btor)) of.close() From 093706c1631d690996d389f0bfa0ba27db60092b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 2 Mar 2021 14:28:53 +0100 Subject: [PATCH 281/293] set BOUT_TOP absolute in case BOUT_TOP is set --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 0b9aa3b594..9a1ff065ce 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -BOUT_TOP = . +BOUT_TOP = $(PWD) DIRS = src From 2c8f6e707d5d46ff7132602ab0748f4e8cf7c377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 2 Mar 2021 15:33:32 +0100 Subject: [PATCH 282/293] skip test-laplacexy with 3d metrics --- tests/integrated/test-laplacexy-fv/runtest | 3 ++- tests/integrated/test-laplacexy-short/runtest | 9 ++------- tests/integrated/test-laplacexy/runtest | 1 + tests/integrated/test-laplacexy/test-laplacexy.cxx | 3 +++ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/integrated/test-laplacexy-fv/runtest b/tests/integrated/test-laplacexy-fv/runtest index f560f22abf..f87a12e2ab 100755 --- a/tests/integrated/test-laplacexy-fv/runtest +++ b/tests/integrated/test-laplacexy-fv/runtest @@ -4,6 +4,7 @@ # Run the test, compare results against the benchmark # +# requires: not metric_3d # requires: petsc # cores: 8 @@ -59,7 +60,7 @@ for nproc in [8]: "hypre not available as pre-conditioner in PETSc. Re-running with " + "pctype=shell..." ) - s, out = launch(cmd, nproc=nproc, pipe=True, verbose=True) + _, out = launch_safe(cmd, nproc=nproc, pipe=True, verbose=True) f = open("run.log." + str(nproc), "w") f.write(out) diff --git a/tests/integrated/test-laplacexy-short/runtest b/tests/integrated/test-laplacexy-short/runtest index 8d20d96cdf..3325a32f4d 100755 --- a/tests/integrated/test-laplacexy-short/runtest +++ b/tests/integrated/test-laplacexy-short/runtest @@ -4,6 +4,7 @@ # Run the test, compare results against the benchmark # +# requires: not metric_3d # requires: petsc # cores: 8 @@ -13,12 +14,6 @@ from sys import exit tol = 5.0e-8 -# Note accuracy of test is limited when g12!=0 by inconsistency between the way boundary -# conditions are applied in LaplaceXY and the way they are applied in the D2DXDY() -# operator called by Laplace_perp(). In D2DXDY(f) 'free_o3' boundary conditions are -# applied to dfdy before calculating DDX(dfdy). -tol_nonorth = 2.0e-5 - argslist = [ "laplacexy:core_bndry_dirichlet=true laplacexy:pf_bndry_dirichlet=true laplacexy:y_bndry=dirichlet " "f:bndry_xin=dirichlet f:bndry_xout=dirichlet f:bndry_yup=dirichlet f:bndry_ydown=dirichlet", @@ -73,7 +68,7 @@ for nproc in [8]: "hypre not available as pre-conditioner in PETSc. Re-running with " + "pctype=shell..." ) - s, out = launch(cmd, nproc=nproc, pipe=True, verbose=True) + _, out = launch_safe(cmd, nproc=nproc, pipe=True, verbose=True) f = open("run.log." + str(nproc), "w") f.write(out) diff --git a/tests/integrated/test-laplacexy/runtest b/tests/integrated/test-laplacexy/runtest index 30a3f36e0e..d2f99c5100 100755 --- a/tests/integrated/test-laplacexy/runtest +++ b/tests/integrated/test-laplacexy/runtest @@ -4,6 +4,7 @@ # Run the test, compare results against the benchmark # +# requires: not metric_3d # requires: petsc # requires: all_tests # cores: 8 diff --git a/tests/integrated/test-laplacexy/test-laplacexy.cxx b/tests/integrated/test-laplacexy/test-laplacexy.cxx index 4e85b48fef..e3219e68f6 100644 --- a/tests/integrated/test-laplacexy/test-laplacexy.cxx +++ b/tests/integrated/test-laplacexy/test-laplacexy.cxx @@ -30,6 +30,9 @@ #include #include +using bout::globals::dump; +using bout::globals::mesh; + int main(int argc, char** argv) { BoutInitialise(argc, argv); From 4fd9dfb999f056996a23c72cc0357cca55cdf2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 3 Mar 2021 09:48:45 +0100 Subject: [PATCH 283/293] skip mpi plugin in clang format --- .github/workflows/clang-tidy-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml index 1e3f3c1483..5dfb044b49 100644 --- a/.github/workflows/clang-tidy-review.yml +++ b/.github/workflows/clang-tidy-review.yml @@ -47,7 +47,7 @@ jobs: with: build_dir: build apt_packages: "libfftw3-dev,libnetcdf-c++4-dev,libopenmpi-dev,petsc-dev,slepc-dev,liblapack-dev,libparpack2-dev,libsundials-dev,uuid-dev" - clang_tidy_checks: '-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-misc-non-private-member-variables-in-classes,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-vararg' + clang_tidy_checks: '-*,performance-*,readability-*,bugprone-*,clang-analyzer-*,cppcoreguidelines-*,mpi-*,misc-*,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-misc-non-private-member-variables-in-classes,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-vararg,-clang-analyzer-optin.mpi*' # Googletest triggers a _lot_ of clang-tidy warnings, so ignore all # the unit tests until they're fixed or ignored upstream exclude: "tests/unit/*cxx" From 2ef34fd36f9df0ae9d21213d8117c9c075730a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 22 Mar 2021 14:07:28 +0100 Subject: [PATCH 284/293] Fix boundary detection Previously no boundary was detection because the index cannot be out of bounds in both directions --- src/mesh/parallel/fci.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/parallel/fci.cxx b/src/mesh/parallel/fci.cxx index 89aa426636..78f344b92d 100644 --- a/src/mesh/parallel/fci.cxx +++ b/src/mesh/parallel/fci.cxx @@ -170,7 +170,7 @@ FCIMap::FCIMap(Mesh& mesh, const Coordinates::FieldMetric& dy, Options& options, } } - if ((xt_prime[i] >= 0.0) or (xt_prime[i] <= map_mesh.xend)) { + if ((xt_prime[i] >= 0.0) and (xt_prime[i] <= map_mesh.xend)) { // Not a boundary continue; } From 6ab21362eb0498215cc5f0afc34800d93e0dcf1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Mon, 22 Mar 2021 15:40:40 +0100 Subject: [PATCH 285/293] Return non-const should be preferred Returning non-const objects has no disadvantage for const correctness and is easier to read. --- include/bout/paralleltransform.hxx | 95 ++++++++++++----------- src/mesh/parallel/fci.hxx | 14 ++-- src/mesh/parallel/shiftedmetric.cxx | 27 +++---- src/mesh/parallel/shiftedmetricinterp.cxx | 7 +- src/mesh/parallel/shiftedmetricinterp.hxx | 17 ++-- tests/unit/field/test_field_factory.cxx | 8 +- 6 files changed, 87 insertions(+), 81 deletions(-) diff --git a/include/bout/paralleltransform.hxx b/include/bout/paralleltransform.hxx index 2aaa038ead..3acc5854f0 100644 --- a/include/bout/paralleltransform.hxx +++ b/include/bout/paralleltransform.hxx @@ -49,42 +49,46 @@ public: /// Convert a field into field-aligned coordinates /// so that the y index is along the magnetic field - virtual const Field3D toFieldAligned(const Field3D &f, const std::string& region = "RGN_ALL") = 0; + virtual Field3D toFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") = 0; [[deprecated("Please use toFieldAligned(const Field3D& f, " - "const std::string& region = \"RGN_ALL\") instead")]] - const Field3D toFieldAligned(const Field3D &f, REGION region) { + "const std::string& region = \"RGN_ALL\") instead")]] Field3D + toFieldAligned(const Field3D& f, REGION region) { return toFieldAligned(f, toString(region)); } - virtual const FieldPerp toFieldAligned(const FieldPerp &f, const std::string& region = "RGN_ALL") = 0; + virtual FieldPerp toFieldAligned(const FieldPerp& f, + const std::string& region = "RGN_ALL") = 0; [[deprecated("Please use toFieldAligned(const FieldPerp& f, " - "const std::string& region = \"RGN_ALL\") instead")]] - const FieldPerp toFieldAligned(const FieldPerp &f, REGION region) { + "const std::string& region = \"RGN_ALL\") instead")]] FieldPerp + toFieldAligned(const FieldPerp& f, REGION region) { return toFieldAligned(f, toString(region)); } - + /// Convert back from field-aligned coordinates /// into standard form - virtual const Field3D fromFieldAligned(const Field3D &f, const std::string& region = "RGN_ALL") = 0; + virtual Field3D fromFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") = 0; [[deprecated("Please use fromFieldAligned(const Field3D& f, " - "const std::string& region = \"RGN_ALL\") instead")]] - const Field3D fromFieldAligned(const Field3D &f, REGION region) { + "const std::string& region = \"RGN_ALL\") instead")]] Field3D + fromFieldAligned(const Field3D& f, REGION region) { return fromFieldAligned(f, toString(region)); } - virtual const FieldPerp fromFieldAligned(const FieldPerp &f, const std::string& region = "RGN_ALL") = 0; + virtual FieldPerp fromFieldAligned(const FieldPerp& f, + const std::string& region = "RGN_ALL") = 0; [[deprecated("Please use fromFieldAligned(const FieldPerp& f, " - "const std::string& region = \"RGN_ALL\") instead")]] - const FieldPerp fromFieldAligned(const FieldPerp &f, REGION region) { + "const std::string& region = \"RGN_ALL\") instead")]] FieldPerp + fromFieldAligned(const FieldPerp& f, REGION region) { return fromFieldAligned(f, toString(region)); } /// Field2D are axisymmetric, so transformation to or from field-aligned coordinates is /// a null operation. - virtual const Field2D toFieldAligned(const Field2D& f, - const std::string& UNUSED(region) = "RGN_ALL") { + virtual Field2D toFieldAligned(const Field2D& f, + const std::string& UNUSED(region) = "RGN_ALL") { return f; } - virtual const Field2D fromFieldAligned(const Field2D& f, - const std::string& UNUSED(region) = "RGN_ALL") { + virtual Field2D fromFieldAligned(const Field2D& f, + const std::string& UNUSED(region) = "RGN_ALL") { return f; } @@ -150,12 +154,14 @@ public: * The field is already aligned in Y, so this * does nothing */ - const Field3D toFieldAligned(const Field3D& f, const std::string& UNUSED(region) = "RGN_ALL") override { + Field3D toFieldAligned(const Field3D& f, + const std::string& UNUSED(region) = "RGN_ALL") override { ASSERT2(f.getDirectionY() == YDirectionType::Standard); Field3D result = f; return result.setDirectionY(YDirectionType::Aligned); } - const FieldPerp toFieldAligned(const FieldPerp& f, const std::string& UNUSED(region) = "RGN_ALL") override { + FieldPerp toFieldAligned(const FieldPerp& f, + const std::string& UNUSED(region) = "RGN_ALL") override { ASSERT2(f.getDirectionY() == YDirectionType::Standard); FieldPerp result = f; return result.setDirectionY(YDirectionType::Aligned); @@ -165,12 +171,14 @@ public: * The field is already aligned in Y, so this * does nothing */ - const Field3D fromFieldAligned(const Field3D& f, const std::string& UNUSED(region) = "RGN_ALL") override { + Field3D fromFieldAligned(const Field3D& f, + const std::string& UNUSED(region) = "RGN_ALL") override { ASSERT2(f.getDirectionY() == YDirectionType::Aligned); Field3D result = f; return result.setDirectionY(YDirectionType::Standard); } - const FieldPerp fromFieldAligned(const FieldPerp& f, const std::string& UNUSED(region) = "RGN_ALL") override { + FieldPerp fromFieldAligned(const FieldPerp& f, + const std::string& UNUSED(region) = "RGN_ALL") override { ASSERT2(f.getDirectionY() == YDirectionType::Aligned); FieldPerp result = f; return result.setDirectionY(YDirectionType::Standard); @@ -222,18 +230,19 @@ public: * in X-Z, and the metric tensor will need to be changed * if X derivatives are used. */ - const Field3D toFieldAligned(const Field3D& f, const std::string& region = "RGN_ALL") override; - const FieldPerp toFieldAligned(const FieldPerp& f, - const std::string& region = "RGN_ALL") override; + Field3D toFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") override; + FieldPerp toFieldAligned(const FieldPerp& f, + const std::string& region = "RGN_ALL") override; /*! * Converts a field back to X-Z orthogonal coordinates * from field aligned coordinates. */ - const Field3D fromFieldAligned(const Field3D& f, - const std::string& region = "RGN_ALL") override; - const FieldPerp fromFieldAligned(const FieldPerp& f, - const std::string& region = "RGN_ALL") override; + Field3D fromFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") override; + FieldPerp fromFieldAligned(const FieldPerp& f, + const std::string& region = "RGN_ALL") override; bool canToFromFieldAligned() override { return true; } @@ -288,14 +297,13 @@ private: * Shift a 2D field in Z. * Since 2D fields are constant in Z, this has no effect */ - const Field2D shiftZ(const Field2D& f, const Field2D& UNUSED(zangle), - const std::string UNUSED(region) = "RGN_NOX") const { + Field2D shiftZ(const Field2D& f, const Field2D& UNUSED(zangle), + const std::string UNUSED(region) = "RGN_NOX") const { return f; }; [[deprecated("Please use shiftZ(const Field2D& f, const Field2D& zangle, " - "const std::string& region = \"RGN_NOX\") instead")]] - const Field2D shiftZ(const Field2D& f, const Field2D& UNUSED(zangle), - REGION UNUSED(region)) const { + "const std::string& region = \"RGN_NOX\") instead")]] Field2D + shiftZ(const Field2D& f, const Field2D& UNUSED(zangle), REGION UNUSED(region)) const { return f; }; @@ -306,12 +314,11 @@ private: * @param[in] zangle Toroidal angle (z) * */ - const Field3D shiftZ(const Field3D& f, const Field2D& zangle, - const std::string& region = "RGN_NOX") const; + Field3D shiftZ(const Field3D& f, const Field2D& zangle, + const std::string& region = "RGN_NOX") const; [[deprecated("Please use shiftZ(const Field3D& f, const Field2D& zangle, " - "const std::string& region = \"RGN_NOX\") instead")]] - const Field3D shiftZ(const Field3D& f, const Field2D& zangle, - REGION region) const { + "const std::string& region = \"RGN_NOX\") instead")]] Field3D + shiftZ(const Field3D& f, const Field2D& zangle, REGION region) const { return shiftZ(f, zangle, toString(region)); }; @@ -325,12 +332,12 @@ private: * @param[in] phs The phase to shift by * @param[in] y_direction_out The value to set yDirectionType of the result to */ - const Field3D shiftZ(const Field3D& f, const Tensor& phs, - const YDirectionType y_direction_out, - const std::string& region = "RGN_NOX") const; - const FieldPerp shiftZ(const FieldPerp& f, const Tensor& phs, - const YDirectionType y_direction_out, - const std::string& region = "RGN_NOX") const; + Field3D shiftZ(const Field3D& f, const Tensor& phs, + const YDirectionType y_direction_out, + const std::string& region = "RGN_NOX") const; + FieldPerp shiftZ(const FieldPerp& f, const Tensor& phs, + const YDirectionType y_direction_out, + const std::string& region = "RGN_NOX") const; /*! * Shift a given 1D array, assumed to be in Z, by the given \p zangle diff --git a/src/mesh/parallel/fci.hxx b/src/mesh/parallel/fci.hxx index d32179a4e8..3ecd964bfa 100644 --- a/src/mesh/parallel/fci.hxx +++ b/src/mesh/parallel/fci.hxx @@ -106,18 +106,22 @@ public: void calcParallelSlices(Field3D &f) override; void integrateParallelSlices(Field3D &f) override; - - const Field3D toFieldAligned(const Field3D &UNUSED(f), const std::string& UNUSED(region) = "RGN_ALL") override { + + Field3D toFieldAligned(const Field3D& UNUSED(f), + const std::string& UNUSED(region) = "RGN_ALL") override { throw BoutException("FCI method cannot transform into field aligned grid"); } - const FieldPerp toFieldAligned(const FieldPerp &UNUSED(f), const std::string& UNUSED(region) = "RGN_ALL") override { + FieldPerp toFieldAligned(const FieldPerp& UNUSED(f), + const std::string& UNUSED(region) = "RGN_ALL") override { throw BoutException("FCI method cannot transform into field aligned grid"); } - const Field3D fromFieldAligned(const Field3D &UNUSED(f), const std::string& UNUSED(region) = "RGN_ALL") override { + Field3D fromFieldAligned(const Field3D& UNUSED(f), + const std::string& UNUSED(region) = "RGN_ALL") override { throw BoutException("FCI method cannot transform from field aligned grid"); } - const FieldPerp fromFieldAligned(const FieldPerp &UNUSED(f), const std::string& UNUSED(region) = "RGN_ALL") override { + FieldPerp fromFieldAligned(const FieldPerp& UNUSED(f), + const std::string& UNUSED(region) = "RGN_ALL") override { throw BoutException("FCI method cannot transform from field aligned grid"); } diff --git a/src/mesh/parallel/shiftedmetric.cxx b/src/mesh/parallel/shiftedmetric.cxx index a204364d28..14b0af9d4b 100644 --- a/src/mesh/parallel/shiftedmetric.cxx +++ b/src/mesh/parallel/shiftedmetric.cxx @@ -121,12 +121,11 @@ void ShiftedMetric::cachePhases() { * Shift the field so that X-Z is not orthogonal, * and Y is then field aligned. */ -const Field3D ShiftedMetric::toFieldAligned(const Field3D& f, const std::string& region) { +Field3D ShiftedMetric::toFieldAligned(const Field3D& f, const std::string& region) { ASSERT2(f.getDirectionY() == YDirectionType::Standard); return shiftZ(f, toAlignedPhs, YDirectionType::Aligned, region); } -const FieldPerp ShiftedMetric::toFieldAligned(const FieldPerp& f, - const std::string& region) { +FieldPerp ShiftedMetric::toFieldAligned(const FieldPerp& f, const std::string& region) { ASSERT2(f.getDirectionY() == YDirectionType::Standard); // In principle, other regions are possible, but not yet implemented ASSERT2(region == "RGN_NOX"); @@ -137,22 +136,20 @@ const FieldPerp ShiftedMetric::toFieldAligned(const FieldPerp& f, * Shift back, so that X-Z is orthogonal, * but Y is not field aligned. */ -const Field3D ShiftedMetric::fromFieldAligned(const Field3D& f, - const std::string& region) { +Field3D ShiftedMetric::fromFieldAligned(const Field3D& f, const std::string& region) { ASSERT2(f.getDirectionY() == YDirectionType::Aligned); return shiftZ(f, fromAlignedPhs, YDirectionType::Standard, region); } -const FieldPerp ShiftedMetric::fromFieldAligned(const FieldPerp& f, - const std::string& region) { +FieldPerp ShiftedMetric::fromFieldAligned(const FieldPerp& f, const std::string& region) { ASSERT2(f.getDirectionY() == YDirectionType::Aligned); // In principle, other regions are possible, but not yet implemented ASSERT2(region == "RGN_NOX"); return shiftZ(f, fromAlignedPhs, YDirectionType::Standard, region); } -const Field3D ShiftedMetric::shiftZ(const Field3D& f, const Tensor& phs, - const YDirectionType y_direction_out, - const std::string& region) const { +Field3D ShiftedMetric::shiftZ(const Field3D& f, const Tensor& phs, + const YDirectionType y_direction_out, + const std::string& region) const { ASSERT1(f.getMesh() == &mesh); ASSERT1(f.getLocation() == location); @@ -171,9 +168,9 @@ const Field3D ShiftedMetric::shiftZ(const Field3D& f, const Tensor& ph return result; } -const FieldPerp ShiftedMetric::shiftZ(const FieldPerp& f, const Tensor& phs, - const YDirectionType y_direction_out, - const std::string& UNUSED(region)) const { +FieldPerp ShiftedMetric::shiftZ(const FieldPerp& f, const Tensor& phs, + const YDirectionType y_direction_out, + const std::string& UNUSED(region)) const { ASSERT1(f.getMesh() == &mesh); ASSERT1(f.getLocation() == location); @@ -284,8 +281,8 @@ ShiftedMetric::shiftZ(const Field3D& f, } // Old approach retained so we can still specify a general zShift -const Field3D ShiftedMetric::shiftZ(const Field3D& f, const Field2D& zangle, - const std::string& region) const { +Field3D ShiftedMetric::shiftZ(const Field3D& f, const Field2D& zangle, + const std::string& region) const { ASSERT1(&mesh == f.getMesh()); ASSERT1(f.getLocation() == zangle.getLocation()); if (mesh.LocalNz == 1) diff --git a/src/mesh/parallel/shiftedmetricinterp.cxx b/src/mesh/parallel/shiftedmetricinterp.cxx index 70c671c0a9..62140bc388 100644 --- a/src/mesh/parallel/shiftedmetricinterp.cxx +++ b/src/mesh/parallel/shiftedmetricinterp.cxx @@ -224,8 +224,7 @@ void ShiftedMetricInterp::calcParallelSlices(Field3D& f) { * Shift the field so that X-Z is not orthogonal, * and Y is then field aligned. */ -const Field3D ShiftedMetricInterp::toFieldAligned(const Field3D& f, - const std::string& region) { +Field3D ShiftedMetricInterp::toFieldAligned(const Field3D& f, const std::string& region) { ASSERT2(f.getDirectionY() == YDirectionType::Standard); return interp_to_aligned->interpolate(f, region).setDirectionY(YDirectionType::Aligned); } @@ -234,8 +233,8 @@ const Field3D ShiftedMetricInterp::toFieldAligned(const Field3D& f, * Shift back, so that X-Z is orthogonal, * but Y is not field aligned. */ -const Field3D ShiftedMetricInterp::fromFieldAligned(const Field3D& f, - const std::string& region) { +Field3D ShiftedMetricInterp::fromFieldAligned(const Field3D& f, + const std::string& region) { ASSERT2(f.getDirectionY() == YDirectionType::Aligned); return interp_from_aligned->interpolate(f, region).setDirectionY( YDirectionType::Standard); diff --git a/src/mesh/parallel/shiftedmetricinterp.hxx b/src/mesh/parallel/shiftedmetricinterp.hxx index c25939579e..9665b50302 100644 --- a/src/mesh/parallel/shiftedmetricinterp.hxx +++ b/src/mesh/parallel/shiftedmetricinterp.hxx @@ -57,10 +57,10 @@ public: * Note that the returned field will no longer be orthogonal in X-Z, and the * metric tensor will need to be changed if X derivatives are used. */ - const Field3D toFieldAligned(const Field3D& f, - const std::string& region = "RGN_ALL") override; - const FieldPerp toFieldAligned(const FieldPerp& UNUSED(f), - const std::string& UNUSED(region) = "RGN_ALL") override { + Field3D toFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") override; + FieldPerp toFieldAligned(const FieldPerp& UNUSED(f), + const std::string& UNUSED(region) = "RGN_ALL") override { throw BoutException("Not implemented yet"); } @@ -68,11 +68,10 @@ public: * Converts a field back to X-Z orthogonal coordinates * from field aligned coordinates. */ - const Field3D fromFieldAligned(const Field3D& f, - const std::string& region = "RGN_ALL") override; - const FieldPerp - fromFieldAligned(const FieldPerp& UNUSED(f), - const std::string& UNUSED(region) = "RGN_ALL") override { + Field3D fromFieldAligned(const Field3D& f, + const std::string& region = "RGN_ALL") override; + FieldPerp fromFieldAligned(const FieldPerp& UNUSED(f), + const std::string& UNUSED(region) = "RGN_ALL") override { throw BoutException("Not implemented yet"); } diff --git a/tests/unit/field/test_field_factory.cxx b/tests/unit/field/test_field_factory.cxx index 560a3f1177..7e064f1505 100644 --- a/tests/unit/field/test_field_factory.cxx +++ b/tests/unit/field/test_field_factory.cxx @@ -815,27 +815,27 @@ class MockParallelTransform : public ParallelTransform { void checkInputGrid() override {} - const Field3D fromFieldAligned(const Field3D& f, const std::string&) override { + Field3D fromFieldAligned(const Field3D& f, const std::string&) override { if (f.getDirectionY() != YDirectionType::Aligned) { throw BoutException("Unaligned field passed to fromFieldAligned"); } return -f; } - const FieldPerp fromFieldAligned(const FieldPerp& f, const std::string&) override { + FieldPerp fromFieldAligned(const FieldPerp& f, const std::string&) override { if (f.getDirectionY() != YDirectionType::Aligned) { throw BoutException("Unaligned field passed to fromFieldAligned"); } return -f; } - const Field3D toFieldAligned(const Field3D& f, const std::string&) override { + Field3D toFieldAligned(const Field3D& f, const std::string&) override { if (f.getDirectionY() != YDirectionType::Standard) { throw BoutException("Aligned field passed to toFieldAligned"); } return -f; } - const FieldPerp toFieldAligned(const FieldPerp& f, const std::string&) override { + FieldPerp toFieldAligned(const FieldPerp& f, const std::string&) override { if (f.getDirectionY() != YDirectionType::Standard) { throw BoutException("Aligned field passed to toFieldAligned"); } From 9eae08e2c28c09855a370fbc4ec74f5959610418 Mon Sep 17 00:00:00 2001 From: BS Date: Fri, 26 Mar 2021 11:48:49 +0100 Subject: [PATCH 286/293] Set all boundary cells in petsc-laplacexz. * Previously, only the inner-most boundary point was set, which could cause problems with interpolation --- src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx index 24b62fe5d9..b360a55edd 100644 --- a/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx +++ b/src/invert/laplacexz/impls/petsc/laplacexz-petsc.cxx @@ -959,7 +959,9 @@ Field3D LaplaceXZpetsc::solve(const Field3D &bin, const Field3D &x0in) { for(int z=0; z < localmesh->LocalNz; z++) { PetscScalar val; VecGetValues(xs, 1, &ind, &val ); - result(localmesh->xstart-1,y,z) = val; + for(int x=0; xxstart; ++x){ + result(x,y,z) = val; + } ind++; } } @@ -978,7 +980,9 @@ Field3D LaplaceXZpetsc::solve(const Field3D &bin, const Field3D &x0in) { for(int z=0; z < localmesh->LocalNz; z++) { PetscScalar val; VecGetValues(xs, 1, &ind, &val ); - result(localmesh->xend+1,y,z) = val; + for(int x=localmesh->xend+1; xLocalNx; ++x){ + result(x,y,z) = val; + } ind++; } } From a351b17b852f927b67097d117e0ed6cecb5fb67f Mon Sep 17 00:00:00 2001 From: BS Date: Wed, 12 May 2021 10:21:36 +0200 Subject: [PATCH 287/293] Use Bxy.ydown() for div_a_laplace_perp --- src/mesh/fv_ops.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mesh/fv_ops.cxx b/src/mesh/fv_ops.cxx index 118b8139db..1640c1bf0b 100644 --- a/src/mesh/fv_ops.cxx +++ b/src/mesh/fv_ops.cxx @@ -166,6 +166,11 @@ namespace FV { yzresult(i, j, k) = fout / (dyc(i, j, k) * Jc(i, j, k)); // Calculate flux between j and j-1 + coef = + 0.5 + * (g_23c(i, j, k) / SQ(Jc(i, j, k) * Bxyc(i, j, k)) + + g_23down(i, j - 1, k) / SQ(Jdown(i, j - 1, k) * Bxydown(i, j - 1, k))); + dfdz = 0.5 * (fc(i, j, kp) - fc(i, j, km) + fdown(i, j - 1, kp) - fdown(i, j - 1, km)) From af698ef0dbde4bd5783010f60f1a6a1e3fafabf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Fri, 7 May 2021 16:47:30 +0200 Subject: [PATCH 288/293] Ensure boundaries are valid After communication we might have invalid points, this is fixed by applying boundaries. --- src/mesh/coordinates.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mesh/coordinates.cxx b/src/mesh/coordinates.cxx index d910815c00..4e067ddebf 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1626,6 +1626,7 @@ Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& m if (! f.hasParallelSlices() and ! transform->canToFromFieldAligned()) { Field3D f_parallel = f; transform->calcParallelSlices(f_parallel); + f_parallel.applyParallelBoundary("parallel_neumann"); return bout::derivatives::index::DDY(f_parallel, outloc, method, region); } #endif From 7701426c915af0fc0ba3bb8bed5dbf5566714ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 19 May 2021 16:01:32 +0200 Subject: [PATCH 289/293] fix bad merge --- src/mesh/boundary_standard.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mesh/boundary_standard.cxx b/src/mesh/boundary_standard.cxx index e2fe69145d..ad95a4ab6a 100644 --- a/src/mesh/boundary_standard.cxx +++ b/src/mesh/boundary_standard.cxx @@ -2658,10 +2658,11 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { #endif } - void BoundaryDivCurl::apply(Vector3D& var) { + void BoundaryZeroLaplace2::apply(Field3D & f) { #if not(BOUT_USE_METRIC_3D) - Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == var.getMesh()); + Mesh* mesh = bndry->localmesh; + ASSERT1(mesh == f.getMesh()); + const int ncz = mesh->LocalNz; ASSERT0(ncz % 2 == 0); // Allocation assumes even number @@ -2849,7 +2850,7 @@ void BoundaryNeumann_NonOrthogonal::apply(Field3D& f) { void BoundaryDivCurl::apply(Vector3D & var) { #if not(BOUT_USE_METRIC_3D) Mesh* mesh = bndry->localmesh; - ASSERT1(mesh == var.x.getMesh()); + ASSERT1(mesh == var.getMesh()); int jx, jy, jz, jzp, jzm; BoutReal tmp; From b5712fbd9d8c78c026591db8a6795c5669749e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Thu, 3 Jun 2021 17:04:11 +0200 Subject: [PATCH 290/293] Fix pcr for dz being a Field2D --- src/invert/laplace/impls/pcr/pcr.cxx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/invert/laplace/impls/pcr/pcr.cxx b/src/invert/laplace/impls/pcr/pcr.cxx index 508bc57041..373abb730c 100644 --- a/src/invert/laplace/impls/pcr/pcr.cxx +++ b/src/invert/laplace/impls/pcr/pcr.cxx @@ -158,6 +158,7 @@ FieldPerp LaplacePCR::solve(const FieldPerp& rhs, const FieldPerp& x0) { } if (dst) { + const BoutReal zlen = getUniform(coords->dz) * (localmesh->LocalNz - 3); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = Array( @@ -189,7 +190,6 @@ FieldPerp LaplacePCR::solve(const FieldPerp& rhs, const FieldPerp& x0) { // including boundary conditions BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { - BoutReal zlen = coords->dz * (localmesh->LocalNz - 3); BoutReal kwave = kz * 2.0 * PI / (2. * zlen); // wave number is 1/[rad]; DST has extra 2. @@ -200,7 +200,7 @@ FieldPerp LaplacePCR::solve(const FieldPerp& rhs, const FieldPerp& x0) { &C1coef, &C2coef, &Dcoef, false); // Don't include guard cells in arrays } - } + } // BOUT_OMP(parallel) // Solve tridiagonal systems cr_pcr_solver(a, b, c, bcmplx, xcmplx); @@ -228,6 +228,7 @@ FieldPerp LaplacePCR::solve(const FieldPerp& rhs, const FieldPerp& x0) { } } } else { + const BoutReal zlength = getUniform(coords->zlength()); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = Array((localmesh->LocalNz) / 2 @@ -259,7 +260,7 @@ FieldPerp LaplacePCR::solve(const FieldPerp& rhs, const FieldPerp& x0) { // including boundary conditions BOUT_OMP(for nowait) for (int kz = 0; kz < nmode; kz++) { - BoutReal kwave = kz * 2.0 * PI / (coords->zlength()); // wave number is 1/[rad] + BoutReal kwave = kz * 2.0 * PI / zlength; // wave number is 1/[rad] tridagMatrix(&a(kz, 0), &b(kz, 0), &c(kz, 0), &bcmplx(kz, 0), jy, kz, // True for the component constant (DC) in Z kwave, // Z wave number @@ -267,7 +268,7 @@ FieldPerp LaplacePCR::solve(const FieldPerp& rhs, const FieldPerp& x0) { &C1coef, &C2coef, &Dcoef, false); // Don't include guard cells in arrays } - } + } // BOUT_OMP(parallel) // Solve tridiagonal systems cr_pcr_solver(a, b, c, bcmplx, xcmplx); @@ -363,6 +364,7 @@ Field3D LaplacePCR::solve(const Field3D& rhs, const Field3D& x0) { auto bcmplx3D = Matrix(nsys, nx); if (dst) { + const BoutReal zlen = getUniform(coords->dz) * (localmesh->LocalNz - 3); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = Array( @@ -402,7 +404,6 @@ Field3D LaplacePCR::solve(const Field3D& rhs, const Field3D& x0) { int iy = ys + ind / nmode; int kz = ind % nmode; - BoutReal zlen = coords->dz * (localmesh->LocalNz - 3); BoutReal kwave = kz * 2.0 * PI / (2. * zlen); // wave number is 1/[rad]; DST has extra 2. @@ -413,7 +414,7 @@ Field3D LaplacePCR::solve(const Field3D& rhs, const Field3D& x0) { &C1coef, &C2coef, &Dcoef, false); // Don't include guard cells in arrays } - } + } // BOUT_OMP(parallel) // Solve tridiagonal systems cr_pcr_solver(a3D, b3D, c3D, bcmplx3D, xcmplx3D); @@ -445,6 +446,7 @@ Field3D LaplacePCR::solve(const Field3D& rhs, const Field3D& x0) { } } } else { + const BoutReal zlength = getUniform(coords->zlength()); BOUT_OMP(parallel) { /// Create a local thread-scope working array auto k1d = Array(localmesh->LocalNz / 2 @@ -485,7 +487,7 @@ Field3D LaplacePCR::solve(const Field3D& rhs, const Field3D& x0) { int iy = ys + ind / nmode; int kz = ind % nmode; - BoutReal kwave = kz * 2.0 * PI / (coords->zlength()); // wave number is 1/[rad] + BoutReal kwave = kz * 2.0 * PI / zlength; // wave number is 1/[rad] tridagMatrix(&a3D(ind, 0), &b3D(ind, 0), &c3D(ind, 0), &bcmplx3D(ind, 0), iy, kz, // True for the component constant (DC) in Z kwave, // Z wave number @@ -493,7 +495,7 @@ Field3D LaplacePCR::solve(const Field3D& rhs, const Field3D& x0) { &C1coef, &C2coef, &Dcoef, false); // Don't include guard cells in arrays } - } + } // BOUT_OMP(parallel) // Solve tridiagonal systems cr_pcr_solver(a3D, b3D, c3D, bcmplx3D, xcmplx3D); From d54512ff4ec17dbf8f7f55561cc1222d2fcd618f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Tue, 29 Jun 2021 14:15:12 +0200 Subject: [PATCH 291/293] Don't specify boundary condition --- 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 4e067ddebf..10a0073a4b 100644 --- a/src/mesh/coordinates.cxx +++ b/src/mesh/coordinates.cxx @@ -1626,7 +1626,7 @@ Field3D Coordinates::DDY(const Field3D& f, CELL_LOC outloc, const std::string& m if (! f.hasParallelSlices() and ! transform->canToFromFieldAligned()) { Field3D f_parallel = f; transform->calcParallelSlices(f_parallel); - f_parallel.applyParallelBoundary("parallel_neumann"); + f_parallel.applyParallelBoundary(); return bout::derivatives::index::DDY(f_parallel, outloc, method, region); } #endif From 867e303d15bddd48901d07e7230797143bc15712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Schw=C3=B6rer?= Date: Wed, 30 Jun 2021 10:50:02 +0200 Subject: [PATCH 292/293] Temporarily disable python interface with 3D in CI --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1a8fa75702..d1dcfbb6ab 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -87,6 +87,7 @@ jobs: -DBOUT_USE_SLEPC=ON -DBOUT_USE_HDF5=ON -DBOUT_USE_SUNDIALS=ON + -DBOUT_ENABLE_PYTHON=OFF -DSUNDIALS_ROOT=/home/runner/local" omp_num_threads: 2 From 1ba36af45a50a16bbdaf2ac18ccd2373225bb866 Mon Sep 17 00:00:00 2001 From: Peter Hill Date: Tue, 16 Feb 2021 11:51:18 +0000 Subject: [PATCH 293/293] CMake: Add CMakeLists.txt for test-laplacexz --- tests/integrated/CMakeLists.txt | 1 + tests/integrated/test-laplacexz/CMakeLists.txt | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 tests/integrated/test-laplacexz/CMakeLists.txt diff --git a/tests/integrated/CMakeLists.txt b/tests/integrated/CMakeLists.txt index bac6fb0507..aa3f2b2c3e 100644 --- a/tests/integrated/CMakeLists.txt +++ b/tests/integrated/CMakeLists.txt @@ -23,6 +23,7 @@ add_subdirectory(test-laplace) add_subdirectory(test-laplace-petsc3d) add_subdirectory(test-laplacexy-fv) add_subdirectory(test-laplacexy-short) +add_subdirectory(test-laplacexz) add_subdirectory(test-multigrid_laplace) add_subdirectory(test-naulin-laplace) add_subdirectory(test-options-netcdf) diff --git a/tests/integrated/test-laplacexz/CMakeLists.txt b/tests/integrated/test-laplacexz/CMakeLists.txt new file mode 100644 index 0000000000..b19aa986ad --- /dev/null +++ b/tests/integrated/test-laplacexz/CMakeLists.txt @@ -0,0 +1,7 @@ +bout_add_integrated_test(test-laplacexz + SOURCES test-laplacexz.cxx + REQUIRES BOUT_HAS_PETSC + CONFLICTS BOUT_USE_METRIC_3D + USE_RUNTEST + USE_DATA_BOUT_INP + )