From 71f0e9f9cebee928a1a1c5a1f63ccc3dd1bc11a8 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 2 May 2019 16:13:33 -0700 Subject: [PATCH 01/62] Unify original DSL interface with published compiler APIs. Closes #110. --- include/Soln.hpp | 351 ++++++++++++++++ include/yask_common_api.hpp | 4 +- include/yask_compiler_api.hpp | 27 +- include/yask_kernel_api.hpp | 5 +- include/yc_node_api.hpp | 216 ++++++---- include/yk_grid_api.hpp | 5 +- include/yk_solution_api.hpp | 5 +- src/common/common_utils.cpp | 2 +- src/common/yask_assert.hpp | 2 +- src/compiler/Makefile | 4 +- src/compiler/{main.cpp => compiler_main.cpp} | 78 +++- src/compiler/lib/Cpp.cpp | 6 +- src/compiler/lib/Eqs.cpp | 12 +- src/compiler/lib/Expr.cpp | 378 +++++++----------- src/compiler/lib/Expr.hpp | 177 +------- src/compiler/lib/Grid.cpp | 78 ++-- src/compiler/lib/Grid.hpp | 105 +---- src/compiler/lib/Print.hpp | 2 +- src/compiler/lib/Settings.cpp | 4 +- src/compiler/lib/{Soln.cpp => Solution.cpp} | 9 +- src/compiler/lib/{Soln.hpp => Solution.hpp} | 126 +----- src/compiler/lib/YaskKernel.cpp | 10 +- src/kernel/lib/context.hpp | 2 +- src/kernel/yask_main.cpp | 6 +- .../ElasticStencil/Elastic2Stencil.hpp | 27 +- .../ElasticStencil/ElasticStencil.hpp | 27 +- src/stencils/TTIStencil.cpp | 7 +- 27 files changed, 824 insertions(+), 851 deletions(-) create mode 100644 include/Soln.hpp rename src/compiler/{main.cpp => compiler_main.cpp} (88%) rename src/compiler/lib/{Soln.cpp => Solution.cpp} (96%) rename src/compiler/lib/{Soln.hpp => Solution.hpp} (68%) diff --git a/include/Soln.hpp b/include/Soln.hpp new file mode 100644 index 00000000..59eada7c --- /dev/null +++ b/include/Soln.hpp @@ -0,0 +1,351 @@ +/***************************************************************************** + +YASK: Yet Another Stencil Kernel +Copyright (c) 2014-2019, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*****************************************************************************/ + +// This file contains convenience functions and macros for defining +// stencils to be included in the YASK compiler binary utility. + +#pragma once + +// Standard headers not provided by API. +#include + +// These functions and macros are built upon the YASK compiler APIs. +#include "yask_compiler_api.hpp" + +namespace yask { + + // Forward defn. + class StencilBase; + + // Function provided by the YASK compiler binary utility + // to create a new solution and register 'base_ptr' + // as a known StencilBase object. + yc_solution_ptr yc_new_solution(const std::string& name, + StencilBase* base_ptr); + + // Dummy type and object for backward-compatibility. + class StencilList { }; + extern StencilList stub_stencils; + + // The class all C++ stencil solutions written for the YASK compiler + // binary must implement. Mostly, this is a wrapper around a + // 'yc_solution_ptr'. The 'define()' method must be overloaded by + // the YASK DSL programmer to add stencil equations. + class StencilBase { + protected: + + // Pointer to the YASK stencil solution. + yc_solution_ptr _soln; + + // Factory to create new nodes. + yc_node_factory _node_factory; + + public: + + // Constructor. Creates a new yc_solution object and + // registers this object in the list for the YASK compiler. + // The 'define()' method will be called from the YASK + // compiler for the selected solution. + StencilBase(const std::string name) { + _soln = yc_new_solution(name, this); + } + + // Constructor that uses an existing StencilBase to share underlying + // solutions. When using this version, the 'define()' method will + // not be called directly from the YASK compiler, but it (or any + // other method) may be called by the parent 'base' object + // explicitly. + StencilBase(StencilBase& base) { + _soln = base.get_solution(); + } + + // Backward-compatibility contructor. Deprecated. + StencilBase(const std::string name, StencilList& stencils) : + StencilBase(name) { } + + // Destructor. + virtual ~StencilBase() { } + + // Define grid values relative to current domain indices in each dimension. + // This must be implemented by each concrete stencil solution. + virtual void define() { + std::cout << "Warning: no stencil equations are defined in solution '" << + _soln->get_name() << "'\n"; + } + + // Accessors. + virtual yc_solution_ptr get_solution() { + return _soln; + } + virtual yc_node_factory& get_node_factory() { + return _node_factory; + } + + // Create a constant expression. + // Usually not needed due to operator overloading. + virtual yc_number_node_ptr constNum(double val) { + return _node_factory.new_const_number_node(val); + } + + // Create boundary indices, e.g., 'first_index(x)'. + virtual yc_number_node_ptr first_index(yc_index_node_ptr dim) { + return _node_factory.new_first_domain_index(dim); + } + virtual yc_number_node_ptr last_index(yc_index_node_ptr dim) { + return _node_factory.new_last_domain_index(dim); + } + + // Radius-access methods. The default implementations indicate that + // the solution does not use the "radius" sizing feature. + virtual bool uses_radius() const { return false; } + virtual bool set_radius(int radius) { return false; } + virtual int get_radius() const { return 0; } + }; + + // A base class for stencils that have a 'radius'. + class StencilRadiusBase : public StencilBase { + protected: + + // A variable that controls the size the stencil, i.e., the number of + // points that are read to calculate a new value. In many cases, + // this is the number of points in the spatial dimension(s) from the + // center point of a finite-difference approximation, but it does + // not have to be. For example, it could be the minimum or maximum + // radius for an asymmetical stencil. + int _radius; + + public: + // Constructor. + StencilRadiusBase(const std::string name, int radius) : + StencilBase(name) { + set_radius(radius); + } + + // Backward-compatibility constructor. + StencilRadiusBase(const std::string name, StencilList& stencils, int radius) : + StencilRadiusBase(name, radius) { + } + + // This object does use radius. + virtual bool uses_radius() const override { return true; } + + // Set radius. + // Return true if successful. + virtual bool set_radius(int radius) override { + _radius = radius; + _soln->set_description(_soln->get_name() + " radius " + std::to_string(radius)); + return radius >= 0; // support only non-neg. radius. + } + + // Get radius. + virtual int get_radius() const override { return _radius; } + }; + + // A simple wrapper to provide automatic construction + // of a NumExpr ptr from other types. + class NumExprArg : public yc_number_node_ptr { + + // Factory to create new nodes. + yc_node_factory _node_factory; + + // Create a constant expression. + virtual yc_number_node_ptr constNum(double val) { + return _node_factory.new_const_number_node(val); + } + + public: + NumExprArg(yc_number_node_ptr p) : + yc_number_node_ptr(p) { } + NumExprArg(yc_index_node_ptr p) : + yc_number_node_ptr(p) { } + NumExprArg(idx_t i) : + yc_number_node_ptr(constNum(i)) { } + NumExprArg(int i) : + yc_number_node_ptr(constNum(i)) { } + NumExprArg(double f) : + yc_number_node_ptr(constNum(f)) { } + }; + + // A wrapper class around a 'yc_grid_ptr', providing + // convenience functions for declaring grid vars and + // creating expression nodes with references to points + // in grid vars. + class Grid { + protected: + yc_grid_ptr _grid; + typedef std::vector num_node_vec; + + public: + + // Contructor taking a vector of index vars. + Grid(const std::string& name, + bool is_scratch, + yc_solution_ptr soln, + const std::vector< yc_index_node_ptr > &dims) { + if (is_scratch) + _grid = soln->new_scratch_grid(name, dims); + else + _grid = soln->new_grid(name, dims); + } + + // Contructor taking an initializer_list of index vars. + Grid(const std::string& name, + bool is_scratch, + yc_solution_ptr soln, + const std::initializer_list< yc_index_node_ptr > &dims) { + if (is_scratch) + _grid = soln->new_scratch_grid(name, dims); + else + _grid = soln->new_grid(name, dims); + } + + // Convenience wrapper functions around 'new_grid_point()'. + // These allow a simplified syntax for creating grid point + // nodes. Example usage for defining equation for grid 'A': + // 0D grid var 'B': A(t+1, x) EQUALS A(t, x) + B. + // 0D grid var 'B': A(t+1, x) EQUALS A(t, x) + B(). + // 1D grid var 'B': A(t+1, x) EQUALS A(t, x) + B(x). + // 1D grid var 'B': A(t+1, x) EQUALS A(t, x) + B[x]. + // 2D grid var 'B': A(t+1, x) EQUALS A(t, x) + B(x, 4). + + // Convenience functions for zero dimensions (scalar). + virtual operator yc_number_node_ptr() { // implicit conversion. + return _grid->new_grid_point({}); + } + virtual operator yc_grid_point_node_ptr() { // implicit conversion. + return _grid->new_grid_point({}); + } + virtual yc_grid_point_node_ptr operator()() { + return _grid->new_grid_point({}); + } + + // Convenience functions for one dimension (array). + virtual yc_grid_point_node_ptr operator[](const NumExprArg i1) { + num_node_vec args; + args.push_back(i1); + return _grid->new_grid_point(args); + } + virtual yc_grid_point_node_ptr operator()(const NumExprArg i1) { + return operator[](i1); + } + + // Convenience functions for more dimensions. + virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, + const NumExprArg i2) { + num_node_vec args; + args.push_back(i1); + args.push_back(i2); + return _grid->new_grid_point(args); + } + virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, + const NumExprArg i2, + const NumExprArg i3) { + num_node_vec args; + args.push_back(i1); + args.push_back(i2); + args.push_back(i3); + return _grid->new_grid_point(args); + } + virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, + const NumExprArg i2, + const NumExprArg i3, + const NumExprArg i4) { + num_node_vec args; + args.push_back(i1); + args.push_back(i2); + args.push_back(i3); + args.push_back(i4); + return _grid->new_grid_point(args); + } + virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, + const NumExprArg i2, + const NumExprArg i3, + const NumExprArg i4, + const NumExprArg i5) { + num_node_vec args; + args.push_back(i1); + args.push_back(i2); + args.push_back(i3); + args.push_back(i4); + args.push_back(i5); + return _grid->new_grid_point(args); + } + virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, + const NumExprArg i2, + const NumExprArg i3, + const NumExprArg i4, + const NumExprArg i5, + const NumExprArg i6) { + num_node_vec args; + args.push_back(i1); + args.push_back(i2); + args.push_back(i3); + args.push_back(i4); + args.push_back(i5); + args.push_back(i6); + return _grid->new_grid_point(args); + } + + }; + + // Aliases for expression types. + typedef yc_number_node_ptr GridIndex; + typedef yc_number_node_ptr GridValue; + typedef yc_bool_node_ptr Condition; + typedef yc_grid_point_node_ptr GridPointPtr; + +} // namespace yask. + +// Macro for backward compatibility. +#define REGISTER_STENCIL_CONTEXT_EXTENSION(...) + +// Convenience macro for declaring an instance of a stencil and registering +// it in the list used by the default provided YASK compiler binary. +#define REGISTER_STENCIL(class_name) static class_name registered_ ## class_name(stub_stencils) + +// Convenience macros for declaring dims in a class implementing get_node_factory(). +// The 'd' arg is the new var name and the dim name. +#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = get_node_factory().new_step_index(#d); +#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = get_node_factory().new_domain_index(#d); +#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = get_node_factory().new_misc_index(#d); + +// Convenience macros for creating grids in a class implementing get_solution(). +// The 'gvar' arg is the var name and the grid name. +// The remaining args are the dimension names. +#define MAKE_GRID(gvar, ...) \ + Grid gvar = Grid(#gvar, false, get_solution(), { __VA_ARGS__ }) +#define MAKE_SCALAR(gvar) MAKE_GRID(gvar) +#define MAKE_ARRAY(gvar, d1) MAKE_GRID(gvar, d1) +#define MAKE_SCRATCH_GRID(gvar, ...) \ + Grid gvar = Grid(#gvar, true, get_solution(), { __VA_ARGS__ }) +#define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) +#define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) + +// Namespaces for stencil code. +#ifndef NO_NAMESPACES +using namespace yask; +using namespace std; +#endif + diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index fdcb662a..fad1453c 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -29,8 +29,7 @@ IN THE SOFTWARE. // See http://www.stack.nl/~dimitri/doxygen. /** @file yask_common_api.hpp */ -#ifndef YASK_COMMON_API -#define YASK_COMMON_API +#pragma once #include #include @@ -258,4 +257,3 @@ namespace yask { } // namespace yask. -#endif diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index e1a58f10..6bf45b9d 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -29,8 +29,7 @@ IN THE SOFTWARE. // See http://www.stack.nl/~dimitri/doxygen. /** @file yask_compiler_api.hpp */ -#ifndef YASK_COMPILER_API -#define YASK_COMPILER_API +#pragma once #include "yask_common_api.hpp" #include @@ -131,9 +130,10 @@ namespace yask { /// Get the name of the solution. /** - @returns String containing the solution name provided via new_solution(). + @returns String containing the solution name provided via new_solution() + or set_name(). */ - virtual const std::string& + virtual std::string get_name() const =0; /// Set the name of the solution. @@ -144,6 +144,24 @@ namespace yask { set_name(std::string name /**< [in] Name; must be a valid C++ identifier. */ ) =0; + /// Get the description of the solution. + /** + See set_description(). + @returns String containing the solution description. + */ + virtual std::string + get_description() const =0; + + /// Set the description of the solution. + /** + By default, the solution description is the same as that + provided via new_solution() or set_name(). + This allows setting the description to any string. + */ + virtual void + set_description(std::string description + /**< [in] Any descriptive phrase. */ ) =0; + /// Get current floating-point precision setting. /** @returns Number of bytes in a FP number. */ virtual int @@ -608,4 +626,3 @@ namespace yask { } // namespace yask. -#endif diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 646ed661..a8c3b604 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -29,8 +29,7 @@ IN THE SOFTWARE. // See http://www.stack.nl/~dimitri/doxygen. /** @file yask_kernel_api.hpp */ -#ifndef YASK_KERNEL_API -#define YASK_KERNEL_API +#pragma once #include "yask_common_api.hpp" #include @@ -189,5 +188,3 @@ namespace yask { /** @}*/ } // namespace yask. - -#endif diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index 1897054e..08f09d7c 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -29,8 +29,7 @@ IN THE SOFTWARE. // See http://www.stack.nl/~dimitri/doxygen. /** @file yc_node_api.hpp */ -#ifndef YC_NODES -#define YC_NODES +#pragma once namespace yask { @@ -208,9 +207,10 @@ namespace yask { /// Create a constant numerical value node. /** - This is unary negation. - Use new_subtraction_node() for binary `-`. - @returns Pointer to new \ref yc_const_number_node object. + Use to add a constant to an expression. + The overloaded arithmetic operators allow `double` arguments, + so in most cases, it is not necessary to call this directly. + @returns Pointer to new \ref yc_const_number_node object. */ virtual yc_number_node_ptr new_const_number_node(double val /**< [in] Value to store in node. */ ); @@ -218,6 +218,8 @@ namespace yask { /// Create a constant numerical value node. /** Integer version of new_const_number_node(double). + It may be necessary to cast other integer types to `idx_t` to + avoid ambiguous overloading of this function. @returns Pointer to new \ref yc_const_number_node object. */ virtual yc_number_node_ptr @@ -233,11 +235,9 @@ namespace yask { /// Create an addition node. /** - Nodes must be created with at least two operands, and more can - be added by calling add_operand() on the returned node. - - New addition nodes can also be created via the overloaded `+` operator. - @returns Pointer to new \ref yc_add_node object. + New addition nodes can also be created via the overloaded `+` operator. + @returns Pointer to new \ref yc_add_node object. + Returns `rhs` if `lhs` is a null node pointer and vice-versa. */ virtual yc_number_node_ptr new_add_node(yc_number_node_ptr lhs /**< [in] Expression before `+` sign. */, @@ -245,11 +245,9 @@ namespace yask { /// Create a multiplication node. /** - Nodes must be created with at least two operands, and more can - be added by calling add_operand() on the returned node. - - New multiplication nodes can also be created via the overloaded `*` operator. + New multiplication nodes can also be created via the overloaded `*` operator. @returns Pointer to new \ref yc_multiply_node object. + Returns `rhs` if `lhs` is a null node pointer and vice-versa. */ virtual yc_number_node_ptr new_multiply_node(yc_number_node_ptr lhs /**< [in] Expression before `*` sign. */, @@ -260,8 +258,10 @@ namespace yask { This is binary subtraction. Use new_negation_node() for unary `-`. - New subtraction nodes can also be created via the overloaded `-` operator. + New subtraction nodes can also be created via the overloaded `-` operator. @returns Pointer to new \ref yc_subtract_node object. + Returns `- rhs` if `lhs` is a null node pointer and + `lhs` if `rhs` is null. */ virtual yc_number_node_ptr new_subtract_node(yc_number_node_ptr lhs /**< [in] Expression before `-` sign. */, @@ -269,8 +269,10 @@ namespace yask { /// Create a division node. /** - New division nodes can also be created via the overloaded `/` operator. + New division nodes can also be created via the overloaded `/` operator. @returns Pointer to new \ref yc_divide_node object. + Returns `1.0 / rhs` if `lhs` is a null node pointer and + `lhs` if `rhs` is null. */ virtual yc_number_node_ptr new_divide_node(yc_number_node_ptr lhs /**< [in] Expression before `/` sign. */, @@ -278,9 +280,9 @@ namespace yask { /// Create a modulo node. /** - New modulo nodes can also be created via the overloaded `%` operator. - The modulo operator converts both operands to integers before performing - the operation. + New modulo nodes can also be created via the overloaded `%` operator. + The modulo operator converts both operands to integers before performing + the operation. @returns Pointer to new \ref yc_mod_node object. */ virtual yc_number_node_ptr @@ -760,7 +762,7 @@ namespace yask { // Also, these are not defined for SWIG because // the Python operators are defined in the ".i" file. -#if !defined USE_INTERNAL_DSL && !defined SWIG +#if !defined SWIG /// Operator version of yc_node_factory::new_negation_node(). yc_number_node_ptr operator-(yc_number_node_ptr rhs); @@ -800,75 +802,141 @@ namespace yask { yc_number_node_ptr operator-(yc_number_node_ptr lhs, double rhs); ///@} - /// Operator version of yc_node_factory::new_not_node(). - /** For Python, use `rhs.yc_not()` */ - yc_bool_node_ptr operator!(yc_bool_node_ptr rhs); - - /// Operator version of yc_node_factory::new_or_node(). - /** For Python, use `lhs.yc_or(rhs)` */ - yc_bool_node_ptr operator||(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs); - - /// Operator version of yc_node_factory::new_and_node(). - /** For Python, use `lhs.yc_and(rhs)` */ - yc_bool_node_ptr operator&&(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs); - - // Note that the following operators provide explicit - // 'yc_index_node_ptr' versions to avoid the compiler using built-in - // pointer comparisons, which would result in bools rather than YASK - // nodes in expressions like 'x >= fac.new_first_domain_index(x) + 5'. - ///@{ - /// Operator version of yc_node_factory::new_equals_node(). - yc_bool_node_ptr operator==(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator==(yc_index_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator==(yc_number_node_ptr lhs, yc_index_node_ptr rhs); - yc_bool_node_ptr operator==(yc_index_node_ptr lhs, yc_index_node_ptr rhs); + /// Shortcut for creating expression A = A + B. + void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + void operator+=(yc_number_node_ptr& lhs, double rhs); ///@} ///@{ - /// Operator version of yc_node_factory::new_greater_than_node(). - yc_bool_node_ptr operator>(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator>(yc_index_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator>(yc_number_node_ptr lhs, yc_index_node_ptr rhs); - yc_bool_node_ptr operator>(yc_index_node_ptr lhs, yc_index_node_ptr rhs); + /// Shortcut for creating expression A = A - B. + void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + void operator-=(yc_number_node_ptr& lhs, double rhs); ///@} ///@{ - /// Operator version of yc_node_factory::new_less_than_node(). - yc_bool_node_ptr operator<(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator<(yc_index_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator<(yc_number_node_ptr lhs, yc_index_node_ptr rhs); - yc_bool_node_ptr operator<(yc_index_node_ptr lhs, yc_index_node_ptr rhs); + /// Shortcut for creating expression A = A * B. + void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + void operator*=(yc_number_node_ptr& lhs, double rhs); ///@} ///@{ - /// Operator version of yc_node_factory::new_not_equals_node(). - yc_bool_node_ptr operator!=(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator!=(yc_index_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator!=(yc_number_node_ptr lhs, yc_index_node_ptr rhs); - yc_bool_node_ptr operator!=(yc_index_node_ptr lhs, yc_index_node_ptr rhs); + /// Shortcut for creating expression A = A / B. + void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + void operator/=(yc_number_node_ptr& lhs, double rhs); ///@} - ///@{ - /// Operator version of yc_node_factory::new_not_greater_than_node(). - yc_bool_node_ptr operator<=(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator<=(yc_index_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator<=(yc_number_node_ptr lhs, yc_index_node_ptr rhs); - yc_bool_node_ptr operator<=(yc_index_node_ptr lhs, yc_index_node_ptr rhs); - ///@} + /// Operator version of yc_node_factory::new_not_node(). + /** For Python, use `rhs.yc_not()` */ + yc_bool_node_ptr operator!(yc_bool_node_ptr rhs); - ///@{ - /// Operator version of yc_node_factory::new_not_less_than_node(). - yc_bool_node_ptr operator>=(const yc_number_node_ptr lhs, const yc_number_node_ptr rhs); - yc_bool_node_ptr operator>=(yc_index_node_ptr lhs, yc_number_node_ptr rhs); - yc_bool_node_ptr operator>=(yc_number_node_ptr lhs, yc_index_node_ptr rhs); - yc_bool_node_ptr operator>=(yc_index_node_ptr lhs, yc_index_node_ptr rhs); - ///@} + /// Operator version of yc_node_factory::new_or_node(). + /** For Python, use `lhs.yc_or(rhs)` */ + yc_bool_node_ptr operator||(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs); + + /// Operator version of yc_node_factory::new_and_node(). + /** For Python, use `lhs.yc_and(rhs)` */ + yc_bool_node_ptr operator&&(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs); + + /// Binary numerical-to-boolean operators. + /** + Must provide more explicit ptr-type operands than used with math + operators to keep compiler from using built-in pointer comparison. + Const values must be on RHS of operator, e.g., 'x > 5' is ok, but + '5 < x' is not. + */ +#define BOOL_OPER(oper, fn) \ + inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, const yc_number_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, const yc_index_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_number_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_index_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_number_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_index_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ + inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, double rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, nfac.new_const_number_node(rhs)); } \ + inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, double rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, nfac.new_const_number_node(rhs)); } \ + inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, double rhs) { \ + yc_node_factory nfac; return nfac.fn(lhs, nfac.new_const_number_node(rhs)); } + + BOOL_OPER(==, new_equals_node) + BOOL_OPER(!=, new_not_equals_node) + BOOL_OPER(<, new_less_than_node) + BOOL_OPER(>, new_greater_than_node) + BOOL_OPER(<=, new_not_greater_than_node) + BOOL_OPER(>=, new_not_less_than_node) +#undef BOOL_OPER + + /// Unary math functions. +#define FUNC_EXPR(fn_name) yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) + FUNC_EXPR(sqrt); + FUNC_EXPR(cbrt); + FUNC_EXPR(fabs); + FUNC_EXPR(erf); + FUNC_EXPR(exp); + FUNC_EXPR(log); + FUNC_EXPR(sin); + FUNC_EXPR(cos); + FUNC_EXPR(atan); +#undef FUNC_EXPR + + /// Binary math functions. +#define FUNC_EXPR(fn_name) \ + yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ + yc_number_node_ptr fn_name(double arg1, const yc_number_node_ptr arg2); \ + yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, double arg2) + FUNC_EXPR(pow); +#undef FUNC_EXPR + +#define EQUALS_OPER << +#define EQUALS EQUALS_OPER +#define IS_EQUIV_TO EQUALS_OPER +#define IS_EQUIVALENT_TO EQUALS_OPER + /// The operator used for defining a grid value. + /** + Use an otherwise unneeded binary operator that has a lower priority + than the math ops and a higher priority than the IF_OPER. + See http://en.cppreference.com/w/cpp/language/operator_precedence. + This should not be an operator that is defined for shared pointers. + See https://en.cppreference.com/w/cpp/memory/shared_ptr. + */ + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_number_node_ptr rhs); + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_grid_point_node_ptr rhs); + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, double rhs); + +#define IF_OPER ^= +#define IF IF_OPER + /// A operator to add a domain condition. + /** + Use an otherwise unneeded binary operator that has a low priority. + See http://en.cppreference.com/w/cpp/language/operator_precedence. + */ + yc_equation_node_ptr operator IF_OPER(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond); +#define IF_STEP_OPER |= +#define IF_STEP IF_STEP_OPER + /// A operator to add a step condition. + /** + Use an otherwise unneeded binary operator that has a low priority. + See http://en.cppreference.com/w/cpp/language/operator_precedence. + */ + yc_equation_node_ptr operator IF_STEP_OPER(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond); -#endif +#endif // !SWIG. /** @}*/ } // namespace yask. - -#endif diff --git a/include/yk_grid_api.hpp b/include/yk_grid_api.hpp index 6fc7c7b2..91b6d394 100644 --- a/include/yk_grid_api.hpp +++ b/include/yk_grid_api.hpp @@ -29,8 +29,7 @@ IN THE SOFTWARE. // See http://www.stack.nl/~dimitri/doxygen. /** @file yk_grid_api.hpp */ -#ifndef YK_GRID_API -#define YK_GRID_API +#pragma once #include "yask_kernel_api.hpp" @@ -1114,5 +1113,3 @@ namespace yask { /** @}*/ } // namespace yask. - -#endif diff --git a/include/yk_solution_api.hpp b/include/yk_solution_api.hpp index 913a0b29..0621a519 100644 --- a/include/yk_solution_api.hpp +++ b/include/yk_solution_api.hpp @@ -29,8 +29,7 @@ IN THE SOFTWARE. // See http://www.stack.nl/~dimitri/doxygen. /** @file yk_solution_api.hpp */ -#ifndef YK_SOLN_API -#define YK_SOLN_API +#pragma once #include "yask_kernel_api.hpp" @@ -930,5 +929,3 @@ namespace yask { /** @}*/ } // namespace yask. - -#endif diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index ebfd596c..a34fa75c 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -43,7 +43,7 @@ namespace yask { // for numbers above 9 (at least up to 99). // Format: "major.minor.patch". - const string version = "2.22.00"; + const string version = "2.23.00"; string yask_get_version_string() { return version; diff --git a/src/common/yask_assert.hpp b/src/common/yask_assert.hpp index 01ee7677..3920e83f 100644 --- a/src/common/yask_assert.hpp +++ b/src/common/yask_assert.hpp @@ -27,7 +27,7 @@ IN THE SOFTWARE. // Control assert() by turning on with CHECK instead of turning off with // NDEBUG. This makes it off by default. #ifdef CHECK -#include +#include #else #define assert(expr) ((void)0) #define NDEBUG diff --git a/src/compiler/Makefile b/src/compiler/Makefile index d260d6c2..0745a592 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -46,7 +46,7 @@ YC_PY_LIB := $(PY_OUT_DIR)/_$(YC_MODULE)$(SO_SUFFIX) YC_PY_MOD := $(PY_OUT_DIR)/$(YC_MODULE).py YC_TEST_EXEC := $(BIN_OUT_DIR)/$(YC_BASE)_api_test.exe YC_TEST_EXEC_WITH_EXCEPTION := $(BIN_OUT_DIR)/$(YC_BASE)_api_exception_test.exe -YC_SRC_NAMES := Expr ExprUtils Grid Settings Eqs Print Vec Cpp CppIntrin YaskKernel Soln +YC_SRC_NAMES := Expr ExprUtils Grid Settings Eqs Print Vec Cpp CppIntrin YaskKernel Solution YC_STENCIL_NAMES:= $(notdir $(patsubst %.cpp,%,$(wildcard $(YC_STENCIL_DIR)/*.cpp))) YC_OBJS := $(addprefix $(YC_OBJ_DIR)/,$(addsuffix .o,$(YC_SRC_NAMES) $(COMM_SRC_NAMES))) YC_STENCIL_OBJS := $(addprefix $(YC_OBJ_DIR)/,$(addsuffix .o,$(YC_STENCIL_NAMES))) @@ -106,7 +106,7 @@ $(YC_LIB): $(YC_OBJS) $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) -shared -o $@ $^ @ls -l $@ -$(YC_EXEC): main.cpp $(YC_STENCIL_OBJS) $(YC_LIB) +$(YC_EXEC): compiler_main.cpp $(YC_STENCIL_OBJS) $(YC_LIB) $(MKDIR) $(dir $@) $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $^ $(YC_LFLAGS) -o $@ @ls -l $@ diff --git a/src/compiler/main.cpp b/src/compiler/compiler_main.cpp similarity index 88% rename from src/compiler/main.cpp rename to src/compiler/compiler_main.cpp index c64dd627..de0bbfc4 100644 --- a/src/compiler/main.cpp +++ b/src/compiler/compiler_main.cpp @@ -25,22 +25,53 @@ IN THE SOFTWARE. /////////////// Main vector-folding code-generation code. ///////////// -// YASK compiler-solution code. +// YASK compiler APIs. +#include "yask_compiler_api.hpp" + +// API for using this utility. #include "Soln.hpp" + +// YASK compiler-solution code. +// TODO: remove all non-API includes. #include "CppIntrin.hpp" #include "Parse.hpp" using namespace yask; -// output streams. -map outfiles; +// Declarations to live in the 'yask' namespace. +namespace yask { + + // Compiler API factory. + yc_factory factory; -// other vars set via cmd-line options. -CompilerSettings settings; -int vlenForStats = 0; -StencilBase* stencilSoln = NULL; -string solutionName; -int radius = -1; + // output streams. + map outfiles; + + // other vars set via cmd-line options. + CompilerSettings settings; + int vlenForStats = 0; + StencilBase* stencilSoln = NULL; + string solutionName; + int radius = -1; + + // Collection of known stencils. + typedef map StencilMap; + StencilMap stencils; + + // Dummy object for backward-compatibility with old stencil DSL. + StencilList stub_stencils; + + // Create new solution and register it. + yc_solution_ptr yc_new_solution(const std::string& name, + StencilBase* base_ptr) { + if (stencils.count(name)) + THROW_YASK_EXCEPTION("Error: stencil '" + name + + "' already defined"); + auto soln = factory.new_solution(name); + stencils[name] = base_ptr; + return soln; + } +} // yask namespace. void usage(const string& cmd) { @@ -60,7 +91,7 @@ void usage(const string& cmd) { if ((name.rfind("test_", 0) == 0) == show_test) { auto sp = si.second; cout << " " << name; - if (sp->usesRadius()) + if (sp->uses_radius()) cout << " *"; cout << endl; } @@ -345,22 +376,32 @@ void parseOpts(int argc, const char* argv[]) } stencilSoln = stencilIter->second; assert(stencilSoln); + auto soln = stencilSoln->get_solution(); - cout << "Stencil-solution name: " << solutionName << endl; - if (stencilSoln->usesRadius()) { + cout << "Stencil-solution name: " << soln->get_name() << endl; + if (stencilSoln->uses_radius()) { if (radius >= 0) { - bool rOk = stencilSoln->setRadius(radius); + bool rOk = stencilSoln->set_radius(radius); if (!rOk) { cerr << "Error: invalid radius=" << radius << " for stencil type '" << solutionName << "'." << endl; usage(argv[0]); } } - cout << "Stencil radius: " << stencilSoln->getRadius() << endl; + cout << "Stencil radius: " << stencilSoln->get_radius() << endl; } + cout << "Stencil-solution description: " << soln->get_description() << endl; // Copy cmd-line settings into solution. - stencilSoln->setSettings(settings); + // TODO: remove this reliance on internal (non-API) functionality. + auto sp = dynamic_pointer_cast(soln); + assert(sp); + sp->setSettings(settings); + + // Create equations from the overloaded 'define()' methods. + stencilSoln->define(); + cout << "Num grids defined: " << soln->get_num_grids() << endl; + cout << "Num equations defined: " << soln->get_num_equations() << endl; } // Main program. @@ -375,7 +416,10 @@ int main(int argc, const char* argv[]) { // Parse options and create the stencil-solution object. parseOpts(argc, argv); - // Create the requested output... + if (outfiles.size() == 0) + cout << "Use the '-p' option to generate output from this stencil.\n"; + + // Create the requested output. for (auto i : outfiles) { auto& type = i.first; auto& fname = i.second; @@ -386,7 +430,7 @@ int main(int argc, const char* argv[]) { os = ofac.new_stdout_output(); else os = ofac.new_file_output(fname); - stencilSoln->format(type, os); + stencilSoln->get_solution()->format(type, os); } } catch (yask_exception& e) { cerr << "YASK Stencil Compiler: " << e.get_message() << ".\n"; diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index ea7df5f5..357c5b4a 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -399,9 +399,9 @@ namespace yask { auto vp = printVecPointCall(os, gp, "getVecPtrNorm", "", "false", true); // Ptr will be unique if: - // - Grid doesn't have step dim, or - // - Grid doesn't allow dynamic step allocs and the alloc size is one (TODO), or - // - Grid doesn't allow dynamic step allocs and all accesses are via + // - GridVar doesn't have step dim, or + // - GridVar doesn't allow dynamic step allocs and the alloc size is one (TODO), or + // - GridVar doesn't allow dynamic step allocs and all accesses are via // offsets from the step dim w/compatible offsets (TODO). // TODO: must also share pointers during code gen in last 2 cases. auto* grid = gp.getGrid(); diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index 587dc814..daa78525 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -40,8 +40,8 @@ namespace yask { class PointVisitor : public ExprVisitor { // A type to hold a mapping of equations to a set of grids in each. - typedef unordered_set GridSet; - typedef unordered_map GridMap; + typedef unordered_set GridSet; + typedef unordered_map GridMap; typedef unordered_map GridSetMap; GridMap _lhs_grids; // outputs of eqs. @@ -768,7 +768,7 @@ namespace yask { // Find scratch-grid eqs in this dep path that are // needed for 'eq1'. Walk dep path from 'eq1' to 'b' // until a non-scratch grid is found. - unordered_set scratches_seen; + unordered_set scratches_seen; for (auto eq2 : path) { // Don't process 'eq1', the initial non-scratch eq. @@ -1122,7 +1122,7 @@ namespace yask { // halos. // At the end, the real grids will be updated // from the shadows. - vector< map> shadows; + vector< map> shadows; // Packs. for (auto& bp : getAll()) { @@ -1181,14 +1181,14 @@ namespace yask { // Output grid. auto* og = pv.getOutputGrids().at(eq.get()); if (shadow_map.count(og) == 0) - shadow_map[og] = new Grid(*og); + shadow_map[og] = new GridVar(*og); // Input grids. auto& inPts = pv.getInputPts().at(eq.get()); for (auto* ip : inPts) { auto* ig = ip->getGrid(); if (shadow_map.count(ig) == 0) - shadow_map[ig] = new Grid(*ig); + shadow_map[ig] = new GridVar(*ig); } } diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 9b811dbb..4d5beb42 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -25,8 +25,6 @@ IN THE SOFTWARE. ///////// Stencil AST Expressions. //////////// -// TODO: break this up into several smaller files. - #include "Print.hpp" #include "ExprUtils.hpp" #include "Parse.hpp" @@ -83,24 +81,47 @@ namespace yask { yc_number_node_ptr yc_node_factory::new_add_node(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + if (!lhs) + return rhs; + if (!rhs) + return lhs; auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); assert(rp); - return make_shared(lp, rp); + + // Add to commutative operand list. + auto ex = make_shared(); + ex->mergeExpr(lp); + ex->mergeExpr(rp); + return ex; } yc_number_node_ptr yc_node_factory::new_multiply_node(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + if (!lhs) + return rhs; + if (!rhs) + return lhs; auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); assert(rp); - return make_shared(lp, rp); + + // Add to commutative operand list. + auto ex = make_shared(); + ex->mergeExpr(lp); + ex->mergeExpr(rp); + return ex; } yc_number_node_ptr yc_node_factory::new_subtract_node(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_node_factory nfac; + if (!lhs) + return nfac.new_negate_node(rhs); + if (!rhs) + return lhs; auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -110,6 +131,11 @@ namespace yask { yc_number_node_ptr yc_node_factory::new_divide_node(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_node_factory nfac; + if (!lhs) + return nfac.new_divide_node(nfac.new_const_number_node(1.0), rhs); + if (!rhs) + return lhs; auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -208,90 +234,122 @@ namespace yask { auto p = dynamic_pointer_cast(idx); if (!p) THROW_YASK_EXCEPTION("Error: new_first_domain_index() called without index-node argument"); - return first_index(p); + if (p->getType() != DOMAIN_INDEX) + THROW_YASK_EXCEPTION("Error: new_first_domain_index() called without domain-index-node argument"); + return make_shared(p->getName(), FIRST_INDEX); } yc_number_node_ptr yc_node_factory::new_last_domain_index(yc_index_node_ptr idx) { auto p = dynamic_pointer_cast(idx); if (!p) THROW_YASK_EXCEPTION("Error: new_last_domain_index() called without index-node argument"); - return last_index(p); + if (p->getType() != DOMAIN_INDEX) + THROW_YASK_EXCEPTION("Error: new_last_domain_index() called without domain-index-node argument"); + return make_shared(p->getName(), LAST_INDEX); } + + // Unary. yc_number_node_ptr operator-(yc_number_node_ptr rhs) { - auto p = dynamic_pointer_cast(rhs); - assert(p); - return make_shared(p); + yc_node_factory nfac; + return nfac.new_negate_node(rhs); } + + // Binary. yc_number_node_ptr operator+(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_add_node(lhs, rhs); } yc_number_node_ptr operator+(double lhs, yc_number_node_ptr rhs) { - return operator+(constNum(lhs), rhs); + yc_node_factory nfac; + return operator+(nfac.new_const_number_node(lhs), rhs); } yc_number_node_ptr operator+(yc_number_node_ptr lhs, double rhs) { - return operator+(lhs, constNum(rhs)); + yc_node_factory nfac; + return operator+(lhs, nfac.new_const_number_node(rhs)); } yc_number_node_ptr operator/(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_divide_node(lhs, rhs); } yc_number_node_ptr operator/(double lhs, yc_number_node_ptr rhs) { - return operator/(constNum(lhs), rhs); + yc_node_factory nfac; + return operator/(nfac.new_const_number_node(lhs), rhs); } yc_number_node_ptr operator/(yc_number_node_ptr lhs, double rhs) { - return operator/(lhs, constNum(rhs)); + yc_node_factory nfac; + return operator/(lhs, nfac.new_const_number_node(rhs)); } yc_number_node_ptr operator%(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_mod_node(lhs, rhs); } yc_number_node_ptr operator%(double lhs, yc_number_node_ptr rhs) { - return operator%(constNum(lhs), rhs); + yc_node_factory nfac; + return operator%(nfac.new_const_number_node(lhs), rhs); } yc_number_node_ptr operator%(yc_number_node_ptr lhs, double rhs) { - return operator%(lhs, constNum(rhs)); + yc_node_factory nfac; + return operator%(lhs, nfac.new_const_number_node(rhs)); } yc_number_node_ptr operator*(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_multiply_node(lhs, rhs); } yc_number_node_ptr operator*(double lhs, yc_number_node_ptr rhs) { - return operator*(constNum(lhs), rhs); + yc_node_factory nfac; + return operator*(nfac.new_const_number_node(lhs), rhs); } yc_number_node_ptr operator*(yc_number_node_ptr lhs, double rhs) { - return operator*(lhs, constNum(rhs)); + yc_node_factory nfac; + return operator*(lhs, nfac.new_const_number_node(rhs)); } yc_number_node_ptr operator-(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_subtract_node(lhs, rhs); } yc_number_node_ptr operator-(double lhs, yc_number_node_ptr rhs) { - return operator-(constNum(lhs), rhs); + yc_node_factory nfac; + return operator-(nfac.new_const_number_node(lhs), rhs); } yc_number_node_ptr operator-(yc_number_node_ptr lhs, double rhs) { - return operator-(lhs, constNum(rhs)); + yc_node_factory nfac; + return operator-(lhs, nfac.new_const_number_node(rhs)); + } + + // Modifiers. + void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { + lhs = lhs + rhs; + } + void operator+=(yc_number_node_ptr& lhs, double rhs) { + lhs = lhs + rhs; + } + void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { + lhs = lhs - rhs; + } + void operator-=(yc_number_node_ptr& lhs, double rhs) { + lhs = lhs - rhs; + } + void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { + lhs = lhs * rhs; + } + void operator*=(yc_number_node_ptr& lhs, double rhs) { + lhs = lhs * rhs; } + void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { + lhs = lhs / rhs; + } + void operator/=(yc_number_node_ptr& lhs, double rhs) { + lhs = lhs / rhs; + } + + // Boolean unary. yc_bool_node_ptr operator!(yc_bool_node_ptr rhs) { auto p = dynamic_pointer_cast(rhs); assert(p); return make_shared(p); } + + // Boolean binary. yc_bool_node_ptr operator||(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs) { auto lp = dynamic_pointer_cast(lhs); assert(lp); @@ -307,34 +365,6 @@ namespace yask { return make_shared(lp, rp); } -// Boolean binary operators with numerical inputs. -#define BIN_NUM2BOOL_OP(type, oper) \ - yc_bool_node_ptr operator oper(yc_number_node_ptr lhs, \ - yc_number_node_ptr rhs) { \ - auto lp = dynamic_pointer_cast(lhs); \ - assert(lp); \ - auto rp = dynamic_pointer_cast(rhs); \ - assert(rp); \ - return make_shared(lp, rp); \ - } \ - yc_bool_node_ptr operator oper(yc_index_node_ptr lhs, \ - yc_number_node_ptr rhs) { \ - return operator>=(dynamic_pointer_cast(lhs), rhs); \ - } \ - yc_bool_node_ptr operator oper(yc_number_node_ptr lhs, yc_index_node_ptr rhs) { \ - return operator>=(lhs, dynamic_pointer_cast(rhs)); \ - } \ - yc_bool_node_ptr operator oper(yc_index_node_ptr lhs, yc_index_node_ptr rhs) { \ - return operator>=(dynamic_pointer_cast(lhs), \ - dynamic_pointer_cast(rhs)); \ - } - BIN_NUM2BOOL_OP(IsEqualExpr, ==) - BIN_NUM2BOOL_OP(NotEqualExpr, !=) - BIN_NUM2BOOL_OP(IsLessExpr, <) - BIN_NUM2BOOL_OP(NotLessExpr, >=) - BIN_NUM2BOOL_OP(IsGreaterExpr, >) - BIN_NUM2BOOL_OP(NotGreaterExpr, <=) - // Compare 2 expr pointers and return whether the expressions are // equivalent. // TODO: Be much smarter about matching symbolically-equivalent exprs. @@ -350,15 +380,12 @@ namespace yask { return e1->isSame(e2); } - // Unary. - NumExprPtr operator-(const NumExprPtr rhs) { - return make_shared(rhs); - } - // Function calls. #define FUNC_EXPR(fn) \ - NumExprPtr fn(const NumExprPtr rhs) { \ - return make_shared(#fn, std::initializer_list< const NumExprPtr >{ rhs }); \ + yc_number_node_ptr fn(const yc_number_node_ptr rhs) { \ + auto rp = dynamic_pointer_cast(rhs); \ + assert(rp); \ + return make_shared(#fn, std::initializer_list< const NumExprPtr >{ rp }); \ } FUNC_EXPR(sqrt) FUNC_EXPR(cbrt) @@ -371,165 +398,67 @@ namespace yask { FUNC_EXPR(cos) #undef FUNC_EXPR #define FUNC_EXPR(fn) \ - NumExprPtr fn(const NumExprPtr arg1, const NumExprPtr arg2) { \ - return make_shared(#fn, std::initializer_list< const NumExprPtr >{ arg1, arg2 }); \ + yc_number_node_ptr fn(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2) { \ + auto p1 = dynamic_pointer_cast(arg1); \ + assert(p1); \ + auto p2 = dynamic_pointer_cast(arg2); \ + assert(p2); \ + return make_shared(#fn, std::initializer_list< const NumExprPtr >{ p1, p2 }); \ } \ - NumExprPtr fn(const NumExprPtr arg1, double arg2) { \ - return make_shared(#fn, std::initializer_list< const NumExprPtr >{ arg1, constNum(arg2) }); \ + yc_number_node_ptr fn(const yc_number_node_ptr arg1, double arg2) { \ + yc_node_factory nfac; \ + auto p2 = nfac.new_const_number_node(arg2); \ + return fn(arg1, p2); \ } \ - NumExprPtr fn(double arg1, const NumExprPtr arg2) { \ - return make_shared(#fn, std::initializer_list< const NumExprPtr >{ constNum(arg1), arg2 }); \ + yc_number_node_ptr fn(double arg1, const yc_number_node_ptr arg2) { \ + yc_node_factory nfac; \ + auto p1 = nfac.new_const_number_node(arg1); \ + return fn(p1, arg2); \ } FUNC_EXPR(pow) #undef FUNC_EXPR - // A free function to create a constant expression. - NumExprPtr constNum(double rhs) { - return make_shared(rhs); - } - - // Free functions to create boundary indices, e.g., 'first_index(x)'. - NumExprPtr first_index(IndexExprPtr dim) { - assert(dim->getType() == DOMAIN_INDEX); - return make_shared(dim->getName(), FIRST_INDEX); - } - NumExprPtr last_index(IndexExprPtr dim) { - assert(dim->getType() == DOMAIN_INDEX); - return make_shared(dim->getName(), LAST_INDEX); - } - - // Commutative. - // If one side is nothing, just return other side; - // This allows us to start with an uninitialized GridValue - // and do the right thing. - // Start with an empty expression. - // If LHS is the same expr type, add its operands. - // Othewise, add the whole expr. - // Repeat for RHS. -#define COMM_OPER(oper, exprtype) \ - NumExprPtr operator oper(const NumExprPtr lhs, \ - const NumExprPtr rhs) { \ - if (lhs.get() == NULL) \ - return rhs; \ - else if (rhs.get() == NULL) \ - return lhs; \ - auto ex = make_shared(); \ - ex->mergeExpr(lhs); \ - ex->mergeExpr(rhs); \ - return ex; \ - } \ - NumExprPtr operator oper(double lhs, \ - const NumExprPtr rhs) { \ - NumExprPtr p = make_shared(lhs); \ - return p oper rhs; \ - } \ - NumExprPtr operator oper(const NumExprPtr lhs, \ - double rhs) { \ - NumExprPtr p = make_shared(rhs); \ - return lhs oper p; \ - } - COMM_OPER(+, AddExpr) - COMM_OPER(*, MultExpr) - - // Self-modifying versions. - void operator+=(NumExprPtr& lhs, const NumExprPtr rhs) { - lhs = lhs + rhs; - } - void operator+=(NumExprPtr& lhs, double rhs) { - lhs = lhs + rhs; - } - void operator*=(NumExprPtr& lhs, const NumExprPtr rhs) { - lhs = lhs * rhs; - } - void operator*=(NumExprPtr& lhs, double rhs) { - lhs = lhs * rhs; - } - - // Binary. - NumExprPtr operator-(const NumExprPtr lhs, const NumExprPtr rhs) { -#ifdef USE_ADD_NEG - // Generate A + -B instead of A - B to allow easy reordering. - NumExprPtr nrhs = make_shared(rhs); - return lhs + nrhs; -#else - return make_shared(lhs, rhs); -#endif - } - NumExprPtr operator-(double lhs, const NumExprPtr rhs) { - NumExprPtr p = make_shared(lhs); - return p - rhs; - } - NumExprPtr operator-(const NumExprPtr lhs, double rhs) { - NumExprPtr p = make_shared(rhs); - return lhs - p; - } - - void operator-=(NumExprPtr& lhs, const NumExprPtr rhs) { - lhs = lhs - rhs; - } - void operator-=(NumExprPtr& lhs, double rhs) { - lhs = lhs - rhs; - } - - NumExprPtr operator/(const NumExprPtr lhs, const NumExprPtr rhs) { - return make_shared(lhs, rhs); - } - NumExprPtr operator/(double lhs, const NumExprPtr rhs) { - NumExprPtr p = make_shared(lhs); - return p / rhs; - } - NumExprPtr operator/(const NumExprPtr lhs, double rhs) { - NumExprPtr p = make_shared(rhs); - return lhs / p; - } - - void operator/=(NumExprPtr& lhs, const NumExprPtr rhs) { - lhs = lhs / rhs; - } - void operator/=(NumExprPtr& lhs, double rhs) { - lhs = lhs / rhs; - } - - NumExprPtr operator%(const NumExprPtr lhs, const NumExprPtr rhs) { - return make_shared(lhs, rhs); - } - NumExprPtr operator%(double lhs, const NumExprPtr rhs) { - NumExprPtr p = make_shared(lhs); - return p % rhs; - } - NumExprPtr operator%(const NumExprPtr lhs, double rhs) { - NumExprPtr p = make_shared(rhs); - return lhs % p; - } - // Define a conditional. - EqualsExprPtr operator IF_OPER(EqualsExprPtr expr, const BoolExprPtr cond) { + yc_equation_node_ptr operator IF_OPER(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond) { + auto ep = dynamic_pointer_cast(expr); + assert(ep); + auto cp = dynamic_pointer_cast(cond); + assert(cp); // Add cond to expr. - assert(expr); - expr->setCond(cond); - return expr; + ep->setCond(cp); + return ep; } - EqualsExprPtr operator IF_STEP_OPER(EqualsExprPtr expr, const BoolExprPtr step_cond) { + yc_equation_node_ptr operator IF_STEP_OPER(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond) { + auto ep = dynamic_pointer_cast(expr); + assert(ep); + auto cp = dynamic_pointer_cast(cond); + assert(cp); // Add cond to expr. - assert(expr); - expr->setStepCond(step_cond); - return expr; + ep->setStepCond(cp); + return ep; } // Define the value of a grid point. // Add this equation to the list of eqs for this stencil. - EqualsExprPtr operator EQUALS_OPER(GridPointPtr gpp, const NumExprPtr rhs) { + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr lhs, + const yc_number_node_ptr rexpr) { - if (!gpp) + if (!lhs) THROW_YASK_EXCEPTION("Error: empty LHS of equation"); - if (!rhs) + auto gpp = dynamic_pointer_cast(lhs); + assert(gpp); + if (!rexpr) THROW_YASK_EXCEPTION("Error: empty RHS of " + gpp->makeQuotedStr() + " equation"); + auto rhs = dynamic_pointer_cast(rexpr); + assert(rhs); // Get to list of equations in soln indirectly thru grid. - Grid* gp = gpp->getGrid(); + GridVar* gp = gpp->getGrid(); assert(gp); auto* soln = gp->getSoln(); assert(soln); @@ -548,10 +477,11 @@ namespace yask { return expr; } - EqualsExprPtr operator EQUALS_OPER(GridPointPtr gpp, double rhs) { - return gpp EQUALS_OPER constNum(rhs); + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, double rhs) { + yc_node_factory nfac; + return gpp EQUALS_OPER nfac.new_const_number_node(rhs); } - EqualsExprPtr operator EQUALS_OPER(GridPointPtr gpp, GridPointPtr rhs) { + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, GridPointPtr rhs) { auto p = dynamic_pointer_cast(rhs); assert(p); return gpp EQUALS_OPER p; @@ -606,7 +536,7 @@ namespace yask { // EqualsExpr methods. bool EqualsExpr::isScratch() { - Grid* gp = getGrid(); + GridVar* gp = getGrid(); return gp && gp->isScratch(); } bool EqualsExpr::isSame(const Expr* other) const { @@ -692,7 +622,7 @@ namespace yask { } // GridPoint methods. - GridPoint::GridPoint(Grid* grid, const NumExprPtrVec& args) : + GridPoint::GridPoint(GridVar* grid, const NumExprPtrVec& args) : _grid(grid), _args(args) { // Check for correct number of args. @@ -875,11 +805,11 @@ namespace yask { auto ie = gdim->clone(); NumExprPtr nep; if (ofs > 0) { - auto op = constNum(ofs); + auto op = make_shared(ofs); nep = make_shared(ie, op); } else if (ofs < 0) { - auto op = constNum(-ofs); + auto op = make_shared(-ofs); nep = make_shared(ie, op); } else // 0 offset. @@ -913,7 +843,7 @@ namespace yask { // Make const expr. int v = val.getVal(); - auto vp = constNum(v); + auto vp = make_shared(v); // Replace in args. _args[i] = vp; diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 75af66c2..77ed0696 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -76,7 +76,7 @@ namespace yask { // More forward-decls. class ExprVisitor; - class Grid; + class GridVar; class StencilSolution; struct Dimensions; @@ -218,7 +218,7 @@ namespace yask { } }; - // Grid index types. + // GridVar index types. enum IndexType { STEP_INDEX, // the step dim. DOMAIN_INDEX, // a domain dim. @@ -275,29 +275,6 @@ namespace yask { } }; - // A free function to create a constant expression. - // Usually not needed due to operator overloading. - NumExprPtr constNum(double val); - - // Free functions to create boundary indices, e.g., 'first_index(x)'. - NumExprPtr first_index(IndexExprPtr dim); - NumExprPtr last_index(IndexExprPtr dim); - - // A simple wrapper to provide automatic construction - // of a NumExpr ptr from other types. - class NumExprArg : public NumExprPtr { - - public: - NumExprArg(NumExprPtr p) : - NumExprPtr(p) { } - NumExprArg(IndexExprPtr p) : - NumExprPtr(p) { } - NumExprArg(int i) : - NumExprPtr(constNum(i)) { } - NumExprArg(double f) : - NumExprPtr(constNum(f)) { } - }; - // Boolean value. class BoolExpr : public Expr, public virtual yc_bool_node { @@ -333,6 +310,7 @@ namespace yask { FORMAT_AND_THROW_YASK_EXCEPTION("Error: integer value " << i << " cannot be stored accurately as a double"); } + ConstExpr(int i) : ConstExpr(idx_t(i)) { } ConstExpr(const ConstExpr& src) : _f(src._f) { } virtual ~ConstExpr() { } @@ -653,7 +631,10 @@ namespace yask { // If op is another CommutativeExpr with the // same operator, add its operands to this. - // Otherwise, just clone and add the whole op. + // Otherwise, just add the whole node. + // Example: if 'this' is 'A+B', 'mergeExpr(C+D)' + // returns 'A+B+C+D', and 'mergeExpr(E*F)' + // returns 'A+B+(E*F)'. virtual void mergeExpr(NumExprPtr op) { auto opp = dynamic_pointer_cast(op); if (opp && opp->getOpStr() == _opStr) { @@ -790,24 +771,6 @@ namespace yask { } }; -#define FUNC_EXPR(fn_name) NumExprPtr fn_name(const NumExprPtr rhs) - FUNC_EXPR(sqrt); - FUNC_EXPR(cbrt); - FUNC_EXPR(fabs); - FUNC_EXPR(erf); - FUNC_EXPR(exp); - FUNC_EXPR(log); - FUNC_EXPR(sin); - FUNC_EXPR(cos); - FUNC_EXPR(atan); -#undef FUNC_EXPR -#define FUNC_EXPR(fn_name) \ - NumExprPtr fn_name(const NumExprPtr arg1, const NumExprPtr arg2); \ - NumExprPtr fn_name(double arg1, const NumExprPtr arg2); \ - NumExprPtr fn_name(const NumExprPtr arg1, double arg2) - FUNC_EXPR(pow); -#undef FUNC_EXPR - // One specific point in a grid. // This is an expression leaf-node. class GridPoint : public NumExpr, @@ -832,7 +795,7 @@ namespace yask { }; protected: - Grid* _grid = 0; // the grid this point is from. + GridVar* _grid = 0; // the grid this point is from. // Index exprs for each dim, e.g., // "3, x-5, y*2, z+4" for dims "n, x, y, z". @@ -861,14 +824,14 @@ namespace yask { public: // Construct a point given a grid and an arg for each dim. - GridPoint(Grid* grid, const NumExprPtrVec& args); + GridPoint(GridVar* grid, const NumExprPtrVec& args); // Dtor. virtual ~GridPoint() {} // Get parent grid info. - const Grid* getGrid() const { return _grid; } - Grid* getGrid() { return _grid; } + const GridVar* getGrid() const { return _grid; } + GridVar* getGrid() { return _grid; } virtual const string& getGridName() const; virtual string getGridPtr() const; virtual bool isGridFoldable() const; @@ -1031,7 +994,7 @@ namespace yask { static string stepCondOpStr() { return "IF_STEP"; } // Get pointer to grid on LHS or NULL if not set. - virtual Grid* getGrid() { + virtual GridVar* getGrid() { if (_lhs.get()) return _lhs->getGrid(); return NULL; @@ -1072,126 +1035,10 @@ namespace yask { } }; - ///// The following are operators and functions used in stencil expressions. - - // Various unary operators. - NumExprPtr operator-(const NumExprPtr rhs); - - // Various binary operators. - NumExprPtr operator+(const NumExprPtr lhs, const NumExprPtr rhs); - NumExprPtr operator+(double lhs, const NumExprPtr rhs); - NumExprPtr operator+(const NumExprPtr lhs, double rhs); - void operator+=(NumExprPtr& lhs, const NumExprPtr rhs); - void operator+=(NumExprPtr& lhs, double rhs); - - NumExprPtr operator-(const NumExprPtr lhs, const NumExprPtr rhs); - NumExprPtr operator-(double lhs, const NumExprPtr rhs); - NumExprPtr operator-(const NumExprPtr lhs, double rhs); - void operator-=(NumExprPtr& lhs, const NumExprPtr rhs); - void operator-=(NumExprPtr& lhs, double rhs); - - NumExprPtr operator*(const NumExprPtr lhs, const NumExprPtr rhs); - NumExprPtr operator*(double lhs, const NumExprPtr rhs); - NumExprPtr operator*(const NumExprPtr lhs, double rhs); - void operator*=(NumExprPtr& lhs, const NumExprPtr rhs); - void operator*=(NumExprPtr& lhs, double rhs); - - NumExprPtr operator/(const NumExprPtr lhs, const NumExprPtr rhs); - NumExprPtr operator/(double lhs, const NumExprPtr rhs); - NumExprPtr operator/(const NumExprPtr lhs, double rhs); - void operator/=(NumExprPtr& lhs, const NumExprPtr rhs); - void operator/=(NumExprPtr& lhs, double rhs); - - NumExprPtr operator%(const NumExprPtr lhs, const NumExprPtr rhs); - NumExprPtr operator%(double lhs, const NumExprPtr rhs); - NumExprPtr operator%(const NumExprPtr lhs, double rhs); - - // A conditional evaluation. - // We use an otherwise unneeded binary operator that has a low priority. - // See http://en.cppreference.com/w/cpp/language/operator_precedence. -#define IF_OPER ^= - EqualsExprPtr operator IF_OPER(EqualsExprPtr expr, const BoolExprPtr cond); -#define IF IF_OPER -#define IF_STEP_OPER |= - EqualsExprPtr operator IF_STEP_OPER(EqualsExprPtr expr, const BoolExprPtr step_cond); -#define IF_STEP IF_STEP_OPER - - // The operator used for defining a grid value. - // We use an otherwise unneeded binary operator that has a lower priority - // than the math ops and a higher priority than the IF_OPER. - // See http://en.cppreference.com/w/cpp/language/operator_precedence. - // This should not be an operator that is defined for shared pointers. - // See https://en.cppreference.com/w/cpp/memory/shared_ptr. -#define EQUALS_OPER << - EqualsExprPtr operator EQUALS_OPER(GridPointPtr gpp, const NumExprPtr rhs); - EqualsExprPtr operator EQUALS_OPER(GridPointPtr gpp, const GridPointPtr rhs); - EqualsExprPtr operator EQUALS_OPER(GridPointPtr gpp, double rhs); -#define EQUALS EQUALS_OPER -#define IS_EQUIV_TO EQUALS_OPER -#define IS_EQUIVALENT_TO EQUALS_OPER - - // Binary numerical-to-boolean operators. Must provide more explicit - // ptr-type operands than used with math operators to keep compiler from - // using built-in pointer comparison. This means we need all - // permutations of {NumExpr,IndexExpr,GridPoint}Ptr. Const values must - // be on RHS of operator, e.g., 'x > 5' is ok, but '5 < x' is not. -#define BOOL_OPER(oper, type, implType) \ - inline BoolExprPtr operator oper(const NumExprPtr lhs, const NumExprPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const NumExprPtr lhs, const IndexExprPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const NumExprPtr lhs, const GridPointPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const IndexExprPtr lhs, const NumExprPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const IndexExprPtr lhs, const IndexExprPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const IndexExprPtr lhs, const GridPointPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const GridPointPtr lhs, const NumExprPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const GridPointPtr lhs, const IndexExprPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const GridPointPtr lhs, const GridPointPtr rhs) { \ - return make_shared(lhs, rhs); } \ - inline BoolExprPtr operator oper(const NumExprPtr lhs, double rhs) { \ - return make_shared(lhs, constNum(rhs)); } \ - inline BoolExprPtr operator oper(const IndexExprPtr lhs, double rhs) { \ - return make_shared(lhs, constNum(rhs)); } \ - inline BoolExprPtr operator oper(const GridPointPtr lhs, double rhs) { \ - return make_shared(lhs, constNum(rhs)); } - - BOOL_OPER(==, IsEqualExpr, yc_equals_node) - BOOL_OPER(!=, NotEqualExpr, yc_not_equals_node) - BOOL_OPER(<, IsLessExpr, yc_less_than_node) - BOOL_OPER(>, IsGreaterExpr, yc_greater_than_node) - BOOL_OPER(<=, NotGreaterExpr, yc_not_greater_than_node) - BOOL_OPER(>=, NotLessExpr, yc_not_less_than_node) - - // Logical operators. - inline BoolExprPtr operator&&(const BoolExprPtr lhs, const BoolExprPtr rhs) { - return make_shared(lhs, rhs); - } - inline BoolExprPtr operator||(const BoolExprPtr lhs, const BoolExprPtr rhs) { - return make_shared(lhs, rhs); - } - inline BoolExprPtr operator!(const BoolExprPtr rhs) { - return make_shared(rhs); - } - typedef set GridPointSet; typedef set GridPointPtrSet; typedef vector GridPointVec; - // A 'GridIndex' is simply a pointer to a numerical expression. - typedef NumExprPtr GridIndex; - - // A 'Condition' is simply a pointer to a binary expression. - typedef BoolExprPtr Condition; - - // A 'GridValue' is simply a pointer to an expression. - typedef NumExprPtr GridValue; - // Use SET_VALUE_FROM_EXPR for creating a string to insert any C++ code // that evaluates to a real_t. // The 1st arg must be the LHS of an assignment statement. diff --git a/src/compiler/lib/Grid.cpp b/src/compiler/lib/Grid.cpp index c29d7ca8..117b810f 100644 --- a/src/compiler/lib/Grid.cpp +++ b/src/compiler/lib/Grid.cpp @@ -37,7 +37,7 @@ namespace yask { // grid APIs. yc_grid_point_node_ptr - Grid::new_grid_point(const std::vector& index_exprs) { + GridVar::new_grid_point(const std::vector& index_exprs) { // Check for correct number of indices. if (_dims.size() != index_exprs.size()) { @@ -60,7 +60,7 @@ namespace yask { } yc_grid_point_node_ptr - Grid::new_relative_grid_point(const std::vector& dim_offsets) { + GridVar::new_relative_grid_point(const std::vector& dim_offsets) { // Check for correct number of indices. if (_dims.size() != dim_offsets.size()) { @@ -97,72 +97,40 @@ namespace yask { return gpp; } - vector Grid::get_dim_names() const { + vector GridVar::get_dim_names() const { vector ret; for (auto dn : getDims()) ret.push_back(dn->getName()); return ret; } - // Create an expression to a specific point in this grid. - // Note that this doesn't actually 'read' or 'write' a value; - // it's just a node in an expression. - GridPointPtr Grid::makePoint(const NumExprPtrVec& args) { - auto gpp = make_shared(this, args); - return gpp; - } - - // Ctor for Grid. - Grid::Grid(string name, - bool isScratch, - StencilSolution* soln, - IndexExprPtr dim1, - IndexExprPtr dim2, - IndexExprPtr dim3, - IndexExprPtr dim4, - IndexExprPtr dim5, - IndexExprPtr dim6) : - _name(name), // TODO: validate that name is legal C++ var. - _isScratch(isScratch), - _soln(soln) + // Ctor for GridVar. + GridVar::GridVar(string name, + bool isScratch, + StencilSolution* soln, + const IndexExprPtrVec& dims) : + _name(name), // TODO: validate that name is legal C++ var. + _isScratch(isScratch), + _soln(soln) { assert(soln); // Name already used? auto& grids = soln->getGrids(); for (auto gp : grids) { - if (gp->getName() == _name) - THROW_YASK_EXCEPTION("Error: grid name '" + _name + "' already used"); + if (gp->getName() == name) + THROW_YASK_EXCEPTION("Error: grid name '" + name + "' already used"); } // Register in soln. - if (soln) - grids.insert(this); - - // Add dims that are not null. - if (dim1) - _dims.push_back(dim1); - if (dim2) - _dims.push_back(dim2); - if (dim3) - _dims.push_back(dim3); - if (dim4) - _dims.push_back(dim4); - if (dim5) - _dims.push_back(dim5); - if (dim6) - _dims.push_back(dim6); - } - Grid::Grid(string name, - bool isScratch, - StencilSolution* soln, - const IndexExprPtrVec& dims) : - Grid(name, isScratch, soln) { + grids.insert(this); + + // Define dims. _dims = dims; } // Determine whether grid can be folded. - void Grid::setFolding(const Dimensions& dims) { + void GridVar::setFolding(const Dimensions& dims) { _numFoldableDims = 0; @@ -198,7 +166,7 @@ namespace yask { } // Determine whether halo sizes are equal. - bool Grid::isHaloSame(const Grid& other) const { + bool GridVar::isHaloSame(const GridVar& other) const { // Same dims? if (!areDimsSame(other)) @@ -222,7 +190,7 @@ namespace yask { // Update halos based on halo in 'other' grid. // This grid's halos can only be increased. - void Grid::updateHalo(const Grid& other) { + void GridVar::updateHalo(const GridVar& other) { assert(areDimsSame(other)); // Loop thru other grid's halo values. @@ -261,7 +229,7 @@ namespace yask { // Update halos based on each value in 'offsets' in some // read or write to this grid. // This grid's halos can only be increased. - void Grid::updateHalo(const string& packName, const IntTuple& offsets) { + void GridVar::updateHalo(const string& packName, const IntTuple& offsets) { // Find step value or use 0 if none. int stepVal = 0; @@ -302,7 +270,7 @@ namespace yask { } // Update const indices based on 'indices'. - void Grid::updateConstIndices(const IntTuple& indices) { + void GridVar::updateConstIndices(const IntTuple& indices) { for (auto& dim : indices.getDims()) { auto& dname = dim.getName(); @@ -325,7 +293,7 @@ namespace yask { } // Determine how many values in step-dim are needed. - int Grid::getStepDimSize() const + int GridVar::getStepDimSize() const { // Specified by API. if (_stepAlloc > 0) @@ -425,7 +393,7 @@ namespace yask { } // Description of this grid. - string Grid::getDescr() const { + string GridVar::getDescr() const { string d = _name + "("; int i = 0; for (auto dn : getDims()) { diff --git a/src/compiler/lib/Grid.hpp b/src/compiler/lib/Grid.hpp index de44a2ff..5ef089d0 100644 --- a/src/compiler/lib/Grid.hpp +++ b/src/compiler/lib/Grid.hpp @@ -36,11 +36,11 @@ namespace yask { // Fwd decl. struct Dimensions; - // A class for a Grid. + // A class for a GridVar. // This is a generic container for all variables to be accessed // from the kernel. A 0-D grid is a scalar, a 1-D grid is an array, etc. // Dims can be the step dim, a domain dim, or anything else. - class Grid : public virtual yc_grid { + class GridVar : public virtual yc_grid { protected: string _name; // name of this grid. @@ -74,22 +74,13 @@ namespace yask { public: // Ctors. - Grid(string name, + GridVar(string name, bool isScratch, StencilSolution* soln, const IndexExprPtrVec& dims); - Grid(string name, - bool isScratch, - StencilSolution* soln, - IndexExprPtr dim1 = nullptr, - IndexExprPtr dim2 = nullptr, - IndexExprPtr dim3 = nullptr, - IndexExprPtr dim4 = nullptr, - IndexExprPtr dim5 = nullptr, - IndexExprPtr dim6 = nullptr); // Dtor. - virtual ~Grid() { } + virtual ~GridVar() { } // Name accessors. const string& getName() const { return _name; } @@ -160,7 +151,7 @@ namespace yask { } // Determine whether dims are same. - virtual bool areDimsSame(const Grid& other) const { + virtual bool areDimsSame(const GridVar& other) const { if (_dims.size() != other._dims.size()) return false; size_t i = 0; @@ -180,10 +171,10 @@ namespace yask { virtual void setFolding(const Dimensions& dims); // Determine whether halo sizes are equal. - virtual bool isHaloSame(const Grid& other) const; + virtual bool isHaloSame(const GridVar& other) const; // Update halos based on halo in 'other' grid. - virtual void updateHalo(const Grid& other); + virtual void updateHalo(const GridVar& other); // Update halos based on each value in 'offsets'. virtual void updateHalo(const string& packName, const IntTuple& offsets); @@ -191,84 +182,6 @@ namespace yask { // Update const indices based on 'indices'. virtual void updateConstIndices(const IntTuple& indices); - // Create an expression to a specific point in this grid. - // Note that this doesn't actually 'read' or 'write' a value; - // it's just a node in an expression. - virtual GridPointPtr makePoint(const NumExprPtrVec& args); - virtual GridPointPtr makePoint() { - NumExprPtrVec args; - return makePoint(args); - } - - // Convenience functions for zero dimensions (scalar). - virtual operator NumExprPtr() { // implicit conversion. - return makePoint(); - } - virtual operator GridPointPtr() { // implicit conversion. - return makePoint(); - } - virtual GridPointPtr operator()() { - return makePoint(); - } - - // Convenience functions for one dimension (array). - virtual GridPointPtr operator[](const NumExprArg i1) { - NumExprPtrVec args; - args.push_back(i1); - return makePoint(args); - } - virtual GridPointPtr operator()(const NumExprArg i1) { - return operator[](i1); - } - - // Convenience functions for more dimensions. - virtual GridPointPtr operator()(const NumExprArg i1, const NumExprArg i2) { - NumExprPtrVec args; - args.push_back(i1); - args.push_back(i2); - return makePoint(args); - } - virtual GridPointPtr operator()(const NumExprArg i1, const NumExprArg i2, - const NumExprArg i3) { - NumExprPtrVec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - return makePoint(args); - } - virtual GridPointPtr operator()(const NumExprArg i1, const NumExprArg i2, - const NumExprArg i3, const NumExprArg i4) { - NumExprPtrVec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - args.push_back(i4); - return makePoint(args); - } - virtual GridPointPtr operator()(const NumExprArg i1, const NumExprArg i2, - const NumExprArg i3, const NumExprArg i4, - const NumExprArg i5) { - NumExprPtrVec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - args.push_back(i4); - args.push_back(i5); - return makePoint(args); - } - virtual GridPointPtr operator()(const NumExprArg i1, const NumExprArg i2, - const NumExprArg i3, const NumExprArg i4, - const NumExprArg i5, const NumExprArg i6) { - NumExprPtrVec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - args.push_back(i4); - args.push_back(i5); - args.push_back(i6); - return makePoint(args); - } - // APIs. virtual const string& get_name() const { return _name; @@ -318,7 +231,7 @@ namespace yask { // A list of grids. This holds pointers to grids defined by the stencil // class in the order in which they are added via the INIT_GRID_* macros. - class Grids : public vector_set { + class Grids : public vector_set { public: Grids() {} @@ -326,7 +239,7 @@ namespace yask { // Copy ctor. // Copies list of grid pointers, but not grids (shallow copy). - Grids(const Grids& src) : vector_set(src) {} + Grids(const Grids& src) : vector_set(src) {} // Determine whether each grid can be folded. virtual void setFolding(const Dimensions& dims) { diff --git a/src/compiler/lib/Print.hpp b/src/compiler/lib/Print.hpp index 7bc7613d..7099af06 100644 --- a/src/compiler/lib/Print.hpp +++ b/src/compiler/lib/Print.hpp @@ -30,7 +30,7 @@ IN THE SOFTWARE. #include "ExprUtils.hpp" #include "Eqs.hpp" -#include "Soln.hpp" +#include "Solution.hpp" namespace yask { diff --git a/src/compiler/lib/Settings.cpp b/src/compiler/lib/Settings.cpp index db14d4e2..0c0895ad 100644 --- a/src/compiler/lib/Settings.cpp +++ b/src/compiler/lib/Settings.cpp @@ -40,7 +40,7 @@ namespace yask { return yask_get_version_string(); } yc_solution_ptr yc_factory::new_solution(const std::string& name) const { - return make_shared(name); + return make_shared(name); } // Find the dimensions to be used based on the grids in @@ -73,7 +73,7 @@ namespace yask { // Get dims from grids. for (auto& gp : grids) { auto& gname = gp->getName(); - os << "Grid: " << gp->getDescr() << endl; + os << "GridVar: " << gp->getDescr() << endl; // Dimensions in this grid. for (auto dim : gp->getDims()) { diff --git a/src/compiler/lib/Soln.cpp b/src/compiler/lib/Solution.cpp similarity index 96% rename from src/compiler/lib/Soln.cpp rename to src/compiler/lib/Solution.cpp index 5e3fe8e8..6ccc506a 100644 --- a/src/compiler/lib/Soln.cpp +++ b/src/compiler/lib/Solution.cpp @@ -32,9 +32,6 @@ using namespace std; namespace yask { - // A global register of stencils. - StencilList stencils; - // Stencil-solution APIs. yc_grid_ptr StencilSolution::newGrid(const std::string& name, bool isScratch, @@ -51,7 +48,7 @@ namespace yask { dims2.push_back(d2); } - auto* gp = new Grid(name, isScratch, this, dims2); + auto* gp = new GridVar(name, isScratch, this, dims2); assert(gp); return gp; } @@ -72,10 +69,6 @@ namespace yask { void StencilSolution::analyze_solution(int vlen, bool is_folding_efficient) { - // Call the stencil 'define' method to create ASTs. - // ASTs and grids can also be created via the APIs. - define(); - // Find all the stencil dimensions from the grids. // Create the final folds and clusters from the cmd-line options. _dims.setDims(_grids, _settings, vlen, is_folding_efficient, *_dos); diff --git a/src/compiler/lib/Soln.hpp b/src/compiler/lib/Solution.hpp similarity index 68% rename from src/compiler/lib/Soln.hpp rename to src/compiler/lib/Solution.hpp index 90275c78..dd8b37ad 100644 --- a/src/compiler/lib/Soln.hpp +++ b/src/compiler/lib/Solution.hpp @@ -36,16 +36,14 @@ using namespace std; namespace yask { + // TODO: add API to add to this. typedef enum { STENCIL_CONTEXT } YASKSection; typedef vector CodeList; typedef map ExtensionsList; - class StencilSolution; - class StencilBase; - typedef map StencilList; - - // Global list for registering stencils. - extern StencilList stencils; +// Convenience macros for adding 'extension' code to a stencil. +#define _REGISTER_CODE_EXTENSION(section, code) _extensions[section].push_back(code); +#define _REGISTER_STENCIL_CONTEXT_EXTENSION(...) REGISTER_CODE_EXTENSION(STENCIL_CONTEXT, #__VA_ARGS__) // A base class for whole stencil solutions. This is used by solutions // defined in C++ that are inherited from StencilBase as well as those @@ -129,10 +127,6 @@ namespace yask { return *_dos; } - // Define grid values relative to current domain indices in each dimension. - // This must be implemented by each concrete stencil solution. - virtual void define() = 0; - // Make a new grid. virtual yc_grid_ptr newGrid(const std::string& name, bool isScratch, @@ -153,10 +147,10 @@ namespace yask { virtual void set_description(std::string str) { _long_name = str; } - virtual const std::string& get_name() const { + virtual std::string get_name() const { return _name; } - virtual const std::string get_description() const { + virtual std::string get_description() const { return getLongName(); } @@ -259,112 +253,4 @@ namespace yask { }; - // A stencil solution that does not define any grids. - // This is used by a program via the compiler API to add grids - // programmatically. - class EmptyStencil : public StencilSolution { - - // Do not define any dims. - // Do not define any grids. - - public: - EmptyStencil(std::string name) : - StencilSolution(name) { } - - // Do not define any equations. - virtual void define() { } - }; - - // An interface for all objects that participate in stencil definitions. - // This allows a programmer to use object composition in addition to - // inheritance from StencilBase to define stencils. - class StencilPart { - - public: - StencilPart() {} - virtual ~StencilPart() {} - - // Return a reference to the main stencil object. - virtual StencilSolution& get_stencil_solution() =0; - }; - - // The class all C++ stencil solutions must implement. - class StencilBase : public StencilSolution, - public StencilPart { - - public: - // Initialize name and register this new object in a list. - StencilBase(const string name, StencilList& stencils) : - StencilSolution(name) - { - if (stencils.count(name)) - THROW_YASK_EXCEPTION("Error: stencil '" + name + - "' already defined"); - stencils[name] = this; - } - virtual ~StencilBase() { } - - // Return a reference to the main stencil-solution object. - // For StencilBase, simply this object. - virtual StencilSolution& get_stencil_solution() { - return *this; - } - - // Radius stub methods. - virtual bool usesRadius() const { return false; } - virtual bool setRadius(int radius) { return false; } - virtual int getRadius() const { return 0; } - - }; - - // A base class for stencils that have a 'radius'. - class StencilRadiusBase : public StencilBase { - protected: - int _radius; // stencil radius. - - public: - StencilRadiusBase(const string name, StencilList& stencils, int radius) : - StencilBase(name, stencils) { - setRadius(radius); - } - - // Does use radius. - virtual bool usesRadius() const override { return true; } - - // Set radius. - // Return true if successful. - virtual bool setRadius(int radius) override { - _radius = radius; - _long_name = _name + " radius " + to_string(radius); - return radius >= 0; // support only non-neg. radius. - } - - // Get radius. - virtual int getRadius() const override { return _radius; } - }; - } // namespace yask. - -// Convenience macro for declaring an instance of a stencil and registering -// it in the list used by the default YASK compiler. -#define REGISTER_STENCIL(Class) static Class registered_ ## Class(stencils) - -// Convenience macros for adding 'extension' code to a stencil. -#define REGISTER_CODE_EXTENSION(section, code) _extensions[section].push_back(code); -#define REGISTER_STENCIL_CONTEXT_EXTENSION(...) REGISTER_CODE_EXTENSION(STENCIL_CONTEXT, #__VA_ARGS__) - -// Convenience macro for declaring dims. -#define MAKE_STEP_INDEX(d) IndexExprPtr d = make_shared(#d, STEP_INDEX); -#define MAKE_DOMAIN_INDEX(d) IndexExprPtr d = make_shared(#d, DOMAIN_INDEX); -#define MAKE_MISC_INDEX(d) IndexExprPtr d = make_shared(#d, MISC_INDEX); - -// Convenience macros for creating grids in a class implementing StencilPart. -// The 'gvar' arg is the var name and the grid name. -// The remaining args are the dimension names. -#define MAKE_GRID(gvar, ...) \ - Grid gvar = Grid(#gvar, false, &get_stencil_solution(), ##__VA_ARGS__) -#define MAKE_SCRATCH_GRID(gvar, ...) \ - Grid gvar = Grid(#gvar, true, &get_stencil_solution(), ##__VA_ARGS__) -#define MAKE_SCALAR(gvar) MAKE_GRID(gvar) -#define MAKE_ARRAY(gvar, d1) MAKE_GRID(gvar, d1) - diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index d37f5b41..bd41fc14 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -192,7 +192,7 @@ namespace yask { set newGridDims; // Grids. - os << "\n ///// Grid(s)." << endl; + os << "\n ///// GridVar(s)." << endl; for (auto gp : _grids) { string grid = gp->getName(); int ndims = gp->get_num_dims(); @@ -329,7 +329,7 @@ namespace yask { " typedef std::shared_ptr<" << typeDef << "> " << ptrTypeDef << ";\n" " GridDimNames " + grid + "_dim_names;\n"; - ctorCode += "\n // Grid '" + grid + "'.\n"; + ctorCode += "\n // GridVar '" + grid + "'.\n"; ctorCode += " " + grid + "_dim_names = {" + gdims.makeDimStr(", ", "\"", "\"") + "};\n"; string gbp = grid + "_base_ptr"; @@ -339,7 +339,7 @@ namespace yask { " " + grid + "_ptr = std::make_shared(" + gbp + ");\n" " assert(" + grid + "_ptr->gbp());\n"; - // Grid vars. + // GridVar vars. if (gp->isScratch()) { // Collection of scratch grids. @@ -348,7 +348,7 @@ namespace yask { } else { - // Grid ptr declaration. + // GridVar ptr declaration. // Default ctor gives null ptr. os << " YkGridPtr " << grid << "_ptr;\n"; } @@ -414,7 +414,7 @@ namespace yask { // If not scratch, init grids in ctor. if (!gp->isScratch()) { - // Grid init. + // GridVar init. ctorCode += initCode; ctorCode += " addGrid(" + grid + "_ptr, true, "; if (_eqBundles.getOutputGrids().count(gp)) diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 3160eef3..d9cc10a0 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -408,7 +408,7 @@ namespace yask { // Init all grids & params. // By default it uses the initSame initialization routine. virtual void initData() { - initSame(); + initDiff(); // Safer than initSame() to avoid NaNs due to div-by-zero. } // Compare grids in contexts for validation. diff --git a/src/kernel/yask_main.cpp b/src/kernel/yask_main.cpp index 5185e6e5..535e2f5b 100644 --- a/src/kernel/yask_main.cpp +++ b/src/kernel/yask_main.cpp @@ -399,7 +399,7 @@ int main(int argc, char** argv) // init data before each trial for comparison if validating. if (opts->validate) - context->initDiff(); + context->initData(); // Warn if tuning. if (ksoln->is_auto_tuner_enabled()) @@ -508,14 +508,14 @@ int main(int argc, char** argv) ref_soln->prepare_solution(); // init to same value used in context. - ref_context->initDiff(); + ref_context->initData(); #ifdef CHECK_INIT // Debug code to determine if data compares immediately after init matches. os << endl << divLine << "Reinitializing data for minimal validation...\n" << flush; - context->initDiff(); + context->initData(); #else // Ref trial. diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index 96e113fd..148436ff 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -29,12 +29,11 @@ IN THE SOFTWARE. #include "ElasticStencil.hpp" -// This class implements StencilPart but is not the main solution. +// This class implements StencilBase but is not the main solution. // The main solution is provided during construction. -class Elastic2BoundaryCondition : public StencilPart +class Elastic2BoundaryCondition : public StencilBase { protected: - StencilSolution& _sol; // Indices & dimensions. MAKE_STEP_INDEX(t); // step in time dim. @@ -49,18 +48,13 @@ class Elastic2BoundaryCondition : public StencilPart MAKE_MISC_INDEX(spidx); public: - Elastic2BoundaryCondition(StencilSolution& solution) : - _sol(solution) {} + Elastic2BoundaryCondition(StencilBase& base) : + StencilBase(base) { } virtual ~Elastic2BoundaryCondition() {} // Determine whether current indices are at boundary. virtual Condition is_at_boundary() =0; virtual Condition is_not_at_boundary() =0; - - // Return a reference to the main stencil-solution object provided during construction. - virtual StencilSolution& get_stencil_solution() { - return _sol; - } }; class Elastic2StencilBase : public StencilBase { @@ -102,18 +96,7 @@ class Elastic2StencilBase : public StencilBase { Elastic2StencilBase(const string& name, StencilList& stencils, Elastic2BoundaryCondition *_bc = NULL) : StencilBase(name, stencils), bc(_bc) - { - init(); - } - - void init() { - // StencilContex specific code - REGISTER_STENCIL_CONTEXT_EXTENSION( - virtual void initData() { - initDiff(); - } - ); - } + { } bool hasBoundaryCondition() { diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index f8c0a229..9f9e93b4 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -44,12 +44,11 @@ struct X: public StencilDimension{}; struct Y: public StencilDimension{}; struct Z: public StencilDimension{}; -// This class implements StencilPart but is not the main solution. +// This class implements StencilBase but is not the main solution. // The main solution is provided during construction. -class ElasticBoundaryCondition : public StencilPart +class ElasticBoundaryCondition : public StencilBase { protected: - StencilSolution& _sol; // Indices & dimensions. MAKE_STEP_INDEX(t); // step in time dim. @@ -58,18 +57,13 @@ class ElasticBoundaryCondition : public StencilPart MAKE_DOMAIN_INDEX(z); // spatial dim. public: - ElasticBoundaryCondition(StencilSolution& solution) : - _sol(solution) {} + ElasticBoundaryCondition(StencilBase& base) : + StencilBase(base) { } virtual ~ElasticBoundaryCondition() {} // Determine whether current indices are at boundary. virtual Condition is_at_boundary() =0; virtual Condition is_not_at_boundary() =0; - - // Return a reference to the main stencil-solution object provided during construction. - virtual StencilSolution& get_stencil_solution() { - return _sol; - } }; class ElasticStencilBase : public StencilBase { @@ -105,18 +99,7 @@ class ElasticStencilBase : public StencilBase { ElasticStencilBase(const string& name, StencilList& stencils, ElasticBoundaryCondition *_bc = NULL) : StencilBase(name, stencils), bc(_bc) - { - init(); - } - - void init() { - // StencilContex specific code - REGISTER_STENCIL_CONTEXT_EXTENSION( - virtual void initData() { - initDiff(); - } - ); - } + { } bool hasBoundaryCondition() { diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index 94ccfbc8..f14e428e 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -2492,9 +2492,10 @@ TTIStencil (StencilList & stencils, int radius = 2): case 4: define_so8 (); break; - default: - THROW_YASK_EXCEPTION - ("Error: only radius values of 2 and 4 are currently supported (radius is half the spatial accuracy-order)"); + default: { + yask_exception e("Error: only radius values of 2 and 4 are currently supported for the TTI stencil example"); + throw e; + } } } }; From 58567132a54ddc6c4e99c89a2f85eadf4724de7b Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 2 May 2019 16:29:30 -0700 Subject: [PATCH 02/62] Add more expression-pointer types for backward-compatibility. --- include/Soln.hpp | 4 + src/compiler/lib/Cpp.cpp | 4 +- src/compiler/lib/Cpp.hpp | 2 +- src/compiler/lib/Eqs.cpp | 16 ++-- src/compiler/lib/Eqs.hpp | 16 ++-- src/compiler/lib/Expr.cpp | 14 ++-- src/compiler/lib/Expr.hpp | 148 ++++++++++++++++----------------- src/compiler/lib/ExprUtils.cpp | 2 +- src/compiler/lib/ExprUtils.hpp | 4 +- src/compiler/lib/Grid.cpp | 10 +-- src/compiler/lib/Grid.hpp | 8 +- src/compiler/lib/Print.cpp | 4 +- src/compiler/lib/Print.hpp | 2 +- src/compiler/lib/Solution.cpp | 2 +- src/compiler/lib/Vec.cpp | 2 +- 15 files changed, 121 insertions(+), 117 deletions(-) diff --git a/include/Soln.hpp b/include/Soln.hpp index 59eada7c..21a92aff 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -315,6 +315,10 @@ namespace yask { typedef yc_number_node_ptr GridValue; typedef yc_bool_node_ptr Condition; typedef yc_grid_point_node_ptr GridPointPtr; + typedef yc_expr_node_ptr ExprPtr; + typedef yc_number_node_ptr NumExprPtr; + typedef yc_index_node_ptr IndexExprPtr; + typedef yc_bool_node_ptr BoolExprPtr; } // namespace yask. diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index 357c5b4a..7f5139cc 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -364,8 +364,8 @@ namespace yask { } // Make base point (misc & inner-dim indices = 0). - GridPointPtr CppVecPrintHelper::makeBasePoint(const GridPoint& gp) { - GridPointPtr bgp = gp.cloneGridPoint(); + gridPointPtr CppVecPrintHelper::makeBasePoint(const GridPoint& gp) { + gridPointPtr bgp = gp.cloneGridPoint(); for (auto& dim : gp.getDims()) { auto& dname = dim->getName(); auto type = dim->getType(); diff --git a/src/compiler/lib/Cpp.hpp b/src/compiler/lib/Cpp.hpp index ac1b01a2..cdeca07e 100644 --- a/src/compiler/lib/Cpp.hpp +++ b/src/compiler/lib/Cpp.hpp @@ -182,7 +182,7 @@ namespace yask { virtual void printBasePtrs(ostream& os); // Make base point (misc & inner-dim indices = 0). - virtual GridPointPtr makeBasePoint(const GridPoint& gp); + virtual gridPointPtr makeBasePoint(const GridPoint& gp); // Print prefetches for each base pointer. // Print only 'ptrVar' if provided. diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index daa78525..7b3439c0 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -105,7 +105,7 @@ namespace yask { lhs->accept(this); // visit RHS. - NumExprPtr rhs = ee->getRhs(); + numExprPtr rhs = ee->getRhs(); _state = _in_rhs; rhs->accept(this); @@ -193,7 +193,7 @@ namespace yask { auto& ip1 = inPts.at(eq1p); auto cond1 = eq1p->getCond(); auto stcond1 = eq1p->getStepCond(); - NumExprPtr step_expr1 = op1->getArg(stepDim); // may be null. + numExprPtr step_expr1 = op1->getArg(stepDim); // may be null. #ifdef DEBUG_DEP cout << " Checking internal consistency of equation " << @@ -211,7 +211,7 @@ namespace yask { // LHS must have all domain dims. for (auto& dd : dims._domainDims.getDims()) { auto& dname = dd.getName(); - NumExprPtr dexpr = op1->getArg(dname); + numExprPtr dexpr = op1->getArg(dname); if (!dexpr) THROW_YASK_EXCEPTION("Error: grid equation " + eq1->makeQuotedStr() + " does not use domain-dimension '" + dname + @@ -372,7 +372,7 @@ namespace yask { //auto& ip1 = inPts.at(eq1p); auto cond1 = eq1p->getCond(); auto stcond1 = eq1p->getStepCond(); - NumExprPtr step_expr1 = op1->getArg(stepDim); + numExprPtr step_expr1 = op1->getArg(stepDim); // Check each 'eq2' to see if it depends on 'eq1'. for (auto eq2 : getAll()) { @@ -480,7 +480,7 @@ namespace yask { // Both points at same step? bool same_step = false; - NumExprPtr step_expr2 = i2->getArg(stepDim); + numExprPtr step_expr2 = i2->getArg(stepDim); if (step_expr1 && step_expr2 && areExprsSame(step_expr1, step_expr2)) same_step = true; @@ -762,7 +762,7 @@ namespace yask { // For each 'b', 'eq1' is 'b' or depends on 'b', // immediately or indirectly; 'path' leads from // 'eq1' to 'b'. - (eq1, [&](EqualsExprPtr b, EqList& path) { + (eq1, [&](equalsExprPtr b, EqList& path) { //auto* ogb = pv.getOutputGrids().at(b.get()); // Find scratch-grid eqs in this dep path that are @@ -833,7 +833,7 @@ namespace yask { } // Add an equation to an EqBundle. - void EqBundle::addEq(EqualsExprPtr ee) + void EqBundle::addEq(equalsExprPtr ee) { #ifdef DEBUG_EQ_BUNDLE cout << "EqBundle: adding " << ee->makeQuotedStr() << endl; @@ -942,7 +942,7 @@ namespace yask { // be incremented if a new bundle is created. Returns whether a new // bundle was created. bool EqBundles::addEqToBundle(Eqs& allEqs, - EqualsExprPtr eq, + equalsExprPtr eq, const string& baseName, const CompilerSettings& settings) { assert(_dims); diff --git a/src/compiler/lib/Eqs.hpp b/src/compiler/lib/Eqs.hpp index 0faafa64..ae97057e 100644 --- a/src/compiler/lib/Eqs.hpp +++ b/src/compiler/lib/Eqs.hpp @@ -351,7 +351,7 @@ namespace yask { }; // A list of unique equation ptrs. - typedef vector_set EqList; + typedef vector_set EqList; // A set of equations and related dependency data. class Eqs : public DepGroup { @@ -450,11 +450,11 @@ namespace yask { // TODO: move these into protected section and make accessors. // Common conditions. - BoolExprPtr cond; - BoolExprPtr step_cond; + boolExprPtr cond; + boolExprPtr step_cond; // Common step expr. - NumExprPtr step_expr; + numExprPtr step_expr; // Create a copy containing clones of the equations. virtual shared_ptr clone() const { @@ -481,7 +481,7 @@ namespace yask { string quote = "'") const; // Add an equation to this bundle. - virtual void addEq(EqualsExprPtr ee); + virtual void addEq(equalsExprPtr ee); // Get the list of all equations. virtual const EqList& getItems() const { @@ -528,14 +528,14 @@ namespace yask { map _indices; // Track equations that have been added already. - set _eqs_in_bundles; + set _eqs_in_bundles; // Add 'eq' from 'eqs' to eq-bundle with 'baseName' // unless already added or illegal. The corresponding index in // '_indices' will be incremented if a new bundle is created. // Returns whether a new bundle was created. virtual bool addEqToBundle(Eqs& eqs, - EqualsExprPtr eq, + equalsExprPtr eq, const string& baseName, const CompilerSettings& settings); @@ -608,7 +608,7 @@ namespace yask { public: // Common condition. - BoolExprPtr step_cond; + boolExprPtr step_cond; // Ctor. EqBundlePack(bool is_scratch) : diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 4d5beb42..e4b309d6 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -385,7 +385,7 @@ namespace yask { yc_number_node_ptr fn(const yc_number_node_ptr rhs) { \ auto rp = dynamic_pointer_cast(rhs); \ assert(rp); \ - return make_shared(#fn, std::initializer_list< const NumExprPtr >{ rp }); \ + return make_shared(#fn, std::initializer_list< const numExprPtr >{ rp }); \ } FUNC_EXPR(sqrt) FUNC_EXPR(cbrt) @@ -403,7 +403,7 @@ namespace yask { assert(p1); \ auto p2 = dynamic_pointer_cast(arg2); \ assert(p2); \ - return make_shared(#fn, std::initializer_list< const NumExprPtr >{ p1, p2 }); \ + return make_shared(#fn, std::initializer_list< const numExprPtr >{ p1, p2 }); \ } \ yc_number_node_ptr fn(const yc_number_node_ptr arg1, double arg2) { \ yc_node_factory nfac; \ @@ -481,7 +481,7 @@ namespace yask { yc_node_factory nfac; return gpp EQUALS_OPER nfac.new_const_number_node(rhs); } - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, GridPointPtr rhs) { + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, gridPointPtr rhs) { auto p = dynamic_pointer_cast(rhs); assert(p); return gpp EQUALS_OPER p; @@ -622,7 +622,7 @@ namespace yask { } // GridPoint methods. - GridPoint::GridPoint(GridVar* grid, const NumExprPtrVec& args) : + GridPoint::GridPoint(GridVar* grid, const numExprPtrVec& args) : _grid(grid), _args(args) { // Check for correct number of args. @@ -667,7 +667,7 @@ namespace yask { } _updateStr(); } - const NumExprPtr GridPoint::getArg(const string& dim) const { + const numExprPtr GridPoint::getArg(const string& dim) const { for (int di = 0; di < _grid->get_num_dims(); di++) { auto& dn = _grid->get_dim_name(di); // name of this dim. if (dim == dn) @@ -711,7 +711,7 @@ namespace yask { str += "(" + _consts.makeDimValStr() + ")"; return str; } - const IndexExprPtrVec& GridPoint::getDims() const { + const indexExprPtrVec& GridPoint::getDims() const { return _grid->getDims(); } @@ -803,7 +803,7 @@ namespace yask { // Make offset equation. int ofs = offset.getVal(); auto ie = gdim->clone(); - NumExprPtr nep; + numExprPtr nep; if (ofs > 0) { auto op = make_shared(ofs); nep = make_shared(ie, op); diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 77ed0696..9cdc5431 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -60,19 +60,19 @@ namespace yask { // Forward-decls of expressions. class Expr; - typedef shared_ptr ExprPtr; + typedef shared_ptr exprPtr; class NumExpr; - typedef shared_ptr NumExprPtr; - typedef vector NumExprPtrVec; + typedef shared_ptr numExprPtr; + typedef vector numExprPtrVec; class GridPoint; - typedef shared_ptr GridPointPtr; + typedef shared_ptr gridPointPtr; class IndexExpr; - typedef shared_ptr IndexExprPtr; - typedef vector IndexExprPtrVec; + typedef shared_ptr indexExprPtr; + typedef vector indexExprPtrVec; class BoolExpr; - typedef shared_ptr BoolExprPtr; + typedef shared_ptr boolExprPtr; class EqualsExpr; - typedef shared_ptr EqualsExprPtr; + typedef shared_ptr equalsExprPtr; // More forward-decls. class ExprVisitor; @@ -104,7 +104,7 @@ namespace yask { // Does *not* check value equivalency except for // constants. virtual bool isSame(const Expr* other) const =0; - virtual bool isSame(const ExprPtr& other) const { + virtual bool isSame(const exprPtr& other) const { return isSame(other.get()); } @@ -113,7 +113,7 @@ namespace yask { virtual bool makePair(Expr* other) { return false; } - virtual bool makePair(ExprPtr other) { + virtual bool makePair(exprPtr other) { return makePair(other.get()); } @@ -151,7 +151,7 @@ namespace yask { }; // Convert pointer to the given ptr type or die trying. - template shared_ptr castExpr(ExprPtr ep, const string& descrip) { + template shared_ptr castExpr(exprPtr ep, const string& descrip) { auto tp = dynamic_pointer_cast(ep); if (!tp) { THROW_YASK_EXCEPTION("Error: expression '" + ep->makeStr() + @@ -163,13 +163,13 @@ namespace yask { // Compare 2 expr pointers and return whether the expressions are // equivalent. bool areExprsSame(const Expr* e1, const Expr* e2); - inline bool areExprsSame(const ExprPtr e1, const Expr* e2) { + inline bool areExprsSame(const exprPtr e1, const Expr* e2) { return areExprsSame(e1.get(), e2); } - inline bool areExprsSame(const Expr* e1, const ExprPtr e2) { + inline bool areExprsSame(const Expr* e1, const exprPtr e2) { return areExprsSame(e1, e2.get()); } - inline bool areExprsSame(const ExprPtr e1, const ExprPtr e2) { + inline bool areExprsSame(const exprPtr e1, const exprPtr e2) { return areExprsSame(e1.get(), e2.get()); } @@ -212,7 +212,7 @@ namespace yask { // Create a deep copy of this expression. // For this to work properly, each derived type // should also implement a deep-copy copy ctor. - virtual NumExprPtr clone() const =0; + virtual numExprPtr clone() const =0; virtual yc_number_node_ptr clone_ast() const { return clone(); } @@ -267,7 +267,7 @@ namespace yask { } // Create a deep copy of this expression. - virtual NumExprPtr clone() const { return make_shared(*this); } + virtual numExprPtr clone() const { return make_shared(*this); } // APIs. virtual const string& get_name() const { @@ -290,7 +290,7 @@ namespace yask { // Create a deep copy of this expression. // For this to work properly, each derived type // should also implement a copy ctor. - virtual BoolExprPtr clone() const =0; + virtual boolExprPtr clone() const =0; virtual yc_bool_node_ptr clone_ast() const { return clone(); } @@ -326,7 +326,7 @@ namespace yask { } // Create a deep copy of this expression. - virtual NumExprPtr clone() const { return make_shared(*this); } + virtual numExprPtr clone() const { return make_shared(*this); } // APIs. virtual void set_value(double val) { _f = val; } @@ -359,7 +359,7 @@ namespace yask { } // Create a deep copy of this expression. - virtual NumExprPtr clone() const { return make_shared(*this); } + virtual numExprPtr clone() const { return make_shared(*this); } }; // Base class for any generic unary operator. @@ -395,15 +395,15 @@ namespace yask { }; // Various types of unary operators depending on input and output types. - typedef UnaryExpr UnaryNumExpr; - typedef UnaryExpr UnaryNum2BoolExpr; - typedef UnaryExpr UnaryBoolExpr; + typedef UnaryExpr UnaryNumExpr; + typedef UnaryExpr UnaryNum2BoolExpr; + typedef UnaryExpr UnaryBoolExpr; // Negate operator. class NegExpr : public UnaryNumExpr, public virtual yc_negate_node { public: - NegExpr(NumExprPtr rhs) : + NegExpr(numExprPtr rhs) : UnaryNumExpr(opStr(), rhs) { } NegExpr(const NegExpr& src) : UnaryExpr(src) { } @@ -416,7 +416,7 @@ namespace yask { double rhs = _rhs->getNumVal(); return -rhs; } - virtual NumExprPtr clone() const { + virtual numExprPtr clone() const { return make_shared(*this); } @@ -430,7 +430,7 @@ namespace yask { class NotExpr : public UnaryBoolExpr, public virtual yc_not_node { public: - NotExpr(BoolExprPtr rhs) : + NotExpr(boolExprPtr rhs) : UnaryBoolExpr(opStr(), rhs) { } NotExpr(const NotExpr& src) : UnaryBoolExpr(src) { } @@ -440,7 +440,7 @@ namespace yask { bool rhs = _rhs->getBoolVal(); return !rhs; } - virtual BoolExprPtr clone() const { + virtual boolExprPtr clone() const { return make_shared(*this); } virtual yc_bool_node_ptr get_rhs() { @@ -489,11 +489,11 @@ namespace yask { // Various types of binary operators depending on input and output types. typedef BinaryExpr BinaryNumExpr; // fn(num, num) -> num. + numExprPtr, yc_number_node_ptr> BinaryNumExpr; // fn(num, num) -> num. typedef BinaryExpr BinaryBoolExpr; // fn(bool, bool) -> bool. + boolExprPtr, yc_bool_node_ptr> BinaryBoolExpr; // fn(bool, bool) -> bool. typedef BinaryExpr BinaryNum2BoolExpr; // fn(num, num) -> bool. + numExprPtr, yc_number_node_ptr> BinaryNum2BoolExpr; // fn(num, num) -> bool. // Numerical binary operators. // TODO: redo this with a template. @@ -501,7 +501,7 @@ namespace yask { class type : public BinaryNumExpr, \ public virtual implType { \ public: \ - type(NumExprPtr lhs, NumExprPtr rhs) : \ + type(numExprPtr lhs, numExprPtr rhs) : \ BinaryNumExpr(lhs, opStr(), rhs) { } \ type(const type& src) : \ BinaryNumExpr(src) { } \ @@ -516,7 +516,7 @@ namespace yask { double rhs = _rhs->getNumVal(); \ return oper; \ } \ - virtual NumExprPtr clone() const { \ + virtual numExprPtr clone() const { \ return make_shared(*this); \ } \ } @@ -536,7 +536,7 @@ namespace yask { class type : public BinaryNum2BoolExpr, \ public virtual implType { \ public: \ - type(NumExprPtr lhs, NumExprPtr rhs) : \ + type(numExprPtr lhs, numExprPtr rhs) : \ BinaryNum2BoolExpr(lhs, opStr(), rhs) { } \ type(const type& src) : \ BinaryNum2BoolExpr(src) { } \ @@ -546,7 +546,7 @@ namespace yask { double rhs = _rhs->getNumVal(); \ return oper; \ } \ - virtual BoolExprPtr clone() const { \ + virtual boolExprPtr clone() const { \ return make_shared(*this); \ } \ virtual yc_number_node_ptr get_lhs() { \ @@ -570,7 +570,7 @@ namespace yask { class type : public BinaryBoolExpr, \ public virtual implType { \ public: \ - type(BoolExprPtr lhs, BoolExprPtr rhs) : \ + type(boolExprPtr lhs, boolExprPtr rhs) : \ BinaryBoolExpr(lhs, opStr(), rhs) { } \ type(const type& src) : \ BinaryBoolExpr(src) { } \ @@ -580,7 +580,7 @@ namespace yask { bool rhs = _rhs->getBoolVal(); \ return oper; \ } \ - virtual BoolExprPtr clone() const { \ + virtual boolExprPtr clone() const { \ return make_shared(*this); \ } \ virtual yc_bool_node_ptr get_lhs() { \ @@ -600,14 +600,14 @@ namespace yask { class CommutativeExpr : public NumExpr, public virtual yc_commutative_number_node { protected: - NumExprPtrVec _ops; + numExprPtrVec _ops; string _opStr; public: CommutativeExpr(const string& opStr) : _opStr(opStr) { } - CommutativeExpr(NumExprPtr lhs, const string& opStr, NumExprPtr rhs) : + CommutativeExpr(numExprPtr lhs, const string& opStr, numExprPtr rhs) : _opStr(opStr) { _ops.push_back(lhs->clone()); _ops.push_back(rhs->clone()); @@ -620,12 +620,12 @@ namespace yask { virtual ~CommutativeExpr() { } // Accessors. - NumExprPtrVec& getOps() { return _ops; } - const NumExprPtrVec& getOps() const { return _ops; } + numExprPtrVec& getOps() { return _ops; } + const numExprPtrVec& getOps() const { return _ops; } const string& getOpStr() const { return _opStr; } // Clone and add an operand. - virtual void appendOp(NumExprPtr op) { + virtual void appendOp(numExprPtr op) { _ops.push_back(op->clone()); } @@ -635,7 +635,7 @@ namespace yask { // Example: if 'this' is 'A+B', 'mergeExpr(C+D)' // returns 'A+B+C+D', and 'mergeExpr(E*F)' // returns 'A+B+(E*F)'. - virtual void mergeExpr(NumExprPtr op) { + virtual void mergeExpr(numExprPtr op) { auto opp = dynamic_pointer_cast(op); if (opp && opp->getOpStr() == _opStr) { for(auto op2 : opp->_ops) @@ -688,7 +688,7 @@ namespace yask { public: \ type() : \ CommutativeExpr(opStr()) { } \ - type(NumExprPtr lhs, NumExprPtr rhs) : \ + type(numExprPtr lhs, numExprPtr rhs) : \ CommutativeExpr(lhs, opStr(), rhs) { } \ type(const type& src) : \ CommutativeExpr(src) { } \ @@ -704,7 +704,7 @@ namespace yask { } \ return val; \ } \ - virtual NumExprPtr clone() const { return make_shared(*this); } \ + virtual numExprPtr clone() const { return make_shared(*this); } \ }; COMM_EXPR(MultExpr, yc_multiply_node, "*", 1.0, lhs * rhs) COMM_EXPR(AddExpr, yc_add_node, "+", 0.0, lhs + rhs) @@ -716,13 +716,13 @@ namespace yask { class FuncExpr : public NumExpr { protected: string _opStr; // name of function. - NumExprPtrVec _ops; // args to function. + numExprPtrVec _ops; // args to function. // Special handler for pairable functions like sincos(). FuncExpr* _paired = nullptr; // ptr to counterpart. public: - FuncExpr(const string& opStr, const std::initializer_list< const NumExprPtr > & ops) : + FuncExpr(const string& opStr, const std::initializer_list< const numExprPtr > & ops) : _opStr(opStr) { for (auto& op : ops) _ops.push_back(op->clone()); @@ -736,8 +736,8 @@ namespace yask { } // Accessors. - NumExprPtrVec& getOps() { return _ops; } - const NumExprPtrVec& getOps() const { return _ops; } + numExprPtrVec& getOps() { return _ops; } + const numExprPtrVec& getOps() const { return _ops; } const string& getOpStr() const { return _opStr; } virtual string accept(ExprVisitor* ev); @@ -755,7 +755,7 @@ namespace yask { } return true; } - virtual NumExprPtr clone() const { + virtual numExprPtr clone() const { return make_shared(*this); } @@ -799,7 +799,7 @@ namespace yask { // Index exprs for each dim, e.g., // "3, x-5, y*2, z+4" for dims "n, x, y, z". - NumExprPtrVec _args; + numExprPtrVec _args; // Vars below are calculated from above. @@ -824,7 +824,7 @@ namespace yask { public: // Construct a point given a grid and an arg for each dim. - GridPoint(GridVar* grid, const NumExprPtrVec& args); + GridPoint(GridVar* grid, const numExprPtrVec& args); // Dtor. virtual ~GridPoint() {} @@ -835,10 +835,10 @@ namespace yask { virtual const string& getGridName() const; virtual string getGridPtr() const; virtual bool isGridFoldable() const; - virtual const IndexExprPtrVec& getDims() const; + virtual const indexExprPtrVec& getDims() const; // Accessors. - virtual const NumExprPtrVec& getArgs() const { return _args; } + virtual const numExprPtrVec& getArgs() const { return _args; } virtual const IntTuple& getArgOffsets() const { return _offsets; } virtual const IntTuple& getArgConsts() const { return _consts; } virtual VecType getVecType() const { @@ -857,7 +857,7 @@ namespace yask { } // Get arg for 'dim' or return null if none. - virtual const NumExprPtr getArg(const string& dim) const; + virtual const numExprPtr getArg(const string& dim) const; // Set given arg to given offset; ignore if not in step or domain grid dims. virtual void setArgOffset(const IntScalar& offset); @@ -926,8 +926,8 @@ namespace yask { // Create a deep copy of this expression, // except pointed-to grid is not copied. - virtual NumExprPtr clone() const { return make_shared(*this); } - virtual GridPointPtr cloneGridPoint() const { return make_shared(*this); } + virtual numExprPtr clone() const { return make_shared(*this); } + virtual gridPointPtr cloneGridPoint() const { return make_shared(*this); } // APIs. virtual yc_grid* get_grid(); @@ -955,15 +955,15 @@ namespace yask { class EqualsExpr : public Expr, public virtual yc_equation_node { protected: - GridPointPtr _lhs; - NumExprPtr _rhs; - BoolExprPtr _cond; - BoolExprPtr _step_cond; + gridPointPtr _lhs; + numExprPtr _rhs; + boolExprPtr _cond; + boolExprPtr _step_cond; public: - EqualsExpr(GridPointPtr lhs, NumExprPtr rhs, - BoolExprPtr cond = nullptr, - BoolExprPtr step_cond = nullptr) : + EqualsExpr(gridPointPtr lhs, numExprPtr rhs, + boolExprPtr cond = nullptr, + boolExprPtr step_cond = nullptr) : _lhs(lhs), _rhs(rhs), _cond(cond), _step_cond(step_cond) { } EqualsExpr(const EqualsExpr& src) : _lhs(src._lhs->cloneGridPoint()), @@ -978,16 +978,16 @@ namespace yask { _step_cond = nullptr; } - GridPointPtr& getLhs() { return _lhs; } - const GridPointPtr& getLhs() const { return _lhs; } - NumExprPtr& getRhs() { return _rhs; } - const NumExprPtr& getRhs() const { return _rhs; } - BoolExprPtr& getCond() { return _cond; } - const BoolExprPtr& getCond() const { return _cond; } - void setCond(BoolExprPtr cond) { _cond = cond; } - BoolExprPtr& getStepCond() { return _step_cond; } - const BoolExprPtr& getStepCond() const { return _step_cond; } - void setStepCond(BoolExprPtr step_cond) { _step_cond = step_cond; } + gridPointPtr& getLhs() { return _lhs; } + const gridPointPtr& getLhs() const { return _lhs; } + numExprPtr& getRhs() { return _rhs; } + const numExprPtr& getRhs() const { return _rhs; } + boolExprPtr& getCond() { return _cond; } + const boolExprPtr& getCond() const { return _cond; } + void setCond(boolExprPtr cond) { _cond = cond; } + boolExprPtr& getStepCond() { return _step_cond; } + const boolExprPtr& getStepCond() const { return _step_cond; } + void setStepCond(boolExprPtr step_cond) { _step_cond = step_cond; } virtual string accept(ExprVisitor* ev); static string exprOpStr() { return "EQUALS"; } static string condOpStr() { return "IF"; } @@ -1007,7 +1007,7 @@ namespace yask { virtual bool isSame(const Expr* other) const; // Create a deep copy of this expression. - virtual EqualsExprPtr clone() const { return make_shared(*this); } + virtual equalsExprPtr clone() const { return make_shared(*this); } virtual yc_equation_node_ptr clone_ast() const { return clone(); } @@ -1036,7 +1036,7 @@ namespace yask { }; typedef set GridPointSet; - typedef set GridPointPtrSet; + typedef set gridPointPtrSet; typedef vector GridPointVec; // Use SET_VALUE_FROM_EXPR for creating a string to insert any C++ code diff --git a/src/compiler/lib/ExprUtils.cpp b/src/compiler/lib/ExprUtils.cpp index 83cb91ee..3f3405f3 100644 --- a/src/compiler/lib/ExprUtils.cpp +++ b/src/compiler/lib/ExprUtils.cpp @@ -73,7 +73,7 @@ namespace yask { // If 'ep' has already been seen, just return true. // Else if 'ep' has a match, change pointer to that match, return true. // Else, return false. - bool CseVisitor::findMatchTo(NumExprPtr& ep) { + bool CseVisitor::findMatchTo(numExprPtr& ep) { #if DEBUG_CSE >= 1 cout << " //** checking '" << ep->makeStr() << "'@" << ep << endl; #endif diff --git a/src/compiler/lib/ExprUtils.hpp b/src/compiler/lib/ExprUtils.hpp index 74e2dae8..d5a20455 100644 --- a/src/compiler/lib/ExprUtils.hpp +++ b/src/compiler/lib/ExprUtils.hpp @@ -77,12 +77,12 @@ namespace yask { // example: a+b+c * b+d+a => c+(a+b) * d+(a+b) w/expr a+b combined. class CseVisitor : public OptVisitor { protected: - set _seen; + set _seen; // If 'ep' has already been seen, just return true. // Else if 'ep' has a match, change pointer to that match, return true. // Else, return false. - virtual bool findMatchTo(NumExprPtr& ep); + virtual bool findMatchTo(numExprPtr& ep); public: CseVisitor() : diff --git a/src/compiler/lib/Grid.cpp b/src/compiler/lib/Grid.cpp index 117b810f..9ef7884f 100644 --- a/src/compiler/lib/Grid.cpp +++ b/src/compiler/lib/Grid.cpp @@ -47,7 +47,7 @@ namespace yask { } // Make args. - NumExprPtrVec args; + numExprPtrVec args; for (size_t i = 0; i < _dims.size(); i++) { auto p = dynamic_pointer_cast(index_exprs.at(i)); assert(p); @@ -55,7 +55,7 @@ namespace yask { } // Create a point from the args. - GridPointPtr gpp = make_shared(this, args); + gridPointPtr gpp = make_shared(this, args); return gpp; } @@ -71,7 +71,7 @@ namespace yask { // Check dim types. // Make default args w/just index. - NumExprPtrVec args; + numExprPtrVec args; for (size_t i = 0; i < _dims.size(); i++) { auto dim = _dims.at(i); if (dim->getType() == MISC_INDEX) { @@ -85,7 +85,7 @@ namespace yask { } // Create a point from the args. - GridPointPtr gpp = make_shared(this, args); + gridPointPtr gpp = make_shared(this, args); // Set the offsets, which creates a new // expression for each index. @@ -108,7 +108,7 @@ namespace yask { GridVar::GridVar(string name, bool isScratch, StencilSolution* soln, - const IndexExprPtrVec& dims) : + const indexExprPtrVec& dims) : _name(name), // TODO: validate that name is legal C++ var. _isScratch(isScratch), _soln(soln) diff --git a/src/compiler/lib/Grid.hpp b/src/compiler/lib/Grid.hpp index 5ef089d0..f52ec447 100644 --- a/src/compiler/lib/Grid.hpp +++ b/src/compiler/lib/Grid.hpp @@ -44,7 +44,7 @@ namespace yask { protected: string _name; // name of this grid. - IndexExprPtrVec _dims; // dimensions of this grid. + indexExprPtrVec _dims; // dimensions of this grid. bool _isScratch = false; // true if a temp grid. // Step-dim info. @@ -77,7 +77,7 @@ namespace yask { GridVar(string name, bool isScratch, StencilSolution* soln, - const IndexExprPtrVec& dims); + const indexExprPtrVec& dims); // Dtor. virtual ~GridVar() { } @@ -88,10 +88,10 @@ namespace yask { string getDescr() const; // Access dims. - virtual const IndexExprPtrVec& getDims() const { return _dims; } + virtual const indexExprPtrVec& getDims() const { return _dims; } // Step dim or null if none. - virtual const IndexExprPtr getStepDim() const { + virtual const indexExprPtr getStepDim() const { for (auto d : _dims) if (d->getType() == STEP_INDEX) return d; diff --git a/src/compiler/lib/Print.cpp b/src/compiler/lib/Print.cpp index 10a0af67..acd21970 100644 --- a/src/compiler/lib/Print.cpp +++ b/src/compiler/lib/Print.cpp @@ -156,7 +156,7 @@ namespace yask { string rhs = ee->getRhs()->accept(this); // Write statement with embedded rhs. - GridPointPtr gpp = ee->getLhs(); + gridPointPtr gpp = ee->getLhs(); _os << _ph.getLinePrefix() << _ph.writeToPoint(_os, *gpp, rhs); // Null ptr => no condition. @@ -441,7 +441,7 @@ namespace yask { makeNextTempVar(tmp, rp) << rhs << _ph.getLineSuffix(); // sets _exprStr. // Comment about update. - GridPointPtr gpp = ee->getLhs(); + gridPointPtr gpp = ee->getLhs(); _os << "\n // Update value at " << gpp->makeStr(); // Comment about condition. diff --git a/src/compiler/lib/Print.hpp b/src/compiler/lib/Print.hpp index 7099af06..9787f2eb 100644 --- a/src/compiler/lib/Print.hpp +++ b/src/compiler/lib/Print.hpp @@ -350,7 +350,7 @@ namespace yask { } return key; } - virtual string getLabel(ExprPtr ep, bool once = true) { + virtual string getLabel(exprPtr ep, bool once = true) { return getLabel(ep.get(), once); } diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 6ccc506a..d32167f7 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -41,7 +41,7 @@ namespace yask { // TODO: fix this mem leak--make smart ptr. // Copy pointers to concrete type. - IndexExprPtrVec dims2; + indexExprPtrVec dims2; for (auto d : dims) { auto d2 = dynamic_pointer_cast(d); assert(d2); diff --git a/src/compiler/lib/Vec.cpp b/src/compiler/lib/Vec.cpp index 4186a15c..b1a836ba 100644 --- a/src/compiler/lib/Vec.cpp +++ b/src/compiler/lib/Vec.cpp @@ -219,7 +219,7 @@ namespace yask { string ExprReorderVisitor::visit(CommutativeExpr* ce) { auto& oev = ce->getOps(); // old exprs. - NumExprPtrVec nev; // new exprs. + numExprPtrVec nev; // new exprs. // Simple, greedy algorithm: // Select first element that needs the fewest new aligned vecs. From cad6799701253fbd1dc1dd4997d86509d08ca142 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 3 May 2019 17:34:04 -0700 Subject: [PATCH 03/62] Add APIs for new-style solutions for the compiler utility. --- include/Soln.hpp | 320 ++--------- include/yask_compiler_api.hpp | 129 ++++- include/yask_compiler_utility_api.hpp | 177 ++++++ include/yc_node_api.hpp | 739 +++++++++++++++----------- src/common/common.mk | 4 + src/compiler/Makefile | 19 +- src/compiler/compiler_main.cpp | 13 +- src/compiler/lib/Expr.cpp | 246 ++++----- 8 files changed, 904 insertions(+), 743 deletions(-) create mode 100644 include/yask_compiler_utility_api.hpp diff --git a/include/Soln.hpp b/include/Soln.hpp index 21a92aff..b2994156 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -25,292 +25,57 @@ IN THE SOFTWARE. // This file contains convenience functions and macros for defining // stencils to be included in the YASK compiler binary utility. +// It is to be used only for backward compatibility for old-style +// stencil DSL code before YASK version 2.23.00. #pragma once -// Standard headers not provided by API. -#include - -// These functions and macros are built upon the YASK compiler APIs. -#include "yask_compiler_api.hpp" +// These functions and macros are built upon the YASK compiler utility APIs. +#include "yask_compiler_utility_api.hpp" namespace yask { - // Forward defn. - class StencilBase; - - // Function provided by the YASK compiler binary utility - // to create a new solution and register 'base_ptr' - // as a known StencilBase object. - yc_solution_ptr yc_new_solution(const std::string& name, - StencilBase* base_ptr); - - // Dummy type and object for backward-compatibility. + /// Dummy type for backward-compatibility. class StencilList { }; - extern StencilList stub_stencils; - // The class all C++ stencil solutions written for the YASK compiler - // binary must implement. Mostly, this is a wrapper around a - // 'yc_solution_ptr'. The 'define()' method must be overloaded by - // the YASK DSL programmer to add stencil equations. - class StencilBase { - protected: - - // Pointer to the YASK stencil solution. - yc_solution_ptr _soln; + /// Dummy object from compiler utility for backward-compatibility. + extern StencilList stub_stencils; - // Factory to create new nodes. - yc_node_factory _node_factory; + /// **[Deprecated]** The class all old-style C++ stencil solutions + /// written for the YASK compiler binary must implement. + class StencilBase : public yc_solution_base { public: - // Constructor. Creates a new yc_solution object and - // registers this object in the list for the YASK compiler. - // The 'define()' method will be called from the YASK - // compiler for the selected solution. - StencilBase(const std::string name) { - _soln = yc_new_solution(name, this); - } - - // Constructor that uses an existing StencilBase to share underlying - // solutions. When using this version, the 'define()' method will - // not be called directly from the YASK compiler, but it (or any - // other method) may be called by the parent 'base' object - // explicitly. - StencilBase(StencilBase& base) { - _soln = base.get_solution(); - } - - // Backward-compatibility contructor. Deprecated. - StencilBase(const std::string name, StencilList& stencils) : - StencilBase(name) { } + /// Backward-compatibility contructor. + StencilBase(const std::string& name, StencilList& stencils) : + yc_solution_base(name) { } - // Destructor. - virtual ~StencilBase() { } - - // Define grid values relative to current domain indices in each dimension. - // This must be implemented by each concrete stencil solution. - virtual void define() { - std::cout << "Warning: no stencil equations are defined in solution '" << - _soln->get_name() << "'\n"; - } - - // Accessors. - virtual yc_solution_ptr get_solution() { - return _soln; - } - virtual yc_node_factory& get_node_factory() { - return _node_factory; - } - - // Create a constant expression. - // Usually not needed due to operator overloading. + /// Create a constant expression. + /** Usually not needed due to operator overloading. */ virtual yc_number_node_ptr constNum(double val) { return _node_factory.new_const_number_node(val); } - - // Create boundary indices, e.g., 'first_index(x)'. - virtual yc_number_node_ptr first_index(yc_index_node_ptr dim) { - return _node_factory.new_first_domain_index(dim); - } - virtual yc_number_node_ptr last_index(yc_index_node_ptr dim) { - return _node_factory.new_last_domain_index(dim); - } - - // Radius-access methods. The default implementations indicate that - // the solution does not use the "radius" sizing feature. - virtual bool uses_radius() const { return false; } - virtual bool set_radius(int radius) { return false; } - virtual int get_radius() const { return 0; } }; - // A base class for stencils that have a 'radius'. - class StencilRadiusBase : public StencilBase { - protected: - - // A variable that controls the size the stencil, i.e., the number of - // points that are read to calculate a new value. In many cases, - // this is the number of points in the spatial dimension(s) from the - // center point of a finite-difference approximation, but it does - // not have to be. For example, it could be the minimum or maximum - // radius for an asymmetical stencil. - int _radius; + /// **[Deprecated]** A base class for stencils that have a 'radius'. + class StencilRadiusBase : public yc_solution_with_radius_base { public: - // Constructor. - StencilRadiusBase(const std::string name, int radius) : - StencilBase(name) { - set_radius(radius); - } - - // Backward-compatibility constructor. - StencilRadiusBase(const std::string name, StencilList& stencils, int radius) : - StencilRadiusBase(name, radius) { - } - - // This object does use radius. - virtual bool uses_radius() const override { return true; } - - // Set radius. - // Return true if successful. - virtual bool set_radius(int radius) override { - _radius = radius; - _soln->set_description(_soln->get_name() + " radius " + std::to_string(radius)); - return radius >= 0; // support only non-neg. radius. - } - - // Get radius. - virtual int get_radius() const override { return _radius; } - }; - - // A simple wrapper to provide automatic construction - // of a NumExpr ptr from other types. - class NumExprArg : public yc_number_node_ptr { - - // Factory to create new nodes. - yc_node_factory _node_factory; - // Create a constant expression. + /// Backward-compatibility constructor. + StencilRadiusBase(const std::string& name, StencilList& stencils, int radius) : + yc_solution_with_radius_base(name, radius) { } + + /// Create a constant expression. + /** Usually not needed due to operator overloading. */ virtual yc_number_node_ptr constNum(double val) { return _node_factory.new_const_number_node(val); } - - public: - NumExprArg(yc_number_node_ptr p) : - yc_number_node_ptr(p) { } - NumExprArg(yc_index_node_ptr p) : - yc_number_node_ptr(p) { } - NumExprArg(idx_t i) : - yc_number_node_ptr(constNum(i)) { } - NumExprArg(int i) : - yc_number_node_ptr(constNum(i)) { } - NumExprArg(double f) : - yc_number_node_ptr(constNum(f)) { } - }; - - // A wrapper class around a 'yc_grid_ptr', providing - // convenience functions for declaring grid vars and - // creating expression nodes with references to points - // in grid vars. - class Grid { - protected: - yc_grid_ptr _grid; - typedef std::vector num_node_vec; - - public: - - // Contructor taking a vector of index vars. - Grid(const std::string& name, - bool is_scratch, - yc_solution_ptr soln, - const std::vector< yc_index_node_ptr > &dims) { - if (is_scratch) - _grid = soln->new_scratch_grid(name, dims); - else - _grid = soln->new_grid(name, dims); - } - - // Contructor taking an initializer_list of index vars. - Grid(const std::string& name, - bool is_scratch, - yc_solution_ptr soln, - const std::initializer_list< yc_index_node_ptr > &dims) { - if (is_scratch) - _grid = soln->new_scratch_grid(name, dims); - else - _grid = soln->new_grid(name, dims); - } - - // Convenience wrapper functions around 'new_grid_point()'. - // These allow a simplified syntax for creating grid point - // nodes. Example usage for defining equation for grid 'A': - // 0D grid var 'B': A(t+1, x) EQUALS A(t, x) + B. - // 0D grid var 'B': A(t+1, x) EQUALS A(t, x) + B(). - // 1D grid var 'B': A(t+1, x) EQUALS A(t, x) + B(x). - // 1D grid var 'B': A(t+1, x) EQUALS A(t, x) + B[x]. - // 2D grid var 'B': A(t+1, x) EQUALS A(t, x) + B(x, 4). - - // Convenience functions for zero dimensions (scalar). - virtual operator yc_number_node_ptr() { // implicit conversion. - return _grid->new_grid_point({}); - } - virtual operator yc_grid_point_node_ptr() { // implicit conversion. - return _grid->new_grid_point({}); - } - virtual yc_grid_point_node_ptr operator()() { - return _grid->new_grid_point({}); - } - - // Convenience functions for one dimension (array). - virtual yc_grid_point_node_ptr operator[](const NumExprArg i1) { - num_node_vec args; - args.push_back(i1); - return _grid->new_grid_point(args); - } - virtual yc_grid_point_node_ptr operator()(const NumExprArg i1) { - return operator[](i1); - } - - // Convenience functions for more dimensions. - virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, - const NumExprArg i2) { - num_node_vec args; - args.push_back(i1); - args.push_back(i2); - return _grid->new_grid_point(args); - } - virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, - const NumExprArg i2, - const NumExprArg i3) { - num_node_vec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - return _grid->new_grid_point(args); - } - virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, - const NumExprArg i2, - const NumExprArg i3, - const NumExprArg i4) { - num_node_vec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - args.push_back(i4); - return _grid->new_grid_point(args); - } - virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, - const NumExprArg i2, - const NumExprArg i3, - const NumExprArg i4, - const NumExprArg i5) { - num_node_vec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - args.push_back(i4); - args.push_back(i5); - return _grid->new_grid_point(args); - } - virtual yc_grid_point_node_ptr operator()(const NumExprArg i1, - const NumExprArg i2, - const NumExprArg i3, - const NumExprArg i4, - const NumExprArg i5, - const NumExprArg i6) { - num_node_vec args; - args.push_back(i1); - args.push_back(i2); - args.push_back(i3); - args.push_back(i4); - args.push_back(i5); - args.push_back(i6); - return _grid->new_grid_point(args); - } - }; - // Aliases for expression types. + // Aliases for backward-compatibility. + typedef yc_grid_var Grid; typedef yc_number_node_ptr GridIndex; typedef yc_number_node_ptr GridValue; typedef yc_bool_node_ptr Condition; @@ -322,28 +87,31 @@ namespace yask { } // namespace yask. -// Macro for backward compatibility. +/// Macro for backward compatibility. #define REGISTER_STENCIL_CONTEXT_EXTENSION(...) -// Convenience macro for declaring an instance of a stencil and registering -// it in the list used by the default provided YASK compiler binary. -#define REGISTER_STENCIL(class_name) static class_name registered_ ## class_name(stub_stencils) - -// Convenience macros for declaring dims in a class implementing get_node_factory(). -// The 'd' arg is the new var name and the dim name. -#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = get_node_factory().new_step_index(#d); -#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = get_node_factory().new_domain_index(#d); -#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = get_node_factory().new_misc_index(#d); - -// Convenience macros for creating grids in a class implementing get_solution(). -// The 'gvar' arg is the var name and the grid name. -// The remaining args are the dimension names. +/// Convenience macro for declaring an object of a type derived from \ref StencilBase +/// and registering it in the list used by the default provided YASK compiler binary. +/** The derived class must implement a constructor that takes only a \ref StencilList + reference. */ +#define REGISTER_STENCIL(class_name) \ + static class_name registered_ ## class_name(stub_stencils) + +/// Convenience macros for declaring dims in a class derived from \ref StencilBase. +/// The 'd' arg is the new var name and the dim name. +#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = _node_factory.new_step_index(#d); +#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = _node_factory.new_domain_index(#d); +#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = _node_factory.new_misc_index(#d); + +/// Convenience macros for creating grids in a class implementing get_solution(). +/// The 'gvar' arg is the var name and the grid name. +/// The remaining args are the dimension names. #define MAKE_GRID(gvar, ...) \ - Grid gvar = Grid(#gvar, false, get_solution(), { __VA_ARGS__ }) + Grid gvar = Grid(#gvar, get_solution(), { __VA_ARGS__ }, false) #define MAKE_SCALAR(gvar) MAKE_GRID(gvar) #define MAKE_ARRAY(gvar, d1) MAKE_GRID(gvar, d1) #define MAKE_SCRATCH_GRID(gvar, ...) \ - Grid gvar = Grid(#gvar, true, get_solution(), { __VA_ARGS__ }) + Grid gvar = Grid(#gvar, get_solution(), { __VA_ARGS__ }, true) #define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) #define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 6bf45b9d..88a4bf45 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -189,7 +189,7 @@ namespace yask { */ virtual yc_grid_ptr new_grid(const std::string& name - /**< [in] Unique name of the grid; must be a valid C++ + /**< [in] Name of the new grid; must be a valid C++ identifier and unique across grids. */, const std::vector& dims /**< [in] Dimensions of the grid. @@ -204,7 +204,7 @@ namespace yask { @returns Pointer to the new \ref yc_grid object. */ virtual yc_grid_ptr - new_grid(const std::string& name /**< [in] Unique name of the grid; must be + new_grid(const std::string& name /**< [in] Name of the new grid; must be a valid C++ identifier and unique across grids. */, const std::initializer_list& dims @@ -230,7 +230,7 @@ namespace yask { */ virtual yc_grid_ptr new_scratch_grid(const std::string& name - /**< [in] Unique name of the grid; must be a valid C++ + /**< [in] Name of the new grid; must be a valid C++ identifier and unique across grids. */, const std::vector& dims /**< [in] Dimensions of the grid. @@ -246,7 +246,7 @@ namespace yask { */ virtual yc_grid_ptr new_scratch_grid(const std::string& name - /**< [in] Unique name of the grid; must be + /**< [in] Name of the new grid; must be a valid C++ identifier and unique across grids. */, const std::initializer_list& dims @@ -622,6 +622,127 @@ namespace yask { /**< [in] Number of elements to allocate in the step dimension. */) =0; }; + /// A wrapper class around a 'yc_grid_ptr', providing + /// convenience functions for declaring grid vars and + /// creating expression nodes with references to points + /// in grid vars. + class yc_grid_var { + private: + yc_grid_ptr _grid; + + public: + + /// Contructor taking a vector of index vars. + yc_grid_var(const std::string& name + /**< [in] Name of the new grid; must be a valid C++ + identifier and unique across grids. */, + yc_solution_ptr soln + /**< [in] Pointer to solution that will own the grid. */, + const std::vector< yc_index_node_ptr > &dims + /**< [in] Dimensions of the grid. + Each dimension is identified by an associated index. */, + bool is_scratch = false + /**< [in] Whether to make a scratch grid. */) { + if (is_scratch) + _grid = soln->new_scratch_grid(name, dims); + else + _grid = soln->new_grid(name, dims); + } + + // Contructor taking an initializer_list of index vars. + yc_grid_var(const std::string& name + /**< [in] Name of the new grid; must be a valid C++ + identifier and unique across grids. */, + yc_solution_ptr soln + /**< [in] Pointer to solution that will own the grid. */, + const std::initializer_list< yc_index_node_ptr > &dims + /**< [in] Dimensions of the grid. + Each dimension is identified by an associated index. */, + bool is_scratch = false + /**< [in] Whether to make a scratch grid. */) { + if (is_scratch) + _grid = soln->new_scratch_grid(name, dims); + else + _grid = soln->new_grid(name, dims); + } + + /// Get the underlying \ref yc_grid_ptr. + virtual yc_grid_ptr get_grid() { + return _grid; + } + + /// Get the underlying \ref yc_grid_ptr. + virtual const yc_grid_ptr get_grid() const { + return _grid; + } + + /// Create an expression for a point in a zero-dim (scalar) grid + /// using implicit conversion. + /** + Example w/0D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B`. + */ + virtual operator yc_number_arg_ptr() { + return _grid->new_grid_point({}); + } + + /// Create an expression for a point in a one-dim (array) grid. + /** + Example w/1D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. + */ + virtual yc_grid_point_node_ptr operator[](const yc_number_arg_any i1) { + return _grid->new_grid_point({i1}); + } + + /// Create an expression for a point in a 1-6 dim grid. + /// The number of arguments must match the dimensionality of the grid. + /** + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. + */ + virtual yc_grid_point_node_ptr operator()(const yc_number_arg_any i1 = nullptr, + const yc_number_arg_any i2 = nullptr, + const yc_number_arg_any i3 = nullptr, + const yc_number_arg_any i4 = nullptr, + const yc_number_arg_any i5 = nullptr, + const yc_number_arg_any i6 = nullptr) { + std::vector args; + if (i1) + args.push_back(i1); + if (i2) + args.push_back(i2); + if (i3) + args.push_back(i3); + if (i4) + args.push_back(i4); + if (i5) + args.push_back(i5); + if (i6) + args.push_back(i6); + return _grid->new_grid_point(args); + } + + /// Create an expression for a point in any grid. + /// The number of arguments must match the dimensionality of the grid. + /// Create an expression for a point in a 1-6 dim grid. + /// The number of arguments must match the dimensionality of the grid. + /** + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, + where `vec` is a 2-element vector of \ref yc_number_node_ptr. + */ + virtual yc_grid_point_node_ptr + operator()(const std::vector& index_exprs) { + return _grid->new_grid_point(index_exprs); + } + + /// Create an expression for a point in a grid. + /// The number of arguments must match the dimensionality of the grid. + /** + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. + */ + virtual yc_grid_point_node_ptr + operator()(const std::initializer_list& index_exprs) { + return _grid->new_grid_point(index_exprs); + } + }; /** @}*/ } // namespace yask. diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp new file mode 100644 index 00000000..57aa7646 --- /dev/null +++ b/include/yask_compiler_utility_api.hpp @@ -0,0 +1,177 @@ +/***************************************************************************** + +YASK: Yet Another Stencil Kernel +Copyright (c) 2014-2019, Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +* The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +*****************************************************************************/ + +// This file contains a base class and macros to create +// stencils to be included in the YASK compiler binary utility. +/** @file yask_compiler_utility_api.hpp */ + +#pragma once + +// Standard headers not provided by API. +#include + +// These functions and macros are built upon the YASK compiler APIs. +#include "yask_compiler_api.hpp" + +namespace yask { + + /** + * \addtogroup yc + * @{ + */ + + // Forward defn. + class yc_solution_base; + + /// Function provided by the YASK compiler binary utility + /// to create a new solution and register 'base_ptr' + /// as a known \ref yc_solution_base object. + yc_solution_ptr yc_new_solution(const std::string& name, + yc_solution_base* base_ptr); + + /// The class all C++ stencil solutions written for the YASK compiler + /// binary must implement. + /** + Mostly, this is a wrapper around a \ref yc_solution_ptr. + The `define()` method must be overloaded by + the YASK DSL programmer to add stencil equations. + */ + class yc_solution_base { + protected: + + // Pointer to the YASK stencil solution. + yc_solution_ptr _soln; + + // Factory to create new nodes. + yc_node_factory _node_factory; + + public: + + /// Commonly-used constructor. + /** + Creates a new yc_solution object and + registers this object in the list for the YASK compiler. + The `define()` method will be called from the YASK + compiler for the selected solution. + */ + yc_solution_base(const std::string& name) { + _soln = yc_new_solution(name, this); + } + + /// Constructor that uses an existing yc_solution_base to share underlying + /// solutions. + /** + This constructor allows the use of object-oriented composition + instead of inheritance when creating classes that participate + in solution definition. + When using this version, the `define()` method will + _not_ be called directly from the YASK compiler, but it (or any + other method) may be called by the parent 'base' object + explicitly. + */ + yc_solution_base(yc_solution_base& base) { + _soln = base.get_solution(); + } + + /// Destructor. + virtual ~yc_solution_base() { } + + // Define grid values relative to current domain indices in each dimension. + // This must be implemented by each concrete stencil solution. + virtual void define() { + std::cout << "Warning: no stencil equations are defined in solution '" << + _soln->get_name() << "'\n"; + } + + /// Access the underlying solution. + virtual yc_solution_ptr get_solution() { + return _soln; + } + + + /// Create boundary index expression, e.g., 'first_index(x)'. + virtual yc_number_node_ptr first_index(yc_index_node_ptr dim) { + return _node_factory.new_first_domain_index(dim); + } + + /// Create boundary index expression, e.g., 'last_index(x)'. + virtual yc_number_node_ptr last_index(yc_index_node_ptr dim) { + return _node_factory.new_last_domain_index(dim); + } + + /// This solution does _not_ use the "radius" sizing feature. + virtual bool uses_radius() const { return false; } + + /// Dummy function for setting radius. + virtual bool set_radius(int radius) { return false; } + + /// Dummy function for accessing radius. + virtual int get_radius() const { return 0; } + }; + + /// A base class for stencils that have a 'radius'. + class yc_solution_with_radius_base : public yc_solution_base { + protected: + + // A variable that controls the size the stencil, i.e., the number of + // points that are read to calculate a new value. In many cases, + // this is the number of points in the spatial dimension(s) from the + // center point of a finite-difference approximation, but it does + // not have to be. For example, it could be the minimum or maximum + // radius for an asymmetical stencil. + int _radius; + + public: + // Constructor. + yc_solution_with_radius_base(const std::string& name, int radius) : + yc_solution_base(name) { + set_radius(radius); + } + + /// This object does use radius. + virtual bool uses_radius() const override { return true; } + + /// Set radius. + /** @returns `true` if successful. */ + virtual bool set_radius(int radius) override { + _radius = radius; + _soln->set_description(_soln->get_name() + " radius " + std::to_string(radius)); + return radius >= 0; // support only non-neg. radius. + } + + /// Get radius. + virtual int get_radius() const override { return _radius; } + }; + + /** @}*/ + +} // namespace yask. + +/// Convenience macro for declaring a static object of a type derived from +/// \ref yc_solution_base and registering it in the list used by the +/// provided YASK compiler utility. +/** The derived class must implement a default constructor. */ +#define YASK_REGISTER_SOLUTION(class_name) \ + static class_name registered_ ## class_name() diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index 08f09d7c..464a3444 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -120,288 +120,6 @@ namespace yask { /// Shared pointer to \ref yc_or_node typedef std::shared_ptr yc_or_node_ptr; - - /// Factory to create AST nodes. - /** @note Grid-point reference nodes are created from a \ref yc_grid object - instead of from a \ref yc_node_factory. */ - class yc_node_factory { - public: - virtual ~yc_node_factory() {} - - /// Create a step-index node. - /** - Create a variable to be used to index grids in the - solution-step dimension. - The name usually describes time, e.g. "t". - @returns Pointer to new \ref yc_index_node object. - */ - virtual yc_index_node_ptr - new_step_index(const std::string& name - /**< [in] Step dimension name. */ ); - - /// Create a domain-index node. - /** - Create a variable to be used to index grids in the - solution-domain dimension. - The name usually describes spatial dimensions, e.g. "x" or "y", - but it can be any dimension that is specified at run-time, - such as an index into a number of parallel problems - being solved simultaneously. - - @note This should *not* include the step dimension, which is specified via - new_step_index(). - @returns Pointer to new \ref yc_index_node object. - */ - virtual yc_index_node_ptr - new_domain_index(const std::string& name - /**< [in] Domain index name. */ ); - - /// Create a new miscellaneous index. - /** - Create an variable to be used to index grids in the - some dimension that is not the step dimension - or a domain dimension. - The value of these indices are normally compile-time - constants, e.g., a fixed index into an array. - @returns Pointer to new \ref yc_index_node object. - */ - virtual yc_index_node_ptr - new_misc_index(const std::string& name - /**< [in] Index name. */ ); - - /// Create an equation node. - /** Indicates grid point on LHS is equivalent to expression on - RHS. This is NOT a test for equality. When an equation is - created, it is automatically added to the list of equations for - the yc_solution that contains the grid that is on the - LHS. - - An optional domain condition may be provided to define the sub-domain - to which this equation applies. - Domain conditions are always evaluated with respect to the overall - problem domain, i.e., independent of any specific - MPI domain decomposition that might occur at run-time. - If a domain condition is not provided, the equation applies to the - entire problem domain. - A domain condition can be added to an equation after its creation - via yc_equation_node.set_cond(). - See yc_equation_node.set_cond() for more information and an example. - - A step condition is similar to a domain condition, but - enables or disables the entire equation based on the current step (usually time) - and/or other values. - A step condition can only be added to an equation after its creation - via yc_equation_node.set_step_cond(). - See yc_equation_node.set_step_cond() for more information and an example. - - @returns Pointer to new \ref yc_equation_node object. - */ - virtual yc_equation_node_ptr - new_equation_node(yc_grid_point_node_ptr lhs - /**< [in] Grid-point before EQUALS operator. */, - yc_number_node_ptr rhs - /**< [in] Expression after EQUALS operator. */, - yc_bool_node_ptr sub_domain_cond = nullptr - /**< [in] Optional expression defining sub-domain - where `lhs EQUALS rhs` is valid. */ ); - - /// Create a constant numerical value node. - /** - Use to add a constant to an expression. - The overloaded arithmetic operators allow `double` arguments, - so in most cases, it is not necessary to call this directly. - @returns Pointer to new \ref yc_const_number_node object. - */ - virtual yc_number_node_ptr - new_const_number_node(double val /**< [in] Value to store in node. */ ); - - /// Create a constant numerical value node. - /** - Integer version of new_const_number_node(double). - It may be necessary to cast other integer types to `idx_t` to - avoid ambiguous overloading of this function. - @returns Pointer to new \ref yc_const_number_node object. - */ - virtual yc_number_node_ptr - new_const_number_node(idx_t val /**< [in] Value to store in node. */ ); - - /// Create a numerical negation operator node. - /** - New negation nodes can also be created via the overloaded unary `-` operator. - @returns Pointer to new \ref yc_negate_node object. - */ - virtual yc_number_node_ptr - new_negate_node(yc_number_node_ptr rhs /**< [in] Expression after `-` sign. */ ); - - /// Create an addition node. - /** - New addition nodes can also be created via the overloaded `+` operator. - @returns Pointer to new \ref yc_add_node object. - Returns `rhs` if `lhs` is a null node pointer and vice-versa. - */ - virtual yc_number_node_ptr - new_add_node(yc_number_node_ptr lhs /**< [in] Expression before `+` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `+` sign. */ ); - - /// Create a multiplication node. - /** - New multiplication nodes can also be created via the overloaded `*` operator. - @returns Pointer to new \ref yc_multiply_node object. - Returns `rhs` if `lhs` is a null node pointer and vice-versa. - */ - virtual yc_number_node_ptr - new_multiply_node(yc_number_node_ptr lhs /**< [in] Expression before `*` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `*` sign. */ ); - - /// Create a subtraction node. - /** - This is binary subtraction. - Use new_negation_node() for unary `-`. - - New subtraction nodes can also be created via the overloaded `-` operator. - @returns Pointer to new \ref yc_subtract_node object. - Returns `- rhs` if `lhs` is a null node pointer and - `lhs` if `rhs` is null. - */ - virtual yc_number_node_ptr - new_subtract_node(yc_number_node_ptr lhs /**< [in] Expression before `-` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `-` sign. */ ); - - /// Create a division node. - /** - New division nodes can also be created via the overloaded `/` operator. - @returns Pointer to new \ref yc_divide_node object. - Returns `1.0 / rhs` if `lhs` is a null node pointer and - `lhs` if `rhs` is null. - */ - virtual yc_number_node_ptr - new_divide_node(yc_number_node_ptr lhs /**< [in] Expression before `/` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `/` sign. */ ); - - /// Create a modulo node. - /** - New modulo nodes can also be created via the overloaded `%` operator. - The modulo operator converts both operands to integers before performing - the operation. - @returns Pointer to new \ref yc_mod_node object. - */ - virtual yc_number_node_ptr - new_mod_node(yc_number_node_ptr lhs /**< [in] Expression before `%` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `%` sign. */ ); - - /// Create a symbol for the first index value in a given dimension. - /** - Create an expression that indicates the first value in the overall problem - domain in `dim` dimension. - The `dim` argument is created via new_domain_index(). - - See yc_equation_node.set_cond() for more information and an example. - - @returns Pointer to new \ref yc_index_node object. - */ - virtual yc_number_node_ptr - new_first_domain_index(yc_index_node_ptr idx - /**< [in] Domain index. */ ); - - /// Create a symbol for the last index value in a given dimension. - /** - Create an expression that indicates the last value in the overall problem - domain in `dim` dimension. - The `dim` argument is created via new_domain_index(). - - See yc_equation_node.set_cond() for more information and an example. - - @returns Pointer to new \ref yc_index_node object. - */ - virtual yc_number_node_ptr - new_last_domain_index(yc_index_node_ptr idx - /**< [in] Domain index. */ ); - - /// Create a binary inverse operator node. - /** - New "not" nodes can also be created via the overloaded `!` operator - or the `yc_not` function in Python. - @returns Pointer to new \ref yc_not_node object. - */ - virtual yc_bool_node_ptr - new_not_node(yc_bool_node_ptr rhs /**< [in] Expression after `!` sign. */ ); - - /// Create a boolean 'and' node. - /** - New "and" nodes can also be created via the overloaded `&&` operator - or the `yc_and` function in Python. - @returns Pointer to new \ref yc_and_node object. - */ - virtual yc_bool_node_ptr - new_and_node(yc_bool_node_ptr lhs /**< [in] Expression before `&&` sign. */, - yc_bool_node_ptr rhs /**< [in] Expression after `&&` sign. */ ); - - /// Create a boolean 'or' node. - /** - New "or" nodes can also be created via the overloaded `||` operator - or the `yc_or` function in Python. - @returns Pointer to new \ref yc_or_node object. - */ - virtual yc_bool_node_ptr - new_or_node(yc_bool_node_ptr lhs /**< [in] Expression before `||` sign. */, - yc_bool_node_ptr rhs /**< [in] Expression after `||` sign. */ ); - - /// Create a numerical-comparison 'equals' node. - /** - New "equals" nodes can also be created via the overloaded `==` operator. - @returns Pointer to new \ref yc_equals_node object. - */ - virtual yc_bool_node_ptr - new_equals_node(yc_number_node_ptr lhs /**< [in] Expression before `==` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `==` sign. */ ); - - /// Create a numerical-comparison 'not-equals' node. - /** - New "not-equals" nodes can also be created via the overloaded `!=` operator. - @returns Pointer to new \ref yc_not_equals_node object. - */ - virtual yc_bool_node_ptr - new_not_equals_node(yc_number_node_ptr lhs /**< [in] Expression before `!=` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `!=` sign. */ ); - - /// Create a numerical-comparison 'less-than' node. - /** - New "less-than" nodes can also be created via the overloaded `<` operator. - @returns Pointer to new \ref yc_less_than_node object. - */ - virtual yc_bool_node_ptr - new_less_than_node(yc_number_node_ptr lhs /**< [in] Expression before `<` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `<` sign. */ ); - - /// Create a numerical-comparison 'greater-than' node. - /** - New "greater-than" nodes can also be created via the overloaded `>` operator. - @returns Pointer to new \ref yc_greater_than_node object. - */ - virtual yc_bool_node_ptr - new_greater_than_node(yc_number_node_ptr lhs /**< [in] Expression before `>` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `>` sign. */ ); - - /// Create a numerical-comparison 'greater-than or equals' node. - /** - New "greater-than or equals" nodes can also be created via the overloaded `>=` operator. - @returns Pointer to new \ref yc_not_less_than_node object. - */ - virtual yc_bool_node_ptr - new_not_less_than_node(yc_number_node_ptr lhs /**< [in] Expression before `>=` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `>=` sign. */ ); - - /// Create a numerical-comparison 'less-than or equals' node. - /** - New "less-than or equals" nodes can also be created via the overloaded `<=` operator. - @returns Pointer to new \ref yc_not_greater_than_node object. - */ - virtual yc_bool_node_ptr - new_not_greater_than_node(yc_number_node_ptr lhs /**< [in] Expression before `<=` sign. */, - yc_number_node_ptr rhs /**< [in] Expression after `<=` sign. */ ); - - }; - /// Base class for all AST nodes. /** An object of this abstract type cannot be created. */ class yc_expr_node { @@ -755,75 +473,464 @@ namespace yask { */ class yc_not_greater_than_node : public virtual yc_binary_comparison_node { }; - // Non-class operators. - // These are only defined if the older "internal DSL" is not used. - // The internal version will eventually be deprecated and - // perhaps removed in favor of this API. - // Also, these are not defined for SWIG because - // the Python operators are defined in the ".i" file. + /// A simple wrapper class to provide automatic + /// construction of a 'yc_number_node_ptr' from + /// other YASK pointer types. + class yc_number_arg_ptr : public virtual yc_number_node_ptr { -#if !defined SWIG + public: + + /// Arg can be a number-node pointer. + yc_number_arg_ptr(yc_number_node_ptr p) : + yc_number_node_ptr(p) { } + + /// Arg can be an index-node pointer. + yc_number_arg_ptr(yc_index_node_ptr p) : + yc_number_node_ptr(p) { } + + /// Arg can be a grid-point-node pointer. + yc_number_arg_ptr(yc_grid_point_node_ptr p) : + yc_number_node_ptr(p) { } + }; + + /// A simple wrapper class to provide automatic + /// construction of a 'yc_number_node_ptr' from + /// non-YASK fundamental numeric types. + class yc_number_arg_const : public virtual yc_number_node_ptr { + + protected: + + /// Create an argument from a constant value. + virtual yc_number_node_ptr _convert_const(double val) const; + + public: + + /// Arg can be an index type. + yc_number_arg_const(idx_t i) : + yc_number_node_ptr(_convert_const(i)) { } + + /// Arg can be an int. + yc_number_arg_const(int i) : + yc_number_node_ptr(_convert_const(i)) { } + + /// Arg can be a double. + yc_number_arg_const(double f) : + yc_number_node_ptr(_convert_const(f)) { } + + /// Arg can be a float. + yc_number_arg_const(float f) : + yc_number_node_ptr(_convert_const(f)) { } + }; + + /// A simple wrapper class to provide automatic + /// construction of a 'yc_number_node_ptr' from + /// a YASK pointer or non-YASK fundamental numeric types. + class yc_number_arg_any : public virtual yc_number_node_ptr { + + protected: + + /// Create an argument from a constant value. + virtual yc_number_node_ptr _convert_const(double val) const; + + public: + + /// Arg can be a number-node pointer. + yc_number_arg_any(yc_number_node_ptr p) : + yc_number_node_ptr(p) { } + + /// Arg can be an index-node pointer. + yc_number_arg_any(yc_index_node_ptr p) : + yc_number_node_ptr(p) { } + + /// Arg can be a grid-point-node pointer. + yc_number_arg_any(yc_grid_point_node_ptr p) : + yc_number_node_ptr(p) { } + + /// Arg can be an index type. + yc_number_arg_any(idx_t i) : + yc_number_node_ptr(_convert_const(i)) { } + + /// Arg can be an int. + yc_number_arg_any(int i) : + yc_number_node_ptr(_convert_const(i)) { } + + /// Arg can be a double. + yc_number_arg_any(double f) : + yc_number_node_ptr(_convert_const(f)) { } + + /// Arg can be a float. + yc_number_arg_any(float f) : + yc_number_node_ptr(_convert_const(f)) { } + + /// Arg can be a null pointer. + yc_number_arg_any(std::nullptr_t p) : + yc_number_node_ptr(p) { } + }; + + /// Factory to create AST nodes. + /** @note Grid-point reference nodes are created from a \ref yc_grid object + instead of from a \ref yc_node_factory. */ + class yc_node_factory { + public: + virtual ~yc_node_factory() {} + + /// Create a step-index node. + /** + Create a variable to be used to index grids in the + solution-step dimension. + The name usually describes time, e.g. "t". + @returns Pointer to new \ref yc_index_node object. + */ + virtual yc_index_node_ptr + new_step_index(const std::string& name + /**< [in] Step dimension name. */ ) const; + + /// Create a domain-index node. + /** + Create a variable to be used to index grids in the + solution-domain dimension. + The name usually describes spatial dimensions, e.g. "x" or "y", + but it can be any dimension that is specified at run-time, + such as an index into a number of parallel problems + being solved simultaneously. + + @note This should *not* include the step dimension, which is specified via + new_step_index(). + @returns Pointer to new \ref yc_index_node object. + */ + virtual yc_index_node_ptr + new_domain_index(const std::string& name + /**< [in] Domain index name. */ ) const; + + /// Create a new miscellaneous index. + /** + Create an variable to be used to index grids in the + some dimension that is not the step dimension + or a domain dimension. + The value of these indices are normally compile-time + constants, e.g., a fixed index into an array. + @returns Pointer to new \ref yc_index_node object. + */ + virtual yc_index_node_ptr + new_misc_index(const std::string& name + /**< [in] Index name. */ ) const; + + /// Create an equation node. + /** Indicates grid point on LHS is equivalent to expression on + RHS. This is NOT a test for equality. When an equation is + created, it is automatically added to the list of equations for + the yc_solution that contains the grid that is on the + LHS. + + An optional domain condition may be provided to define the sub-domain + to which this equation applies. + Domain conditions are always evaluated with respect to the overall + problem domain, i.e., independent of any specific + MPI domain decomposition that might occur at run-time. + If a domain condition is not provided, the equation applies to the + entire problem domain. + A domain condition can be added to an equation after its creation + via yc_equation_node.set_cond(). + See yc_equation_node.set_cond() for more information and an example. + + A step condition is similar to a domain condition, but + enables or disables the entire equation based on the current step (usually time) + and/or other values. + A step condition can only be added to an equation after its creation + via yc_equation_node.set_step_cond(). + See yc_equation_node.set_step_cond() for more information and an example. + + @returns Pointer to new \ref yc_equation_node object. + */ + virtual yc_equation_node_ptr + new_equation_node(yc_grid_point_node_ptr lhs + /**< [in] Grid-point before EQUALS operator. */, + yc_number_arg_any rhs + /**< [in] Expression after EQUALS operator. */, + yc_bool_node_ptr sub_domain_cond = nullptr + /**< [in] Optional expression defining sub-domain + where `lhs EQUALS rhs` is valid. */ ) const; + + /// Create a numerical-value expression node. + /** + A generic method to create a pointer to a numerical expression + from any type supported by \ref yc_number_arg_any constructors. + */ + virtual yc_number_node_ptr + new_number_node(yc_number_arg_any arg + /**< [in] Argument to convert to a numerical expression. */) const { + return arg; + } + + /// Create a constant numerical-value node. + /** + Use to add a constant to an expression. + The overloaded arithmetic operators allow `double` arguments, + so in most cases, it is not necessary to call this directly. + @returns Pointer to new \ref yc_const_number_node object. + */ + virtual yc_number_node_ptr + new_const_number_node(double val + /**< [in] Value to store in node. */ ) const; + + /// Create a constant numerical value node. + /** + Integer version of new_const_number_node(double). + It may be necessary to cast other integer types to `idx_t` to + avoid ambiguous overloading of this function. + @returns Pointer to new \ref yc_const_number_node object. + */ + virtual yc_number_node_ptr + new_const_number_node(idx_t val + /**< [in] Value to store in node. */ ) const; + + /// Create a numerical negation operator node. + /** + New negation nodes can also be created via the overloaded unary `-` operator. + @returns Pointer to new \ref yc_negate_node object. + */ + virtual yc_number_node_ptr + new_negate_node(yc_number_arg_any rhs + /**< [in] Expression after `-` sign. */ ) const; + + /// Create an addition node. + /** + New addition nodes can also be created via the overloaded `+` operator. + @returns Pointer to new \ref yc_add_node object. + Returns `rhs` if `lhs` is a null node pointer and vice-versa. + */ + virtual yc_number_node_ptr + new_add_node(yc_number_arg_any lhs /**< [in] Expression before `+` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `+` sign. */ ) const; + + /// Create a multiplication node. + /** + New multiplication nodes can also be created via the overloaded `*` operator. + @returns Pointer to new \ref yc_multiply_node object. + Returns `rhs` if `lhs` is a null node pointer and vice-versa. + */ + virtual yc_number_node_ptr + new_multiply_node(yc_number_arg_any lhs /**< [in] Expression before `*` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `*` sign. */ ) const; + + /// Create a subtraction node. + /** + This is binary subtraction. + Use new_negation_node() for unary `-`. + + New subtraction nodes can also be created via the overloaded `-` operator. + @returns Pointer to new \ref yc_subtract_node object. + Returns `- rhs` if `lhs` is a null node pointer and + `lhs` if `rhs` is null. + */ + virtual yc_number_node_ptr + new_subtract_node(yc_number_arg_any lhs /**< [in] Expression before `-` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `-` sign. */ ) const; + + /// Create a division node. + /** + New division nodes can also be created via the overloaded `/` operator. + @returns Pointer to new \ref yc_divide_node object. + Returns `1.0 / rhs` if `lhs` is a null node pointer and + `lhs` if `rhs` is null. + */ + virtual yc_number_node_ptr + new_divide_node(yc_number_arg_any lhs /**< [in] Expression before `/` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `/` sign. */ ) const; + + /// Create a modulo node. + /** + New modulo nodes can also be created via the overloaded `%` operator. + The modulo operator converts both operands to integers before performing + the operation. + @returns Pointer to new \ref yc_mod_node object. + */ + virtual yc_number_node_ptr + new_mod_node(yc_number_arg_any lhs /**< [in] Expression before `%` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `%` sign. */ ) const; + + /// Create a symbol for the first index value in a given dimension. + /** + Create an expression that indicates the first value in the overall problem + domain in `dim` dimension. + The `dim` argument is created via new_domain_index(). + + See yc_equation_node.set_cond() for more information and an example. + + @returns Pointer to new \ref yc_index_node object. + */ + virtual yc_number_node_ptr + new_first_domain_index(yc_index_node_ptr idx + /**< [in] Domain index. */ ) const; + + /// Create a symbol for the last index value in a given dimension. + /** + Create an expression that indicates the last value in the overall problem + domain in `dim` dimension. + The `dim` argument is created via new_domain_index(). + + See yc_equation_node.set_cond() for more information and an example. + + @returns Pointer to new \ref yc_index_node object. + */ + virtual yc_number_node_ptr + new_last_domain_index(yc_index_node_ptr idx + /**< [in] Domain index. */ ) const; + + /// Create a binary inverse operator node. + /** + New "not" nodes can also be created via the overloaded `!` operator + or the `yc_not` function in Python. + @returns Pointer to new \ref yc_not_node object. + */ + virtual yc_bool_node_ptr + new_not_node(yc_bool_node_ptr rhs /**< [in] Expression after `!` sign. */ ) const; + + /// Create a boolean 'and' node. + /** + New "and" nodes can also be created via the overloaded `&&` operator + or the `yc_and` function in Python. + @returns Pointer to new \ref yc_and_node object. + */ + virtual yc_bool_node_ptr + new_and_node(yc_bool_node_ptr lhs /**< [in] Expression before `&&` sign. */, + yc_bool_node_ptr rhs /**< [in] Expression after `&&` sign. */ ) const; + + /// Create a boolean 'or' node. + /** + New "or" nodes can also be created via the overloaded `||` operator + or the `yc_or` function in Python. + @returns Pointer to new \ref yc_or_node object. + */ + virtual yc_bool_node_ptr + new_or_node(yc_bool_node_ptr lhs /**< [in] Expression before `||` sign. */, + yc_bool_node_ptr rhs /**< [in] Expression after `||` sign. */ ) const; + + /// Create a numerical-comparison 'equals' node. + /** + New "equals" nodes can also be created via the overloaded `==` operator. + @returns Pointer to new \ref yc_equals_node object. + */ + virtual yc_bool_node_ptr + new_equals_node(yc_number_arg_any lhs /**< [in] Expression before `==` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `==` sign. */ ) const; + + /// Create a numerical-comparison 'not-equals' node. + /** + New "not-equals" nodes can also be created via the overloaded `!=` operator. + @returns Pointer to new \ref yc_not_equals_node object. + */ + virtual yc_bool_node_ptr + new_not_equals_node(yc_number_arg_any lhs /**< [in] Expression before `!=` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `!=` sign. */ ) const; + + /// Create a numerical-comparison 'less-than' node. + /** + New "less-than" nodes can also be created via the overloaded `<` operator. + @returns Pointer to new \ref yc_less_than_node object. + */ + virtual yc_bool_node_ptr + new_less_than_node(yc_number_arg_any lhs /**< [in] Expression before `<` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `<` sign. */ ) const; + + /// Create a numerical-comparison 'greater-than' node. + /** + New "greater-than" nodes can also be created via the overloaded `>` operator. + @returns Pointer to new \ref yc_greater_than_node object. + */ + virtual yc_bool_node_ptr + new_greater_than_node(yc_number_arg_any lhs /**< [in] Expression before `>` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `>` sign. */ ) const; + + /// Create a numerical-comparison 'greater-than or equals' node. + /** + New "greater-than or equals" nodes can also be created via the overloaded `>=` operator. + @returns Pointer to new \ref yc_not_less_than_node object. + */ + virtual yc_bool_node_ptr + new_not_less_than_node(yc_number_arg_any lhs /**< [in] Expression before `>=` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `>=` sign. */ ) const; + + /// Create a numerical-comparison 'less-than or equals' node. + /** + New "less-than or equals" nodes can also be created via the overloaded `<=` operator. + @returns Pointer to new \ref yc_not_greater_than_node object. + */ + virtual yc_bool_node_ptr + new_not_greater_than_node(yc_number_arg_any lhs /**< [in] Expression before `<=` sign. */, + yc_number_arg_any rhs /**< [in] Expression after `<=` sign. */ ) const; + + }; + +#if !defined SWIG + + // Non-class operators. + // These are not defined for SWIG because + // the Python operators are defined in the ".i" file. + // For the binary operators, we define 3 combinations to implicitly + // avoid the const-const combinations, which conflict with built-in + // operators on fundamental C++ types, e.g., '5+8'. /// Operator version of yc_node_factory::new_negation_node(). - yc_number_node_ptr operator-(yc_number_node_ptr rhs); + yc_number_node_ptr operator-(yc_number_arg_ptr rhs); ///@{ /// Operator version of yc_node_factory::new_addition_node(). - yc_number_node_ptr operator+(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator+(double lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator+(yc_number_node_ptr lhs, double rhs); + yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator+(yc_number_arg_const lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_const rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_division_node(). - yc_number_node_ptr operator/(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator/(double lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator/(yc_number_node_ptr lhs, double rhs); + yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator/(yc_number_arg_const lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_const rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_mod_node(). - yc_number_node_ptr operator%(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator%(double lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator%(yc_number_node_ptr lhs, double rhs); + yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator%(yc_number_arg_const lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_const rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_multiplication_node(). - yc_number_node_ptr operator*(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator*(double lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator*(yc_number_node_ptr lhs, double rhs); + yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator*(yc_number_arg_const lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_const rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_subtraction_node(). - yc_number_node_ptr operator-(yc_number_node_ptr lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator-(double lhs, yc_number_node_ptr rhs); - yc_number_node_ptr operator-(yc_number_node_ptr lhs, double rhs); + yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator-(yc_number_arg_const lhs, yc_number_arg_ptr rhs); + yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_const rhs); ///@} ///@{ /// Shortcut for creating expression A = A + B. void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator+=(yc_number_node_ptr& lhs, double rhs); + void operator+=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); ///@} ///@{ /// Shortcut for creating expression A = A - B. void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator-=(yc_number_node_ptr& lhs, double rhs); + void operator-=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); ///@} ///@{ /// Shortcut for creating expression A = A * B. void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator*=(yc_number_node_ptr& lhs, double rhs); + void operator*=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); ///@} ///@{ /// Shortcut for creating expression A = A / B. void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator/=(yc_number_node_ptr& lhs, double rhs); + void operator/=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); ///@} /// Operator version of yc_node_factory::new_not_node(). @@ -865,11 +972,11 @@ namespace yask { inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, double rhs) { \ - yc_node_factory nfac; return nfac.fn(lhs, nfac.new_const_number_node(rhs)); } \ + yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } \ inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, double rhs) { \ - yc_node_factory nfac; return nfac.fn(lhs, nfac.new_const_number_node(rhs)); } \ + yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } \ inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, double rhs) { \ - yc_node_factory nfac; return nfac.fn(lhs, nfac.new_const_number_node(rhs)); } + yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } BOOL_OPER(==, new_equals_node) BOOL_OPER(!=, new_not_equals_node) @@ -895,8 +1002,8 @@ namespace yask { /// Binary math functions. #define FUNC_EXPR(fn_name) \ yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ - yc_number_node_ptr fn_name(double arg1, const yc_number_node_ptr arg2); \ - yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, double arg2) + yc_number_node_ptr fn_name(yc_number_arg_const arg1, const yc_number_node_ptr arg2); \ + yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, yc_number_arg_const arg2) FUNC_EXPR(pow); #undef FUNC_EXPR @@ -912,9 +1019,7 @@ namespace yask { This should not be an operator that is defined for shared pointers. See https://en.cppreference.com/w/cpp/memory/shared_ptr. */ - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_number_node_ptr rhs); - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_grid_point_node_ptr rhs); - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, double rhs); + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_number_arg_any rhs); #define IF_OPER ^= #define IF IF_OPER diff --git a/src/common/common.mk b/src/common/common.mk index 2b9faac9..9869418d 100644 --- a/src/common/common.mk +++ b/src/common/common.mk @@ -58,6 +58,10 @@ COMM_DIR := $(SRC_DIR)/common COMM_SRC_NAMES := output common_utils tuple combo fd_coeff fd_coeff2 COEFF_DIR := $(SRC_DIR)/contrib/coefficients +# Globs and flags. +INC_GLOB := $(wildcard $(addsuffix /*.hpp,$(INC_DIR))) +INC_CXXFLAGS := $(addprefix -I,$(INC_DIR)) + # YASK stencil compiler. # This is here because both the compiler and kernel # Makefiles need to know about the compiler. diff --git a/src/compiler/Makefile b/src/compiler/Makefile index 0745a592..cf98c26a 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -58,7 +58,8 @@ YC_STENCIL_INC_GLOB := $(wildcard $(YC_STENCIL_DIR)/*.hpp $(YC_STENCIL_DIR)/*/*. YC_CXX ?= g++ # usually faster than icpc for building the compiler. YC_CXXOPT := -O2 YC_CXXFLAGS := -g -std=c++11 -Wall $(YC_CXXOPT) -YC_CXXFLAGS += $(addprefix -I,$(YC_INC_DIRS) $(YC_STENCIL_DIR)) +YC_CXXFLAGS += $(INC_CXXFLAGS) +YC_INC_CXXFLAGS := $(addprefix -I,$(YC_INC_DIRS)) # Add user-defined flags. YC_CXXFLAGS += $(EXTRA_YC_CXXFLAGS) @@ -72,24 +73,24 @@ YC_LFLAGS := -lrt -Wl,-rpath=$(LIB_OUT_DIR) -L$(LIB_OUT_DIR) -l$(YC_BASE) # - Build at O0 to avoid C++ compiler wasting time optimizing them. # - Set macro to use internal DSL instead of conflicting API operators. -$(YC_OBJ_DIR)/%.o: $(YC_STENCIL_DIR)/%.cpp $(YC_INC_GLOB) $(YC_STENCIL_INC_GLOB) +$(YC_OBJ_DIR)/%.o: $(YC_STENCIL_DIR)/%.cpp $(INC_GLOB) $(YC_STENCIL_INC_GLOB) $(MKDIR) $(YC_OBJ_DIR) $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) -x c++ -DUSE_INTERNAL_DSL -O0 -c -o $@ $< @ls -l $@ -$(YC_OBJ_DIR)/%.o: $(YC_LIB_SRC_DIR)/%.cpp $(YC_INC_GLOB) +$(YC_OBJ_DIR)/%.o: $(COMM_DIR)/%.cpp $(YC_INC_GLOB) $(MKDIR) $(YC_OBJ_DIR) - $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) -x c++ -fPIC -c -o $@ $< + $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) -x c++ -fPIC -c -o $@ $< @ls -l $@ -$(YC_OBJ_DIR)/%.o: $(COMM_DIR)/%.cpp $(YC_INC_GLOB) +$(YC_OBJ_DIR)/%.o: $(COEFF_DIR)/%.cpp $(YC_INC_GLOB) $(MKDIR) $(YC_OBJ_DIR) - $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) -x c++ -fPIC -c -o $@ $< + $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) -x c++ -fPIC -c -o $@ $< @ls -l $@ -$(YC_OBJ_DIR)/%.o: $(COEFF_DIR)/%.cpp $(YC_INC_GLOB) +$(YC_OBJ_DIR)/%.o: $(YC_LIB_SRC_DIR)/%.cpp $(YC_INC_GLOB) $(MKDIR) $(YC_OBJ_DIR) - $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) -x c++ -fPIC -c -o $@ $< + $(CXX_PREFIX) $(YC_CXX) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) -x c++ -fPIC -c -o $@ $< @ls -l $@ ######## Primary targets. @@ -108,7 +109,7 @@ $(YC_LIB): $(YC_OBJS) $(YC_EXEC): compiler_main.cpp $(YC_STENCIL_OBJS) $(YC_LIB) $(MKDIR) $(dir $@) - $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $^ $(YC_LFLAGS) -o $@ + $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) $^ $(YC_LFLAGS) -o $@ @ls -l $@ $(MAKE) echo-settings diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index de0bbfc4..12d85e38 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -29,11 +29,14 @@ IN THE SOFTWARE. #include "yask_compiler_api.hpp" // API for using this utility. +#include "yask_compiler_utility_api.hpp" + +// Backward-compatible API. #include "Soln.hpp" // YASK compiler-solution code. -// TODO: remove all non-API includes. -#include "CppIntrin.hpp" +// TODO: remove these non-API includes. +#include "Solution.hpp" #include "Parse.hpp" using namespace yask; @@ -50,12 +53,12 @@ namespace yask { // other vars set via cmd-line options. CompilerSettings settings; int vlenForStats = 0; - StencilBase* stencilSoln = NULL; + yc_solution_base* stencilSoln = NULL; string solutionName; int radius = -1; // Collection of known stencils. - typedef map StencilMap; + typedef map StencilMap; StencilMap stencils; // Dummy object for backward-compatibility with old stencil DSL. @@ -63,7 +66,7 @@ namespace yask { // Create new solution and register it. yc_solution_ptr yc_new_solution(const std::string& name, - StencilBase* base_ptr) { + yc_solution_base* base_ptr) { if (stencils.count(name)) THROW_YASK_EXCEPTION("Error: stencil '" + name + "' already defined"); diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index e4b309d6..8a713138 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -40,47 +40,68 @@ namespace yask { //node_factory API methods. yc_index_node_ptr - yc_node_factory::new_step_index(const std::string& name) { + yc_node_factory::new_step_index(const std::string& name) const { return make_shared(name, STEP_INDEX); } yc_index_node_ptr - yc_node_factory::new_domain_index(const std::string& name) { + yc_node_factory::new_domain_index(const std::string& name) const { return make_shared(name, DOMAIN_INDEX); } yc_index_node_ptr - yc_node_factory::new_misc_index(const std::string& name) { + yc_node_factory::new_misc_index(const std::string& name) const { return make_shared(name, MISC_INDEX); } yc_equation_node_ptr yc_node_factory::new_equation_node(yc_grid_point_node_ptr lhs, - yc_number_node_ptr rhs, - yc_bool_node_ptr cond) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - auto ep = operator EQUALS_OPER(lp, rp); - ep->set_cond(cond); - return ep; + yc_number_arg_any rexpr, + yc_bool_node_ptr cond) const { + if (!lhs) + THROW_YASK_EXCEPTION("Error: empty LHS of equation"); + auto gpp = dynamic_pointer_cast(lhs); + assert(gpp); + if (!rexpr) + THROW_YASK_EXCEPTION("Error: empty RHS of " + + gpp->makeQuotedStr() + " equation"); + auto rhs = dynamic_pointer_cast(rexpr); + assert(rhs); + + // Get to list of equations in soln indirectly thru grid. + GridVar* gp = gpp->getGrid(); + assert(gp); + auto* soln = gp->getSoln(); + assert(soln); + auto& eqs = soln->getEqs(); + auto& settings = soln->getSettings(); + + // Make expression node. + auto expr = make_shared(gpp, rhs); + expr->set_cond(cond); + if (settings._printEqs) + soln->get_ostr() << "Equation defined: " << expr->getDescr() << endl; + + // Save the expression in list of equations. + eqs.addItem(expr); + + return expr; } yc_number_node_ptr - yc_node_factory::new_const_number_node(double val) { + yc_node_factory::new_const_number_node(double val) const { return make_shared(val); } yc_number_node_ptr - yc_node_factory::new_const_number_node(idx_t val) { + yc_node_factory::new_const_number_node(idx_t val) const { return make_shared(val); } yc_number_node_ptr - yc_node_factory::new_negate_node(yc_number_node_ptr rhs) { + yc_node_factory::new_negate_node(yc_number_arg_any rhs) const { auto p = dynamic_pointer_cast(rhs); assert(p); return make_shared(p); } yc_number_node_ptr - yc_node_factory::new_add_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_add_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { if (!lhs) return rhs; if (!rhs) @@ -97,8 +118,8 @@ namespace yask { return ex; } yc_number_node_ptr - yc_node_factory::new_multiply_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_multiply_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { if (!lhs) return rhs; if (!rhs) @@ -115,8 +136,8 @@ namespace yask { return ex; } yc_number_node_ptr - yc_node_factory::new_subtract_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_subtract_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { yc_node_factory nfac; if (!lhs) return nfac.new_negate_node(rhs); @@ -129,8 +150,8 @@ namespace yask { return make_shared(lp, rp); } yc_number_node_ptr - yc_node_factory::new_divide_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_divide_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { yc_node_factory nfac; if (!lhs) return nfac.new_divide_node(nfac.new_const_number_node(1.0), rhs); @@ -143,8 +164,8 @@ namespace yask { return make_shared(lp, rp); } yc_number_node_ptr - yc_node_factory::new_mod_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_mod_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -152,14 +173,14 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_node(yc_bool_node_ptr rhs) { + yc_node_factory::new_not_node(yc_bool_node_ptr rhs) const { auto p = dynamic_pointer_cast(rhs); assert(p); return make_shared(p); } yc_bool_node_ptr yc_node_factory::new_and_node(yc_bool_node_ptr lhs, - yc_bool_node_ptr rhs) { + yc_bool_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -168,7 +189,7 @@ namespace yask { } yc_bool_node_ptr yc_node_factory::new_or_node(yc_bool_node_ptr lhs, - yc_bool_node_ptr rhs) { + yc_bool_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -176,8 +197,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_equals_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_equals_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -185,8 +206,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_equals_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_not_equals_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -194,8 +215,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_less_than_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_less_than_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -203,8 +224,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_greater_than_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_greater_than_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -212,8 +233,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_less_than_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_not_less_than_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -221,8 +242,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_greater_than_node(yc_number_node_ptr lhs, - yc_number_node_ptr rhs) { + yc_node_factory::new_not_greater_than_node(yc_number_arg_any lhs, + yc_number_arg_any rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -230,7 +251,7 @@ namespace yask { return make_shared(lp, rp); } yc_number_node_ptr - yc_node_factory::new_first_domain_index(yc_index_node_ptr idx) { + yc_node_factory::new_first_domain_index(yc_index_node_ptr idx) const { auto p = dynamic_pointer_cast(idx); if (!p) THROW_YASK_EXCEPTION("Error: new_first_domain_index() called without index-node argument"); @@ -239,7 +260,7 @@ namespace yask { return make_shared(p->getName(), FIRST_INDEX); } yc_number_node_ptr - yc_node_factory::new_last_domain_index(yc_index_node_ptr idx) { + yc_node_factory::new_last_domain_index(yc_index_node_ptr idx) const { auto p = dynamic_pointer_cast(idx); if (!p) THROW_YASK_EXCEPTION("Error: new_last_domain_index() called without index-node argument"); @@ -248,121 +269,123 @@ namespace yask { return make_shared(p->getName(), LAST_INDEX); } + yc_number_node_ptr yc_number_arg_const::_convert_const(double val) const { + yc_node_factory nfac; + return nfac.new_const_number_node(val); + } + yc_number_node_ptr yc_number_arg_any::_convert_const(double val) const { + yc_node_factory nfac; + return nfac.new_const_number_node(val); + } + // Unary. - yc_number_node_ptr operator-(yc_number_node_ptr rhs) { + yc_number_node_ptr operator-(yc_number_arg_ptr rhs) { yc_node_factory nfac; return nfac.new_negate_node(rhs); } // Binary. - yc_number_node_ptr operator+(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; return nfac.new_add_node(lhs, rhs); } - yc_number_node_ptr operator+(double lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator+(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; - return operator+(nfac.new_const_number_node(lhs), rhs); + return nfac.new_add_node(lhs, rhs); } - yc_number_node_ptr operator+(yc_number_node_ptr lhs, double rhs) { + yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { yc_node_factory nfac; - return operator+(lhs, nfac.new_const_number_node(rhs)); + return nfac.new_add_node(lhs, rhs); } - yc_number_node_ptr operator/(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; return nfac.new_divide_node(lhs, rhs); } - yc_number_node_ptr operator/(double lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator/(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; - return operator/(nfac.new_const_number_node(lhs), rhs); + return nfac.new_divide_node(lhs, rhs); } - yc_number_node_ptr operator/(yc_number_node_ptr lhs, double rhs) { + yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { yc_node_factory nfac; - return operator/(lhs, nfac.new_const_number_node(rhs)); + return nfac.new_divide_node(lhs, rhs); } - yc_number_node_ptr operator%(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; return nfac.new_mod_node(lhs, rhs); } - yc_number_node_ptr operator%(double lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator%(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; - return operator%(nfac.new_const_number_node(lhs), rhs); + return nfac.new_mod_node(lhs, rhs); } - yc_number_node_ptr operator%(yc_number_node_ptr lhs, double rhs) { + yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { yc_node_factory nfac; - return operator%(lhs, nfac.new_const_number_node(rhs)); + return nfac.new_mod_node(lhs, rhs); } - yc_number_node_ptr operator*(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; return nfac.new_multiply_node(lhs, rhs); } - yc_number_node_ptr operator*(double lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator*(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; - return operator*(nfac.new_const_number_node(lhs), rhs); + return nfac.new_multiply_node(lhs, rhs); } - yc_number_node_ptr operator*(yc_number_node_ptr lhs, double rhs) { + yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { yc_node_factory nfac; - return operator*(lhs, nfac.new_const_number_node(rhs)); + return nfac.new_multiply_node(lhs, rhs); } - yc_number_node_ptr operator-(yc_number_node_ptr lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; return nfac.new_subtract_node(lhs, rhs); } - yc_number_node_ptr operator-(double lhs, yc_number_node_ptr rhs) { + yc_number_node_ptr operator-(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { yc_node_factory nfac; - return operator-(nfac.new_const_number_node(lhs), rhs); + return nfac.new_subtract_node(lhs, rhs); } - yc_number_node_ptr operator-(yc_number_node_ptr lhs, double rhs) { + yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { yc_node_factory nfac; - return operator-(lhs, nfac.new_const_number_node(rhs)); + return nfac.new_subtract_node(lhs, rhs); } // Modifiers. void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs + rhs; } - void operator+=(yc_number_node_ptr& lhs, double rhs) { + void operator+=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { lhs = lhs + rhs; } void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs - rhs; } - void operator-=(yc_number_node_ptr& lhs, double rhs) { + void operator-=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { lhs = lhs - rhs; } void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs * rhs; } - void operator*=(yc_number_node_ptr& lhs, double rhs) { + void operator*=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { lhs = lhs * rhs; } void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs / rhs; } - void operator/=(yc_number_node_ptr& lhs, double rhs) { + void operator/=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { lhs = lhs / rhs; } // Boolean unary. yc_bool_node_ptr operator!(yc_bool_node_ptr rhs) { - auto p = dynamic_pointer_cast(rhs); - assert(p); - return make_shared(p); + yc_node_factory nfac; + return nfac.new_not_node(rhs); } // Boolean binary. yc_bool_node_ptr operator||(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_or_node(lhs, rhs); } yc_bool_node_ptr operator&&(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs) { - auto lp = dynamic_pointer_cast(lhs); - assert(lp); - auto rp = dynamic_pointer_cast(rhs); - assert(rp); - return make_shared(lp, rp); + yc_node_factory nfac; + return nfac.new_and_node(lhs, rhs); } // Compare 2 expr pointers and return whether the expressions are @@ -405,15 +428,11 @@ namespace yask { assert(p2); \ return make_shared(#fn, std::initializer_list< const numExprPtr >{ p1, p2 }); \ } \ - yc_number_node_ptr fn(const yc_number_node_ptr arg1, double arg2) { \ - yc_node_factory nfac; \ - auto p2 = nfac.new_const_number_node(arg2); \ - return fn(arg1, p2); \ + yc_number_node_ptr fn(const yc_number_node_ptr arg1, yc_number_arg_const arg2) { \ + return fn(arg1, arg2); \ } \ - yc_number_node_ptr fn(double arg1, const yc_number_node_ptr arg2) { \ - yc_node_factory nfac; \ - auto p1 = nfac.new_const_number_node(arg1); \ - return fn(p1, arg2); \ + yc_number_node_ptr fn(yc_number_arg_const arg1, const yc_number_node_ptr arg2) { \ + return fn(arg1, arg2); \ } FUNC_EXPR(pow) #undef FUNC_EXPR @@ -445,46 +464,9 @@ namespace yask { // Define the value of a grid point. // Add this equation to the list of eqs for this stencil. yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr lhs, - const yc_number_node_ptr rexpr) { - - if (!lhs) - THROW_YASK_EXCEPTION("Error: empty LHS of equation"); - auto gpp = dynamic_pointer_cast(lhs); - assert(gpp); - if (!rexpr) - THROW_YASK_EXCEPTION("Error: empty RHS of " + - gpp->makeQuotedStr() + " equation"); - auto rhs = dynamic_pointer_cast(rexpr); - assert(rhs); - - // Get to list of equations in soln indirectly thru grid. - GridVar* gp = gpp->getGrid(); - assert(gp); - auto* soln = gp->getSoln(); - assert(soln); - auto& eqs = soln->getEqs(); - auto& settings = soln->getSettings(); - - // Make expression node. - // Conditions may be added later if/when the IF or IF_STEP - // operators are processed. - auto expr = make_shared(gpp, rhs); - if (settings._printEqs) - soln->get_ostr() << "Equation defined: " << expr->getDescr() << endl; - - // Save the expression in list of equations. - eqs.addItem(expr); - - return expr; - } - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, double rhs) { + const yc_number_arg_any rhs) { yc_node_factory nfac; - return gpp EQUALS_OPER nfac.new_const_number_node(rhs); - } - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, gridPointPtr rhs) { - auto p = dynamic_pointer_cast(rhs); - assert(p); - return gpp EQUALS_OPER p; + return nfac.new_equation_node(lhs, rhs); } // Visitor acceptors. From 6c6de01820b51c936e3fffbdb143215958bffd23 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Sun, 5 May 2019 15:48:22 -0700 Subject: [PATCH 04/62] Revert some implicit conversions for Python API via SWIG. --- include/yask_compiler_api.hpp | 43 ++++---- include/yc_node_api.hpp | 141 +++++++++++++------------- src/compiler/Makefile | 3 +- src/compiler/lib/Expr.cpp | 98 +++++++++--------- src/compiler/swig/yask_compiler_api.i | 17 ++-- 5 files changed, 160 insertions(+), 142 deletions(-) diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 88a4bf45..c79a6842 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -666,6 +666,9 @@ namespace yask { _grid = soln->new_grid(name, dims); } + /// Provide a virtual destructor. + virtual ~yc_grid_var() { } + /// Get the underlying \ref yc_grid_ptr. virtual yc_grid_ptr get_grid() { return _grid; @@ -676,34 +679,38 @@ namespace yask { return _grid; } +#ifndef SWIG /// Create an expression for a point in a zero-dim (scalar) grid /// using implicit conversion. /** Example w/0D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B`. + @note Not available in Python API. Use more explicit methods. */ - virtual operator yc_number_arg_ptr() { + virtual operator yc_number_ptr_arg() { return _grid->new_grid_point({}); } /// Create an expression for a point in a one-dim (array) grid. /** Example w/1D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. + @note Not available in Python API. Use vector version. */ - virtual yc_grid_point_node_ptr operator[](const yc_number_arg_any i1) { + virtual yc_grid_point_node_ptr operator[](const yc_number_any_arg i1) { return _grid->new_grid_point({i1}); } - + /// Create an expression for a point in a 1-6 dim grid. /// The number of arguments must match the dimensionality of the grid. /** Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. + @note Not available in Python API. Use vector version. */ - virtual yc_grid_point_node_ptr operator()(const yc_number_arg_any i1 = nullptr, - const yc_number_arg_any i2 = nullptr, - const yc_number_arg_any i3 = nullptr, - const yc_number_arg_any i4 = nullptr, - const yc_number_arg_any i5 = nullptr, - const yc_number_arg_any i6 = nullptr) { + virtual yc_grid_point_node_ptr operator()(const yc_number_any_arg i1 = nullptr, + const yc_number_any_arg i2 = nullptr, + const yc_number_any_arg i3 = nullptr, + const yc_number_any_arg i4 = nullptr, + const yc_number_any_arg i5 = nullptr, + const yc_number_any_arg i6 = nullptr) { std::vector args; if (i1) args.push_back(i1); @@ -720,26 +727,28 @@ namespace yask { return _grid->new_grid_point(args); } - /// Create an expression for a point in any grid. - /// The number of arguments must match the dimensionality of the grid. - /// Create an expression for a point in a 1-6 dim grid. + /// Create an expression for a point in a grid. /// The number of arguments must match the dimensionality of the grid. /** - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, - where `vec` is a 2-element vector of \ref yc_number_node_ptr. + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. + @note Not available in Python API. Use vector version. */ virtual yc_grid_point_node_ptr - operator()(const std::vector& index_exprs) { + operator()(const std::initializer_list& index_exprs) { return _grid->new_grid_point(index_exprs); } +#endif /// Create an expression for a point in a grid. /// The number of arguments must match the dimensionality of the grid. + /// Create an expression for a point in a 1-6 dim grid. + /// The number of arguments must match the dimensionality of the grid. /** - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, + where `vec` is a 2-element vector of \ref yc_number_node_ptr. */ virtual yc_grid_point_node_ptr - operator()(const std::initializer_list& index_exprs) { + operator()(const std::vector& index_exprs) { return _grid->new_grid_point(index_exprs); } }; diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index 464a3444..60199020 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -473,30 +473,31 @@ namespace yask { */ class yc_not_greater_than_node : public virtual yc_binary_comparison_node { }; +#ifndef SWIG /// A simple wrapper class to provide automatic /// construction of a 'yc_number_node_ptr' from /// other YASK pointer types. - class yc_number_arg_ptr : public virtual yc_number_node_ptr { + class yc_number_ptr_arg : public virtual yc_number_node_ptr { public: /// Arg can be a number-node pointer. - yc_number_arg_ptr(yc_number_node_ptr p) : + yc_number_ptr_arg(yc_number_node_ptr p) : yc_number_node_ptr(p) { } /// Arg can be an index-node pointer. - yc_number_arg_ptr(yc_index_node_ptr p) : + yc_number_ptr_arg(yc_index_node_ptr p) : yc_number_node_ptr(p) { } /// Arg can be a grid-point-node pointer. - yc_number_arg_ptr(yc_grid_point_node_ptr p) : + yc_number_ptr_arg(yc_grid_point_node_ptr p) : yc_number_node_ptr(p) { } }; /// A simple wrapper class to provide automatic /// construction of a 'yc_number_node_ptr' from /// non-YASK fundamental numeric types. - class yc_number_arg_const : public virtual yc_number_node_ptr { + class yc_number_const_arg : public virtual yc_number_node_ptr { protected: @@ -506,26 +507,26 @@ namespace yask { public: /// Arg can be an index type. - yc_number_arg_const(idx_t i) : + yc_number_const_arg(idx_t i) : yc_number_node_ptr(_convert_const(i)) { } /// Arg can be an int. - yc_number_arg_const(int i) : + yc_number_const_arg(int i) : yc_number_node_ptr(_convert_const(i)) { } /// Arg can be a double. - yc_number_arg_const(double f) : + yc_number_const_arg(double f) : yc_number_node_ptr(_convert_const(f)) { } /// Arg can be a float. - yc_number_arg_const(float f) : + yc_number_const_arg(float f) : yc_number_node_ptr(_convert_const(f)) { } }; /// A simple wrapper class to provide automatic /// construction of a 'yc_number_node_ptr' from /// a YASK pointer or non-YASK fundamental numeric types. - class yc_number_arg_any : public virtual yc_number_node_ptr { + class yc_number_any_arg : public virtual yc_number_node_ptr { protected: @@ -535,38 +536,39 @@ namespace yask { public: /// Arg can be a number-node pointer. - yc_number_arg_any(yc_number_node_ptr p) : + yc_number_any_arg(yc_number_node_ptr p) : yc_number_node_ptr(p) { } /// Arg can be an index-node pointer. - yc_number_arg_any(yc_index_node_ptr p) : + yc_number_any_arg(yc_index_node_ptr p) : yc_number_node_ptr(p) { } /// Arg can be a grid-point-node pointer. - yc_number_arg_any(yc_grid_point_node_ptr p) : + yc_number_any_arg(yc_grid_point_node_ptr p) : yc_number_node_ptr(p) { } /// Arg can be an index type. - yc_number_arg_any(idx_t i) : + yc_number_any_arg(idx_t i) : yc_number_node_ptr(_convert_const(i)) { } /// Arg can be an int. - yc_number_arg_any(int i) : + yc_number_any_arg(int i) : yc_number_node_ptr(_convert_const(i)) { } /// Arg can be a double. - yc_number_arg_any(double f) : + yc_number_any_arg(double f) : yc_number_node_ptr(_convert_const(f)) { } /// Arg can be a float. - yc_number_arg_any(float f) : + yc_number_any_arg(float f) : yc_number_node_ptr(_convert_const(f)) { } /// Arg can be a null pointer. - yc_number_arg_any(std::nullptr_t p) : + yc_number_any_arg(std::nullptr_t p) : yc_number_node_ptr(p) { } }; - +#endif + /// Factory to create AST nodes. /** @note Grid-point reference nodes are created from a \ref yc_grid object instead of from a \ref yc_node_factory. */ @@ -645,22 +647,25 @@ namespace yask { virtual yc_equation_node_ptr new_equation_node(yc_grid_point_node_ptr lhs /**< [in] Grid-point before EQUALS operator. */, - yc_number_arg_any rhs + yc_number_node_ptr rhs /**< [in] Expression after EQUALS operator. */, yc_bool_node_ptr sub_domain_cond = nullptr /**< [in] Optional expression defining sub-domain where `lhs EQUALS rhs` is valid. */ ) const; +#ifndef SWIG /// Create a numerical-value expression node. /** A generic method to create a pointer to a numerical expression - from any type supported by \ref yc_number_arg_any constructors. + from any type supported by \ref yc_number_any_arg constructors. + @node Not available in Python API. Use a more explicit method. */ virtual yc_number_node_ptr - new_number_node(yc_number_arg_any arg + new_number_node(yc_number_any_arg arg /**< [in] Argument to convert to a numerical expression. */) const { return arg; } +#endif /// Create a constant numerical-value node. /** @@ -690,7 +695,7 @@ namespace yask { @returns Pointer to new \ref yc_negate_node object. */ virtual yc_number_node_ptr - new_negate_node(yc_number_arg_any rhs + new_negate_node(yc_number_node_ptr rhs /**< [in] Expression after `-` sign. */ ) const; /// Create an addition node. @@ -700,8 +705,8 @@ namespace yask { Returns `rhs` if `lhs` is a null node pointer and vice-versa. */ virtual yc_number_node_ptr - new_add_node(yc_number_arg_any lhs /**< [in] Expression before `+` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `+` sign. */ ) const; + new_add_node(yc_number_node_ptr lhs /**< [in] Expression before `+` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `+` sign. */ ) const; /// Create a multiplication node. /** @@ -710,8 +715,8 @@ namespace yask { Returns `rhs` if `lhs` is a null node pointer and vice-versa. */ virtual yc_number_node_ptr - new_multiply_node(yc_number_arg_any lhs /**< [in] Expression before `*` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `*` sign. */ ) const; + new_multiply_node(yc_number_node_ptr lhs /**< [in] Expression before `*` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `*` sign. */ ) const; /// Create a subtraction node. /** @@ -724,8 +729,8 @@ namespace yask { `lhs` if `rhs` is null. */ virtual yc_number_node_ptr - new_subtract_node(yc_number_arg_any lhs /**< [in] Expression before `-` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `-` sign. */ ) const; + new_subtract_node(yc_number_node_ptr lhs /**< [in] Expression before `-` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `-` sign. */ ) const; /// Create a division node. /** @@ -735,8 +740,8 @@ namespace yask { `lhs` if `rhs` is null. */ virtual yc_number_node_ptr - new_divide_node(yc_number_arg_any lhs /**< [in] Expression before `/` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `/` sign. */ ) const; + new_divide_node(yc_number_node_ptr lhs /**< [in] Expression before `/` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `/` sign. */ ) const; /// Create a modulo node. /** @@ -746,8 +751,8 @@ namespace yask { @returns Pointer to new \ref yc_mod_node object. */ virtual yc_number_node_ptr - new_mod_node(yc_number_arg_any lhs /**< [in] Expression before `%` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `%` sign. */ ) const; + new_mod_node(yc_number_node_ptr lhs /**< [in] Expression before `%` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `%` sign. */ ) const; /// Create a symbol for the first index value in a given dimension. /** @@ -812,8 +817,8 @@ namespace yask { @returns Pointer to new \ref yc_equals_node object. */ virtual yc_bool_node_ptr - new_equals_node(yc_number_arg_any lhs /**< [in] Expression before `==` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `==` sign. */ ) const; + new_equals_node(yc_number_node_ptr lhs /**< [in] Expression before `==` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `==` sign. */ ) const; /// Create a numerical-comparison 'not-equals' node. /** @@ -821,8 +826,8 @@ namespace yask { @returns Pointer to new \ref yc_not_equals_node object. */ virtual yc_bool_node_ptr - new_not_equals_node(yc_number_arg_any lhs /**< [in] Expression before `!=` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `!=` sign. */ ) const; + new_not_equals_node(yc_number_node_ptr lhs /**< [in] Expression before `!=` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `!=` sign. */ ) const; /// Create a numerical-comparison 'less-than' node. /** @@ -830,8 +835,8 @@ namespace yask { @returns Pointer to new \ref yc_less_than_node object. */ virtual yc_bool_node_ptr - new_less_than_node(yc_number_arg_any lhs /**< [in] Expression before `<` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `<` sign. */ ) const; + new_less_than_node(yc_number_node_ptr lhs /**< [in] Expression before `<` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `<` sign. */ ) const; /// Create a numerical-comparison 'greater-than' node. /** @@ -839,8 +844,8 @@ namespace yask { @returns Pointer to new \ref yc_greater_than_node object. */ virtual yc_bool_node_ptr - new_greater_than_node(yc_number_arg_any lhs /**< [in] Expression before `>` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `>` sign. */ ) const; + new_greater_than_node(yc_number_node_ptr lhs /**< [in] Expression before `>` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `>` sign. */ ) const; /// Create a numerical-comparison 'greater-than or equals' node. /** @@ -848,8 +853,8 @@ namespace yask { @returns Pointer to new \ref yc_not_less_than_node object. */ virtual yc_bool_node_ptr - new_not_less_than_node(yc_number_arg_any lhs /**< [in] Expression before `>=` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `>=` sign. */ ) const; + new_not_less_than_node(yc_number_node_ptr lhs /**< [in] Expression before `>=` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `>=` sign. */ ) const; /// Create a numerical-comparison 'less-than or equals' node. /** @@ -857,8 +862,8 @@ namespace yask { @returns Pointer to new \ref yc_not_greater_than_node object. */ virtual yc_bool_node_ptr - new_not_greater_than_node(yc_number_arg_any lhs /**< [in] Expression before `<=` sign. */, - yc_number_arg_any rhs /**< [in] Expression after `<=` sign. */ ) const; + new_not_greater_than_node(yc_number_node_ptr lhs /**< [in] Expression before `<=` sign. */, + yc_number_node_ptr rhs /**< [in] Expression after `<=` sign. */ ) const; }; @@ -872,65 +877,65 @@ namespace yask { // operators on fundamental C++ types, e.g., '5+8'. /// Operator version of yc_node_factory::new_negation_node(). - yc_number_node_ptr operator-(yc_number_arg_ptr rhs); + yc_number_node_ptr operator-(yc_number_ptr_arg rhs); ///@{ /// Operator version of yc_node_factory::new_addition_node(). - yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator+(yc_number_arg_const lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_const rhs); + yc_number_node_ptr operator+(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator+(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator+(yc_number_ptr_arg lhs, yc_number_const_arg rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_division_node(). - yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator/(yc_number_arg_const lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_const rhs); + yc_number_node_ptr operator/(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator/(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator/(yc_number_ptr_arg lhs, yc_number_const_arg rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_mod_node(). - yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator%(yc_number_arg_const lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_const rhs); + yc_number_node_ptr operator%(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator%(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator%(yc_number_ptr_arg lhs, yc_number_const_arg rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_multiplication_node(). - yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator*(yc_number_arg_const lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_const rhs); + yc_number_node_ptr operator*(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator*(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator*(yc_number_ptr_arg lhs, yc_number_const_arg rhs); ///@} ///@{ /// Operator version of yc_node_factory::new_subtraction_node(). - yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator-(yc_number_arg_const lhs, yc_number_arg_ptr rhs); - yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_const rhs); + yc_number_node_ptr operator-(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator-(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + yc_number_node_ptr operator-(yc_number_ptr_arg lhs, yc_number_const_arg rhs); ///@} ///@{ /// Shortcut for creating expression A = A + B. void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator+=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); + void operator+=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); ///@} ///@{ /// Shortcut for creating expression A = A - B. void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator-=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); + void operator-=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); ///@} ///@{ /// Shortcut for creating expression A = A * B. void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator*=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); + void operator*=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); ///@} ///@{ /// Shortcut for creating expression A = A / B. void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); - void operator/=(yc_number_node_ptr& lhs, yc_number_arg_const rhs); + void operator/=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); ///@} /// Operator version of yc_node_factory::new_not_node(). @@ -1002,8 +1007,8 @@ namespace yask { /// Binary math functions. #define FUNC_EXPR(fn_name) \ yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ - yc_number_node_ptr fn_name(yc_number_arg_const arg1, const yc_number_node_ptr arg2); \ - yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, yc_number_arg_const arg2) + yc_number_node_ptr fn_name(yc_number_const_arg arg1, const yc_number_node_ptr arg2); \ + yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, yc_number_const_arg arg2) FUNC_EXPR(pow); #undef FUNC_EXPR @@ -1019,7 +1024,7 @@ namespace yask { This should not be an operator that is defined for shared pointers. See https://en.cppreference.com/w/cpp/memory/shared_ptr. */ - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_number_arg_any rhs); + yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_number_any_arg rhs); #define IF_OPER ^= #define IF IF_OPER diff --git a/src/compiler/Makefile b/src/compiler/Makefile index cf98c26a..7d4c126d 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -57,7 +57,8 @@ YC_STENCIL_INC_GLOB := $(wildcard $(YC_STENCIL_DIR)/*.hpp $(YC_STENCIL_DIR)/*/*. # Compiler and default flags. YC_CXX ?= g++ # usually faster than icpc for building the compiler. YC_CXXOPT := -O2 -YC_CXXFLAGS := -g -std=c++11 -Wall $(YC_CXXOPT) +YC_CXXFLAGS := -g -std=c++11 $(YC_CXXOPT) -Wall +YC_CXXFLAGS += -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-but-set-variable YC_CXXFLAGS += $(INC_CXXFLAGS) YC_INC_CXXFLAGS := $(addprefix -I,$(YC_INC_DIRS)) diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 8a713138..cea66ac9 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -54,7 +54,7 @@ namespace yask { yc_equation_node_ptr yc_node_factory::new_equation_node(yc_grid_point_node_ptr lhs, - yc_number_arg_any rexpr, + yc_number_node_ptr rexpr, yc_bool_node_ptr cond) const { if (!lhs) THROW_YASK_EXCEPTION("Error: empty LHS of equation"); @@ -94,14 +94,14 @@ namespace yask { return make_shared(val); } yc_number_node_ptr - yc_node_factory::new_negate_node(yc_number_arg_any rhs) const { + yc_node_factory::new_negate_node(yc_number_node_ptr rhs) const { auto p = dynamic_pointer_cast(rhs); assert(p); return make_shared(p); } yc_number_node_ptr - yc_node_factory::new_add_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_add_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { if (!lhs) return rhs; if (!rhs) @@ -118,8 +118,8 @@ namespace yask { return ex; } yc_number_node_ptr - yc_node_factory::new_multiply_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_multiply_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { if (!lhs) return rhs; if (!rhs) @@ -136,8 +136,8 @@ namespace yask { return ex; } yc_number_node_ptr - yc_node_factory::new_subtract_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_subtract_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { yc_node_factory nfac; if (!lhs) return nfac.new_negate_node(rhs); @@ -150,8 +150,8 @@ namespace yask { return make_shared(lp, rp); } yc_number_node_ptr - yc_node_factory::new_divide_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_divide_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { yc_node_factory nfac; if (!lhs) return nfac.new_divide_node(nfac.new_const_number_node(1.0), rhs); @@ -164,8 +164,8 @@ namespace yask { return make_shared(lp, rp); } yc_number_node_ptr - yc_node_factory::new_mod_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_mod_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -197,8 +197,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_equals_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_equals_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -206,8 +206,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_equals_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_not_equals_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -215,8 +215,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_less_than_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_less_than_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -224,8 +224,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_greater_than_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_greater_than_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -233,8 +233,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_less_than_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_not_less_than_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -242,8 +242,8 @@ namespace yask { return make_shared(lp, rp); } yc_bool_node_ptr - yc_node_factory::new_not_greater_than_node(yc_number_arg_any lhs, - yc_number_arg_any rhs) const { + yc_node_factory::new_not_greater_than_node(yc_number_node_ptr lhs, + yc_number_node_ptr rhs) const { auto lp = dynamic_pointer_cast(lhs); assert(lp); auto rp = dynamic_pointer_cast(rhs); @@ -269,79 +269,79 @@ namespace yask { return make_shared(p->getName(), LAST_INDEX); } - yc_number_node_ptr yc_number_arg_const::_convert_const(double val) const { + yc_number_node_ptr yc_number_const_arg::_convert_const(double val) const { yc_node_factory nfac; return nfac.new_const_number_node(val); } - yc_number_node_ptr yc_number_arg_any::_convert_const(double val) const { + yc_number_node_ptr yc_number_any_arg::_convert_const(double val) const { yc_node_factory nfac; return nfac.new_const_number_node(val); } // Unary. - yc_number_node_ptr operator-(yc_number_arg_ptr rhs) { + yc_number_node_ptr operator-(yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_negate_node(rhs); } // Binary. - yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator+(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_add_node(lhs, rhs); } - yc_number_node_ptr operator+(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator+(yc_number_const_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_add_node(lhs, rhs); } - yc_number_node_ptr operator+(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { + yc_number_node_ptr operator+(yc_number_ptr_arg lhs, yc_number_const_arg rhs) { yc_node_factory nfac; return nfac.new_add_node(lhs, rhs); } - yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator/(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_divide_node(lhs, rhs); } - yc_number_node_ptr operator/(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator/(yc_number_const_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_divide_node(lhs, rhs); } - yc_number_node_ptr operator/(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { + yc_number_node_ptr operator/(yc_number_ptr_arg lhs, yc_number_const_arg rhs) { yc_node_factory nfac; return nfac.new_divide_node(lhs, rhs); } - yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator%(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_mod_node(lhs, rhs); } - yc_number_node_ptr operator%(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator%(yc_number_const_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_mod_node(lhs, rhs); } - yc_number_node_ptr operator%(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { + yc_number_node_ptr operator%(yc_number_ptr_arg lhs, yc_number_const_arg rhs) { yc_node_factory nfac; return nfac.new_mod_node(lhs, rhs); } - yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator*(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_multiply_node(lhs, rhs); } - yc_number_node_ptr operator*(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator*(yc_number_const_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_multiply_node(lhs, rhs); } - yc_number_node_ptr operator*(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { + yc_number_node_ptr operator*(yc_number_ptr_arg lhs, yc_number_const_arg rhs) { yc_node_factory nfac; return nfac.new_multiply_node(lhs, rhs); } - yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator-(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_subtract_node(lhs, rhs); } - yc_number_node_ptr operator-(yc_number_arg_const lhs, yc_number_arg_ptr rhs) { + yc_number_node_ptr operator-(yc_number_const_arg lhs, yc_number_ptr_arg rhs) { yc_node_factory nfac; return nfac.new_subtract_node(lhs, rhs); } - yc_number_node_ptr operator-(yc_number_arg_ptr lhs, yc_number_arg_const rhs) { + yc_number_node_ptr operator-(yc_number_ptr_arg lhs, yc_number_const_arg rhs) { yc_node_factory nfac; return nfac.new_subtract_node(lhs, rhs); } @@ -350,25 +350,25 @@ namespace yask { void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs + rhs; } - void operator+=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { + void operator+=(yc_number_node_ptr& lhs, yc_number_const_arg rhs) { lhs = lhs + rhs; } void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs - rhs; } - void operator-=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { + void operator-=(yc_number_node_ptr& lhs, yc_number_const_arg rhs) { lhs = lhs - rhs; } void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs * rhs; } - void operator*=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { + void operator*=(yc_number_node_ptr& lhs, yc_number_const_arg rhs) { lhs = lhs * rhs; } void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs) { lhs = lhs / rhs; } - void operator/=(yc_number_node_ptr& lhs, yc_number_arg_const rhs) { + void operator/=(yc_number_node_ptr& lhs, yc_number_const_arg rhs) { lhs = lhs / rhs; } @@ -428,10 +428,10 @@ namespace yask { assert(p2); \ return make_shared(#fn, std::initializer_list< const numExprPtr >{ p1, p2 }); \ } \ - yc_number_node_ptr fn(const yc_number_node_ptr arg1, yc_number_arg_const arg2) { \ + yc_number_node_ptr fn(const yc_number_node_ptr arg1, yc_number_const_arg arg2) { \ return fn(arg1, arg2); \ } \ - yc_number_node_ptr fn(yc_number_arg_const arg1, const yc_number_node_ptr arg2) { \ + yc_number_node_ptr fn(yc_number_const_arg arg1, const yc_number_node_ptr arg2) { \ return fn(arg1, arg2); \ } FUNC_EXPR(pow) @@ -464,7 +464,7 @@ namespace yask { // Define the value of a grid point. // Add this equation to the list of eqs for this stencil. yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr lhs, - const yc_number_arg_any rhs) { + const yc_number_any_arg rhs) { yc_node_factory nfac; return nfac.new_equation_node(lhs, rhs); } diff --git a/src/compiler/swig/yask_compiler_api.i b/src/compiler/swig/yask_compiler_api.i index 3db4b223..6109d88c 100644 --- a/src/compiler/swig/yask_compiler_api.i +++ b/src/compiler/swig/yask_compiler_api.i @@ -29,7 +29,7 @@ IN THE SOFTWARE. %module YC_MODULE -// See http://www.swig.org/Doc3.0/Library.html +// See http://www.swig.org/Doc4.0/Library.html %include %include %include @@ -66,6 +66,9 @@ IN THE SOFTWARE. %shared_ptr(yask::yc_not_greater_than_node) %shared_ptr(yask::yc_and_node) %shared_ptr(yask::yc_or_node) +%shared_ptr(yask::yc_number_ptr_arg) +%shared_ptr(yask::yc_number_const_arg) +%shared_ptr(yask::yc_number_any_arg) %{ #define SWIG_FILE_WITH_INIT @@ -73,12 +76,12 @@ IN THE SOFTWARE. %} // All vector types used in API. -%template(vector_int) std::vector; -%template(vector_str) std::vector; -%template(vector_index) std::vector>; -%template(vector_num) std::vector>; -%template(vector_eq) std::vector>; -%template(vector_grid) std::vector; +%template(yc_vector_int) std::vector; +%template(yc_vector_str) std::vector; +%template(yc_vector_index) std::vector>; +%template(yc_vector_num) std::vector>; +%template(yc_vector_eq) std::vector>; +%template(yc_vector_grid) std::vector; // Tell SWIG how to catch a YASK exception and rethrow it in Python. %exception { From b79d01a919ae5aeee46fe3118523351ce52aa866 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Sun, 5 May 2019 16:20:27 -0700 Subject: [PATCH 05/62] Fix infinite recursion in pow(). --- include/yc_node_api.hpp | 42 +++++++++++++++++++-------------------- src/compiler/lib/Expr.cpp | 16 ++++++++------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index 60199020..7aadc220 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -867,6 +867,27 @@ namespace yask { }; + /// Unary math functions. +#define FUNC_EXPR(fn_name) yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) + FUNC_EXPR(sqrt); + FUNC_EXPR(cbrt); + FUNC_EXPR(fabs); + FUNC_EXPR(erf); + FUNC_EXPR(exp); + FUNC_EXPR(log); + FUNC_EXPR(sin); + FUNC_EXPR(cos); + FUNC_EXPR(atan); +#undef FUNC_EXPR + + /// Binary math functions. +#define FUNC_EXPR(fn_name) \ + yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ + yc_number_node_ptr fn_name(double arg1, const yc_number_node_ptr arg2); \ + yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, double arg2) + FUNC_EXPR(pow); +#undef FUNC_EXPR + #if !defined SWIG // Non-class operators. @@ -991,27 +1012,6 @@ namespace yask { BOOL_OPER(>=, new_not_less_than_node) #undef BOOL_OPER - /// Unary math functions. -#define FUNC_EXPR(fn_name) yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) - FUNC_EXPR(sqrt); - FUNC_EXPR(cbrt); - FUNC_EXPR(fabs); - FUNC_EXPR(erf); - FUNC_EXPR(exp); - FUNC_EXPR(log); - FUNC_EXPR(sin); - FUNC_EXPR(cos); - FUNC_EXPR(atan); -#undef FUNC_EXPR - - /// Binary math functions. -#define FUNC_EXPR(fn_name) \ - yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ - yc_number_node_ptr fn_name(yc_number_const_arg arg1, const yc_number_node_ptr arg2); \ - yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, yc_number_const_arg arg2) - FUNC_EXPR(pow); -#undef FUNC_EXPR - #define EQUALS_OPER << #define EQUALS EQUALS_OPER #define IS_EQUIV_TO EQUALS_OPER diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index cea66ac9..0ab733ee 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -426,13 +426,15 @@ namespace yask { assert(p1); \ auto p2 = dynamic_pointer_cast(arg2); \ assert(p2); \ - return make_shared(#fn, std::initializer_list< const numExprPtr >{ p1, p2 }); \ - } \ - yc_number_node_ptr fn(const yc_number_node_ptr arg1, yc_number_const_arg arg2) { \ - return fn(arg1, arg2); \ - } \ - yc_number_node_ptr fn(yc_number_const_arg arg1, const yc_number_node_ptr arg2) { \ - return fn(arg1, arg2); \ + return make_shared(#fn, std::initializer_list< const numExprPtr >{ p1, p2 }); \ + } \ + yc_number_node_ptr fn(const yc_number_node_ptr arg1, double arg2) { \ + yc_node_factory nfac; \ + return fn(arg1, nfac.new_const_number_node(arg2)); \ + } \ + yc_number_node_ptr fn(double arg1, const yc_number_node_ptr arg2) { \ + yc_node_factory nfac; \ + return fn(nfac.new_const_number_node(arg1), arg2); \ } FUNC_EXPR(pow) #undef FUNC_EXPR From 1991d1bb007dd020005471cb01644d13d633ed47 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Sun, 5 May 2019 16:57:21 -0700 Subject: [PATCH 06/62] Add wrapper ctor for existing grid. Doc cleanup. --- include/Soln.hpp | 11 +++- include/yask_compiler_api.hpp | 102 ++++++++++++++++++++++++---------- include/yc_node_api.hpp | 36 ++++++++---- 3 files changed, 105 insertions(+), 44 deletions(-) diff --git a/include/Soln.hpp b/include/Soln.hpp index b2994156..9ae1cb4b 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -26,7 +26,7 @@ IN THE SOFTWARE. // This file contains convenience functions and macros for defining // stencils to be included in the YASK compiler binary utility. // It is to be used only for backward compatibility for old-style -// stencil DSL code before YASK version 2.23.00. +// stencil DSL code prior to YASK version 2.23.00. #pragma once @@ -43,6 +43,9 @@ namespace yask { /// **[Deprecated]** The class all old-style C++ stencil solutions /// written for the YASK compiler binary must implement. + /** + New DSL code should use yc_solution_base directly. + */ class StencilBase : public yc_solution_base { public: @@ -52,7 +55,11 @@ namespace yask { yc_solution_base(name) { } /// Create a constant expression. - /** Usually not needed due to operator overloading. */ + /** + Usually not needed due to operator overloading. + New DSL code should use new_const_number_node() or + simply new_number_node(). + */ virtual yc_number_node_ptr constNum(double val) { return _node_factory.new_const_number_node(val); } diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index c79a6842..51b6e237 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -622,10 +622,21 @@ namespace yask { /**< [in] Number of elements to allocate in the step dimension. */) =0; }; - /// A wrapper class around a 'yc_grid_ptr', providing - /// convenience functions for declaring grid vars and - /// creating expression nodes with references to points - /// in grid vars. + /// A wrapper class around a \ref yc_grid_ptr, providing convenience + /// functions for declaring grid vars and creating expression nodes with + /// references to points in grid vars. + /** + Using this class provides a syntactic alternative to calling yc_solution::new_grid() + and/or yc_solution::new_scratch_grid() followed by yc_grid::new_grid_point(). + + *Scoping and lifetime:* Since the \ref yc_grid_ptr in a \ref + yc_grid_var object is a shared pointer also owned by the \ref + yc_solution object used to construct the \ref yc_grid_var object, the + underlying grid will not be destroyed until both the \ref yc_grid_var + object and the \ref yc_solution object are destroyed. + A \ref yc_grid_var object created from an existing \ref yc_grid + object will have the same properties. + */ class yc_grid_var { private: yc_grid_ptr _grid; @@ -633,6 +644,10 @@ namespace yask { public: /// Contructor taking a vector of index vars. + /** + A wrapper around yc_solution::new_grid() and + yc_solution::new_scratch_grid(). + */ yc_grid_var(const std::string& name /**< [in] Name of the new grid; must be a valid C++ identifier and unique across grids. */, @@ -649,7 +664,13 @@ namespace yask { _grid = soln->new_grid(name, dims); } +#ifndef SWIG // Contructor taking an initializer_list of index vars. + /** + A wrapper around yc_solution::new_grid() and + yc_solution::new_scratch_grid(). + @note Not available in the Python API. Use the vector version. + */ yc_grid_var(const std::string& name /**< [in] Name of the new grid; must be a valid C++ identifier and unique across grids. */, @@ -665,7 +686,15 @@ namespace yask { else _grid = soln->new_grid(name, dims); } - +#endif + + /// Contructor taking an existing grid. + /** + Creates a new \ref yc_grid_var wrapper around an + existing grid. + */ + yc_grid_var(yc_grid_ptr& grid) : _grid(grid) { } + /// Provide a virtual destructor. virtual ~yc_grid_var() { } @@ -679,12 +708,43 @@ namespace yask { return _grid; } + /// Create an expression for a point in a grid. + /// The number of arguments must match the dimensionality of the grid. + /// Create an expression for a point in a 1-6 dim grid. + /// The number of arguments must match the dimensionality of the grid. + /** + A wrapper around yc_grid::new_grid_point(). + + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, + where `vec` is a 2-element vector of \ref yc_number_node_ptr. + */ + virtual yc_grid_point_node_ptr + operator()(const std::vector& index_exprs) { + return _grid->new_grid_point(index_exprs); + } + #ifndef SWIG + /// Create an expression for a point in a grid. + /// The number of arguments must match the dimensionality of the grid. + /** + A wrapper around yc_grid::new_grid_point(). + + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. + @note Not available in Python API. Use vector version. + */ + virtual yc_grid_point_node_ptr + operator()(const std::initializer_list& index_exprs) { + return _grid->new_grid_point(index_exprs); + } + /// Create an expression for a point in a zero-dim (scalar) grid /// using implicit conversion. /** + A wrapper around yc_grid::new_grid_point(). + Example w/0D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B`. - @note Not available in Python API. Use more explicit methods. + @note Not available in Python API. + Use vector version with empty vector. */ virtual operator yc_number_ptr_arg() { return _grid->new_grid_point({}); @@ -692,8 +752,11 @@ namespace yask { /// Create an expression for a point in a one-dim (array) grid. /** + A wrapper around yc_grid::new_grid_point(). + Example w/1D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. - @note Not available in Python API. Use vector version. + @note Not available in Python API. + Use vector version with 1-element vector. */ virtual yc_grid_point_node_ptr operator[](const yc_number_any_arg i1) { return _grid->new_grid_point({i1}); @@ -702,6 +765,8 @@ namespace yask { /// Create an expression for a point in a 1-6 dim grid. /// The number of arguments must match the dimensionality of the grid. /** + A wrapper around yc_grid::new_grid_point(). + Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. @note Not available in Python API. Use vector version. */ @@ -726,31 +791,8 @@ namespace yask { args.push_back(i6); return _grid->new_grid_point(args); } - - /// Create an expression for a point in a grid. - /// The number of arguments must match the dimensionality of the grid. - /** - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. - @note Not available in Python API. Use vector version. - */ - virtual yc_grid_point_node_ptr - operator()(const std::initializer_list& index_exprs) { - return _grid->new_grid_point(index_exprs); - } #endif - /// Create an expression for a point in a grid. - /// The number of arguments must match the dimensionality of the grid. - /// Create an expression for a point in a 1-6 dim grid. - /// The number of arguments must match the dimensionality of the grid. - /** - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, - where `vec` is a 2-element vector of \ref yc_number_node_ptr. - */ - virtual yc_grid_point_node_ptr - operator()(const std::vector& index_exprs) { - return _grid->new_grid_point(index_exprs); - } }; /** @}*/ diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index 7aadc220..d8faaf21 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -474,9 +474,12 @@ namespace yask { class yc_not_greater_than_node : public virtual yc_binary_comparison_node { }; #ifndef SWIG - /// A simple wrapper class to provide automatic - /// construction of a 'yc_number_node_ptr' from - /// other YASK pointer types. + /// A simple wrapper class to provide automatic construction of a + /// 'yc_number_node_ptr' from other YASK pointer types. + /** + Used only to provide conversions in function arguments. + @note Not used in Python API. + */ class yc_number_ptr_arg : public virtual yc_number_node_ptr { public: @@ -494,9 +497,12 @@ namespace yask { yc_number_node_ptr(p) { } }; - /// A simple wrapper class to provide automatic - /// construction of a 'yc_number_node_ptr' from - /// non-YASK fundamental numeric types. + /// A simple wrapper class to provide automatic construction of a + /// 'yc_number_node_ptr' from non-YASK fundamental numeric types. + /** + Used only to provide conversions in function arguments. + @note Not used in Python API. + */ class yc_number_const_arg : public virtual yc_number_node_ptr { protected: @@ -523,9 +529,13 @@ namespace yask { yc_number_node_ptr(_convert_const(f)) { } }; - /// A simple wrapper class to provide automatic - /// construction of a 'yc_number_node_ptr' from - /// a YASK pointer or non-YASK fundamental numeric types. + /// A simple wrapper class to provide automatic construction of a + /// 'yc_number_node_ptr' from a YASK pointer or non-YASK fundamental + /// numeric types. + /** + Used only to provide conversions in function arguments. + @note Not used in Python API. + */ class yc_number_any_arg : public virtual yc_number_node_ptr { protected: @@ -868,7 +878,8 @@ namespace yask { }; /// Unary math functions. -#define FUNC_EXPR(fn_name) yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) +#define FUNC_EXPR(fn_name) \ + yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) FUNC_EXPR(sqrt); FUNC_EXPR(cbrt); FUNC_EXPR(fabs); @@ -1016,7 +1027,8 @@ namespace yask { #define EQUALS EQUALS_OPER #define IS_EQUIV_TO EQUALS_OPER #define IS_EQUIVALENT_TO EQUALS_OPER - /// The operator used for defining a grid value. + /// The operator version of yc_node_factory::new_equation_node() used + /// for defining a grid value. /** Use an otherwise unneeded binary operator that has a lower priority than the math ops and a higher priority than the IF_OPER. @@ -1028,7 +1040,7 @@ namespace yask { #define IF_OPER ^= #define IF IF_OPER - /// A operator to add a domain condition. + /// The operator version of to add a domain condition. /** Use an otherwise unneeded binary operator that has a low priority. See http://en.cppreference.com/w/cpp/language/operator_precedence. From 143cf61aaa3acaa5a03c95522bd473920752784f Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Sun, 5 May 2019 17:28:43 -0700 Subject: [PATCH 07/62] Clean up docs and compiler-utility API. --- docs/api/doxygen_config.txt | 2 +- include/yask_compiler_api.hpp | 10 ++-- include/yask_compiler_utility_api.hpp | 66 +++++++++++++++++---------- include/yc_node_api.hpp | 2 +- src/compiler/compiler_main.cpp | 6 +++ 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/docs/api/doxygen_config.txt b/docs/api/doxygen_config.txt index 12571e03..461f0542 100644 --- a/docs/api/doxygen_config.txt +++ b/docs/api/doxygen_config.txt @@ -835,7 +835,7 @@ INPUT_ENCODING = UTF-8 # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, # *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. -FILE_PATTERNS = *.hpp +FILE_PATTERNS = y*.hpp # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 51b6e237..e622fe7e 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -622,14 +622,14 @@ namespace yask { /**< [in] Number of elements to allocate in the step dimension. */) =0; }; - /// A wrapper class around a \ref yc_grid_ptr, providing convenience + /// A wrapper class around a \ref yc_grid pointer, providing convenience /// functions for declaring grid vars and creating expression nodes with /// references to points in grid vars. /** Using this class provides a syntactic alternative to calling yc_solution::new_grid() and/or yc_solution::new_scratch_grid() followed by yc_grid::new_grid_point(). - *Scoping and lifetime:* Since the \ref yc_grid_ptr in a \ref + *Scoping and lifetime:* Since the \ref yc_grid pointer in a \ref yc_grid_var object is a shared pointer also owned by the \ref yc_solution object used to construct the \ref yc_grid_var object, the underlying grid will not be destroyed until both the \ref yc_grid_var @@ -698,12 +698,12 @@ namespace yask { /// Provide a virtual destructor. virtual ~yc_grid_var() { } - /// Get the underlying \ref yc_grid_ptr. + /// Get the underlying \ref yc_grid pointer. virtual yc_grid_ptr get_grid() { return _grid; } - /// Get the underlying \ref yc_grid_ptr. + /// Get the underlying \ref yc_grid pointer. virtual const yc_grid_ptr get_grid() const { return _grid; } @@ -716,7 +716,7 @@ namespace yask { A wrapper around yc_grid::new_grid_point(). Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, - where `vec` is a 2-element vector of \ref yc_number_node_ptr. + where `vec` is a 2-element vector of \ref yc_number_node pointers. */ virtual yc_grid_point_node_ptr operator()(const std::vector& index_exprs) { diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index 57aa7646..7b630675 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -42,21 +42,16 @@ namespace yask { * @{ */ - // Forward defn. - class yc_solution_base; - - /// Function provided by the YASK compiler binary utility - /// to create a new solution and register 'base_ptr' - /// as a known \ref yc_solution_base object. - yc_solution_ptr yc_new_solution(const std::string& name, - yc_solution_base* base_ptr); - /// The class all C++ stencil solutions written for the YASK compiler - /// binary must implement. + /// utility `yask_compiler.exe` must implement. /** - Mostly, this is a wrapper around a \ref yc_solution_ptr. + Mostly, this is a wrapper around a \ref yc_solution pointer. The `define()` method must be overloaded by the YASK DSL programmer to add stencil equations. + + Not to be used by DSL code that is not a part of the YASK compiler + utility `yask_compiler.exe`. For DSL code not using this utility, + call yc_factory::new_solution directly. */ class yc_solution_base { protected: @@ -73,22 +68,20 @@ namespace yask { /** Creates a new yc_solution object and registers this object in the list for the YASK compiler. - The `define()` method will be called from the YASK + The define() method will be called from the YASK compiler for the selected solution. */ - yc_solution_base(const std::string& name) { - _soln = yc_new_solution(name, this); - } + yc_solution_base(const std::string& name); - /// Constructor that uses an existing yc_solution_base to share underlying - /// solutions. + /// **[Advanced]** Constructor that uses an existing + /// yc_solution_base to share underlying solutions. /** This constructor allows the use of object-oriented composition instead of inheritance when creating classes that participate in solution definition. - When using this version, the `define()` method will + When using this version, the define() method will _not_ be called directly from the YASK compiler, but it (or any - other method) may be called by the parent 'base' object + other method) may be called by the parent `base` object explicitly. */ yc_solution_base(yc_solution_base& base) { @@ -98,11 +91,25 @@ namespace yask { /// Destructor. virtual ~yc_solution_base() { } - // Define grid values relative to current domain indices in each dimension. - // This must be implemented by each concrete stencil solution. + /// Define all functionality of this solution. + /** + When a stencil solution is selected by naming it via `stencil=name` + when invoking `make` or via `-stencil name` on the YASK compiler + command-line, this function in the named solution will be called. + + This function must be implemented by each concrete stencil solution to + add grids and grid-value equations as needed to define the stencil. + In general, any YASK compiler API functions may be called from this + function. + + For DSL code not using the YASK compiler + utility `yask_compiler.exe`, the code that would be in define() + could be called from `main()` or any other called function. + */ virtual void define() { std::cout << "Warning: no stencil equations are defined in solution '" << - _soln->get_name() << "'\n"; + _soln->get_name() << "'. Implement the 'define()' method in the class " + "derived from 'yc_solution_base'.\n"; } /// Access the underlying solution. @@ -110,7 +117,6 @@ namespace yask { return _soln; } - /// Create boundary index expression, e.g., 'first_index(x)'. virtual yc_number_node_ptr first_index(yc_index_node_ptr dim) { return _node_factory.new_first_domain_index(dim); @@ -144,12 +150,22 @@ namespace yask { int _radius; public: - // Constructor. + /// Constructor. yc_solution_with_radius_base(const std::string& name, int radius) : yc_solution_base(name) { set_radius(radius); } + /// Define all functionality of this solution. + /** + See yc_solution_base::define(). + */ + virtual void define() override { + std::cout << "Warning: no stencil equations are defined in solution '" << + _soln->get_name() << "'. Implement the 'define()' method in the class " + "derived from 'yc_solution_with_radius_base'.\n"; + } + /// This object does use radius. virtual bool uses_radius() const override { return true; } @@ -170,7 +186,7 @@ namespace yask { } // namespace yask. /// Convenience macro for declaring a static object of a type derived from -/// \ref yc_solution_base and registering it in the list used by the +/// \ref yask::yc_solution_base and registering it in the list used by the /// provided YASK compiler utility. /** The derived class must implement a default constructor. */ #define YASK_REGISTER_SOLUTION(class_name) \ diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index d8faaf21..c0b315c6 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -668,7 +668,7 @@ namespace yask { /** A generic method to create a pointer to a numerical expression from any type supported by \ref yc_number_any_arg constructors. - @node Not available in Python API. Use a more explicit method. + @note Not available in Python API. Use a more explicit method. */ virtual yc_number_node_ptr new_number_node(yc_number_any_arg arg diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 12d85e38..738da0f2 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -74,6 +74,12 @@ namespace yask { stencils[name] = base_ptr; return soln; } + + // Constructor from the DSL API. + yc_solution_base::yc_solution_base(const std::string& name) { + _soln = yc_new_solution(name, this); + } + } // yask namespace. void usage(const string& cmd) { From 88e51a70982c2933e5bfa27d7db9721c171f2f85 Mon Sep 17 00:00:00 2001 From: chuckyount Date: Sun, 5 May 2019 17:35:06 -0700 Subject: [PATCH 08/62] Improve docs --- include/yask_compiler_utility_api.hpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index 7b630675..7c0c6b9d 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -56,10 +56,10 @@ namespace yask { class yc_solution_base { protected: - // Pointer to the YASK stencil solution. + /// Pointer to the YASK stencil solution. yc_solution_ptr _soln; - // Factory to create new nodes. + /// Factory to create new nodes. yc_node_factory _node_factory; public: @@ -141,12 +141,14 @@ namespace yask { class yc_solution_with_radius_base : public yc_solution_base { protected: - // A variable that controls the size the stencil, i.e., the number of - // points that are read to calculate a new value. In many cases, - // this is the number of points in the spatial dimension(s) from the - // center point of a finite-difference approximation, but it does - // not have to be. For example, it could be the minimum or maximum - // radius for an asymmetical stencil. + /// A variable that controls the size the stencil, i.e., the number of + // points that are read to calculate a new value. + /** In many cases, + this is the number of points in the spatial dimension(s) from the + center point of a finite-difference approximation, but it does + not have to be. For example, it could be the minimum or maximum + radius for an asymmetical stencil. + */ int _radius; public: From 7f2ebbdd128701cc8a179c1b1d41d7cbc120a3de Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 08:28:05 -0700 Subject: [PATCH 09/62] Change version to 3.0. Also more doc cleanup. --- include/Soln.hpp | 24 +++++++++----- include/yask_compiler_api.hpp | 21 +++++------- include/yask_compiler_utility_api.hpp | 23 ++++++------- include/yc_node_api.hpp | 48 +++++++++++++-------------- setup.py | 2 +- src/common/common_utils.cpp | 2 +- 6 files changed, 60 insertions(+), 60 deletions(-) diff --git a/include/Soln.hpp b/include/Soln.hpp index 9ae1cb4b..f2a8e86d 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -26,7 +26,9 @@ IN THE SOFTWARE. // This file contains convenience functions and macros for defining // stencils to be included in the YASK compiler binary utility. // It is to be used only for backward compatibility for old-style -// stencil DSL code prior to YASK version 2.23.00. +// stencil DSL code in YASK version 2. +// Newer DSL code using the provided YASK compiler utility should include +// "yask_compiler_utility_api.hpp" and use only published APIs. #pragma once @@ -94,25 +96,25 @@ namespace yask { } // namespace yask. -/// Macro for backward compatibility. +// Macro for backward compatibility. #define REGISTER_STENCIL_CONTEXT_EXTENSION(...) -/// Convenience macro for declaring an object of a type derived from \ref StencilBase -/// and registering it in the list used by the default provided YASK compiler binary. +// Convenience macro for declaring an object of a type derived from \ref StencilBase +// and registering it in the list used by the default provided YASK compiler binary. /** The derived class must implement a constructor that takes only a \ref StencilList reference. */ #define REGISTER_STENCIL(class_name) \ static class_name registered_ ## class_name(stub_stencils) -/// Convenience macros for declaring dims in a class derived from \ref StencilBase. -/// The 'd' arg is the new var name and the dim name. +// Convenience macros for declaring dims in a class derived from \ref StencilBase. +// The 'd' arg is the new var name and the dim name. #define MAKE_STEP_INDEX(d) yc_index_node_ptr d = _node_factory.new_step_index(#d); #define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = _node_factory.new_domain_index(#d); #define MAKE_MISC_INDEX(d) yc_index_node_ptr d = _node_factory.new_misc_index(#d); -/// Convenience macros for creating grids in a class implementing get_solution(). -/// The 'gvar' arg is the var name and the grid name. -/// The remaining args are the dimension names. +// Convenience macros for creating grids in a class implementing get_solution(). +// The 'gvar' arg is the var name and the grid name. +// The remaining args are the dimension names. #define MAKE_GRID(gvar, ...) \ Grid gvar = Grid(#gvar, get_solution(), { __VA_ARGS__ }, false) #define MAKE_SCALAR(gvar) MAKE_GRID(gvar) @@ -122,6 +124,10 @@ namespace yask { #define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) #define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) +// Old aliases for EQUALS. +#define IS_EQUIV_TO EQUALS_OPER +#define IS_EQUIVALENT_TO EQUALS_OPER + // Namespaces for stencil code. #ifndef NO_NAMESPACES using namespace yask; diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index e622fe7e..1830ce27 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -622,9 +622,7 @@ namespace yask { /**< [in] Number of elements to allocate in the step dimension. */) =0; }; - /// A wrapper class around a \ref yc_grid pointer, providing convenience - /// functions for declaring grid vars and creating expression nodes with - /// references to points in grid vars. + /// A wrapper class around a \ref yc_grid pointer. /** Using this class provides a syntactic alternative to calling yc_solution::new_grid() and/or yc_solution::new_scratch_grid() followed by yc_grid::new_grid_point(). @@ -665,7 +663,7 @@ namespace yask { } #ifndef SWIG - // Contructor taking an initializer_list of index vars. + /// Contructor taking an initializer_list of index vars. /** A wrapper around yc_solution::new_grid() and yc_solution::new_scratch_grid(). @@ -709,11 +707,9 @@ namespace yask { } /// Create an expression for a point in a grid. - /// The number of arguments must match the dimensionality of the grid. - /// Create an expression for a point in a 1-6 dim grid. - /// The number of arguments must match the dimensionality of the grid. /** A wrapper around yc_grid::new_grid_point(). + The number of arguments must match the dimensionality of the grid. Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, where `vec` is a 2-element vector of \ref yc_number_node pointers. @@ -725,9 +721,9 @@ namespace yask { #ifndef SWIG /// Create an expression for a point in a grid. - /// The number of arguments must match the dimensionality of the grid. /** A wrapper around yc_grid::new_grid_point(). + The number of arguments must match the dimensionality of the grid. Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. @note Not available in Python API. Use vector version. @@ -737,8 +733,7 @@ namespace yask { return _grid->new_grid_point(index_exprs); } - /// Create an expression for a point in a zero-dim (scalar) grid - /// using implicit conversion. + /// Create an expression for a point in a zero-dim (scalar) grid using implicit conversion. /** A wrapper around yc_grid::new_grid_point(). @@ -762,13 +757,15 @@ namespace yask { return _grid->new_grid_point({i1}); } - /// Create an expression for a point in a 1-6 dim grid. - /// The number of arguments must match the dimensionality of the grid. + /// **[Deprecated]** Create an expression for a point in a 1-6 dim grid. /** A wrapper around yc_grid::new_grid_point(). + The number of arguments must match the dimensionality of the grid. Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. @note Not available in Python API. Use vector version. + + Deprecated: The vector or initializer-list version is recommended instead. */ virtual yc_grid_point_node_ptr operator()(const yc_number_any_arg i1 = nullptr, const yc_number_any_arg i2 = nullptr, diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index 7c0c6b9d..cf9e30b6 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -38,12 +38,12 @@ IN THE SOFTWARE. namespace yask { /** - * \addtogroup yc + * \defgroup ycu YASK Compiler Utility + * Types, clases, and functions used in the provided `yask_compiler.exe` binary utility. * @{ */ - /// The class all C++ stencil solutions written for the YASK compiler - /// utility `yask_compiler.exe` must implement. + /// The class all C++ stencil solutions written for the YASK compiler utility `yask_compiler.exe` must implement. /** Mostly, this is a wrapper around a \ref yc_solution pointer. The `define()` method must be overloaded by @@ -73,8 +73,7 @@ namespace yask { */ yc_solution_base(const std::string& name); - /// **[Advanced]** Constructor that uses an existing - /// yc_solution_base to share underlying solutions. + /// **[Advanced]** Constructor that uses an existing yc_solution_base to share underlying solutions. /** This constructor allows the use of object-oriented composition instead of inheritance when creating classes that participate @@ -141,13 +140,13 @@ namespace yask { class yc_solution_with_radius_base : public yc_solution_base { protected: - /// A variable that controls the size the stencil, i.e., the number of - // points that are read to calculate a new value. - /** In many cases, - this is the number of points in the spatial dimension(s) from the - center point of a finite-difference approximation, but it does - not have to be. For example, it could be the minimum or maximum - radius for an asymmetical stencil. + /// A variable that controls the size the stencil. + /** + For a symmetric finite-difference stencil, this is often the + number of points in the spatial dimension(s) from the center + point of a finite-difference approximation. However, any meaning + may be given to this variable. For example, it could be the + minimum or maximum radius for an asymmetical stencil. */ int _radius; diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index c0b315c6..2ce915f9 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -475,7 +475,7 @@ namespace yask { #ifndef SWIG /// A simple wrapper class to provide automatic construction of a - /// 'yc_number_node_ptr' from other YASK pointer types. + // 'yc_number_node_ptr' from other YASK pointer types. /** Used only to provide conversions in function arguments. @note Not used in Python API. @@ -498,7 +498,7 @@ namespace yask { }; /// A simple wrapper class to provide automatic construction of a - /// 'yc_number_node_ptr' from non-YASK fundamental numeric types. + // 'yc_number_node_ptr' from non-YASK fundamental numeric types. /** Used only to provide conversions in function arguments. @note Not used in Python API. @@ -530,8 +530,8 @@ namespace yask { }; /// A simple wrapper class to provide automatic construction of a - /// 'yc_number_node_ptr' from a YASK pointer or non-YASK fundamental - /// numeric types. + // 'yc_number_node_ptr' from a YASK pointer or non-YASK fundamental + // numeric types. /** Used only to provide conversions in function arguments. @note Not used in Python API. @@ -877,27 +877,27 @@ namespace yask { }; - /// Unary math functions. -#define FUNC_EXPR(fn_name) \ + /// Unary math functions. Used internally to define sqrt(), sin(), etc. +#define UNARY_MATH_EXPR(fn_name) \ yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) - FUNC_EXPR(sqrt); - FUNC_EXPR(cbrt); - FUNC_EXPR(fabs); - FUNC_EXPR(erf); - FUNC_EXPR(exp); - FUNC_EXPR(log); - FUNC_EXPR(sin); - FUNC_EXPR(cos); - FUNC_EXPR(atan); -#undef FUNC_EXPR - - /// Binary math functions. -#define FUNC_EXPR(fn_name) \ + UNARY_MATH_EXPR(sqrt); + UNARY_MATH_EXPR(cbrt); + UNARY_MATH_EXPR(fabs); + UNARY_MATH_EXPR(erf); + UNARY_MATH_EXPR(exp); + UNARY_MATH_EXPR(log); + UNARY_MATH_EXPR(sin); + UNARY_MATH_EXPR(cos); + UNARY_MATH_EXPR(atan); +#undef UNARY_MATH_EXPR + + /// Binary math functions. Used internally to define pow(). +#define BINARY_MATH_EXPR(fn_name) \ yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ yc_number_node_ptr fn_name(double arg1, const yc_number_node_ptr arg2); \ yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, double arg2) - FUNC_EXPR(pow); -#undef FUNC_EXPR + BINARY_MATH_EXPR(pow); +#undef BINARY_MATH_EXPR #if !defined SWIG @@ -982,7 +982,7 @@ namespace yask { /** For Python, use `lhs.yc_and(rhs)` */ yc_bool_node_ptr operator&&(yc_bool_node_ptr lhs, yc_bool_node_ptr rhs); - /// Binary numerical-to-boolean operators. + /// Binary numerical-to-boolean operators. Used internally to define `==`, `<`, etc. /** Must provide more explicit ptr-type operands than used with math operators to keep compiler from using built-in pointer comparison. @@ -1025,8 +1025,6 @@ namespace yask { #define EQUALS_OPER << #define EQUALS EQUALS_OPER -#define IS_EQUIV_TO EQUALS_OPER -#define IS_EQUIVALENT_TO EQUALS_OPER /// The operator version of yc_node_factory::new_equation_node() used /// for defining a grid value. /** @@ -1040,7 +1038,7 @@ namespace yask { #define IF_OPER ^= #define IF IF_OPER - /// The operator version of to add a domain condition. + /// The operator version of yc_equation_node::set_cond() to add a domain condition. /** Use an otherwise unneeded binary operator that has a low priority. See http://en.cppreference.com/w/cpp/language/operator_precedence. diff --git a/setup.py b/setup.py index a719414a..b7ec0195 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ def run(self): setup( name='yask', - version='v2', + version='v3', description='YASK--Yet Another Stencil Kernel', url='https://github.com/intel/yask', author='Intel Corporation', diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index a34fa75c..1d2281f6 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -43,7 +43,7 @@ namespace yask { // for numbers above 9 (at least up to 99). // Format: "major.minor.patch". - const string version = "2.23.00"; + const string version = "3.00.00"; string yask_get_version_string() { return version; From 390948ff25d5addaed7a1d94deaaa0d96a6beb25 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 14:50:22 -0700 Subject: [PATCH 10/62] Update version info. --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 838ba641..759d7981 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ YASK contains a domain-specific compiler to convert scalar stencil code to SIMD- You'll get a warning when running `make` if one of these doesn't exist. Everything will still work, but the generated code will be difficult to read. Reading the generated code is only necessary for debug or curiosity. - * SWIG (3.0.12 or later), + * SWIG (3.0.12 or later; 4.0.0 or later recommended), http://www.swig.org, for creating the Python interface. * Python 2 (2.7.5 or later) or 3 (3.6.1 or later), https://www.python.org/downloads, for creating and using the Python interface. @@ -66,7 +66,13 @@ YASK contains a domain-specific compiler to convert scalar stencil code to SIMD- https://software.intel.com/en-us/articles/intel-software-development-emulator, for functional testing if you don't have native support for any given instruction set. -### Backward-compatibility notices, including changes in default behavior: +## Backward-compatibility notices, including changes in default behavior +### Version 3 +* Version 3.00.00 implemented a unification of the old (v2) internal DSL with the YASK compiler API. +Most v2 DSL code should still work using the "Soln.hpp" backward-compatibility header file. +To convert v2 DSL code to v3 format, use the `./utils/bin/convert_v2_stencil.pl` utility. + +### Version 2 * Version 2.22.00 changed the heuristic to determine vector-folding sizes when some sizes are specified. This did not affect the default folding sizes. * Version 2.21.02 simplified the example 3-D stencils (`3axis`, `3plane`, etc.) From 34c6839ffefc23e7f14f81b5e0499a8b8d85190c Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 14:52:29 -0700 Subject: [PATCH 11/62] Clean up DSL operators. --- include/Soln.hpp | 24 ++-- include/yask_common_api.hpp | 2 +- include/yask_compiler_utility_api.hpp | 7 -- include/yc_node_api.hpp | 175 ++++++++++++++++---------- src/compiler/lib/Expr.cpp | 10 +- 5 files changed, 126 insertions(+), 92 deletions(-) diff --git a/include/Soln.hpp b/include/Soln.hpp index f2a8e86d..8c814603 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -104,30 +104,34 @@ namespace yask { /** The derived class must implement a constructor that takes only a \ref StencilList reference. */ #define REGISTER_STENCIL(class_name) \ - static class_name registered_ ## class_name(stub_stencils) + static class_name class_name ## _instance(stub_stencils) // Convenience macros for declaring dims in a class derived from \ref StencilBase. // The 'd' arg is the new var name and the dim name. -#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = _node_factory.new_step_index(#d); -#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = _node_factory.new_domain_index(#d); -#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = _node_factory.new_misc_index(#d); +#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = _node_factory.new_step_index(#d) +#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = _node_factory.new_domain_index(#d) +#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = _node_factory.new_misc_index(#d) // Convenience macros for creating grids in a class implementing get_solution(). // The 'gvar' arg is the var name and the grid name. // The remaining args are the dimension names. #define MAKE_GRID(gvar, ...) \ - Grid gvar = Grid(#gvar, get_solution(), { __VA_ARGS__ }, false) + yc_grid_var gvar = yc_grid_var(#gvar, get_solution(), { __VA_ARGS__ }, false) #define MAKE_SCALAR(gvar) MAKE_GRID(gvar) #define MAKE_ARRAY(gvar, d1) MAKE_GRID(gvar, d1) #define MAKE_SCRATCH_GRID(gvar, ...) \ - Grid gvar = Grid(#gvar, get_solution(), { __VA_ARGS__ }, true) + yc_grid_var gvar = yc_grid_var(#gvar, get_solution(), { __VA_ARGS__ }, true) #define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) #define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) -// Old aliases for EQUALS. -#define IS_EQUIV_TO EQUALS_OPER -#define IS_EQUIVALENT_TO EQUALS_OPER - +// Old aliases for operators. +#define EQUALS_OPER EQUALS +#define IS_EQUIV_TO EQUALS +#define IS_EQUIVALENT_TO EQUALS +#define IF IF_DOMAIN +#define IF_OPER IF_DOMAIN +#define IF_STEP_OPER IF_STEP + // Namespaces for stencil code. #ifndef NO_NAMESPACES using namespace yask; diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index fad1453c..933b4b33 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -40,7 +40,7 @@ IN THE SOFTWARE. namespace yask { /** - * \defgroup yask YASK Common Utilities + * \defgroup yask YASK Common * Types, clases, and functions used in both the \ref sec_yc and \ref sec_yk. * @{ */ diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index cf9e30b6..b99cce74 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -185,10 +185,3 @@ namespace yask { /** @}*/ } // namespace yask. - -/// Convenience macro for declaring a static object of a type derived from -/// \ref yask::yc_solution_base and registering it in the list used by the -/// provided YASK compiler utility. -/** The derived class must implement a default constructor. */ -#define YASK_REGISTER_SOLUTION(class_name) \ - static class_name registered_ ## class_name() diff --git a/include/yc_node_api.hpp b/include/yc_node_api.hpp index 2ce915f9..a4ecd496 100644 --- a/include/yc_node_api.hpp +++ b/include/yc_node_api.hpp @@ -474,9 +474,11 @@ namespace yask { class yc_not_greater_than_node : public virtual yc_binary_comparison_node { }; #ifndef SWIG - /// A simple wrapper class to provide automatic construction of a - // 'yc_number_node_ptr' from other YASK pointer types. + /// Arguments that may be YASK numeric pointer types. /** + A simple wrapper class to provide automatic construction of a + 'yc_number_node_ptr' from other YASK pointer types. + Used only to provide conversions in function arguments. @note Not used in Python API. */ @@ -497,9 +499,11 @@ namespace yask { yc_number_node_ptr(p) { } }; - /// A simple wrapper class to provide automatic construction of a - // 'yc_number_node_ptr' from non-YASK fundamental numeric types. + /// Arguments that may be non-YASK numeric types. /** + A simple wrapper class to provide automatic construction of a + 'yc_number_node_ptr' from non-YASK fundamental numeric types. + Used only to provide conversions in function arguments. @note Not used in Python API. */ @@ -529,10 +533,12 @@ namespace yask { yc_number_node_ptr(_convert_const(f)) { } }; - /// A simple wrapper class to provide automatic construction of a - // 'yc_number_node_ptr' from a YASK pointer or non-YASK fundamental - // numeric types. + /// Arguments that may be YASK or non-YASK numeric types. /** + A simple wrapper class to provide automatic construction of a + 'yc_number_node_ptr' from a YASK pointer or non-YASK fundamental + numeric types. + Used only to provide conversions in function arguments. @note Not used in Python API. */ @@ -701,8 +707,9 @@ namespace yask { /// Create a numerical negation operator node. /** - New negation nodes can also be created via the overloaded unary `-` operator. - @returns Pointer to new \ref yc_negate_node object. + This is the explicit form, which is usually not needed because + new negation nodes can also be created via the overloaded unary `-` operator. + @returns Pointer to new \ref yc_negate_node object. */ virtual yc_number_node_ptr new_negate_node(yc_number_node_ptr rhs @@ -710,7 +717,8 @@ namespace yask { /// Create an addition node. /** - New addition nodes can also be created via the overloaded `+` operator. + This is the explicit form, which is usually not needed because + new addition nodes can also be created via the overloaded `+` operator. @returns Pointer to new \ref yc_add_node object. Returns `rhs` if `lhs` is a null node pointer and vice-versa. */ @@ -720,7 +728,8 @@ namespace yask { /// Create a multiplication node. /** - New multiplication nodes can also be created via the overloaded `*` operator. + This is the explicit form, which is usually not needed because + new multiplication nodes can also be created via the overloaded `*` operator. @returns Pointer to new \ref yc_multiply_node object. Returns `rhs` if `lhs` is a null node pointer and vice-versa. */ @@ -731,9 +740,10 @@ namespace yask { /// Create a subtraction node. /** This is binary subtraction. - Use new_negation_node() for unary `-`. + Use new_negate_node() for unary `-`. - New subtraction nodes can also be created via the overloaded `-` operator. + This is the explicit form, which is usually not needed because + new subtraction nodes can also be created via the overloaded `-` operator. @returns Pointer to new \ref yc_subtract_node object. Returns `- rhs` if `lhs` is a null node pointer and `lhs` if `rhs` is null. @@ -744,7 +754,8 @@ namespace yask { /// Create a division node. /** - New division nodes can also be created via the overloaded `/` operator. + This is the explicit form, which is usually not needed because + new division nodes can also be created via the overloaded `/` operator. @returns Pointer to new \ref yc_divide_node object. Returns `1.0 / rhs` if `lhs` is a null node pointer and `lhs` if `rhs` is null. @@ -755,7 +766,8 @@ namespace yask { /// Create a modulo node. /** - New modulo nodes can also be created via the overloaded `%` operator. + This is the explicit form, which is usually not needed because + new modulo nodes can also be created via the overloaded `%` operator. The modulo operator converts both operands to integers before performing the operation. @returns Pointer to new \ref yc_mod_node object. @@ -794,7 +806,8 @@ namespace yask { /// Create a binary inverse operator node. /** - New "not" nodes can also be created via the overloaded `!` operator + This is the explicit form, which is usually not needed because + new "not" nodes can also be created via the overloaded `!` operator or the `yc_not` function in Python. @returns Pointer to new \ref yc_not_node object. */ @@ -803,7 +816,8 @@ namespace yask { /// Create a boolean 'and' node. /** - New "and" nodes can also be created via the overloaded `&&` operator + This is the explicit form, which is usually not needed because + new "and" nodes can also be created via the overloaded `&&` operator or the `yc_and` function in Python. @returns Pointer to new \ref yc_and_node object. */ @@ -813,7 +827,8 @@ namespace yask { /// Create a boolean 'or' node. /** - New "or" nodes can also be created via the overloaded `||` operator + This is the explicit form, which is usually not needed because + new "or" nodes can also be created via the overloaded `||` operator or the `yc_or` function in Python. @returns Pointer to new \ref yc_or_node object. */ @@ -823,7 +838,8 @@ namespace yask { /// Create a numerical-comparison 'equals' node. /** - New "equals" nodes can also be created via the overloaded `==` operator. + This is the explicit form, which is usually not needed because + new "equals" nodes can also be created via the overloaded `==` operator. @returns Pointer to new \ref yc_equals_node object. */ virtual yc_bool_node_ptr @@ -832,7 +848,8 @@ namespace yask { /// Create a numerical-comparison 'not-equals' node. /** - New "not-equals" nodes can also be created via the overloaded `!=` operator. + This is the explicit form, which is usually not needed because + new "not-equals" nodes can also be created via the overloaded `!=` operator. @returns Pointer to new \ref yc_not_equals_node object. */ virtual yc_bool_node_ptr @@ -841,7 +858,8 @@ namespace yask { /// Create a numerical-comparison 'less-than' node. /** - New "less-than" nodes can also be created via the overloaded `<` operator. + This is the explicit form, which is usually not needed because + new "less-than" nodes can also be created via the overloaded `<` operator. @returns Pointer to new \ref yc_less_than_node object. */ virtual yc_bool_node_ptr @@ -850,7 +868,8 @@ namespace yask { /// Create a numerical-comparison 'greater-than' node. /** - New "greater-than" nodes can also be created via the overloaded `>` operator. + This is the explicit form, which is usually not needed because + new "greater-than" nodes can also be created via the overloaded `>` operator. @returns Pointer to new \ref yc_greater_than_node object. */ virtual yc_bool_node_ptr @@ -859,7 +878,8 @@ namespace yask { /// Create a numerical-comparison 'greater-than or equals' node. /** - New "greater-than or equals" nodes can also be created via the overloaded `>=` operator. + This is the explicit form, which is usually not needed because + new "greater-than or equals" nodes can also be created via the overloaded `>=` operator. @returns Pointer to new \ref yc_not_less_than_node object. */ virtual yc_bool_node_ptr @@ -868,7 +888,8 @@ namespace yask { /// Create a numerical-comparison 'less-than or equals' node. /** - New "less-than or equals" nodes can also be created via the overloaded `<=` operator. + This is the explicit form, which is usually not needed because + new "less-than or equals" nodes can also be created via the overloaded `<=` operator. @returns Pointer to new \ref yc_not_greater_than_node object. */ virtual yc_bool_node_ptr @@ -880,14 +901,24 @@ namespace yask { /// Unary math functions. Used internally to define sqrt(), sin(), etc. #define UNARY_MATH_EXPR(fn_name) \ yc_number_node_ptr fn_name(const yc_number_node_ptr rhs) + + /// Create an expression node to calculate the square-root of the argument node. UNARY_MATH_EXPR(sqrt); + /// Create an expression node to calculate the cube-root of the argument node. UNARY_MATH_EXPR(cbrt); + /// Create an expression node to calculate the absolute-value of the argument node. UNARY_MATH_EXPR(fabs); + /// Create an expression node to calculate the error function of the argument node. UNARY_MATH_EXPR(erf); + /// Create an expression node to calculate the natural exponent of the argument node. UNARY_MATH_EXPR(exp); + /// Create an expression node to calculate the natural log of the argument node. UNARY_MATH_EXPR(log); + /// Create an expression node to calculate the sine of the argument node. UNARY_MATH_EXPR(sin); + /// Create an expression node to calculate the cosine of the argument node. UNARY_MATH_EXPR(cos); + /// Create an expression node to calculate the arc-tangent of the argument node. UNARY_MATH_EXPR(atan); #undef UNARY_MATH_EXPR @@ -896,6 +927,12 @@ namespace yask { yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, const yc_number_node_ptr arg2); \ yc_number_node_ptr fn_name(double arg1, const yc_number_node_ptr arg2); \ yc_number_node_ptr fn_name(const yc_number_node_ptr arg1, double arg2) + + /// Power function. + /** + Create an expression node to calculate the first argument node raised to + the power of the second argument node. + */ BINARY_MATH_EXPR(pow); #undef BINARY_MATH_EXPR @@ -908,67 +945,63 @@ namespace yask { // avoid the const-const combinations, which conflict with built-in // operators on fundamental C++ types, e.g., '5+8'. - /// Operator version of yc_node_factory::new_negation_node(). + /// Operator version of yc_node_factory::new_negate_node(). yc_number_node_ptr operator-(yc_number_ptr_arg rhs); - ///@{ - /// Operator version of yc_node_factory::new_addition_node(). + /// Operator version of yc_node_factory::new_add_node(). yc_number_node_ptr operator+(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_add_node(). yc_number_node_ptr operator+(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_add_node(). yc_number_node_ptr operator+(yc_number_ptr_arg lhs, yc_number_const_arg rhs); - ///@} - ///@{ - /// Operator version of yc_node_factory::new_division_node(). + /// Operator version of yc_node_factory::new_divide_node(). yc_number_node_ptr operator/(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_divide_node(). yc_number_node_ptr operator/(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_divide_node(). yc_number_node_ptr operator/(yc_number_ptr_arg lhs, yc_number_const_arg rhs); - ///@} - ///@{ /// Operator version of yc_node_factory::new_mod_node(). yc_number_node_ptr operator%(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_mod_node(). yc_number_node_ptr operator%(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_mod_node(). yc_number_node_ptr operator%(yc_number_ptr_arg lhs, yc_number_const_arg rhs); - ///@} - ///@{ - /// Operator version of yc_node_factory::new_multiplication_node(). + /// Operator version of yc_node_factory::new_multiply_node(). yc_number_node_ptr operator*(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_multiply_node(). yc_number_node_ptr operator*(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_multiply_node(). yc_number_node_ptr operator*(yc_number_ptr_arg lhs, yc_number_const_arg rhs); - ///@} - ///@{ - /// Operator version of yc_node_factory::new_subtraction_node(). + /// Operator version of yc_node_factory::new_subtract_node(). yc_number_node_ptr operator-(yc_number_ptr_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_subtract_node(). yc_number_node_ptr operator-(yc_number_const_arg lhs, yc_number_ptr_arg rhs); + /// Operator version of yc_node_factory::new_subtract_node(). yc_number_node_ptr operator-(yc_number_ptr_arg lhs, yc_number_const_arg rhs); - ///@} - ///@{ /// Shortcut for creating expression A = A + B. void operator+=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + /// Shortcut for creating expression A = A + B. void operator+=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); - ///@} - ///@{ /// Shortcut for creating expression A = A - B. void operator-=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + /// Shortcut for creating expression A = A - B. void operator-=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); - ///@} - ///@{ /// Shortcut for creating expression A = A * B. void operator*=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + /// Shortcut for creating expression A = A * B. void operator*=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); - ///@} - ///@{ /// Shortcut for creating expression A = A / B. void operator/=(yc_number_node_ptr& lhs, yc_number_node_ptr rhs); + /// Shortcut for creating expression A = A / B. void operator/=(yc_number_node_ptr& lhs, yc_number_const_arg rhs); - ///@} /// Operator version of yc_node_factory::new_not_node(). /** For Python, use `rhs.yc_not()` */ @@ -1014,7 +1047,7 @@ namespace yask { yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } \ inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, double rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } - + BOOL_OPER(==, new_equals_node) BOOL_OPER(!=, new_not_equals_node) BOOL_OPER(<, new_less_than_node) @@ -1023,37 +1056,41 @@ namespace yask { BOOL_OPER(>=, new_not_less_than_node) #undef BOOL_OPER -#define EQUALS_OPER << -#define EQUALS EQUALS_OPER - /// The operator version of yc_node_factory::new_equation_node() used - /// for defining a grid value. + /// Recommended macro to make the "equality" operator readable and self-explanatory. /** - Use an otherwise unneeded binary operator that has a lower priority - than the math ops and a higher priority than the IF_OPER. + Uses an otherwise unneeded binary operator that has a lower priority + than the math ops and a higher priority than the `IF_*` operators. See http://en.cppreference.com/w/cpp/language/operator_precedence. - This should not be an operator that is defined for shared pointers. - See https://en.cppreference.com/w/cpp/memory/shared_ptr. + It is also required that this not be an operator that is defined for + shared pointers. See + https://en.cppreference.com/w/cpp/memory/shared_ptr. */ - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr gpp, const yc_number_any_arg rhs); +#define EQUALS << -#define IF_OPER ^= -#define IF IF_OPER - /// The operator version of yc_equation_node::set_cond() to add a domain condition. + /// The operator version of yc_node_factory::new_equation_node() used for defining a grid value. + yc_equation_node_ptr operator EQUALS(yc_grid_point_node_ptr gpp, const yc_number_any_arg rhs); + + /// Recommended macro to make the domain-condition operator readable and self-explanatory. /** - Use an otherwise unneeded binary operator that has a low priority. + Uses an otherwise unneeded binary operator that has a low priority. See http://en.cppreference.com/w/cpp/language/operator_precedence. */ - yc_equation_node_ptr operator IF_OPER(yc_equation_node_ptr expr, - const yc_bool_node_ptr cond); -#define IF_STEP_OPER |= -#define IF_STEP IF_STEP_OPER - /// A operator to add a step condition. +#define IF_DOMAIN ^= + + /// The operator version of yc_equation_node::set_cond() to add a domain condition. + yc_equation_node_ptr operator IF_DOMAIN(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond); + + /// Recommended macro to make the step-condition operator readable and self-explanatory. /** - Use an otherwise unneeded binary operator that has a low priority. + Uses an otherwise unneeded binary operator that has a low priority. See http://en.cppreference.com/w/cpp/language/operator_precedence. */ - yc_equation_node_ptr operator IF_STEP_OPER(yc_equation_node_ptr expr, - const yc_bool_node_ptr cond); +#define IF_STEP |= + + /// The operator version of yc_equation_node::set_step_cond() to add a domain condition. + yc_equation_node_ptr operator IF_STEP(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond); #endif // !SWIG. diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 0ab733ee..8d30e852 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -440,8 +440,8 @@ namespace yask { #undef FUNC_EXPR // Define a conditional. - yc_equation_node_ptr operator IF_OPER(yc_equation_node_ptr expr, - const yc_bool_node_ptr cond) { + yc_equation_node_ptr operator IF_DOMAIN(yc_equation_node_ptr expr, + const yc_bool_node_ptr cond) { auto ep = dynamic_pointer_cast(expr); assert(ep); auto cp = dynamic_pointer_cast(cond); @@ -451,7 +451,7 @@ namespace yask { ep->setCond(cp); return ep; } - yc_equation_node_ptr operator IF_STEP_OPER(yc_equation_node_ptr expr, + yc_equation_node_ptr operator IF_STEP(yc_equation_node_ptr expr, const yc_bool_node_ptr cond) { auto ep = dynamic_pointer_cast(expr); assert(ep); @@ -465,8 +465,8 @@ namespace yask { // Define the value of a grid point. // Add this equation to the list of eqs for this stencil. - yc_equation_node_ptr operator EQUALS_OPER(yc_grid_point_node_ptr lhs, - const yc_number_any_arg rhs) { + yc_equation_node_ptr operator EQUALS(yc_grid_point_node_ptr lhs, + const yc_number_any_arg rhs) { yc_node_factory nfac; return nfac.new_equation_node(lhs, rhs); } From 4cda3a87a65150f4b36009cf7e35700ffedcce92 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 14:53:07 -0700 Subject: [PATCH 12/62] Add 3d dependent-eq test and rename subdomain tests. --- src/kernel/Makefile | 9 +++-- src/stencils/SimpleTestStencils.cpp | 62 +++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 3d61a944..a264f54b 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -828,15 +828,16 @@ stencil-tests: $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_func_1d fold=x=4 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_dep_1d fold=x=4 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_dep_2d fold=x=2,y=2 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_dep_3d fold=y=2,x=2 domain_dims=x,z,y $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_misc_2d fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_misc_2d fold=x=2,y=2 EXTRA_YC_FLAGS=-interleave-misc $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_step_cond_1d fold=x=4 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_subdomain_1d fold=x=4 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_subdomain_2d fold=x=2,y=2 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_subdomain_3d fold=x=2,y=2 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_boundary_1d fold=x=4 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_boundary_2d fold=x=2,y=2 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_boundary_3d fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_scratch_1d fold=x=4 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_scratch_3d fold=x=2,z=2 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_scratch_subdomain_1d fold=x=4 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_scratch_boundary_1d fold=x=4 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=iso3dfd radius=3 fold=x=2,y=2 domain_dims=z,x,y $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=iso3dfd_sponge radius=3 fold=x=2,z=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=3axis fold=x=2,y=2 cluster=x=2 diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/SimpleTestStencils.cpp index f327cfaf..3a97e955 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/SimpleTestStencils.cpp @@ -466,6 +466,34 @@ class TestDepStencil2 : public TestBase { REGISTER_STENCIL(TestDepStencil2); +class TestDepStencil3 : public TestBase { + +protected: + + // Vars. + MAKE_GRID(A, t, x, y, z); // time-varying grid. + MAKE_GRID(B, t, x, y, z); // time-varying grid. + +public: + + TestDepStencil3(StencilList& stencils, int radius=2) : + TestBase("test_dep_3d", stencils, radius) { } + + // Define equation to apply to all points in 'A' and 'B' grids. + virtual void define() { + + // Define A(t+1) from A(t) & stencil at B(t). + A(t+1, x, y, z) EQUALS A(t, x, y, z) - + def_3d(B, t, x, 0, 1, y, 2, 1, z, 1, 0); + + // Define B(t+1) from B(t) & stencil at A(t+1). + B(t+1, x, y, z) EQUALS B(t, x, y, z) - + def_3d(A, t+1, x, 1, 0, y, 0, 1, z, 2, 1); + } +}; + +REGISTER_STENCIL(TestDepStencil3); + // Test the use of scratch-pad grids. class TestScratchStencil1 : public TestBase { @@ -532,8 +560,8 @@ class TestScratchStencil3 : public TestBase { REGISTER_STENCIL(TestScratchStencil3); -// Test the use of sub-domains. -class TestSubdomainStencil1 : public TestBase { +// Test the use of boundary code in sub-domains. +class TestBoundaryStencil1 : public TestBase { protected: @@ -542,8 +570,8 @@ class TestSubdomainStencil1 : public TestBase { public: - TestSubdomainStencil1(StencilList& stencils, int radius=2) : - TestBase("test_subdomain_1d", stencils, radius) { } + TestBoundaryStencil1(StencilList& stencils, int radius=2) : + TestBase("test_boundary_1d", stencils, radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -560,9 +588,9 @@ class TestSubdomainStencil1 : public TestBase { } }; -REGISTER_STENCIL(TestSubdomainStencil1); +REGISTER_STENCIL(TestBoundaryStencil1); -class TestSubdomainStencil2 : public TestBase { +class TestBoundaryStencil2 : public TestBase { protected: @@ -571,8 +599,8 @@ class TestSubdomainStencil2 : public TestBase { public: - TestSubdomainStencil2(StencilList& stencils, int radius=2) : - TestBase("test_subdomain_2d", stencils, radius) { } + TestBoundaryStencil2(StencilList& stencils, int radius=2) : + TestBase("test_boundary_2d", stencils, radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -588,9 +616,9 @@ class TestSubdomainStencil2 : public TestBase { } }; -REGISTER_STENCIL(TestSubdomainStencil2); +REGISTER_STENCIL(TestBoundaryStencil2); -class TestSubdomainStencil3 : public TestBase { +class TestBoundaryStencil3 : public TestBase { protected: @@ -599,8 +627,8 @@ class TestSubdomainStencil3 : public TestBase { public: - TestSubdomainStencil3(StencilList& stencils, int radius=2) : - TestBase("test_subdomain_3d", stencils, radius) { } + TestBoundaryStencil3(StencilList& stencils, int radius=2) : + TestBase("test_boundary_3d", stencils, radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -617,7 +645,7 @@ class TestSubdomainStencil3 : public TestBase { } }; -REGISTER_STENCIL(TestSubdomainStencil3); +REGISTER_STENCIL(TestBoundaryStencil3); // Test step condition. class TestStepCondStencil1 : public TestBase { @@ -664,7 +692,7 @@ class TestStepCondStencil1 : public TestBase { REGISTER_STENCIL(TestStepCondStencil1); // Test the use of conditional updates with scratch-pad grids. -class TestScratchSubdomainStencil1 : public TestBase { +class TestScratchBoundaryStencil1 : public TestBase { protected: @@ -676,8 +704,8 @@ class TestScratchSubdomainStencil1 : public TestBase { public: - TestScratchSubdomainStencil1(StencilList& stencils, int radius=2) : - TestBase("test_scratch_subdomain_1d", stencils, radius) { } + TestScratchBoundaryStencil1(StencilList& stencils, int radius=2) : + TestBase("test_scratch_boundary_1d", stencils, radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -695,7 +723,7 @@ class TestScratchSubdomainStencil1 : public TestBase { } }; -REGISTER_STENCIL(TestScratchSubdomainStencil1); +REGISTER_STENCIL(TestScratchBoundaryStencil1); // A stencil that uses svml math functions. class TestFuncStencil1 : public TestBase { From ec7422a1c043b89981e91653d4b27c59ed950937 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 15:04:44 -0700 Subject: [PATCH 13/62] Add scalar value to test. --- src/stencils/SimpleTestStencils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/SimpleTestStencils.cpp index 3a97e955..c3bd9887 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/SimpleTestStencils.cpp @@ -278,6 +278,7 @@ class TestPartialStencil3 : public TestBase { MAKE_GRID(F, y, z); MAKE_GRID(G, z, y); MAKE_GRID(H, y, z, x); // different order. + MAKE_SCALAR(I); public: @@ -296,7 +297,7 @@ class TestPartialStencil3 : public TestBase { def_no_t_2d(E, x, 0, 0, y, 1, 0) + def_no_t_2d(F, y, 0, 1, z, 0, 0) + def_no_t_2d(G, z, 1, 0, y, 0, 1) + - def_no_t_3d(H, y, 1, 0, z, 0, 1, x, 1, 0); + def_no_t_3d(H, y, 1, 0, z, 0, 1, x, 1, 0) + I; } }; From 48ef8f9c9ad2cae58faec588d7693f5d9c074053 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 15:24:20 -0700 Subject: [PATCH 14/62] Add DSL update utility. --- utils/bin/convert_v2_stencil.pl | 184 ++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100755 utils/bin/convert_v2_stencil.pl diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl new file mode 100755 index 00000000..81802cd6 --- /dev/null +++ b/utils/bin/convert_v2_stencil.pl @@ -0,0 +1,184 @@ +#! /usr/bin/env perl +#-*-Perl-*- This line forces emacs to use Perl mode. + +############################################################################## +## YASK: Yet Another Stencil Kernel +## Copyright (c) 2014-2019, Intel Corporation +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to +## deal in the Software without restriction, including without limitation the +## rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +## sell copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## * The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +## IN THE SOFTWARE. +############################################################################## + +# Purpose: Convert old-style (YASK v2) DSL code to use only the published +# YASK compiler APIs. + +use strict; +use File::Basename; +use File::Path; +use lib dirname($0)."/lib"; +use lib dirname($0)."/../lib"; + +use File::Which; +use Text::ParseWords; +use FileHandle; +use CmdLine; + +$| = 1; # autoflush. + +# Globals. +my %OPT; # cmd-line options. + +sub convert($) { + my $fname = shift; + + open INF, "<$fname" or die("error: cannot open '$fname'\n"); + warn "Converting '$fname'...\n"; + + # Read old file and save conversion in a string. + my $result; + my $lineno = 0; + my $class_name; + my $list_var; + while () { + $lineno++; + chomp; + + # Capture class name. + if (/class\s+([_\w]+)/) { + $class_name = $1; + } + + # Capture stencilList parameter name. + if (/StencilList\s*&\s*([_\w]+)/) { + $list_var = $1; + } + + # Register solution. + if (/REGISTER_STENCIL[(](.*)[)]/) { + my $cname = $1; + + $result .= + "// Create an object of type '$cname',\n". + "// making it available in the YASK compiler utility via the\n". + "// '-stencil' commmand-line option or the 'stencil=' build option.\n". + "static $cname ${cname}_instance;\n"; + } + + # Include file. + elsif (/[#]include.*Soln[.]hpp/) { + $result .= "// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility.\n". + "#include \"yask_compiler_utility_api.hpp\"\n"; + } + + # For other code, make substitutions and append changes. + else { + + # Ctor: remove StencilList parameter. + s/$class_name\s*[(]\s*StencilList\s*&\s*$list_var\s*,\s*/$class_name(/ + if defined $class_name; + s/$list_var\s*,\s*//g + if defined $list_var; + + # Index creation. + s/MAKE_STEP_INDEX[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_step_index("$1")/g; + s/MAKE_DOMAIN_INDEX[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_domain_index("$1")/g; + s/MAKE_MISC_INDEX[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_misc_index("$1")/g; + + # Grid creation. + s/MAKE_GRID[(]([^,]+),\s*([^)]+)[)]/auto $1 = yc_grid_var("$1", get_solution(), { $2 })/g; + s/MAKE_ARRAY[(]([^,]+),\s*([^)]+)[)]/auto $1 = yc_grid_var("$1", get_solution(), { $2 })/g; + s/MAKE_SCALAR[(]([^,]+)[)]/auto $1 = yc_grid_var("$1", get_solution(), { })/g; + s/MAKE_SCRATCH_GRID[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; + s/MAKE_SCRATCH_ARRAY[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; + s/MAKE_SCRATCH_SCALAR[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { }, true)/g; + + # Typenames. + s/\bStencilBase\b/yc_solution_base/g; + s/\bStencilRadiusBase\b/yc_solution_with_radius_base/g; + s/\bGrid\b/yc_grid_var/g; + s/\bGridIndex\b/yc_number_node_ptr/g; + s/\bGridValue\b/yc_number_node_ptr/g; + s/\bCondition\b/yc_bool_node_ptr/g; + s/\bGridPointPtr\b/yc_grid_point_node_ptr/g; + s/\bExprPtr\b/yc_expr_node_ptr/g; + s/\bNumExprPtr\b/yc_number_node_ptr/g; + s/\bIndexExprPtr\b/yc_index_node_ptr/g; + s/\bBoolExprPtr\b/yc_bool_node_ptr/g; + + # Other macros. + s/\b(EQUALS_OPER|IS_EQUIV_TO|IS_EQUIVALENT_TO)\b/EQUALS/g; + s/\b(IF|IF_OPER)\b/IF_DOMAIN/g; + s/\b(IF_STEP_OPER)\b/IF_STEP/g; + + # Non-convertable code. + if (/REGISTER_STENCIL_CONTEXT_EXTENSION|StencilPart/) { + warn " Warning: the v2 '$&' construct on line $lineno must be manually edited.\n"; + $result .= " ## Warning: the v2 '$&' construct cannot be automatically converted.\n". + " ## You must manually edit the following line(s).\n"; + } + + $result .= "$_\n"; + } + } + close INF; + + if ($OPT{in_place}) { + open OUTF, ">$fname" or die("error: cannot write back to '$fname'\n"); + + my $fbak = $fname."~"; + rename "$fname", $fbak or die("error: cannot rename original file to '$fbak'\n"); + warn " Original code saved in '$fbak'.\n"; + + print OUTF $result; + close OUTF; + warn " Converted code written back to '$fname'.\n". + " Complete conversion is not guaranteed; please review and test changes.\n"; + } + + # not in-place; print to stdout. + else { + print $result; + } +} + +# Parse arguments and emit code. +sub main() { + + my(@KNOBS) = + ( + # knob, description, optional default + [ "in_place!", "Modify the file(s) in-place. If false, write to stdout.", 1 ], + ); + my($command_line) = process_command_line(\%OPT, \@KNOBS); + print "$command_line\n" if $OPT{verbose}; + + my $script = basename($0); + if (!$command_line || $OPT{help} || @ARGV < 1) { + print "Converts old-style (YASK v2) DSL code to use published YASK compiler APIs.\n", + "Usage: $script [options] \n", + "Options:\n"; + print_options_help(\@KNOBS); + exit 1; + } + + for my $fname (@ARGV) { + convert($fname); + } +} + +main(); From dfe9c38f614fea4625dce657a0e46bf8b3a03d4f Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 6 May 2019 16:59:03 -0700 Subject: [PATCH 15/62] Convert all stencils to use published API format. --- src/stencils/AwpElasticStencil.cpp | 166 +++---- src/stencils/AwpStencil.cpp | 196 ++++---- .../ElasticStencil/Elastic2Stencil.hpp | 180 ++++---- .../ElasticStencil/ElasticStencil.hpp | 113 ++--- src/stencils/ExampleStencil.cpp | 85 ++-- src/stencils/FSGElastic2Stencil.cpp | 383 ++++++++-------- src/stencils/FSGElasticStencil.cpp | 427 +++++++++--------- src/stencils/Iso3dfdStencil.cpp | 59 ++- src/stencils/SSGElastic2Stencil.cpp | 55 +-- src/stencils/SSGElasticStencil.cpp | 71 +-- src/stencils/SimpleTestStencils.cpp | 408 ++++++++++------- src/stencils/TTIStencil.cpp | 254 ++++++----- utils/bin/convert_v2_stencil.pl | 43 +- 13 files changed, 1292 insertions(+), 1148 deletions(-) diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp index 62978e37..7e71e642 100644 --- a/src/stencils/AwpElasticStencil.cpp +++ b/src/stencils/AwpElasticStencil.cpp @@ -44,44 +44,47 @@ IN THE SOFTWARE. // Set the following macro to use intermediate scratch grids. //#define USE_SCRATCH_GRIDS -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; -class AwpElasticStencil : public StencilBase { +class AwpElasticStencil : public yc_solution_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. // Time-varying 3D-spatial velocity grids. - MAKE_GRID(vel_x, t, x, y, z); - MAKE_GRID(vel_y, t, x, y, z); - MAKE_GRID(vel_z, t, x, y, z); + yc_grid_var vel_x = yc_grid_var("vel_x", get_solution(), { t, x, y, z }); + yc_grid_var vel_y = yc_grid_var("vel_y", get_solution(), { t, x, y, z }); + yc_grid_var vel_z = yc_grid_var("vel_z", get_solution(), { t, x, y, z }); // Time-varying 3D-spatial Stress grids. - MAKE_GRID(stress_xx, t, x, y, z); - MAKE_GRID(stress_yy, t, x, y, z); - MAKE_GRID(stress_zz, t, x, y, z); - MAKE_GRID(stress_xy, t, x, y, z); - MAKE_GRID(stress_xz, t, x, y, z); - MAKE_GRID(stress_yz, t, x, y, z); + yc_grid_var stress_xx = yc_grid_var("stress_xx", get_solution(), { t, x, y, z }); + yc_grid_var stress_yy = yc_grid_var("stress_yy", get_solution(), { t, x, y, z }); + yc_grid_var stress_zz = yc_grid_var("stress_zz", get_solution(), { t, x, y, z }); + yc_grid_var stress_xy = yc_grid_var("stress_xy", get_solution(), { t, x, y, z }); + yc_grid_var stress_xz = yc_grid_var("stress_xz", get_solution(), { t, x, y, z }); + yc_grid_var stress_yz = yc_grid_var("stress_yz", get_solution(), { t, x, y, z }); // 3D-spatial Lame' coefficients. - MAKE_GRID(lambda, x, y, z); - MAKE_GRID(rho, x, y, z); - MAKE_GRID(mu, x, y, z); + yc_grid_var lambda = yc_grid_var("lambda", get_solution(), { x, y, z }); + yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); + yc_grid_var mu = yc_grid_var("mu", get_solution(), { x, y, z }); // Sponge coefficients. // (Most of these will be 1.0.) #ifdef FULL_SPONGE_GRID - MAKE_GRID(sponge, x, y, z); + yc_grid_var sponge = yc_grid_var("sponge", get_solution(), { x, y, z }); #else - MAKE_ARRAY(cr_x, x); - MAKE_ARRAY(cr_y, y); - MAKE_ARRAY(cr_z, z); + yc_grid_var cr_x = yc_grid_var("cr_x", get_solution(), { x }); + yc_grid_var cr_y = yc_grid_var("cr_y", get_solution(), { y }); + yc_grid_var cr_z = yc_grid_var("cr_z", get_solution(), { z }); #endif // Spatial FD coefficients. @@ -89,8 +92,8 @@ class AwpElasticStencil : public StencilBase { const double c2 = -1.0/24.0; // Physical dimensions in time and space. - MAKE_SCALAR(delta_t); - MAKE_SCALAR(h); + yc_grid_var delta_t = yc_grid_var("delta_t", get_solution(), { }); + yc_grid_var h = yc_grid_var("h", get_solution(), { }); // For the surface stress conditions, we need to write into 2 points // above the surface. Since we can only write into the "domain", we @@ -99,25 +102,25 @@ class AwpElasticStencil : public StencilBase { #define SURFACE_IDX (last_index(z) - 2) // Define some sub-domains related to the surface. -#define IF_BELOW_SURFACE IF (z < SURFACE_IDX) -#define IF_AT_SURFACE IF (z == SURFACE_IDX) -#define IF_AT_OR_BELOW_SURFACE IF (z <= SURFACE_IDX) -#define IF_ONE_ABOVE_SURFACE IF (z == SURFACE_IDX + 1) -#define IF_TWO_ABOVE_SURFACE IF (z == SURFACE_IDX + 2) +#define IF_BELOW_SURFACE IF_DOMAIN (z < SURFACE_IDX) +#define IF_AT_SURFACE IF_DOMAIN (z == SURFACE_IDX) +#define IF_AT_OR_BELOW_SURFACE IF_DOMAIN (z <= SURFACE_IDX) +#define IF_ONE_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 1) +#define IF_TWO_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 2) #ifdef USE_SCRATCH_GRIDS - MAKE_SCRATCH_GRID(tmp_vel_x, x, y, z); - MAKE_SCRATCH_GRID(tmp_vel_y, x, y, z); - MAKE_SCRATCH_GRID(tmp_vel_z, x, y, z); + yc_grid_var tmp_vel_x = yc_grid_var("tmp_vel_x", get_solution(), { x, y, z }, true); + yc_grid_var tmp_vel_y = yc_grid_var("tmp_vel_y", get_solution(), { x, y, z }, true); + yc_grid_var tmp_vel_z = yc_grid_var("tmp_vel_z", get_solution(), { x, y, z }, true); #endif public: - AwpElasticStencil(StencilList& stencils) : - StencilBase("awp_elastic", stencils) { } + AwpElasticStencil() : + yc_solution_base("awp_elastic") { } // Adjustment for sponge layer. - void adjust_for_sponge(GridValue& val) { + void adjust_for_sponge(yc_number_node_ptr& val) { #ifdef FULL_SPONGE_GRID val *= sponge(x, y, z); @@ -132,55 +135,55 @@ class AwpElasticStencil : public StencilBase { // time or space, so half-steps due to staggered grids are adjusted // appropriately. - GridValue get_next_vel_x(GridIndex x, GridIndex y, GridIndex z) { - GridValue rho_val = (rho(x, y, z ) + + yc_number_node_ptr get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + yc_number_node_ptr rho_val = (rho(x, y, z ) + rho(x, y-1, z ) + rho(x, y, z-1) + rho(x, y-1, z-1)) * (1.0 / 4.0); - GridValue d_val = + yc_number_node_ptr d_val = c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - GridValue next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + yc_number_node_ptr next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_x); // Return the value at t+1. return next_vel_x; } - GridValue get_next_vel_y(GridIndex x, GridIndex y, GridIndex z) { - GridValue rho_val = (rho(x, y, z ) + + yc_number_node_ptr get_next_vel_y(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + yc_number_node_ptr rho_val = (rho(x, y, z ) + rho(x+1, y, z ) + rho(x, y, z-1) + rho(x+1, y, z-1)) * (1.0 / 4.0); - GridValue d_val = + yc_number_node_ptr d_val = c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - GridValue next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + yc_number_node_ptr next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_y); // Return the value at t+1. return next_vel_y; } - GridValue get_next_vel_z(GridIndex x, GridIndex y, GridIndex z) { - GridValue rho_val = (rho(x, y, z) + + yc_number_node_ptr get_next_vel_z(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + yc_number_node_ptr rho_val = (rho(x, y, z) + rho(x+1, y, z) + rho(x, y-1, z) + rho(x+1, y-1, z)) * (1.0 / 4.0); - GridValue d_val = + yc_number_node_ptr d_val = c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - GridValue next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + yc_number_node_ptr next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_z); // Return the value at t+1. @@ -192,7 +195,7 @@ class AwpElasticStencil : public StencilBase { // Since we're defining points when z == surface + 1, // the surface itself will be at z - 1; - GridIndex surf = z - 1; + yc_number_node_ptr surf = z - 1; #ifdef USE_SCRATCH_GRIDS @@ -219,17 +222,17 @@ class AwpElasticStencil : public StencilBase { #endif // A couple of intermediate values. - GridValue d_x_val = VEL_X(x+1, y, surf) - + yc_number_node_ptr d_x_val = VEL_X(x+1, y, surf) - (VEL_Z(x+1, y, surf) - VEL_Z(x, y, surf)); - GridValue d_y_val = VEL_Y(x, y-1, surf) - + yc_number_node_ptr d_y_val = VEL_Y(x, y-1, surf) - (VEL_Z(x, y, surf) - VEL_Z(x, y-1, surf)); // Following values are valid one layer above the free surface. - GridValue plus1_vel_x = VEL_X(x, y, surf) - + yc_number_node_ptr plus1_vel_x = VEL_X(x, y, surf) - (VEL_Z(x, y, surf) - VEL_Z(x-1, y, surf)); - GridValue plus1_vel_y = VEL_Y(x, y, surf) - + yc_number_node_ptr plus1_vel_y = VEL_Y(x, y, surf) - (VEL_Z(x, y+1, surf) - VEL_Z(x, y, surf)); - GridValue plus1_vel_z = VEL_Z(x, y, surf) - + yc_number_node_ptr plus1_vel_z = VEL_Z(x, y, surf) - ((d_x_val - plus1_vel_x) + (VEL_X(x+1, y, surf) - VEL_X(x, y, surf)) + (plus1_vel_y - d_y_val) + @@ -255,7 +258,7 @@ class AwpElasticStencil : public StencilBase { } // Compute average of 8 neighbors. - GridValue ave8(Grid& g, GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr ave8(yc_grid_var& g, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return 8.0 / (g(x, y, z ) + g(x+1, y, z ) + @@ -265,17 +268,17 @@ class AwpElasticStencil : public StencilBase { } // Some common velocity calculations. - GridValue d_x_val(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr d_x_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); } - GridValue d_y_val(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr d_y_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); } - GridValue d_z_val(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr d_z_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); @@ -289,9 +292,9 @@ class AwpElasticStencil : public StencilBase { // space, so half-steps due to staggered grids are adjusted // appropriately. - GridValue get_next_stress_xx(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - GridValue next_stress_xx = stress_xx(t, x, y, z) + + yc_number_node_ptr next_stress_xx = stress_xx(t, x, y, z) + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_x_val(x, y, z)) + (ave8(lambda, x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); @@ -300,9 +303,9 @@ class AwpElasticStencil : public StencilBase { // Return the value at t+1. return next_stress_xx; } - GridValue get_next_stress_yy(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - GridValue next_stress_yy = stress_yy(t, x, y, z) + + yc_number_node_ptr next_stress_yy = stress_yy(t, x, y, z) + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_y_val(x, y, z)) + (ave8(lambda, x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); @@ -311,9 +314,9 @@ class AwpElasticStencil : public StencilBase { // Return the value at t+1. return next_stress_yy; } - GridValue get_next_stress_zz(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - GridValue next_stress_zz = stress_zz(t, x, y, z) + + yc_number_node_ptr next_stress_zz = stress_zz(t, x, y, z) + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_z_val(x, y, z)) + (ave8(lambda, x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); @@ -322,63 +325,63 @@ class AwpElasticStencil : public StencilBase { // return the value at t+1. return next_stress_zz; } - GridValue get_next_stress_xy(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { // Compute average of 2 neighbors. - GridValue mu2 = 2.0 / + yc_number_node_ptr mu2 = 2.0 / (mu(x, y, z ) + mu(x, y, z-1)); // Note that we are using the velocity values at t+1. - GridValue d_xy_val = + yc_number_node_ptr d_xy_val = c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - GridValue d_yx_val = + yc_number_node_ptr d_yx_val = c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - GridValue next_stress_xy = stress_xy(t, x, y, z) + + yc_number_node_ptr next_stress_xy = stress_xy(t, x, y, z) + ((mu2 * delta_t / h) * (d_xy_val + d_yx_val)); adjust_for_sponge(next_stress_xy); // return the value at t+1. return next_stress_xy; } - GridValue get_next_stress_xz(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { // Compute average of 2 neighbors. - GridValue mu2 = 2.0 / + yc_number_node_ptr mu2 = 2.0 / (mu(x, y, z ) + mu(x, y-1, z )); // Note that we are using the velocity values at t+1. - GridValue d_xz_val = + yc_number_node_ptr d_xz_val = c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - GridValue d_zx_val = + yc_number_node_ptr d_zx_val = c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - GridValue next_stress_xz = stress_xz(t, x, y, z) + + yc_number_node_ptr next_stress_xz = stress_xz(t, x, y, z) + ((mu2 * delta_t / h) * (d_xz_val + d_zx_val)); adjust_for_sponge(next_stress_xz); // return the value at t+1. return next_stress_xz; } - GridValue get_next_stress_yz(GridIndex x, GridIndex y, GridIndex z) { + yc_number_node_ptr get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { // Compute average of 2 neighbors. - GridValue mu2 = 2.0 / + yc_number_node_ptr mu2 = 2.0 / (mu(x, y, z ) + mu(x+1, y, z )); // Note that we are using the velocity values at t+1. - GridValue d_yz_val = + yc_number_node_ptr d_yz_val = c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - GridValue d_zy_val = + yc_number_node_ptr d_zy_val = c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - GridValue next_stress_yz = stress_yz(t, x, y, z) + + yc_number_node_ptr next_stress_yz = stress_yz(t, x, y, z) + ((mu2 * delta_t / h) * (d_yz_val + d_zy_val)); adjust_for_sponge(next_stress_yz); @@ -390,7 +393,7 @@ class AwpElasticStencil : public StencilBase { void define_free_surface_stress() { // When z == surface + 1, the surface will be at z - 1; - GridIndex surf = z - 1; + yc_number_node_ptr surf = z - 1; stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf) IF_ONE_ABOVE_SURFACE; stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; @@ -454,7 +457,10 @@ class AwpElasticStencil : public StencilBase { } }; -REGISTER_STENCIL(AwpElasticStencil); +// Create an object of type 'AwpElasticStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static AwpElasticStencil AwpElasticStencil_instance; #undef DO_SURFACE #undef FULL_SPONGE_GRID diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index 213302af..db2ed75b 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -30,61 +30,64 @@ IN THE SOFTWARE. // Set the following macro to use a sponge grid instead of 3 sponge arrays. //#define FULL_SPONGE_GRID -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; -class AwpStencil : public StencilBase { +class AwpStencil : public yc_solution_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. // Time-varying 3D-spatial velocity grids. - MAKE_GRID(vel_x, t, x, y, z); - MAKE_GRID(vel_y, t, x, y, z); - MAKE_GRID(vel_z, t, x, y, z); + yc_grid_var vel_x = yc_grid_var("vel_x", get_solution(), { t, x, y, z }); + yc_grid_var vel_y = yc_grid_var("vel_y", get_solution(), { t, x, y, z }); + yc_grid_var vel_z = yc_grid_var("vel_z", get_solution(), { t, x, y, z }); // Time-varying 3D-spatial Stress grids. - MAKE_GRID(stress_xx, t, x, y, z); - MAKE_GRID(stress_yy, t, x, y, z); - MAKE_GRID(stress_zz, t, x, y, z); - MAKE_GRID(stress_xy, t, x, y, z); - MAKE_GRID(stress_xz, t, x, y, z); - MAKE_GRID(stress_yz, t, x, y, z); + yc_grid_var stress_xx = yc_grid_var("stress_xx", get_solution(), { t, x, y, z }); + yc_grid_var stress_yy = yc_grid_var("stress_yy", get_solution(), { t, x, y, z }); + yc_grid_var stress_zz = yc_grid_var("stress_zz", get_solution(), { t, x, y, z }); + yc_grid_var stress_xy = yc_grid_var("stress_xy", get_solution(), { t, x, y, z }); + yc_grid_var stress_xz = yc_grid_var("stress_xz", get_solution(), { t, x, y, z }); + yc_grid_var stress_yz = yc_grid_var("stress_yz", get_solution(), { t, x, y, z }); // Time-varying attenuation memory grids. - MAKE_GRID(stress_mem_xx, t, x, y, z); - MAKE_GRID(stress_mem_yy, t, x, y, z); - MAKE_GRID(stress_mem_zz, t, x, y, z); - MAKE_GRID(stress_mem_xy, t, x, y, z); - MAKE_GRID(stress_mem_xz, t, x, y, z); - MAKE_GRID(stress_mem_yz, t, x, y, z); + yc_grid_var stress_mem_xx = yc_grid_var("stress_mem_xx", get_solution(), { t, x, y, z }); + yc_grid_var stress_mem_yy = yc_grid_var("stress_mem_yy", get_solution(), { t, x, y, z }); + yc_grid_var stress_mem_zz = yc_grid_var("stress_mem_zz", get_solution(), { t, x, y, z }); + yc_grid_var stress_mem_xy = yc_grid_var("stress_mem_xy", get_solution(), { t, x, y, z }); + yc_grid_var stress_mem_xz = yc_grid_var("stress_mem_xz", get_solution(), { t, x, y, z }); + yc_grid_var stress_mem_yz = yc_grid_var("stress_mem_yz", get_solution(), { t, x, y, z }); // 3D grids used for anelastic attenuation - MAKE_GRID(weight, x, y, z); - MAKE_GRID(tau2, x, y, z); - MAKE_GRID(anelastic_ap, x, y, z); - MAKE_GRID(anelastic_as_diag, x, y, z); - MAKE_GRID(anelastic_xy, x, y, z); - MAKE_GRID(anelastic_xz, x, y, z); - MAKE_GRID(anelastic_yz, x, y, z); + yc_grid_var weight = yc_grid_var("weight", get_solution(), { x, y, z }); + yc_grid_var tau2 = yc_grid_var("tau2", get_solution(), { x, y, z }); + yc_grid_var anelastic_ap = yc_grid_var("anelastic_ap", get_solution(), { x, y, z }); + yc_grid_var anelastic_as_diag = yc_grid_var("anelastic_as_diag", get_solution(), { x, y, z }); + yc_grid_var anelastic_xy = yc_grid_var("anelastic_xy", get_solution(), { x, y, z }); + yc_grid_var anelastic_xz = yc_grid_var("anelastic_xz", get_solution(), { x, y, z }); + yc_grid_var anelastic_yz = yc_grid_var("anelastic_yz", get_solution(), { x, y, z }); // 3D-spatial Lame' coefficients. - MAKE_GRID(lambda, x, y, z); - MAKE_GRID(rho, x, y, z); - MAKE_GRID(mu, x, y, z); + yc_grid_var lambda = yc_grid_var("lambda", get_solution(), { x, y, z }); + yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); + yc_grid_var mu = yc_grid_var("mu", get_solution(), { x, y, z }); // Sponge coefficients. // (Most of these will be 1.0.) #ifdef FULL_SPONGE_GRID - MAKE_GRID(sponge, x, y, z); + yc_grid_var sponge = yc_grid_var("sponge", get_solution(), { x, y, z }); #else - MAKE_ARRAY(cr_x, x); - MAKE_ARRAY(cr_y, y); - MAKE_ARRAY(cr_z, z); + yc_grid_var cr_x = yc_grid_var("cr_x", get_solution(), { x }); + yc_grid_var cr_y = yc_grid_var("cr_y", get_solution(), { y }); + yc_grid_var cr_z = yc_grid_var("cr_z", get_solution(), { z }); #endif // Spatial FD coefficients. @@ -92,16 +95,16 @@ class AwpStencil : public StencilBase { const double c2 = -1.0/24.0; // Physical dimensions in time and space. - MAKE_SCALAR(delta_t); - MAKE_SCALAR(h); + yc_grid_var delta_t = yc_grid_var("delta_t", get_solution(), { }); + yc_grid_var h = yc_grid_var("h", get_solution(), { }); public: - AwpStencil(StencilList& stencils) : - StencilBase("awp", stencils) { } + AwpStencil() : + yc_solution_base("awp") { } // Adjustment for sponge layer. - void adjust_for_sponge(GridValue& val) { + void adjust_for_sponge(yc_number_node_ptr& val) { #ifdef FULL_SPONGE_GRID val *= sponge(x, y, z); @@ -117,54 +120,54 @@ class AwpStencil : public StencilBase { // appropriately. void define_vel_x() { - GridValue rho_val = (rho(x, y, z ) + + yc_number_node_ptr rho_val = (rho(x, y, z ) + rho(x, y-1, z ) + rho(x, y, z-1) + rho(x, y-1, z-1)) * (1.0 / 4.0); - GridValue d_val = + yc_number_node_ptr d_val = c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - GridValue next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + yc_number_node_ptr next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_x); // define the value at t+1. vel_x(t+1, x, y, z) EQUALS next_vel_x; } void define_vel_y() { - GridValue rho_val = (rho(x, y, z ) + + yc_number_node_ptr rho_val = (rho(x, y, z ) + rho(x+1, y, z ) + rho(x, y, z-1) + rho(x+1, y, z-1)) * (1.0 / 4.0); - GridValue d_val = + yc_number_node_ptr d_val = c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - GridValue next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + yc_number_node_ptr next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_y); // define the value at t+1. vel_y(t+1, x, y, z) EQUALS next_vel_y; } void define_vel_z() { - GridValue rho_val = (rho(x, y, z) + + yc_number_node_ptr rho_val = (rho(x, y, z) + rho(x+1, y, z) + rho(x, y-1, z) + rho(x+1, y-1, z)) * (1.0 / 4.0); - GridValue d_val = + yc_number_node_ptr d_val = c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - GridValue next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + yc_number_node_ptr next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_z); // define the value at t+1. @@ -179,18 +182,18 @@ class AwpStencil : public StencilBase { // space, so half-steps due to staggered grids are adjusted // appropriately. - void define_stress_xx(GridValue lambda_val, GridValue mu_val, - GridValue d_x_val, GridValue d_y_val, GridValue d_z_val, - GridValue tau1) { + void define_stress_xx(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, + yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, + yc_number_node_ptr tau1) { - GridValue stress_mem_xx_old = stress_mem_xx(t, x, y, z); + yc_number_node_ptr stress_mem_xx_old = stress_mem_xx(t, x, y, z); - GridValue next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + + yc_number_node_ptr next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + (1.0 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_as_diag(x, y, z) * (d_y_val + d_z_val) - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - GridValue next_stress_xx = stress_xx(t, x, y, z) + + yc_number_node_ptr next_stress_xx = stress_xx(t, x, y, z) + ((delta_t / h) * ((2. * mu_val * d_x_val) + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + delta_t * (next_stress_mem_xx + stress_mem_xx_old); @@ -201,18 +204,18 @@ class AwpStencil : public StencilBase { stress_mem_xx(t+1, x, y, z) EQUALS next_stress_mem_xx; stress_xx(t+1, x, y, z) EQUALS next_stress_xx; } - void define_stress_yy(GridValue lambda_val, GridValue mu_val, - GridValue d_x_val, GridValue d_y_val, GridValue d_z_val, - GridValue tau1) { + void define_stress_yy(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, + yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, + yc_number_node_ptr tau1) { - GridValue stress_mem_yy_old = stress_mem_yy(t, x, y, z); + yc_number_node_ptr stress_mem_yy_old = stress_mem_yy(t, x, y, z); - GridValue next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + + yc_number_node_ptr next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + (1 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_z_val) - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - GridValue next_stress_yy = stress_yy(t, x, y, z) + + yc_number_node_ptr next_stress_yy = stress_yy(t, x, y, z) + ((delta_t / h) * ((2. * mu_val * d_y_val) + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + delta_t * (next_stress_mem_yy + stress_mem_yy_old); @@ -223,18 +226,18 @@ class AwpStencil : public StencilBase { stress_mem_yy(t+1, x, y, z) EQUALS next_stress_mem_yy; stress_yy(t+1, x, y, z) EQUALS next_stress_yy; } - void define_stress_zz(GridValue lambda_val, GridValue mu_val, - GridValue d_x_val, GridValue d_y_val, GridValue d_z_val, - GridValue tau1) { + void define_stress_zz(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, + yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, + yc_number_node_ptr tau1) { - GridValue stress_mem_zz_old = stress_mem_zz(t, x, y, z); + yc_number_node_ptr stress_mem_zz_old = stress_mem_zz(t, x, y, z); - GridValue next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + + yc_number_node_ptr next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + (1 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_y_val) - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - GridValue next_stress_zz = stress_zz(t, x, y, z) + + yc_number_node_ptr next_stress_zz = stress_zz(t, x, y, z) + ((delta_t / h) * ((2. * mu_val * d_z_val) + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + delta_t * (next_stress_mem_zz + stress_mem_zz_old); @@ -245,26 +248,26 @@ class AwpStencil : public StencilBase { stress_mem_zz(t+1, x, y, z) EQUALS next_stress_mem_zz; stress_zz(t+1, x, y, z) EQUALS next_stress_zz; } - void define_stress_xy(GridValue tau1) { + void define_stress_xy(yc_number_node_ptr tau1) { - GridValue mu_val = 2.0 / + yc_number_node_ptr mu_val = 2.0 / (mu(x, y, z ) + mu(x, y, z-1)); // Note that we are using the velocity values at t+1. - GridValue d_xy_val = + yc_number_node_ptr d_xy_val = c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - GridValue d_yx_val = + yc_number_node_ptr d_yx_val = c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - GridValue stress_mem_xy_old = stress_mem_xy(t, x, y, z); + yc_number_node_ptr stress_mem_xy_old = stress_mem_xy(t, x, y, z); - GridValue next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - + yc_number_node_ptr next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - (0.5 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_xy(x, y, z) * (d_xy_val + d_yx_val)); - GridValue next_stress_xy = stress_xy(t, x, y, z) + + yc_number_node_ptr next_stress_xy = stress_xy(t, x, y, z) + ((mu_val * delta_t / h) * (d_xy_val + d_yx_val)) + delta_t * (next_stress_mem_xy + stress_mem_xy_old); @@ -274,26 +277,26 @@ class AwpStencil : public StencilBase { stress_mem_xy(t+1, x, y, z) EQUALS next_stress_mem_xy; stress_xy(t+1, x, y, z) EQUALS next_stress_xy; } - void define_stress_xz(GridValue tau1) { + void define_stress_xz(yc_number_node_ptr tau1) { - GridValue mu_val = 2.0 / + yc_number_node_ptr mu_val = 2.0 / (mu(x, y, z ) + mu(x, y-1, z )); // Note that we are using the velocity values at t+1. - GridValue d_xz_val = + yc_number_node_ptr d_xz_val = c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - GridValue d_zx_val = + yc_number_node_ptr d_zx_val = c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - GridValue stress_mem_xz_old = stress_mem_xz(t, x, y, z); + yc_number_node_ptr stress_mem_xz_old = stress_mem_xz(t, x, y, z); - GridValue next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - + yc_number_node_ptr next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - (0.5 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_xz(x, y, z) * (d_xz_val + d_zx_val)); - GridValue next_stress_xz = stress_xz(t, x, y, z) + + yc_number_node_ptr next_stress_xz = stress_xz(t, x, y, z) + ((mu_val * delta_t / h) * (d_xz_val + d_zx_val)) + delta_t * (next_stress_mem_xz + stress_mem_xz_old); @@ -303,26 +306,26 @@ class AwpStencil : public StencilBase { stress_mem_xz(t+1, x, y, z) EQUALS next_stress_mem_xz; stress_xz(t+1, x, y, z) EQUALS next_stress_xz; } - void define_stress_yz(GridValue tau1) { + void define_stress_yz(yc_number_node_ptr tau1) { - GridValue mu_val = 2.0 / + yc_number_node_ptr mu_val = 2.0 / (mu(x, y, z ) + mu(x+1, y, z )); // Note that we are using the velocity values at t+1. - GridValue d_yz_val = + yc_number_node_ptr d_yz_val = c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - GridValue d_zy_val = + yc_number_node_ptr d_zy_val = c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - GridValue stress_mem_yz_old = stress_mem_yz(t, x, y, z); + yc_number_node_ptr stress_mem_yz_old = stress_mem_yz(t, x, y, z); - GridValue next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - + yc_number_node_ptr next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - (0.5 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_yz(x, y, z) * (d_yz_val + d_zy_val)); - GridValue next_stress_yz = stress_yz(t, x, y, z) + + yc_number_node_ptr next_stress_yz = stress_yz(t, x, y, z) + ((mu_val * delta_t / h) * (d_yz_val + d_zy_val)) + delta_t * (next_stress_mem_yz + stress_mem_yz_old); @@ -342,29 +345,29 @@ class AwpStencil : public StencilBase { define_vel_z(); // Define some values common to the diagonal stress equations. - GridValue lambda_val = 8.0 / + yc_number_node_ptr lambda_val = 8.0 / (lambda(x, y, z ) + lambda(x+1, y, z ) + lambda(x, y-1, z ) + lambda(x+1, y-1, z ) + lambda(x, y, z-1) + lambda(x+1, y, z-1) + lambda(x, y-1, z-1) + lambda(x+1, y-1, z-1)); - GridValue mu_val = 8.0 / + yc_number_node_ptr mu_val = 8.0 / (mu(x, y, z ) + mu(x+1, y, z ) + mu(x, y-1, z ) + mu(x+1, y-1, z ) + mu(x, y, z-1) + mu(x+1, y, z-1) + mu(x, y-1, z-1) + mu(x+1, y-1, z-1)); // Note that we are using the velocity values at t+1. - GridValue d_x_val = + yc_number_node_ptr d_x_val = c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); - GridValue d_y_val = + yc_number_node_ptr d_y_val = c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); - GridValue d_z_val = + yc_number_node_ptr d_z_val = c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); - GridValue tau1 = 1.0 - tau2(x, y, z); + yc_number_node_ptr tau1 = 1.0 - tau2(x, y, z); // Define stress components. define_stress_xx(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); @@ -376,4 +379,7 @@ class AwpStencil : public StencilBase { } }; -REGISTER_STENCIL(AwpStencil); +// Create an object of type 'AwpStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static AwpStencil AwpStencil_instance; diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index 148436ff..fba44f35 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -29,51 +29,51 @@ IN THE SOFTWARE. #include "ElasticStencil.hpp" -// This class implements StencilBase but is not the main solution. +// This class implements yc_solution_base but is not the main solution. // The main solution is provided during construction. -class Elastic2BoundaryCondition : public StencilBase +class Elastic2BoundaryCondition : public yc_solution_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. - // Grid selectors. - MAKE_MISC_INDEX(vidx); - MAKE_MISC_INDEX(sidx); - MAKE_MISC_INDEX(cidx); - MAKE_MISC_INDEX(spidx); + // yc_grid_var selectors. + yc_index_node_ptr vidx = _node_factory.new_misc_index("vidx"); + yc_index_node_ptr sidx = _node_factory.new_misc_index("sidx"); + yc_index_node_ptr cidx = _node_factory.new_misc_index("cidx"); + yc_index_node_ptr spidx = _node_factory.new_misc_index("spidx"); public: - Elastic2BoundaryCondition(StencilBase& base) : - StencilBase(base) { } + Elastic2BoundaryCondition(yc_solution_base& base) : + yc_solution_base(base) { } virtual ~Elastic2BoundaryCondition() {} // Determine whether current indices are at boundary. - virtual Condition is_at_boundary() =0; - virtual Condition is_not_at_boundary() =0; + virtual yc_bool_node_ptr is_at_boundary() =0; + virtual yc_bool_node_ptr is_not_at_boundary() =0; }; -class Elastic2StencilBase : public StencilBase { +class Elastic2StencilBase : public yc_solution_base { protected: // Dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. - // Grid selectors. - MAKE_MISC_INDEX(vidx); - MAKE_MISC_INDEX(sidx); - MAKE_MISC_INDEX(cidx); + // yc_grid_var selectors. + yc_index_node_ptr vidx = _node_factory.new_misc_index("vidx"); + yc_index_node_ptr sidx = _node_factory.new_misc_index("sidx"); + yc_index_node_ptr cidx = _node_factory.new_misc_index("cidx"); // 3D-spatial coefficients. - MAKE_GRID(coef, x, y, z, cidx); + yc_grid_var coef = yc_grid_var("coef", get_solution(), { x, y, z, cidx }); enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2, C_RHO }; // Spatial FD coefficients. @@ -93,9 +93,9 @@ class Elastic2StencilBase : public StencilBase { Elastic2BoundaryCondition *bc = NULL; public: - Elastic2StencilBase(const string& name, StencilList& stencils, + Elastic2StencilBase(const string& name, Elastic2BoundaryCondition *_bc = NULL) : - StencilBase(name, stencils), bc(_bc) + yc_solution_base(name), bc(_bc) { } bool hasBoundaryCondition() @@ -103,25 +103,25 @@ class Elastic2StencilBase : public StencilBase { return bc != NULL; } - GridValue interp_rho(GridIndex x, GridIndex y, GridIndex z, const TL) + yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TL) { return (2.0/ (coef(x , y , z, C_RHO) + coef(x+1, y , z, C_RHO))); } - GridValue interp_rho(GridIndex x, GridIndex y, GridIndex z, const TR) + yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TR) { return (2.0/ (coef(x , y , z, C_RHO) + coef(x , y+1, z, C_RHO))); } - GridValue interp_rho(GridIndex x, GridIndex y, GridIndex z, const BL) + yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BL) { return (2.0/ (coef(x , y , z, C_RHO) + coef(x , y , z+1, C_RHO))); } - GridValue interp_rho(GridIndex x, GridIndex y, GridIndex z, const BR) + yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BR) { return (8.0/ (coef(x , y , z, C_RHO) + coef(x , y , z+1, C_RHO) + @@ -134,13 +134,13 @@ class Elastic2StencilBase : public StencilBase { } template - GridValue interp_rho(GridIndex x, GridIndex y, GridIndex z) + yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return interp_rho(x, y, z, N()); } - GridValue stencil_O8_Z(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const int offset) + yc_number_node_ptr stencil_O8_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const int offset) { return (c0_8 * (g(t,x,y,z +offset, gidx) - @@ -153,20 +153,20 @@ class Elastic2StencilBase : public StencilBase { g(t,x,y,z-4+offset, gidx)))*dzi; } - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const Z, const B) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const Z, const B) { return stencil_O8_Z(t, x, y, z, g, gidx, 0); } - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const Z, const F) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const Z, const F) { return stencil_O8_Z(t, x, y, z, g, gidx, 1); } - GridValue stencil_O8_Y(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const int offset) + yc_number_node_ptr stencil_O8_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const int offset) { return (c0_8 * (g(t,x,y +offset,z, gidx) - @@ -179,19 +179,19 @@ class Elastic2StencilBase : public StencilBase { g(t,x,y-4+offset,z, gidx)))*dyi; } - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const Y, const B) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const Y, const B) { return stencil_O8_Y(t, x, y, z, g, gidx, 0); } - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, GridIndex gidx, const Y, const F) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, yc_number_node_ptr gidx, const Y, const F) { return stencil_O8_Y(t, x, y, z, g, gidx, 1); } - GridValue stencil_O8_X(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const int offset) + yc_number_node_ptr stencil_O8_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const int offset) { return (c0_8 * (g(t,x +offset,y,z, gidx) - @@ -204,22 +204,22 @@ class Elastic2StencilBase : public StencilBase { g(t,x-4+offset,y,z, gidx)))*dxi; } - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const X, const B) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const X, const B) { return stencil_O8_X(t, x, y, z, g, gidx, 0); } - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const X, const F) { return stencil_O8_X(t, x, y, z, g, gidx, 1); } template - GridValue stencil_O8(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx) { return stencil_O8(t, x, y, z, g, gidx, Dim(), Dir()); } @@ -231,111 +231,111 @@ class Elastic2StencilBase : public StencilBase { // appropriately. template - void define_vel(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid& v, GridIndex vidx, - Grid& s, GridIndex sx_idx, GridIndex sy_idx, GridIndex sz_idx) { + void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var& v, yc_number_node_ptr vidx, + yc_grid_var& s, yc_number_node_ptr sx_idx, yc_number_node_ptr sy_idx, yc_number_node_ptr sz_idx) { - GridValue lrho = interp_rho(x, y, z); + yc_number_node_ptr lrho = interp_rho(x, y, z); - GridValue stx = stencil_O8(t, x, y, z, s, sx_idx); - GridValue sty = stencil_O8(t, x, y, z, s, sy_idx); - GridValue stz = stencil_O8(t, x, y, z, s, sz_idx); + yc_number_node_ptr stx = stencil_O8(t, x, y, z, s, sx_idx); + yc_number_node_ptr sty = stencil_O8(t, x, y, z, s, sy_idx); + yc_number_node_ptr stz = stencil_O8(t, x, y, z, s, sz_idx); - GridValue next_v = v(t, x, y, z, vidx) + ((stx + sty + stz) * delta_t * lrho); + yc_number_node_ptr next_v = v(t, x, y, z, vidx) + ((stx + sty + stz) * delta_t * lrho); // define the value at t+1. if (hasBoundaryCondition()) { - Condition not_at_bc = bc->is_not_at_boundary(); - v(t+1, x, y, z, vidx) EQUALS next_v IF not_at_bc; + yc_bool_node_ptr not_at_bc = bc->is_not_at_boundary(); + v(t+1, x, y, z, vidx) EQUALS next_v IF_DOMAIN not_at_bc; } else v(t+1, x, y, z, vidx) EQUALS next_v; } template - void define_vel(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid& v, int vidx, - Grid& s, int sx_idx, int sy_idx, int sz_idx) { + void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var& v, int vidx, + yc_grid_var& s, int sx_idx, int sy_idx, int sz_idx) { define_vel(t, x, y, z, - v, constNum(vidx), - s, constNum(sx_idx), constNum(sy_idx), constNum(sz_idx)); + v, _node_factory.new_number_node(vidx), + s, _node_factory.new_number_node(sx_idx), _node_factory.new_number_node(sy_idx), _node_factory.new_number_node(sz_idx)); } - GridValue stencil_O2_Z(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const int offset) + yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const int offset) { return (g(t,x,y,z, gidx) - g(t,x,y,z+offset, gidx))*dzi; } - GridValue stencil_O2_Z(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const B) + yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const B) { return stencil_O2_Z(t, x, y, z, g, gidx, -1); } - GridValue stencil_O2_Z(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const F) + yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const F) { return stencil_O2_Z(t, x, y, z, g, gidx, 1); } template - GridValue stencil_O2_Z(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx) + yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx) { return stencil_O2_Z(t, x, y, z, g, gidx, D()); } - GridValue stencil_O2_Y(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const int offset) + yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const int offset) { return (g(t,x,y ,z, gidx) - g(t,x,y+offset,z, gidx))*dyi; } - GridValue stencil_O2_Y(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const B) + yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const B) { return stencil_O2_Y(t, x, y, z, g, gidx,-1); } - GridValue stencil_O2_Y(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const F) + yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const F) { return stencil_O2_Y(t, x, y, z, g, gidx, 1); } template - GridValue stencil_O2_Y(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx) + yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx) { return stencil_O2_Y(t, x, y, z, g, gidx, D()); } - GridValue stencil_O2_X(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const int offset) + yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const int offset) { return (g(t,x ,y,z, gidx) - g(t,x+offset,y,z, gidx))*dxi; } - GridValue stencil_O2_X(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const B) + yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const B) { return stencil_O2_X(t, x, y, z, g, gidx,-1); } - GridValue stencil_O2_X(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx, const F) + yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx, const F) { return stencil_O2_X(t, x, y, z, g, gidx, 1); } template - GridValue stencil_O2_X(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &g, GridIndex gidx) + yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &g, yc_number_node_ptr gidx) { return stencil_O2_X(t, x, y, z, g, gidx, D()); } diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index 9f9e93b4..44a83107 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -27,7 +27,10 @@ IN THE SOFTWARE. #pragma once -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; struct Node {}; struct TL: public Node {}; @@ -44,40 +47,40 @@ struct X: public StencilDimension{}; struct Y: public StencilDimension{}; struct Z: public StencilDimension{}; -// This class implements StencilBase but is not the main solution. +// This class implements yc_solution_base but is not the main solution. // The main solution is provided during construction. -class ElasticBoundaryCondition : public StencilBase +class ElasticBoundaryCondition : public yc_solution_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. public: - ElasticBoundaryCondition(StencilBase& base) : - StencilBase(base) { } + ElasticBoundaryCondition(yc_solution_base& base) : + yc_solution_base(base) { } virtual ~ElasticBoundaryCondition() {} // Determine whether current indices are at boundary. - virtual Condition is_at_boundary() =0; - virtual Condition is_not_at_boundary() =0; + virtual yc_bool_node_ptr is_at_boundary() =0; + virtual yc_bool_node_ptr is_not_at_boundary() =0; }; -class ElasticStencilBase : public StencilBase { +class ElasticStencilBase : public yc_solution_base { protected: // Dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. // 3D-spatial coefficients. - MAKE_GRID(rho, x, y, z); + yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); // Spatial FD coefficients. const double c0_8 = 1.2; @@ -96,9 +99,9 @@ class ElasticStencilBase : public StencilBase { ElasticBoundaryCondition *bc = NULL; public: - ElasticStencilBase(const string& name, StencilList& stencils, + ElasticStencilBase(const string& name, ElasticBoundaryCondition *_bc = NULL) : - StencilBase(name, stencils), bc(_bc) + yc_solution_base(name), bc(_bc) { } bool hasBoundaryCondition() @@ -106,25 +109,25 @@ class ElasticStencilBase : public StencilBase { return bc != NULL; } - GridValue interp_rho( GridIndex x, GridIndex y, GridIndex z, const TL ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TL ) { return ( 2.0/ (rho(x , y , z ) + rho(x+1, y , z )) ); } - GridValue interp_rho( GridIndex x, GridIndex y, GridIndex z, const TR ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TR ) { return ( 2.0/ (rho(x , y , z ) + rho(x , y+1, z )) ); } - GridValue interp_rho( GridIndex x, GridIndex y, GridIndex z, const BL ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BL ) { return ( 2.0/ (rho(x , y , z ) + rho(x , y , z+1)) ); } - GridValue interp_rho( GridIndex x, GridIndex y, GridIndex z, const BR ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BR ) { return ( 8.0/ (rho(x , y , z ) + rho(x , y , z+1) + @@ -137,12 +140,12 @@ class ElasticStencilBase : public StencilBase { } template - GridValue interp_rho( GridIndex x, GridIndex y, GridIndex z ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { return interp_rho( x, y, z, N() ); } - GridValue stencil_O8_Z( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const int offset ) + yc_number_node_ptr stencil_O8_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) { return (c0_8 * (g(t,x,y,z +offset) - @@ -155,17 +158,17 @@ class ElasticStencilBase : public StencilBase { g(t,x,y,z-4+offset)))*dzi; } - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const Z, const B ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Z, const B ) { return stencil_O8_Z( t, x, y, z, g, 0 ); } - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const Z, const F ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Z, const F ) { return stencil_O8_Z( t, x, y, z, g, 1 ); } - GridValue stencil_O8_Y( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const int offset ) + yc_number_node_ptr stencil_O8_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) { return (c0_8 * (g(t,x,y +offset,z) - @@ -178,17 +181,17 @@ class ElasticStencilBase : public StencilBase { g(t,x,y-4+offset,z)))*dyi; } - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const Y, const B ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Y, const B ) { return stencil_O8_Y( t, x, y, z, g, 0 ); } - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const Y, const F ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Y, const F ) { return stencil_O8_Y( t, x, y, z, g, 1 ); } - GridValue stencil_O8_X( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const int offset ) + yc_number_node_ptr stencil_O8_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) { return (c0_8 * (g(t,x +offset,y,z) - @@ -201,18 +204,18 @@ class ElasticStencilBase : public StencilBase { g(t,x-4+offset,y,z)))*dxi; } - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const X, const B ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const X, const B ) { return stencil_O8_X( t, x, y, z, g, 0 ); } - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const X, const F ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const X, const F ) { return stencil_O8_X( t, x, y, z, g, 1 ); } template - GridValue stencil_O8( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) { return stencil_O8( t, x, y, z, g, Dim(), Dir() ); } @@ -224,90 +227,90 @@ class ElasticStencilBase : public StencilBase { // appropriately. template - void define_vel(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &v, Grid &sx, Grid &sy, Grid &sz) { + void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &v, yc_grid_var &sx, yc_grid_var &sy, yc_grid_var &sz) { - GridValue lrho = interp_rho( x, y, z ); + yc_number_node_ptr lrho = interp_rho( x, y, z ); - GridValue stx = stencil_O8( t, x, y, z, sx ); - GridValue sty = stencil_O8( t, x, y, z, sy ); - GridValue stz = stencil_O8( t, x, y, z, sz ); + yc_number_node_ptr stx = stencil_O8( t, x, y, z, sx ); + yc_number_node_ptr sty = stencil_O8( t, x, y, z, sy ); + yc_number_node_ptr stz = stencil_O8( t, x, y, z, sz ); - GridValue next_v = v(t, x, y, z) + ((stx + sty + stz) * delta_t * lrho); + yc_number_node_ptr next_v = v(t, x, y, z) + ((stx + sty + stz) * delta_t * lrho); // define the value at t+1. if ( hasBoundaryCondition() ) { - Condition not_at_bc = bc->is_not_at_boundary(); - v(t+1, x, y, z) EQUALS next_v IF not_at_bc; + yc_bool_node_ptr not_at_bc = bc->is_not_at_boundary(); + v(t+1, x, y, z) EQUALS next_v IF_DOMAIN not_at_bc; } else v(t+1, x, y, z) EQUALS next_v; } - GridValue stencil_O2_Z( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const int offset ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) { return (g(t,x,y,z ) - g(t,x,y,z+offset))*dzi; } - GridValue stencil_O2_Z( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const B ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const B ) { return stencil_O2_Z( t, x, y, z, g,-1 ); } - GridValue stencil_O2_Z( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const F ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const F ) { return stencil_O2_Z( t, x, y, z, g, 1 ); } template - GridValue stencil_O2_Z( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) { return stencil_O2_Z( t, x, y, z, g, D() ); } - GridValue stencil_O2_Y( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const int offset ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) { return (g(t,x,y ,z) - g(t,x,y+offset,z))*dyi; } - GridValue stencil_O2_Y( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const B ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const B ) { return stencil_O2_Y( t, x, y, z, g,-1 ); } - GridValue stencil_O2_Y( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const F ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const F ) { return stencil_O2_Y( t, x, y, z, g, 1 ); } template - GridValue stencil_O2_Y( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) { return stencil_O2_Y( t, x, y, z, g, D() ); } - GridValue stencil_O2_X( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const int offset ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) { return (g(t,x ,y,z) - g(t,x+offset,y,z))*dxi; } - GridValue stencil_O2_X( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const B ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const B ) { return stencil_O2_X( t, x, y, z, g,-1 ); } - GridValue stencil_O2_X( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g, const F ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const F ) { return stencil_O2_X( t, x, y, z, g, 1 ); } template - GridValue stencil_O2_X( GridIndex t, GridIndex x, GridIndex y, GridIndex z, Grid &g ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) { return stencil_O2_X( t, x, y, z, g, D() ); } diff --git a/src/stencils/ExampleStencil.cpp b/src/stencils/ExampleStencil.cpp index b4474c1f..c568dfe3 100644 --- a/src/stencils/ExampleStencil.cpp +++ b/src/stencils/ExampleStencil.cpp @@ -28,34 +28,37 @@ IN THE SOFTWARE. // All these stencils compute the average of the points read a la the // heat-dissipation kernels in the miniGhost benchmark. -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; -class AvePtsStencil : public StencilRadiusBase { +class AvePtsStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying 3D grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying 3D grid. // Add additional points to expression v. // Returns number of points added. - virtual int addPoints(GridValue& v) =0; + virtual int addPoints(yc_number_node_ptr& v) =0; public: - AvePtsStencil(const string& name, StencilList& stencils, int radius) : - StencilRadiusBase(name, stencils, radius) { } + AvePtsStencil(const string& name, int radius) : + yc_solution_with_radius_base(name, radius) { } // Define equation at t+1 based on values at t. virtual void define() { // start with center point. - GridValue v = A(t, x, y, z); + yc_number_node_ptr v = A(t, x, y, z); // Add additional points from derived class. int pts = 1 + addPoints(v); @@ -74,7 +77,7 @@ class AxisStencil : public AvePtsStencil { protected: // Add additional points to expression v. - virtual int addPoints(GridValue& v) + virtual int addPoints(yc_number_node_ptr& v) { int pts = 0; for (int r = 1; r <= _radius; r++) { @@ -97,20 +100,23 @@ class AxisStencil : public AvePtsStencil { } public: - AxisStencil(StencilList& stencils, int radius=4) : - AvePtsStencil("3axis", stencils, radius) { } - AxisStencil(const string& name, StencilList& stencils, int radius=4) : - AvePtsStencil(name, stencils, radius) { } + AxisStencil(int radius=4) : + AvePtsStencil("3axis", radius) { } + AxisStencil(const string& name, int radius=4) : + AvePtsStencil(name, radius) { } }; -REGISTER_STENCIL(AxisStencil); +// Create an object of type 'AxisStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static AxisStencil AxisStencil_instance; // Add points from x-y, x-z, and y-z diagonals. class DiagStencil : public AxisStencil { protected: // Add additional points to v. - virtual int addPoints(GridValue& v) + virtual int addPoints(yc_number_node_ptr& v) { // Get points from axes. int pts = AxisStencil::addPoints(v); @@ -142,20 +148,23 @@ class DiagStencil : public AxisStencil { } public: - DiagStencil(StencilList& stencils, int radius=4) : - AxisStencil("3axis_with_diags", stencils, radius) { } - DiagStencil(const string& name, StencilList& stencils, int radius=4) : - AxisStencil(name, stencils, radius) { } + DiagStencil(int radius=4) : + AxisStencil("3axis_with_diags", radius) { } + DiagStencil(const string& name, int radius=4) : + AxisStencil(name, radius) { } }; -REGISTER_STENCIL(DiagStencil); +// Create an object of type 'DiagStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static DiagStencil DiagStencil_instance; // Add points from x-y, x-z, and y-z planes not covered by axes or diagonals. class PlaneStencil : public DiagStencil { protected: // Add additional points to v. - virtual int addPoints(GridValue& v) + virtual int addPoints(yc_number_node_ptr& v) { // Get points from axes and diagonals. int pts = DiagStencil::addPoints(v); @@ -201,20 +210,23 @@ class PlaneStencil : public DiagStencil { } public: - PlaneStencil(StencilList& stencils, int radius=3) : - DiagStencil("3plane", stencils, radius) { } - PlaneStencil(const string& name, StencilList& stencils, int radius=3) : - DiagStencil(name, stencils, radius) { } + PlaneStencil(int radius=3) : + DiagStencil("3plane", radius) { } + PlaneStencil(const string& name, int radius=3) : + DiagStencil(name, radius) { } }; -REGISTER_STENCIL(PlaneStencil); +// Create an object of type 'PlaneStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static PlaneStencil PlaneStencil_instance; // Add points from rest of cube. class CubeStencil : public PlaneStencil { protected: // Add additional points to v. - virtual int addPoints(GridValue& v) + virtual int addPoints(yc_number_node_ptr& v) { // Get points from planes. int pts = PlaneStencil::addPoints(v); @@ -240,10 +252,13 @@ class CubeStencil : public PlaneStencil { } public: - CubeStencil(StencilList& stencils, int radius=2) : - PlaneStencil("cube", stencils, radius) { } - CubeStencil(const string& name, StencilList& stencils, int radius=2) : - PlaneStencil(name, stencils, radius) { } + CubeStencil(int radius=2) : + PlaneStencil("cube", radius) { } + CubeStencil(const string& name, int radius=2) : + PlaneStencil(name, radius) { } }; -REGISTER_STENCIL(CubeStencil); +// Create an object of type 'CubeStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static CubeStencil CubeStencil_instance; diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index aff29e4f..dda732bc 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -28,7 +28,10 @@ IN THE SOFTWARE. // This version varies from the original by grouping related grids into // larger grids with an added dimension. -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; #include "ElasticStencil/Elastic2Stencil.hpp" namespace fsg { @@ -38,10 +41,10 @@ namespace fsg { class FSG2BoundaryCondition : public Elastic2BoundaryCondition { public: - FSG2BoundaryCondition(StencilBase& base) : + FSG2BoundaryCondition(yc_solution_base& base) : Elastic2BoundaryCondition(base) {} - virtual void velocity (GridIndex t, GridIndex x, GridIndex y, GridIndex z) {} - virtual void stress (GridIndex t, GridIndex x, GridIndex y, GridIndex z) {} + virtual void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) {} + virtual void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) {} }; class FSGElastic2StencilBase : public Elastic2StencilBase { @@ -50,20 +53,20 @@ namespace fsg { protected: // Velocity and stress grids. - MAKE_GRID(v, t, x, y, z, vidx); + yc_grid_var v = yc_grid_var("v", get_solution(), { t, x, y, z, vidx }); enum VIDX { V_BL_U, V_BL_V, V_BL_W, V_BR_U, V_BR_V, V_BR_W, V_TL_U, V_TL_V, V_TL_W, V_TR_U, V_TR_V, V_TR_W }; - MAKE_GRID(s, t, x, y, z, sidx); + yc_grid_var s = yc_grid_var("s", get_solution(), { t, x, y, z, sidx }); enum SIDX { S_BL_XX, S_BL_YY, S_BL_ZZ, S_BL_YZ, S_BL_XZ, S_BL_XY, S_BR_XX, S_BR_YY, S_BR_ZZ, S_BR_YZ, S_BR_XZ, S_BR_XY, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TL_YZ, S_TL_XZ, S_TL_XY, S_TR_XX, S_TR_YY, S_TR_ZZ, S_TR_YZ, S_TR_XZ, S_TR_XY }; // 3D-spatial coefficients. - MAKE_GRID(c, x, y, z, cidx); + yc_grid_var c = yc_grid_var("c", get_solution(), { x, y, z, cidx }); enum CIDX { C11, C12, C13, C14, C15, C16, C22, C23, C24, C25, C26, C33, C34, C35, C36, @@ -74,100 +77,100 @@ namespace fsg { public: - FSGElastic2StencilBase( const string &name, StencilList& stencils, + FSGElastic2StencilBase( const string &name, FSG2BoundaryCondition *bc = NULL) : - Elastic2StencilBase(name, stencils, bc) + Elastic2StencilBase(name, bc) { } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const BR) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const BR) { return 1.0 / (0.25*(c(x , y , z, cidx) + c(x , y+1, z, cidx) + c(x , y , z+1, cidx) + c(x , y+1, z+1, cidx))); } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const BL) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const BL) { return 1.0 / (0.25*(c(x , y , z, cidx) + c(x+1, y , z, cidx) + c(x , y , z+1, cidx) + c(x+1, y , z+1, cidx))); } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const TR) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const TR) { return 1.0 / (0.25*(c(x , y , z, cidx) + c(x , y+1, z, cidx) + c(x+1, y , z, cidx) + c(x+1, y+1, z, cidx))); } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const TL) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const TL) { return 1.0 / c(x , y , z, cidx); } template - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx) { return cell_coeff( x, y, z, c, cidx, N()); } template - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, int cidx) { - return cell_coeff(x, y, z, c, constNum(cidx)); + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, int cidx) { + return cell_coeff(x, y, z, c, _node_factory.new_number_node(cidx)); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const BR) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const BR) { return 0.25 *( 1.0 / c(x , y , z, cidx) + 1.0 / c(x , y+1, z, cidx) + 1.0 / c(x , y , z+1, cidx) + 1.0 / c(x , y+1, z+1, cidx)); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const BL) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const BL) { return 0.25 *( 1.0 / c(x , y , z, cidx) + 1.0 / c(x+1, y , z, cidx) + 1.0 / c(x , y , z+1, cidx) + 1.0 / c(x+1, y , z+1, cidx)); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const TR) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const TR) { return 0.25 *( 1.0 / c(x , y , z, cidx) + 1.0 / c(x , y+1, z, cidx) + 1.0 / c(x+1, y , z, cidx) + 1.0 / c(x+1, y+1, z, cidx)); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx, const TL) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx, const TL) { return 1.0 / c(x , y , z, cidx); } template - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, GridIndex cidx) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, yc_number_node_ptr cidx) { return cell_coeff_artm( x, y, z, c, cidx, N()); } template - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, - Grid &c, int cidx) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, + yc_grid_var &c, int cidx) { - return cell_coeff_artm( x, y, z, c, constNum(cidx)); + return cell_coeff_artm( x, y, z, c, _node_factory.new_number_node(cidx)); } - GridValue stress_update( GridValue c1, GridValue c2, GridValue c3, - GridValue c4, GridValue c5, GridValue c6, - GridValue u_z, GridValue u_y, GridValue u_x, - GridValue v_z, GridValue v_y, GridValue v_x, - GridValue w_z, GridValue w_y, GridValue w_x) + yc_number_node_ptr stress_update( yc_number_node_ptr c1, yc_number_node_ptr c2, yc_number_node_ptr c3, + yc_number_node_ptr c4, yc_number_node_ptr c5, yc_number_node_ptr c6, + yc_number_node_ptr u_z, yc_number_node_ptr u_y, yc_number_node_ptr u_x, + yc_number_node_ptr v_z, yc_number_node_ptr v_y, yc_number_node_ptr v_x, + yc_number_node_ptr w_z, yc_number_node_ptr w_y, yc_number_node_ptr w_x) { return delta_t * c1 * u_x + delta_t * c2 * v_y @@ -187,72 +190,72 @@ namespace fsg { // appropriately. template - void define_str(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - GridIndex sxx_idx, GridIndex syy_idx, GridIndex szz_idx, - GridIndex sxy_idx, GridIndex sxz_idx, GridIndex syz_idx, - GridIndex vxu_idx, GridIndex vxv_idx, GridIndex vxw_idx, - GridIndex vyu_idx, GridIndex vyv_idx, GridIndex vyw_idx, - GridIndex vzu_idx, GridIndex vzv_idx, GridIndex vzw_idx) { + void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr sxx_idx, yc_number_node_ptr syy_idx, yc_number_node_ptr szz_idx, + yc_number_node_ptr sxy_idx, yc_number_node_ptr sxz_idx, yc_number_node_ptr syz_idx, + yc_number_node_ptr vxu_idx, yc_number_node_ptr vxv_idx, yc_number_node_ptr vxw_idx, + yc_number_node_ptr vyu_idx, yc_number_node_ptr vyv_idx, yc_number_node_ptr vyw_idx, + yc_number_node_ptr vzu_idx, yc_number_node_ptr vzv_idx, yc_number_node_ptr vzw_idx) { // Interpolate coeffs. - GridValue ic11 = cell_coeff (x, y, z, c, C11); - GridValue ic12 = cell_coeff (x, y, z, c, C12); - GridValue ic13 = cell_coeff (x, y, z, c, C13); - GridValue ic14 = cell_coeff_artm(x, y, z, c, C14); - GridValue ic15 = cell_coeff_artm(x, y, z, c, C15); - GridValue ic16 = cell_coeff_artm(x, y, z, c, C16); - GridValue ic22 = cell_coeff (x, y, z, c, C22); - GridValue ic23 = cell_coeff (x, y, z, c, C23); - GridValue ic24 = cell_coeff_artm(x, y, z, c, C24); - GridValue ic25 = cell_coeff_artm(x, y, z, c, C25); - GridValue ic26 = cell_coeff_artm(x, y, z, c, C26); - GridValue ic33 = cell_coeff (x, y, z, c, C33); - GridValue ic34 = cell_coeff_artm(x, y, z, c, C34); - GridValue ic35 = cell_coeff_artm(x, y, z, c, C35); - GridValue ic36 = cell_coeff_artm(x, y, z, c, C36); - GridValue ic44 = cell_coeff (x, y, z, c, C44); - GridValue ic45 = cell_coeff_artm(x, y, z, c, C45); - GridValue ic46 = cell_coeff_artm(x, y, z, c, C46); - GridValue ic55 = cell_coeff (x, y, z, c, C55); - GridValue ic56 = cell_coeff_artm(x, y, z, c, C56); - GridValue ic66 = cell_coeff (x, y, z, c, C66); + yc_number_node_ptr ic11 = cell_coeff (x, y, z, c, C11); + yc_number_node_ptr ic12 = cell_coeff (x, y, z, c, C12); + yc_number_node_ptr ic13 = cell_coeff (x, y, z, c, C13); + yc_number_node_ptr ic14 = cell_coeff_artm(x, y, z, c, C14); + yc_number_node_ptr ic15 = cell_coeff_artm(x, y, z, c, C15); + yc_number_node_ptr ic16 = cell_coeff_artm(x, y, z, c, C16); + yc_number_node_ptr ic22 = cell_coeff (x, y, z, c, C22); + yc_number_node_ptr ic23 = cell_coeff (x, y, z, c, C23); + yc_number_node_ptr ic24 = cell_coeff_artm(x, y, z, c, C24); + yc_number_node_ptr ic25 = cell_coeff_artm(x, y, z, c, C25); + yc_number_node_ptr ic26 = cell_coeff_artm(x, y, z, c, C26); + yc_number_node_ptr ic33 = cell_coeff (x, y, z, c, C33); + yc_number_node_ptr ic34 = cell_coeff_artm(x, y, z, c, C34); + yc_number_node_ptr ic35 = cell_coeff_artm(x, y, z, c, C35); + yc_number_node_ptr ic36 = cell_coeff_artm(x, y, z, c, C36); + yc_number_node_ptr ic44 = cell_coeff (x, y, z, c, C44); + yc_number_node_ptr ic45 = cell_coeff_artm(x, y, z, c, C45); + yc_number_node_ptr ic46 = cell_coeff_artm(x, y, z, c, C46); + yc_number_node_ptr ic55 = cell_coeff (x, y, z, c, C55); + yc_number_node_ptr ic56 = cell_coeff_artm(x, y, z, c, C56); + yc_number_node_ptr ic66 = cell_coeff (x, y, z, c, C66); // Compute stencils. Note that we are using the velocity values at t+1. - GridValue u_z = stencil_O8( t+1, x, y, z, v, vzu_idx); - GridValue v_z = stencil_O8( t+1, x, y, z, v, vzv_idx); - GridValue w_z = stencil_O8( t+1, x, y, z, v, vzw_idx); + yc_number_node_ptr u_z = stencil_O8( t+1, x, y, z, v, vzu_idx); + yc_number_node_ptr v_z = stencil_O8( t+1, x, y, z, v, vzv_idx); + yc_number_node_ptr w_z = stencil_O8( t+1, x, y, z, v, vzw_idx); - GridValue u_x = stencil_O8( t+1, x, y, z, v, vxu_idx); - GridValue v_x = stencil_O8( t+1, x, y, z, v, vxv_idx); - GridValue w_x = stencil_O8( t+1, x, y, z, v, vxw_idx); + yc_number_node_ptr u_x = stencil_O8( t+1, x, y, z, v, vxu_idx); + yc_number_node_ptr v_x = stencil_O8( t+1, x, y, z, v, vxv_idx); + yc_number_node_ptr w_x = stencil_O8( t+1, x, y, z, v, vxw_idx); - GridValue u_y = stencil_O8( t+1, x, y, z, v, vyu_idx); - GridValue v_y = stencil_O8( t+1, x, y, z, v, vyv_idx); - GridValue w_y = stencil_O8( t+1, x, y, z, v, vyw_idx); + yc_number_node_ptr u_y = stencil_O8( t+1, x, y, z, v, vyu_idx); + yc_number_node_ptr v_y = stencil_O8( t+1, x, y, z, v, vyv_idx); + yc_number_node_ptr w_y = stencil_O8( t+1, x, y, z, v, vyw_idx); // Compute next stress value - GridValue next_sxx = s(t, x, y, z, sxx_idx) + + yc_number_node_ptr next_sxx = s(t, x, y, z, sxx_idx) + stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_syy = s(t, x, y, z, syy_idx) + + yc_number_node_ptr next_syy = s(t, x, y, z, syy_idx) + stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_szz = s(t, x, y, z, szz_idx) + + yc_number_node_ptr next_szz = s(t, x, y, z, szz_idx) + stress_update(ic13,ic23,ic33,ic34,ic35,ic36,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_syz = s(t, x, y, z, syz_idx) + + yc_number_node_ptr next_syz = s(t, x, y, z, syz_idx) + stress_update(ic14,ic24,ic34,ic44,ic45,ic46,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_sxz = s(t, x, y, z, sxz_idx) + + yc_number_node_ptr next_sxz = s(t, x, y, z, sxz_idx) + stress_update(ic15,ic25,ic35,ic45,ic55,ic56,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_sxy = s(t, x, y, z, sxy_idx) + + yc_number_node_ptr next_sxy = s(t, x, y, z, sxy_idx) + stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); // define the value at t+1. if(hasBoundaryCondition()) { - Condition not_at_bc = bc->is_not_at_boundary(); - s(t+1, x, y, z, sxx_idx) EQUALS next_sxx IF not_at_bc; - s(t+1, x, y, z, syy_idx) EQUALS next_syy IF not_at_bc; - s(t+1, x, y, z, szz_idx) EQUALS next_szz IF not_at_bc; - s(t+1, x, y, z, syz_idx) EQUALS next_syz IF not_at_bc; - s(t+1, x, y, z, sxz_idx) EQUALS next_sxz IF not_at_bc; - s(t+1, x, y, z, sxy_idx) EQUALS next_sxy IF not_at_bc; + yc_bool_node_ptr not_at_bc = bc->is_not_at_boundary(); + s(t+1, x, y, z, sxx_idx) EQUALS next_sxx IF_DOMAIN not_at_bc; + s(t+1, x, y, z, syy_idx) EQUALS next_syy IF_DOMAIN not_at_bc; + s(t+1, x, y, z, szz_idx) EQUALS next_szz IF_DOMAIN not_at_bc; + s(t+1, x, y, z, syz_idx) EQUALS next_syz IF_DOMAIN not_at_bc; + s(t+1, x, y, z, sxz_idx) EQUALS next_sxz IF_DOMAIN not_at_bc; + s(t+1, x, y, z, sxy_idx) EQUALS next_sxy IF_DOMAIN not_at_bc; } else { s(t+1, x, y, z, sxx_idx) EQUALS next_sxx; s(t+1, x, y, z, syy_idx) EQUALS next_syy; @@ -263,18 +266,18 @@ namespace fsg { } } template - void define_str(GridIndex t, GridIndex x, GridIndex y, GridIndex z, + void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, int sxx_idx, int syy_idx, int szz_idx, int sxy_idx, int sxz_idx, int syz_idx, int vxu_idx, int vxv_idx, int vxw_idx, int vyu_idx, int vyv_idx, int vyw_idx, int vzu_idx, int vzv_idx, int vzw_idx) { define_str(t, x, y, z, - constNum(sxx_idx), constNum(syy_idx), constNum(szz_idx), - constNum(sxy_idx), constNum(sxz_idx), constNum(syz_idx), - constNum(vxu_idx), constNum(vxv_idx), constNum(vxw_idx), - constNum(vyu_idx), constNum(vyv_idx), constNum(vyw_idx), - constNum(vzu_idx), constNum(vzv_idx), constNum(vzw_idx)); + _node_factory.new_number_node(sxx_idx), _node_factory.new_number_node(syy_idx), _node_factory.new_number_node(szz_idx), + _node_factory.new_number_node(sxy_idx), _node_factory.new_number_node(sxz_idx), _node_factory.new_number_node(syz_idx), + _node_factory.new_number_node(vxu_idx), _node_factory.new_number_node(vxv_idx), _node_factory.new_number_node(vxw_idx), + _node_factory.new_number_node(vyu_idx), _node_factory.new_number_node(vyv_idx), _node_factory.new_number_node(vyw_idx), + _node_factory.new_number_node(vzu_idx), _node_factory.new_number_node(vzv_idx), _node_factory.new_number_node(vzw_idx)); } // Call all the define_* functions. @@ -320,7 +323,7 @@ namespace fsg { const int abc_width = 20; // Sponge coefficients. - MAKE_GRID(sponge, x, y, z, spidx); + yc_grid_var sponge = yc_grid_var("sponge", get_solution(), { x, y, z, spidx }); enum SPONGE_IDX { SPONGE_LX, SPONGE_RX, SPONGE_BZ, SPONGE_TZ, SPONGE_FY, SPONGE_BY, SPONGE_SQ_LX, SPONGE_SQ_RX, SPONGE_SQ_BZ, @@ -335,58 +338,58 @@ namespace fsg { { } - Condition is_at_boundary() + yc_bool_node_ptr is_at_boundary() { - Condition bc = + yc_bool_node_ptr bc = (z < first_index(z)+abc_width || z > last_index(z)-abc_width) || (y < first_index(y)+abc_width || y > last_index(y)-abc_width) || (x < first_index(x)+abc_width || x > last_index(x)-abc_width); return bc; } - Condition is_not_at_boundary() + yc_bool_node_ptr is_not_at_boundary() { return !is_at_boundary(); } template - void define_vel_abc(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - GridIndex vidx, - GridIndex sx_idx, GridIndex sy_idx, GridIndex sz_idx, - GridIndex abc_x_idx, GridIndex abc_y_idx, GridIndex abc_z_idx, - GridIndex abc_sq_x_idx, GridIndex abc_sq_y_idx, GridIndex abc_sq_z_idx) { + void define_vel_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr vidx, + yc_number_node_ptr sx_idx, yc_number_node_ptr sy_idx, yc_number_node_ptr sz_idx, + yc_number_node_ptr abc_x_idx, yc_number_node_ptr abc_y_idx, yc_number_node_ptr abc_z_idx, + yc_number_node_ptr abc_sq_x_idx, yc_number_node_ptr abc_sq_y_idx, yc_number_node_ptr abc_sq_z_idx) { - Condition at_abc = is_at_boundary(); + yc_bool_node_ptr at_abc = is_at_boundary(); - GridValue next_v = fsg.v(t, x, y, z, vidx) * sponge(x,y,z, abc_x_idx) * + yc_number_node_ptr next_v = fsg.v(t, x, y, z, vidx) * sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); - GridValue lrho = fsg.interp_rho( x, y, z); + yc_number_node_ptr lrho = fsg.interp_rho( x, y, z); - GridValue stx = fsg.stencil_O2_X( t, x, y, z, fsg.s, sx_idx); - GridValue sty = fsg.stencil_O2_Y( t, x, y, z, fsg.s, sy_idx); - GridValue stz = fsg.stencil_O2_Z( t, x, y, z, fsg.s, sz_idx); + yc_number_node_ptr stx = fsg.stencil_O2_X( t, x, y, z, fsg.s, sx_idx); + yc_number_node_ptr sty = fsg.stencil_O2_Y( t, x, y, z, fsg.s, sy_idx); + yc_number_node_ptr stz = fsg.stencil_O2_Z( t, x, y, z, fsg.s, sz_idx); next_v += ((stx + sty + stz) * fsg.delta_t * lrho); next_v *= sponge(x,y,z, abc_sq_x_idx) * sponge(x,y,z, abc_sq_y_idx) * sponge(x,y,z, abc_sq_z_idx); // define the value at t+1. - fsg.v(t+1, x, y, z, vidx) EQUALS next_v IF at_abc; + fsg.v(t+1, x, y, z, vidx) EQUALS next_v IF_DOMAIN at_abc; } template - void define_vel_abc(GridIndex t, GridIndex x, GridIndex y, GridIndex z, + void define_vel_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, int vidx, int sx_idx, int sy_idx, int sz_idx, int abc_x_idx, int abc_y_idx, int abc_z_idx, int abc_sq_x_idx, int abc_sq_y_idx, int abc_sq_z_idx) { define_vel_abc(t, x, y, z, - constNum(vidx), - constNum(sx_idx), constNum(sy_idx), constNum(sz_idx), - constNum(abc_x_idx), constNum(abc_y_idx), constNum(abc_z_idx), - constNum(abc_sq_x_idx), constNum(abc_sq_y_idx), constNum(abc_sq_z_idx)); + _node_factory.new_number_node(vidx), + _node_factory.new_number_node(sx_idx), _node_factory.new_number_node(sy_idx), _node_factory.new_number_node(sz_idx), + _node_factory.new_number_node(abc_x_idx), _node_factory.new_number_node(abc_y_idx), _node_factory.new_number_node(abc_z_idx), + _node_factory.new_number_node(abc_sq_x_idx), _node_factory.new_number_node(abc_sq_y_idx), _node_factory.new_number_node(abc_sq_z_idx)); } - void velocity (GridIndex t, GridIndex x, GridIndex y, GridIndex z) + void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { define_vel_abc(t, x, y, z, fsg.V_TL_W, fsg.S_TL_YZ, fsg.S_TR_XZ, fsg.S_BL_ZZ, SPONGE_LX, SPONGE_BY, SPONGE_TZ, SPONGE_SQ_LX, SPONGE_SQ_BY, SPONGE_SQ_TZ); @@ -415,61 +418,61 @@ namespace fsg { } template - void define_str_abc(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - GridIndex sxx_idx, GridIndex syy_idx, GridIndex szz_idx, - GridIndex sxy_idx, GridIndex sxz_idx, GridIndex syz_idx, - GridIndex vxu_idx, GridIndex vxv_idx, GridIndex vxw_idx, - GridIndex vyu_idx, GridIndex vyv_idx, GridIndex vyw_idx, - GridIndex vzu_idx, GridIndex vzv_idx, GridIndex vzw_idx, - GridIndex abc_x_idx, GridIndex abc_y_idx, GridIndex abc_z_idx, - GridIndex abc_sq_x_idx, GridIndex abc_sq_y_idx, GridIndex abc_sq_z_idx) { - - GridValue abc = sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); - GridValue next_sxx = fsg.s(t, x, y, z, sxx_idx) * abc; - GridValue next_syy = fsg.s(t, x, y, z, syy_idx) * abc; - GridValue next_szz = fsg.s(t, x, y, z, szz_idx) * abc; - GridValue next_syz = fsg.s(t, x, y, z, syz_idx) * abc; - GridValue next_sxz = fsg.s(t, x, y, z, sxz_idx) * abc; - GridValue next_sxy = fsg.s(t, x, y, z, sxy_idx) * abc; + void define_str_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr sxx_idx, yc_number_node_ptr syy_idx, yc_number_node_ptr szz_idx, + yc_number_node_ptr sxy_idx, yc_number_node_ptr sxz_idx, yc_number_node_ptr syz_idx, + yc_number_node_ptr vxu_idx, yc_number_node_ptr vxv_idx, yc_number_node_ptr vxw_idx, + yc_number_node_ptr vyu_idx, yc_number_node_ptr vyv_idx, yc_number_node_ptr vyw_idx, + yc_number_node_ptr vzu_idx, yc_number_node_ptr vzv_idx, yc_number_node_ptr vzw_idx, + yc_number_node_ptr abc_x_idx, yc_number_node_ptr abc_y_idx, yc_number_node_ptr abc_z_idx, + yc_number_node_ptr abc_sq_x_idx, yc_number_node_ptr abc_sq_y_idx, yc_number_node_ptr abc_sq_z_idx) { + + yc_number_node_ptr abc = sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); + yc_number_node_ptr next_sxx = fsg.s(t, x, y, z, sxx_idx) * abc; + yc_number_node_ptr next_syy = fsg.s(t, x, y, z, syy_idx) * abc; + yc_number_node_ptr next_szz = fsg.s(t, x, y, z, szz_idx) * abc; + yc_number_node_ptr next_syz = fsg.s(t, x, y, z, syz_idx) * abc; + yc_number_node_ptr next_sxz = fsg.s(t, x, y, z, sxz_idx) * abc; + yc_number_node_ptr next_sxy = fsg.s(t, x, y, z, sxy_idx) * abc; // Interpolate coeffs. - GridValue ic11 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C11); - GridValue ic12 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C12); - GridValue ic13 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C13); - GridValue ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C14); - GridValue ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C15); - GridValue ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C16); - GridValue ic22 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C22); - GridValue ic23 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C23); - GridValue ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C24); - GridValue ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C25); - GridValue ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C26); - GridValue ic33 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C33); - GridValue ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C34); - GridValue ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C35); - GridValue ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C36); - GridValue ic44 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C44); - GridValue ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C45); - GridValue ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C46); - GridValue ic55 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C55); - GridValue ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C56); - GridValue ic66 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C66); + yc_number_node_ptr ic11 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C11); + yc_number_node_ptr ic12 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C12); + yc_number_node_ptr ic13 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C13); + yc_number_node_ptr ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C14); + yc_number_node_ptr ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C15); + yc_number_node_ptr ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C16); + yc_number_node_ptr ic22 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C22); + yc_number_node_ptr ic23 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C23); + yc_number_node_ptr ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C24); + yc_number_node_ptr ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C25); + yc_number_node_ptr ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C26); + yc_number_node_ptr ic33 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C33); + yc_number_node_ptr ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C34); + yc_number_node_ptr ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C35); + yc_number_node_ptr ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C36); + yc_number_node_ptr ic44 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C44); + yc_number_node_ptr ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C45); + yc_number_node_ptr ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C46); + yc_number_node_ptr ic55 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C55); + yc_number_node_ptr ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C56); + yc_number_node_ptr ic66 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C66); // Compute stencils. Note that we are using the velocity values at t+1. - GridValue u_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzu_idx); - GridValue v_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzv_idx); - GridValue w_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzw_idx); + yc_number_node_ptr u_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzu_idx); + yc_number_node_ptr v_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzv_idx); + yc_number_node_ptr w_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzw_idx); - GridValue u_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxu_idx); - GridValue v_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxv_idx); - GridValue w_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxw_idx); + yc_number_node_ptr u_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxu_idx); + yc_number_node_ptr v_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxv_idx); + yc_number_node_ptr w_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxw_idx); - GridValue u_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyu_idx); - GridValue v_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyv_idx); - GridValue w_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyw_idx); + yc_number_node_ptr u_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyu_idx); + yc_number_node_ptr v_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyv_idx); + yc_number_node_ptr w_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyw_idx); // Compute next stress value - GridValue abc_sq = sponge(x,y,z, abc_sq_x_idx) * + yc_number_node_ptr abc_sq = sponge(x,y,z, abc_sq_x_idx) * sponge(x,y,z, abc_sq_y_idx) * sponge(x,y,z, abc_sq_z_idx); next_sxx += fsg.stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; next_syy += fsg.stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; @@ -479,16 +482,16 @@ namespace fsg { next_sxy += fsg.stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; // define the value at t+1. - Condition at_abc = is_at_boundary(); - fsg.s(t+1, x, y, z, sxx_idx) EQUALS next_sxx IF at_abc; - fsg.s(t+1, x, y, z, syy_idx) EQUALS next_syy IF at_abc; - fsg.s(t+1, x, y, z, szz_idx) EQUALS next_szz IF at_abc; - fsg.s(t+1, x, y, z, syz_idx) EQUALS next_syz IF at_abc; - fsg.s(t+1, x, y, z, sxz_idx) EQUALS next_sxz IF at_abc; - fsg.s(t+1, x, y, z, sxy_idx) EQUALS next_sxy IF at_abc; + yc_bool_node_ptr at_abc = is_at_boundary(); + fsg.s(t+1, x, y, z, sxx_idx) EQUALS next_sxx IF_DOMAIN at_abc; + fsg.s(t+1, x, y, z, syy_idx) EQUALS next_syy IF_DOMAIN at_abc; + fsg.s(t+1, x, y, z, szz_idx) EQUALS next_szz IF_DOMAIN at_abc; + fsg.s(t+1, x, y, z, syz_idx) EQUALS next_syz IF_DOMAIN at_abc; + fsg.s(t+1, x, y, z, sxz_idx) EQUALS next_sxz IF_DOMAIN at_abc; + fsg.s(t+1, x, y, z, sxy_idx) EQUALS next_sxy IF_DOMAIN at_abc; } template - void define_str_abc(GridIndex t, GridIndex x, GridIndex y, GridIndex z, + void define_str_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, int sxx_idx, int syy_idx, int szz_idx, int sxy_idx, int sxz_idx, int syz_idx, int vxu_idx, int vxv_idx, int vxw_idx, @@ -497,16 +500,16 @@ namespace fsg { int abc_x_idx, int abc_y_idx, int abc_z_idx, int abc_sq_x_idx, int abc_sq_y_idx, int abc_sq_z_idx) { define_str_abc(t, x, y, z, - constNum(sxx_idx), constNum(syy_idx), constNum(szz_idx), - constNum(sxy_idx), constNum(sxz_idx), constNum(syz_idx), - constNum(vxu_idx), constNum(vxv_idx), constNum(vxw_idx), - constNum(vyu_idx), constNum(vyv_idx), constNum(vyw_idx), - constNum(vzu_idx), constNum(vzv_idx), constNum(vzw_idx), - constNum(abc_x_idx), constNum(abc_y_idx), constNum(abc_z_idx), - constNum(abc_sq_x_idx), constNum(abc_sq_y_idx), constNum(abc_sq_z_idx)); + _node_factory.new_number_node(sxx_idx), _node_factory.new_number_node(syy_idx), _node_factory.new_number_node(szz_idx), + _node_factory.new_number_node(sxy_idx), _node_factory.new_number_node(sxz_idx), _node_factory.new_number_node(syz_idx), + _node_factory.new_number_node(vxu_idx), _node_factory.new_number_node(vxv_idx), _node_factory.new_number_node(vxw_idx), + _node_factory.new_number_node(vyu_idx), _node_factory.new_number_node(vyv_idx), _node_factory.new_number_node(vyw_idx), + _node_factory.new_number_node(vzu_idx), _node_factory.new_number_node(vzv_idx), _node_factory.new_number_node(vzw_idx), + _node_factory.new_number_node(abc_x_idx), _node_factory.new_number_node(abc_y_idx), _node_factory.new_number_node(abc_z_idx), + _node_factory.new_number_node(abc_sq_x_idx), _node_factory.new_number_node(abc_sq_y_idx), _node_factory.new_number_node(abc_sq_z_idx)); } - void stress (GridIndex t, GridIndex x, GridIndex y, GridIndex z) + void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { define_str_abc(t, x, y, z, fsg.S_BR_XX, fsg.S_BR_YY, fsg.S_BR_ZZ, fsg.S_BR_XY, fsg.S_BR_XZ, fsg.S_BR_YZ, fsg.V_BR_U, fsg.V_BR_V, fsg.V_BR_W, fsg.V_BL_U, @@ -530,19 +533,25 @@ namespace fsg { struct FSGElastic2Stencil : public FSGElastic2StencilBase { - FSGElastic2Stencil(StencilList& stencils) : - FSGElastic2StencilBase("fsg2", stencils) { } + FSGElastic2Stencil() : + FSGElastic2StencilBase("fsg2") { } }; struct FSG2ABCElasticStencil : public FSGElastic2StencilBase { - FSG2_ABC abc; // Absorbing Boundary Condition + FSG2_ABC abc; // Absorbing Boundary yc_bool_node_ptr - FSG2ABCElasticStencil(StencilList& stencils) : - FSGElastic2StencilBase("fsg2_abc", stencils, &abc), + FSG2ABCElasticStencil() : + FSGElastic2StencilBase("fsg2_abc", &abc), abc(*this) { } }; - REGISTER_STENCIL(FSGElastic2Stencil); - REGISTER_STENCIL(FSG2ABCElasticStencil); +// Create an object of type 'FSGElastic2Stencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static FSGElastic2Stencil FSGElastic2Stencil_instance; +// Create an object of type 'FSG2ABCElasticStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static FSG2ABCElasticStencil FSG2ABCElasticStencil_instance; } diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index a34e973b..8e7f4eec 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -26,7 +26,10 @@ IN THE SOFTWARE. // Stencil equations for FSG elastic numerics. // Contributed by Albert Farres from the Barcelona Supercomputing Center. -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; #include "ElasticStencil/ElasticStencil.hpp" namespace fsg { @@ -36,10 +39,10 @@ namespace fsg { class FSGBoundaryCondition : public ElasticBoundaryCondition { public: - FSGBoundaryCondition(StencilBase& base) : + FSGBoundaryCondition(yc_solution_base& base) : ElasticBoundaryCondition(base) {} - virtual void velocity (GridIndex t, GridIndex x, GridIndex y, GridIndex z ) {} - virtual void stress (GridIndex t, GridIndex x, GridIndex y, GridIndex z ) {} + virtual void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) {} + virtual void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) {} }; class FSGElasticStencilBase : public ElasticStencilBase { @@ -47,142 +50,142 @@ namespace fsg { protected: - MAKE_GRID(v_bl_u, t, x, y, z); - MAKE_GRID(v_bl_v, t, x, y, z); - MAKE_GRID(v_bl_w, t, x, y, z); - MAKE_GRID(v_br_u, t, x, y, z); - MAKE_GRID(v_br_v, t, x, y, z); - MAKE_GRID(v_br_w, t, x, y, z); - MAKE_GRID(v_tl_u, t, x, y, z); - MAKE_GRID(v_tl_v, t, x, y, z); - MAKE_GRID(v_tl_w, t, x, y, z); - MAKE_GRID(v_tr_u, t, x, y, z); - MAKE_GRID(v_tr_v, t, x, y, z); - MAKE_GRID(v_tr_w, t, x, y, z); - - MAKE_GRID(s_bl_xx, t, x, y, z); - MAKE_GRID(s_bl_yy, t, x, y, z); - MAKE_GRID(s_bl_zz, t, x, y, z); - MAKE_GRID(s_bl_yz, t, x, y, z); - MAKE_GRID(s_bl_xz, t, x, y, z); - MAKE_GRID(s_bl_xy, t, x, y, z); - MAKE_GRID(s_br_xx, t, x, y, z); - MAKE_GRID(s_br_yy, t, x, y, z); - MAKE_GRID(s_br_zz, t, x, y, z); - MAKE_GRID(s_br_yz, t, x, y, z); - MAKE_GRID(s_br_xz, t, x, y, z); - MAKE_GRID(s_br_xy, t, x, y, z); - MAKE_GRID(s_tl_xx, t, x, y, z); - MAKE_GRID(s_tl_yy, t, x, y, z); - MAKE_GRID(s_tl_zz, t, x, y, z); - MAKE_GRID(s_tl_yz, t, x, y, z); - MAKE_GRID(s_tl_xz, t, x, y, z); - MAKE_GRID(s_tl_xy, t, x, y, z); - MAKE_GRID(s_tr_xx, t, x, y, z); - MAKE_GRID(s_tr_yy, t, x, y, z); - MAKE_GRID(s_tr_zz, t, x, y, z); - MAKE_GRID(s_tr_yz, t, x, y, z); - MAKE_GRID(s_tr_xz, t, x, y, z); - MAKE_GRID(s_tr_xy, t, x, y, z); + yc_grid_var v_bl_u = yc_grid_var("v_bl_u", get_solution(), { t, x, y, z }); + yc_grid_var v_bl_v = yc_grid_var("v_bl_v", get_solution(), { t, x, y, z }); + yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_solution(), { t, x, y, z }); + yc_grid_var v_br_u = yc_grid_var("v_br_u", get_solution(), { t, x, y, z }); + yc_grid_var v_br_v = yc_grid_var("v_br_v", get_solution(), { t, x, y, z }); + yc_grid_var v_br_w = yc_grid_var("v_br_w", get_solution(), { t, x, y, z }); + yc_grid_var v_tl_u = yc_grid_var("v_tl_u", get_solution(), { t, x, y, z }); + yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_solution(), { t, x, y, z }); + yc_grid_var v_tl_w = yc_grid_var("v_tl_w", get_solution(), { t, x, y, z }); + yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_solution(), { t, x, y, z }); + yc_grid_var v_tr_v = yc_grid_var("v_tr_v", get_solution(), { t, x, y, z }); + yc_grid_var v_tr_w = yc_grid_var("v_tr_w", get_solution(), { t, x, y, z }); + + yc_grid_var s_bl_xx = yc_grid_var("s_bl_xx", get_solution(), { t, x, y, z }); + yc_grid_var s_bl_yy = yc_grid_var("s_bl_yy", get_solution(), { t, x, y, z }); + yc_grid_var s_bl_zz = yc_grid_var("s_bl_zz", get_solution(), { t, x, y, z }); + yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_solution(), { t, x, y, z }); + yc_grid_var s_bl_xz = yc_grid_var("s_bl_xz", get_solution(), { t, x, y, z }); + yc_grid_var s_bl_xy = yc_grid_var("s_bl_xy", get_solution(), { t, x, y, z }); + yc_grid_var s_br_xx = yc_grid_var("s_br_xx", get_solution(), { t, x, y, z }); + yc_grid_var s_br_yy = yc_grid_var("s_br_yy", get_solution(), { t, x, y, z }); + yc_grid_var s_br_zz = yc_grid_var("s_br_zz", get_solution(), { t, x, y, z }); + yc_grid_var s_br_yz = yc_grid_var("s_br_yz", get_solution(), { t, x, y, z }); + yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_solution(), { t, x, y, z }); + yc_grid_var s_br_xy = yc_grid_var("s_br_xy", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_yz = yc_grid_var("s_tl_yz", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_xz = yc_grid_var("s_tl_xz", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_xy = yc_grid_var("s_tl_xy", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_xx = yc_grid_var("s_tr_xx", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_yy = yc_grid_var("s_tr_yy", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_zz = yc_grid_var("s_tr_zz", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_yz = yc_grid_var("s_tr_yz", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_xz = yc_grid_var("s_tr_xz", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_solution(), { t, x, y, z }); // 3D-spatial coefficients. - MAKE_GRID(c11, x, y, z); - MAKE_GRID(c12, x, y, z); - MAKE_GRID(c13, x, y, z); - MAKE_GRID(c14, x, y, z); - MAKE_GRID(c15, x, y, z); - MAKE_GRID(c16, x, y, z); - MAKE_GRID(c22, x, y, z); - MAKE_GRID(c23, x, y, z); - MAKE_GRID(c24, x, y, z); - MAKE_GRID(c25, x, y, z); - MAKE_GRID(c26, x, y, z); - MAKE_GRID(c33, x, y, z); - MAKE_GRID(c34, x, y, z); - MAKE_GRID(c35, x, y, z); - MAKE_GRID(c36, x, y, z); - MAKE_GRID(c44, x, y, z); - MAKE_GRID(c45, x, y, z); - MAKE_GRID(c46, x, y, z); - MAKE_GRID(c55, x, y, z); - MAKE_GRID(c56, x, y, z); - MAKE_GRID(c66, x, y, z); + yc_grid_var c11 = yc_grid_var("c11", get_solution(), { x, y, z }); + yc_grid_var c12 = yc_grid_var("c12", get_solution(), { x, y, z }); + yc_grid_var c13 = yc_grid_var("c13", get_solution(), { x, y, z }); + yc_grid_var c14 = yc_grid_var("c14", get_solution(), { x, y, z }); + yc_grid_var c15 = yc_grid_var("c15", get_solution(), { x, y, z }); + yc_grid_var c16 = yc_grid_var("c16", get_solution(), { x, y, z }); + yc_grid_var c22 = yc_grid_var("c22", get_solution(), { x, y, z }); + yc_grid_var c23 = yc_grid_var("c23", get_solution(), { x, y, z }); + yc_grid_var c24 = yc_grid_var("c24", get_solution(), { x, y, z }); + yc_grid_var c25 = yc_grid_var("c25", get_solution(), { x, y, z }); + yc_grid_var c26 = yc_grid_var("c26", get_solution(), { x, y, z }); + yc_grid_var c33 = yc_grid_var("c33", get_solution(), { x, y, z }); + yc_grid_var c34 = yc_grid_var("c34", get_solution(), { x, y, z }); + yc_grid_var c35 = yc_grid_var("c35", get_solution(), { x, y, z }); + yc_grid_var c36 = yc_grid_var("c36", get_solution(), { x, y, z }); + yc_grid_var c44 = yc_grid_var("c44", get_solution(), { x, y, z }); + yc_grid_var c45 = yc_grid_var("c45", get_solution(), { x, y, z }); + yc_grid_var c46 = yc_grid_var("c46", get_solution(), { x, y, z }); + yc_grid_var c55 = yc_grid_var("c55", get_solution(), { x, y, z }); + yc_grid_var c56 = yc_grid_var("c56", get_solution(), { x, y, z }); + yc_grid_var c66 = yc_grid_var("c66", get_solution(), { x, y, z }); public: - FSGElasticStencilBase( const string &name, StencilList& stencils, + FSGElasticStencilBase( const string &name, FSGBoundaryCondition *bc = NULL ) : - ElasticStencilBase ( name, stencils, bc ) + ElasticStencilBase ( name, bc ) { } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const BR ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BR ) { return 1.0 / (0.25*(c(x , y , z ) + c(x , y+1, z ) + c(x , y , z+1) + c(x , y+1, z+1))); } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const BL ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BL ) { return 1.0 / (0.25*(c(x , y , z ) + c(x+1, y , z ) + c(x , y , z+1) + c(x+1, y , z+1))); } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const TR ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TR ) { return 1.0 / (0.25*(c(x , y , z ) + c(x , y+1, z ) + c(x+1, y , z ) + c(x+1, y+1, z ))); } - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const TL ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TL ) { return 1.0 / c(x , y , z ); } template - GridValue cell_coeff( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c ) { return cell_coeff( x, y, z, c, N() ); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const BR ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BR ) { return 0.25 *( 1.0 / c(x , y , z ) + 1.0 / c(x , y+1, z ) + 1.0 / c(x , y , z+1) + 1.0 / c(x , y+1, z+1) ); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const BL ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BL ) { return 0.25 *( 1.0 / c(x , y , z ) + 1.0 / c(x+1, y , z ) + 1.0 / c(x , y , z+1) + 1.0 / c(x+1, y , z+1) ); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const TR ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TR ) { return 0.25 *( 1.0 / c(x , y , z ) + 1.0 / c(x , y+1, z ) + 1.0 / c(x+1, y , z ) + 1.0 / c(x+1, y+1, z ) ); } - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c, const TL ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TL ) { return 1.0 / c(x , y , z ); } template - GridValue cell_coeff_artm( const GridIndex x, const GridIndex y, const GridIndex z, Grid &c ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c ) { return cell_coeff_artm( x, y, z, c, N() ); } - GridValue stress_update( GridValue c1, GridValue c2, GridValue c3, - GridValue c4, GridValue c5, GridValue c6, - GridValue u_z, GridValue u_y, GridValue u_x, - GridValue v_z, GridValue v_y, GridValue v_x, - GridValue w_z, GridValue w_y, GridValue w_x ) + yc_number_node_ptr stress_update( yc_number_node_ptr c1, yc_number_node_ptr c2, yc_number_node_ptr c3, + yc_number_node_ptr c4, yc_number_node_ptr c5, yc_number_node_ptr c6, + yc_number_node_ptr u_z, yc_number_node_ptr u_y, yc_number_node_ptr u_x, + yc_number_node_ptr v_z, yc_number_node_ptr v_y, yc_number_node_ptr v_x, + yc_number_node_ptr w_z, yc_number_node_ptr w_y, yc_number_node_ptr w_x ) { return delta_t * c1 * u_x + delta_t * c2 * v_y @@ -202,69 +205,69 @@ namespace fsg { // appropriately. template - void define_str(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &sxx, Grid &syy, Grid &szz, Grid &sxy, Grid &sxz, Grid &syz, - Grid &vxu, Grid &vxv, Grid &vxw, Grid &vyu, Grid &vyv, Grid &vyw, Grid &vzu, Grid &vzv, Grid &vzw ) { + void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &sxx, yc_grid_var &syy, yc_grid_var &szz, yc_grid_var &sxy, yc_grid_var &sxz, yc_grid_var &syz, + yc_grid_var &vxu, yc_grid_var &vxv, yc_grid_var &vxw, yc_grid_var &vyu, yc_grid_var &vyv, yc_grid_var &vyw, yc_grid_var &vzu, yc_grid_var &vzv, yc_grid_var &vzw ) { // Interpolate coeffs. - GridValue ic11 = cell_coeff (x, y, z, c11); - GridValue ic12 = cell_coeff (x, y, z, c12); - GridValue ic13 = cell_coeff (x, y, z, c13); - GridValue ic14 = cell_coeff_artm(x, y, z, c14); - GridValue ic15 = cell_coeff_artm(x, y, z, c15); - GridValue ic16 = cell_coeff_artm(x, y, z, c16); - GridValue ic22 = cell_coeff (x, y, z, c22); - GridValue ic23 = cell_coeff (x, y, z, c23); - GridValue ic24 = cell_coeff_artm(x, y, z, c24); - GridValue ic25 = cell_coeff_artm(x, y, z, c25); - GridValue ic26 = cell_coeff_artm(x, y, z, c26); - GridValue ic33 = cell_coeff (x, y, z, c33); - GridValue ic34 = cell_coeff_artm(x, y, z, c34); - GridValue ic35 = cell_coeff_artm(x, y, z, c35); - GridValue ic36 = cell_coeff_artm(x, y, z, c36); - GridValue ic44 = cell_coeff (x, y, z, c44); - GridValue ic45 = cell_coeff_artm(x, y, z, c45); - GridValue ic46 = cell_coeff_artm(x, y, z, c46); - GridValue ic55 = cell_coeff (x, y, z, c55); - GridValue ic56 = cell_coeff_artm(x, y, z, c56); - GridValue ic66 = cell_coeff (x, y, z, c66); + yc_number_node_ptr ic11 = cell_coeff (x, y, z, c11); + yc_number_node_ptr ic12 = cell_coeff (x, y, z, c12); + yc_number_node_ptr ic13 = cell_coeff (x, y, z, c13); + yc_number_node_ptr ic14 = cell_coeff_artm(x, y, z, c14); + yc_number_node_ptr ic15 = cell_coeff_artm(x, y, z, c15); + yc_number_node_ptr ic16 = cell_coeff_artm(x, y, z, c16); + yc_number_node_ptr ic22 = cell_coeff (x, y, z, c22); + yc_number_node_ptr ic23 = cell_coeff (x, y, z, c23); + yc_number_node_ptr ic24 = cell_coeff_artm(x, y, z, c24); + yc_number_node_ptr ic25 = cell_coeff_artm(x, y, z, c25); + yc_number_node_ptr ic26 = cell_coeff_artm(x, y, z, c26); + yc_number_node_ptr ic33 = cell_coeff (x, y, z, c33); + yc_number_node_ptr ic34 = cell_coeff_artm(x, y, z, c34); + yc_number_node_ptr ic35 = cell_coeff_artm(x, y, z, c35); + yc_number_node_ptr ic36 = cell_coeff_artm(x, y, z, c36); + yc_number_node_ptr ic44 = cell_coeff (x, y, z, c44); + yc_number_node_ptr ic45 = cell_coeff_artm(x, y, z, c45); + yc_number_node_ptr ic46 = cell_coeff_artm(x, y, z, c46); + yc_number_node_ptr ic55 = cell_coeff (x, y, z, c55); + yc_number_node_ptr ic56 = cell_coeff_artm(x, y, z, c56); + yc_number_node_ptr ic66 = cell_coeff (x, y, z, c66); // Compute stencils. Note that we are using the velocity values at t+1. - GridValue u_z = stencil_O8( t+1, x, y, z, vzu ); - GridValue v_z = stencil_O8( t+1, x, y, z, vzv ); - GridValue w_z = stencil_O8( t+1, x, y, z, vzw ); + yc_number_node_ptr u_z = stencil_O8( t+1, x, y, z, vzu ); + yc_number_node_ptr v_z = stencil_O8( t+1, x, y, z, vzv ); + yc_number_node_ptr w_z = stencil_O8( t+1, x, y, z, vzw ); - GridValue u_x = stencil_O8( t+1, x, y, z, vxu ); - GridValue v_x = stencil_O8( t+1, x, y, z, vxv ); - GridValue w_x = stencil_O8( t+1, x, y, z, vxw ); + yc_number_node_ptr u_x = stencil_O8( t+1, x, y, z, vxu ); + yc_number_node_ptr v_x = stencil_O8( t+1, x, y, z, vxv ); + yc_number_node_ptr w_x = stencil_O8( t+1, x, y, z, vxw ); - GridValue u_y = stencil_O8( t+1, x, y, z, vyu ); - GridValue v_y = stencil_O8( t+1, x, y, z, vyv ); - GridValue w_y = stencil_O8( t+1, x, y, z, vyw ); + yc_number_node_ptr u_y = stencil_O8( t+1, x, y, z, vyu ); + yc_number_node_ptr v_y = stencil_O8( t+1, x, y, z, vyv ); + yc_number_node_ptr w_y = stencil_O8( t+1, x, y, z, vyw ); // Compute next stress value - GridValue next_sxx = sxx(t, x, y, z) + + yc_number_node_ptr next_sxx = sxx(t, x, y, z) + stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_syy = syy(t, x, y, z) + + yc_number_node_ptr next_syy = syy(t, x, y, z) + stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_szz = szz(t, x, y, z) + + yc_number_node_ptr next_szz = szz(t, x, y, z) + stress_update(ic13,ic23,ic33,ic34,ic35,ic36,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_syz = syz(t, x, y, z) + + yc_number_node_ptr next_syz = syz(t, x, y, z) + stress_update(ic14,ic24,ic34,ic44,ic45,ic46,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_sxz = sxz(t, x, y, z) + + yc_number_node_ptr next_sxz = sxz(t, x, y, z) + stress_update(ic15,ic25,ic35,ic45,ic55,ic56,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - GridValue next_sxy = sxy(t, x, y, z) + + yc_number_node_ptr next_sxy = sxy(t, x, y, z) + stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); // define the value at t+1. if ( hasBoundaryCondition() ) { - Condition not_at_bc = bc->is_not_at_boundary(); - sxx(t+1, x, y, z) EQUALS next_sxx IF not_at_bc; - syy(t+1, x, y, z) EQUALS next_syy IF not_at_bc; - szz(t+1, x, y, z) EQUALS next_szz IF not_at_bc; - syz(t+1, x, y, z) EQUALS next_syz IF not_at_bc; - sxz(t+1, x, y, z) EQUALS next_sxz IF not_at_bc; - sxy(t+1, x, y, z) EQUALS next_sxy IF not_at_bc; + yc_bool_node_ptr not_at_bc = bc->is_not_at_boundary(); + sxx(t+1, x, y, z) EQUALS next_sxx IF_DOMAIN not_at_bc; + syy(t+1, x, y, z) EQUALS next_syy IF_DOMAIN not_at_bc; + szz(t+1, x, y, z) EQUALS next_szz IF_DOMAIN not_at_bc; + syz(t+1, x, y, z) EQUALS next_syz IF_DOMAIN not_at_bc; + sxz(t+1, x, y, z) EQUALS next_sxz IF_DOMAIN not_at_bc; + sxy(t+1, x, y, z) EQUALS next_sxy IF_DOMAIN not_at_bc; } else { sxx(t+1, x, y, z) EQUALS next_sxx; syy(t+1, x, y, z) EQUALS next_syy; @@ -318,18 +321,18 @@ namespace fsg { const int abc_width = 20; // Sponge coefficients. - MAKE_GRID(sponge_lx, x, y, z); - MAKE_GRID(sponge_rx, x, y, z); - MAKE_GRID(sponge_bz, x, y, z); - MAKE_GRID(sponge_tz, x, y, z); - MAKE_GRID(sponge_fy, x, y, z); - MAKE_GRID(sponge_by, x, y, z); - MAKE_GRID(sponge_sq_lx, x, y, z); - MAKE_GRID(sponge_sq_rx, x, y, z); - MAKE_GRID(sponge_sq_bz, x, y, z); - MAKE_GRID(sponge_sq_tz, x, y, z); - MAKE_GRID(sponge_sq_fy, x, y, z); - MAKE_GRID(sponge_sq_by, x, y, z); + yc_grid_var sponge_lx = yc_grid_var("sponge_lx", get_solution(), { x, y, z }); + yc_grid_var sponge_rx = yc_grid_var("sponge_rx", get_solution(), { x, y, z }); + yc_grid_var sponge_bz = yc_grid_var("sponge_bz", get_solution(), { x, y, z }); + yc_grid_var sponge_tz = yc_grid_var("sponge_tz", get_solution(), { x, y, z }); + yc_grid_var sponge_fy = yc_grid_var("sponge_fy", get_solution(), { x, y, z }); + yc_grid_var sponge_by = yc_grid_var("sponge_by", get_solution(), { x, y, z }); + yc_grid_var sponge_sq_lx = yc_grid_var("sponge_sq_lx", get_solution(), { x, y, z }); + yc_grid_var sponge_sq_rx = yc_grid_var("sponge_sq_rx", get_solution(), { x, y, z }); + yc_grid_var sponge_sq_bz = yc_grid_var("sponge_sq_bz", get_solution(), { x, y, z }); + yc_grid_var sponge_sq_tz = yc_grid_var("sponge_sq_tz", get_solution(), { x, y, z }); + yc_grid_var sponge_sq_fy = yc_grid_var("sponge_sq_fy", get_solution(), { x, y, z }); + yc_grid_var sponge_sq_by = yc_grid_var("sponge_sq_by", get_solution(), { x, y, z }); FSGElasticStencilBase &fsg; @@ -340,42 +343,42 @@ namespace fsg { { } - Condition is_at_boundary() + yc_bool_node_ptr is_at_boundary() { - Condition bc = + yc_bool_node_ptr bc = ( z < first_index(z)+abc_width || z > last_index(z)-abc_width ) || ( y < first_index(y)+abc_width || y > last_index(y)-abc_width ) || ( x < first_index(x)+abc_width || x > last_index(x)-abc_width ); return bc; } - Condition is_not_at_boundary() + yc_bool_node_ptr is_not_at_boundary() { return !is_at_boundary(); } template - void define_vel_abc(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &v, Grid &sx, Grid &sy, Grid &sz, - Grid &abc_x, Grid &abc_y, Grid &abc_z, Grid &abc_sq_x, Grid &abc_sq_y, Grid &abc_sq_z) { + void define_vel_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &v, yc_grid_var &sx, yc_grid_var &sy, yc_grid_var &sz, + yc_grid_var &abc_x, yc_grid_var &abc_y, yc_grid_var &abc_z, yc_grid_var &abc_sq_x, yc_grid_var &abc_sq_y, yc_grid_var &abc_sq_z) { - Condition at_abc = is_at_boundary(); + yc_bool_node_ptr at_abc = is_at_boundary(); - GridValue next_v = v(t, x, y, z) * abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); + yc_number_node_ptr next_v = v(t, x, y, z) * abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); - GridValue lrho = fsg.interp_rho( x, y, z ); + yc_number_node_ptr lrho = fsg.interp_rho( x, y, z ); - GridValue stx = fsg.stencil_O2_X( t, x, y, z, sx ); - GridValue sty = fsg.stencil_O2_Y( t, x, y, z, sy ); - GridValue stz = fsg.stencil_O2_Z( t, x, y, z, sz ); + yc_number_node_ptr stx = fsg.stencil_O2_X( t, x, y, z, sx ); + yc_number_node_ptr sty = fsg.stencil_O2_Y( t, x, y, z, sy ); + yc_number_node_ptr stz = fsg.stencil_O2_Z( t, x, y, z, sz ); next_v += ((stx + sty + stz) * fsg.delta_t * lrho); next_v *= abc_sq_x(x,y,z) * abc_sq_y(x,y,z) * abc_sq_z(x,y,z); // define the value at t+1. - v(t+1, x, y, z) EQUALS next_v IF at_abc; + v(t+1, x, y, z) EQUALS next_v IF_DOMAIN at_abc; } - void velocity (GridIndex t, GridIndex x, GridIndex y, GridIndex z ) + void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { define_vel_abc(t, x, y, z, fsg.v_tl_w, fsg.s_tl_yz, fsg.s_tr_xz, fsg.s_bl_zz, sponge_lx, sponge_by, sponge_tz, sponge_sq_lx, sponge_sq_by, sponge_sq_tz); @@ -404,57 +407,57 @@ namespace fsg { } template - void define_str_abc(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &sxx, Grid &syy, Grid &szz, Grid &sxy, Grid &sxz, Grid &syz, - Grid &vxu, Grid &vxv, Grid &vxw, Grid &vyu, Grid &vyv, Grid &vyw, Grid &vzu, Grid &vzv, Grid &vzw, - Grid &abc_x, Grid &abc_y, Grid &abc_z, Grid &abc_sq_x, Grid &abc_sq_y, Grid &abc_sq_z) { - - GridValue abc = abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); - GridValue next_sxx = sxx(t, x, y, z) * abc; - GridValue next_syy = syy(t, x, y, z) * abc; - GridValue next_szz = szz(t, x, y, z) * abc; - GridValue next_syz = syz(t, x, y, z) * abc; - GridValue next_sxz = sxz(t, x, y, z) * abc; - GridValue next_sxy = sxy(t, x, y, z) * abc; + void define_str_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &sxx, yc_grid_var &syy, yc_grid_var &szz, yc_grid_var &sxy, yc_grid_var &sxz, yc_grid_var &syz, + yc_grid_var &vxu, yc_grid_var &vxv, yc_grid_var &vxw, yc_grid_var &vyu, yc_grid_var &vyv, yc_grid_var &vyw, yc_grid_var &vzu, yc_grid_var &vzv, yc_grid_var &vzw, + yc_grid_var &abc_x, yc_grid_var &abc_y, yc_grid_var &abc_z, yc_grid_var &abc_sq_x, yc_grid_var &abc_sq_y, yc_grid_var &abc_sq_z) { + + yc_number_node_ptr abc = abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); + yc_number_node_ptr next_sxx = sxx(t, x, y, z) * abc; + yc_number_node_ptr next_syy = syy(t, x, y, z) * abc; + yc_number_node_ptr next_szz = szz(t, x, y, z) * abc; + yc_number_node_ptr next_syz = syz(t, x, y, z) * abc; + yc_number_node_ptr next_sxz = sxz(t, x, y, z) * abc; + yc_number_node_ptr next_sxy = sxy(t, x, y, z) * abc; // Interpolate coeffs. - GridValue ic11 = fsg.cell_coeff (x, y, z, fsg.c11); - GridValue ic12 = fsg.cell_coeff (x, y, z, fsg.c12); - GridValue ic13 = fsg.cell_coeff (x, y, z, fsg.c13); - GridValue ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c14); - GridValue ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c15); - GridValue ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c16); - GridValue ic22 = fsg.cell_coeff (x, y, z, fsg.c22); - GridValue ic23 = fsg.cell_coeff (x, y, z, fsg.c23); - GridValue ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c24); - GridValue ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c25); - GridValue ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c26); - GridValue ic33 = fsg.cell_coeff (x, y, z, fsg.c33); - GridValue ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c34); - GridValue ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c35); - GridValue ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c36); - GridValue ic44 = fsg.cell_coeff (x, y, z, fsg.c44); - GridValue ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c45); - GridValue ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c46); - GridValue ic55 = fsg.cell_coeff (x, y, z, fsg.c55); - GridValue ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c56); - GridValue ic66 = fsg.cell_coeff (x, y, z, fsg.c66); + yc_number_node_ptr ic11 = fsg.cell_coeff (x, y, z, fsg.c11); + yc_number_node_ptr ic12 = fsg.cell_coeff (x, y, z, fsg.c12); + yc_number_node_ptr ic13 = fsg.cell_coeff (x, y, z, fsg.c13); + yc_number_node_ptr ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c14); + yc_number_node_ptr ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c15); + yc_number_node_ptr ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c16); + yc_number_node_ptr ic22 = fsg.cell_coeff (x, y, z, fsg.c22); + yc_number_node_ptr ic23 = fsg.cell_coeff (x, y, z, fsg.c23); + yc_number_node_ptr ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c24); + yc_number_node_ptr ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c25); + yc_number_node_ptr ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c26); + yc_number_node_ptr ic33 = fsg.cell_coeff (x, y, z, fsg.c33); + yc_number_node_ptr ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c34); + yc_number_node_ptr ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c35); + yc_number_node_ptr ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c36); + yc_number_node_ptr ic44 = fsg.cell_coeff (x, y, z, fsg.c44); + yc_number_node_ptr ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c45); + yc_number_node_ptr ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c46); + yc_number_node_ptr ic55 = fsg.cell_coeff (x, y, z, fsg.c55); + yc_number_node_ptr ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c56); + yc_number_node_ptr ic66 = fsg.cell_coeff (x, y, z, fsg.c66); // Compute stencils. Note that we are using the velocity values at t+1. - GridValue u_z = fsg.stencil_O2_Z( t+1, x, y, z, vzu ); - GridValue v_z = fsg.stencil_O2_Z( t+1, x, y, z, vzv ); - GridValue w_z = fsg.stencil_O2_Z( t+1, x, y, z, vzw ); + yc_number_node_ptr u_z = fsg.stencil_O2_Z( t+1, x, y, z, vzu ); + yc_number_node_ptr v_z = fsg.stencil_O2_Z( t+1, x, y, z, vzv ); + yc_number_node_ptr w_z = fsg.stencil_O2_Z( t+1, x, y, z, vzw ); - GridValue u_x = fsg.stencil_O2_X( t+1, x, y, z, vxu ); - GridValue v_x = fsg.stencil_O2_X( t+1, x, y, z, vxv ); - GridValue w_x = fsg.stencil_O2_X( t+1, x, y, z, vxw ); + yc_number_node_ptr u_x = fsg.stencil_O2_X( t+1, x, y, z, vxu ); + yc_number_node_ptr v_x = fsg.stencil_O2_X( t+1, x, y, z, vxv ); + yc_number_node_ptr w_x = fsg.stencil_O2_X( t+1, x, y, z, vxw ); - GridValue u_y = fsg.stencil_O2_Y( t+1, x, y, z, vyu ); - GridValue v_y = fsg.stencil_O2_Y( t+1, x, y, z, vyv ); - GridValue w_y = fsg.stencil_O2_Y( t+1, x, y, z, vyw ); + yc_number_node_ptr u_y = fsg.stencil_O2_Y( t+1, x, y, z, vyu ); + yc_number_node_ptr v_y = fsg.stencil_O2_Y( t+1, x, y, z, vyv ); + yc_number_node_ptr w_y = fsg.stencil_O2_Y( t+1, x, y, z, vyw ); // Compute next stress value - GridValue abc_sq = abc_sq_x(x,y,z) * abc_sq_y(x,y,z) * abc_sq_z(x,y,z); + yc_number_node_ptr abc_sq = abc_sq_x(x,y,z) * abc_sq_y(x,y,z) * abc_sq_z(x,y,z); next_sxx += fsg.stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; next_syy += fsg.stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; next_szz += fsg.stress_update(ic13,ic23,ic33,ic34,ic35,ic36,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; @@ -463,16 +466,16 @@ namespace fsg { next_sxy += fsg.stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; // define the value at t+1. - Condition at_abc = is_at_boundary(); - sxx(t+1, x, y, z) EQUALS next_sxx IF at_abc; - syy(t+1, x, y, z) EQUALS next_syy IF at_abc; - szz(t+1, x, y, z) EQUALS next_szz IF at_abc; - syz(t+1, x, y, z) EQUALS next_syz IF at_abc; - sxz(t+1, x, y, z) EQUALS next_sxz IF at_abc; - sxy(t+1, x, y, z) EQUALS next_sxy IF at_abc; + yc_bool_node_ptr at_abc = is_at_boundary(); + sxx(t+1, x, y, z) EQUALS next_sxx IF_DOMAIN at_abc; + syy(t+1, x, y, z) EQUALS next_syy IF_DOMAIN at_abc; + szz(t+1, x, y, z) EQUALS next_szz IF_DOMAIN at_abc; + syz(t+1, x, y, z) EQUALS next_syz IF_DOMAIN at_abc; + sxz(t+1, x, y, z) EQUALS next_sxz IF_DOMAIN at_abc; + sxy(t+1, x, y, z) EQUALS next_sxy IF_DOMAIN at_abc; } - void stress (GridIndex t, GridIndex x, GridIndex y, GridIndex z ) + void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { define_str_abc(t, x, y, z, fsg.s_br_xx, fsg.s_br_yy, fsg.s_br_zz, fsg.s_br_xy, fsg.s_br_xz, fsg.s_br_yz, fsg.v_br_u, fsg.v_br_v, fsg.v_br_w, fsg.v_bl_u, @@ -495,19 +498,25 @@ namespace fsg { }; struct FSGElasticStencil : public FSGElasticStencilBase { - FSGElasticStencil(StencilList& stencils) : - FSGElasticStencilBase("fsg", stencils) { } + FSGElasticStencil() : + FSGElasticStencilBase("fsg") { } }; struct FSGABCElasticStencil : public FSGElasticStencilBase { - FSG_ABC abc; // Absorbing Boundary Condition + FSG_ABC abc; // Absorbing Boundary yc_bool_node_ptr - FSGABCElasticStencil(StencilList& stencils) : - FSGElasticStencilBase("fsg_abc", stencils, &abc), + FSGABCElasticStencil() : + FSGElasticStencilBase("fsg_abc", &abc), abc(*this) { } }; - REGISTER_STENCIL(FSGElasticStencil); - REGISTER_STENCIL(FSGABCElasticStencil); +// Create an object of type 'FSGElasticStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static FSGElasticStencil FSGElasticStencil_instance; +// Create an object of type 'FSGABCElasticStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static FSGABCElasticStencil FSGABCElasticStencil_instance; } diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 38ef0746..a0d0693f 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -27,21 +27,26 @@ IN THE SOFTWARE. // space (where n = 2 * radius) and 2nd-order accurate in time. // See https://software.intel.com/en-us/articles/eight-optimizations-for-3-dimensional-finite-difference-3dfd-code-with-an-isotropic-iso. -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; -class Iso3dfdStencil : public StencilRadiusBase { +class Iso3dfdStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. - // Grids. - MAKE_GRID(pressure, t, x, y, z); // time-varying 3D pressure grid. - MAKE_GRID(vel, x, y, z); // constant 3D vel grid (c(x,y,z)^2 * delta_t^2). + // Grid vars. + yc_grid_var pressure = + yc_grid_var("pressure", get_solution(), { t, x, y, z }); // time-varying 3D pressure grid. + yc_grid_var vel = + yc_grid_var("vel", get_solution(), { x, y, z }); // constant 3D vel grid (c(x,y,z)^2 * delta_t^2). public: @@ -49,14 +54,14 @@ class Iso3dfdStencil : public StencilRadiusBase { // either side of center in each spatial dimension. For example, // radius=8 implements a 16th-order accurate FD stencil. // The accuracy in time is fixed at 2nd order. - Iso3dfdStencil(StencilList& stencils, string suffix="", int radius=8) : - StencilRadiusBase("iso3dfd" + suffix, stencils, radius) { } + Iso3dfdStencil(string suffix="", int radius=8) : + yc_solution_with_radius_base("iso3dfd" + suffix, radius) { } virtual ~Iso3dfdStencil() { } // Define RHS expression for pressure at t+1 based on values from vel and pressure at t. - virtual GridValue get_next_p() { + virtual yc_number_node_ptr get_next_p() { - // Grid spacing. + // yc_grid_var spacing. // In this implementation, it's a constant. // Could make this a YASK variable to allow setting at run-time. double delta_xyz = 50.0; @@ -78,7 +83,7 @@ class Iso3dfdStencil : public StencilRadiusBase { // Calculate FDx + FDy + FDz. // Start with center value multiplied by coeff 0. - GridValue fd_sum = pressure(t, x, y, z) * coeff[c0i]; + yc_number_node_ptr fd_sum = pressure(t, x, y, z) * coeff[c0i]; // Add values from x, y, and z axes multiplied by the // coeff for the given radius. @@ -122,7 +127,7 @@ class Iso3dfdStencil : public StencilRadiusBase { // p(t+1) = 2 * p(t) - p(t-1) + c^2 * fd_sum * delta_t^2. // Let vel = c^2 * delta_t^2 for each grid point. - GridValue next_p = (2.0 * pressure(t, x, y, z)) - + yc_number_node_ptr next_p = (2.0 * pressure(t, x, y, z)) - pressure(t-1, x, y, z) + (fd_sum * vel(x, y, z)); return next_p; @@ -132,7 +137,7 @@ class Iso3dfdStencil : public StencilRadiusBase { virtual void define() { // Get equation for RHS. - GridValue next_p = get_next_p(); + yc_number_node_ptr next_p = get_next_p(); // Define the value at t+1 to be equal to next_p. // Since this implements the finite-difference method, this @@ -141,7 +146,10 @@ class Iso3dfdStencil : public StencilRadiusBase { } }; -REGISTER_STENCIL(Iso3dfdStencil); +// Create an object of type 'Iso3dfdStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static Iso3dfdStencil Iso3dfdStencil_instance; // Add a sponge absorption factor. class Iso3dfdSpongeStencil : public Iso3dfdStencil { @@ -151,20 +159,20 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { // In practice, the interior values would be set to 1.0, // and values nearer the boundary would be set to values // increasingly approaching 0.0. - MAKE_ARRAY(cr_x, x); - MAKE_ARRAY(cr_y, y); - MAKE_ARRAY(cr_z, z); + yc_grid_var cr_x = yc_grid_var("cr_x", get_solution(), { x }); + yc_grid_var cr_y = yc_grid_var("cr_y", get_solution(), { y }); + yc_grid_var cr_z = yc_grid_var("cr_z", get_solution(), { z }); public: - Iso3dfdSpongeStencil(StencilList& stencils, int radius=8) : - Iso3dfdStencil(stencils, "_sponge", radius) { } + Iso3dfdSpongeStencil(int radius=8) : + Iso3dfdStencil("_sponge", radius) { } virtual ~Iso3dfdSpongeStencil() { } // Define equation for pressure at t+1 based on values from vel and pressure at t. virtual void define() { // Get equation for RHS. - GridValue next_p = get_next_p(); + yc_number_node_ptr next_p = get_next_p(); // Apply sponge absorption. next_p *= cr_x(x) * cr_y(y) * cr_z(z); @@ -174,4 +182,7 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { } }; -REGISTER_STENCIL(Iso3dfdSpongeStencil); +// Create an object of type 'Iso3dfdSpongeStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static Iso3dfdSpongeStencil Iso3dfdSpongeStencil_instance; diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index fa9a1a41..a56559a8 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -35,21 +35,21 @@ class SSGElastic2Stencil : public Elastic2StencilBase { protected: // Time-varying 3D-spatial velocity grids. - MAKE_GRID(v, t, x, y, z, vidx); + yc_grid_var v = yc_grid_var("v", get_solution(), { t, x, y, z, vidx }); enum VIDX { V_BL_W, V_TL_V, V_TR_U }; // Time-varying 3D-spatial Stress grids. - MAKE_GRID(s, t, x, y, z, sidx); + yc_grid_var s = yc_grid_var("s", get_solution(), { t, x, y, z, sidx }); enum SIDX { S_BL_YZ, S_BR_XZ, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TR_XY }; public: - SSGElastic2Stencil( StencilList& stencils) : - Elastic2StencilBase("ssg2", stencils) + SSGElastic2Stencil( ) : + Elastic2StencilBase("ssg2") { } - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z, const BR) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BR) { return ( 2.0/ (coef(x , y , z , C_MU) + coef(x , y+1, z , C_MU) + @@ -57,7 +57,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { coef(x , y+1, z+1, C_MU)) ); } - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z, const BL) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BL) { return ( 2.0/ (coef(x , y , z , C_MU) + coef(x+1, y , z , C_MU) + @@ -65,7 +65,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { coef(x+1, y , z+1, C_MU)) ); } - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z, const TR) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TR) { return ( 2.0/ (coef(x , y , z , C_MU) + coef(x+1, y , z , C_MU) + @@ -74,7 +74,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { } template - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return interp_mu( x, y, z, N() ); } @@ -89,43 +89,43 @@ class SSGElastic2Stencil : public Elastic2StencilBase { // appropriately. template - void define_str(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - GridIndex sidx, GridIndex va_idx, GridIndex vb_idx) { + void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr sidx, yc_number_node_ptr va_idx, yc_number_node_ptr vb_idx) { - GridValue lcoeff = interp_mu( x, y, z ); + yc_number_node_ptr lcoeff = interp_mu( x, y, z ); - GridValue vta = stencil_O8( t+1, x, y, z, v, va_idx ); - GridValue vtb = stencil_O8( t+1, x, y, z, v, vb_idx ); + yc_number_node_ptr vta = stencil_O8( t+1, x, y, z, v, va_idx ); + yc_number_node_ptr vtb = stencil_O8( t+1, x, y, z, v, vb_idx ); - GridValue next_s = s(t, x, y, z, sidx) + ((vta + vtb) * lcoeff) * delta_t; + yc_number_node_ptr next_s = s(t, x, y, z, sidx) + ((vta + vtb) * lcoeff) * delta_t; // define the value at t+1. s(t+1, x, y, z, sidx) EQUALS next_s; } template - void define_str(GridIndex t, GridIndex x, GridIndex y, GridIndex z, + void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, int sidx, int va_idx, int vb_idx) { define_str(t, x, y, z, - constNum(sidx), constNum(va_idx), constNum(vb_idx)); + _node_factory.new_number_node(sidx), _node_factory.new_number_node(va_idx), _node_factory.new_number_node(vb_idx)); } - void define_str_TL(GridIndex t, GridIndex x, GridIndex y, GridIndex z ) + void define_str_TL(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { - GridValue ilambdamu2 = 1.0 / coef(x,y,z, C_LAMBDA_MU2); - GridValue ilambda = 1.0 / coef(x,y,z, C_LAMBDA); + yc_number_node_ptr ilambdamu2 = 1.0 / coef(x,y,z, C_LAMBDA_MU2); + yc_number_node_ptr ilambda = 1.0 / coef(x,y,z, C_LAMBDA); - GridValue vtx = stencil_O8( t+1, x, y, z, v, constNum(V_TR_U) ); - GridValue vty = stencil_O8( t+1, x, y, z, v, constNum(V_TL_V) ); - GridValue vtz = stencil_O8( t+1, x, y, z, v, constNum(V_BL_W) ); + yc_number_node_ptr vtx = stencil_O8( t+1, x, y, z, v, _node_factory.new_number_node(V_TR_U) ); + yc_number_node_ptr vty = stencil_O8( t+1, x, y, z, v, _node_factory.new_number_node(V_TL_V) ); + yc_number_node_ptr vtz = stencil_O8( t+1, x, y, z, v, _node_factory.new_number_node(V_BL_W) ); - GridValue next_xx = s(t, x, y, z, S_TL_XX) + ilambdamu2 * vtx * delta_t + yc_number_node_ptr next_xx = s(t, x, y, z, S_TL_XX) + ilambdamu2 * vtx * delta_t + ilambda * vty * delta_t + ilambda * vtz * delta_t; - GridValue next_yy = s(t, x, y, z, S_TL_YY) + ilambda * vtx * delta_t + yc_number_node_ptr next_yy = s(t, x, y, z, S_TL_YY) + ilambda * vtx * delta_t + ilambdamu2 * vty * delta_t + ilambda * vtz * delta_t; - GridValue next_zz = s(t, x, y, z, S_TL_ZZ) + ilambda * vtx * delta_t + yc_number_node_ptr next_zz = s(t, x, y, z, S_TL_ZZ) + ilambda * vtx * delta_t + ilambda * vty * delta_t + ilambdamu2 * vtz * delta_t; @@ -152,4 +152,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { } }; -REGISTER_STENCIL(SSGElastic2Stencil); +// Create an object of type 'SSGElastic2Stencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static SSGElastic2Stencil SSGElastic2Stencil_instance; diff --git a/src/stencils/SSGElasticStencil.cpp b/src/stencils/SSGElasticStencil.cpp index cc3709a9..3ccd83d8 100644 --- a/src/stencils/SSGElasticStencil.cpp +++ b/src/stencils/SSGElasticStencil.cpp @@ -33,31 +33,31 @@ class SSGElasticStencil : public ElasticStencilBase { protected: // Time-varying 3D-spatial velocity grids. - MAKE_GRID(v_bl_w, t, x, y, z); - MAKE_GRID(v_tl_v, t, x, y, z); - MAKE_GRID(v_tr_u, t, x, y, z); + yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_solution(), { t, x, y, z }); + yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_solution(), { t, x, y, z }); + yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_solution(), { t, x, y, z }); // Time-varying 3D-spatial Stress grids. - MAKE_GRID(s_bl_yz, t, x, y, z); - MAKE_GRID(s_br_xz, t, x, y, z); - MAKE_GRID(s_tl_xx, t, x, y, z); - MAKE_GRID(s_tl_yy, t, x, y, z); - MAKE_GRID(s_tl_zz, t, x, y, z); - MAKE_GRID(s_tr_xy, t, x, y, z); + yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_solution(), { t, x, y, z }); + yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_solution(), { t, x, y, z }); + yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_solution(), { t, x, y, z }); + yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_solution(), { t, x, y, z }); // 3D-spatial coefficients. - MAKE_GRID(mu, x, y, z); - MAKE_GRID(lambda, x, y, z); - MAKE_GRID(lambdamu2, x, y, z); + yc_grid_var mu = yc_grid_var("mu", get_solution(), { x, y, z }); + yc_grid_var lambda = yc_grid_var("lambda", get_solution(), { x, y, z }); + yc_grid_var lambdamu2 = yc_grid_var("lambdamu2", get_solution(), { x, y, z }); public: - SSGElasticStencil( StencilList& stencils) : - ElasticStencilBase("ssg", stencils) + SSGElasticStencil( ) : + ElasticStencilBase("ssg") { } - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z, const BR ) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BR ) { return ( 2.0/ (mu(x , y , z ) + mu(x , y+1, z ) + @@ -65,7 +65,7 @@ class SSGElasticStencil : public ElasticStencilBase { mu(x , y+1, z+1)) ); } - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z, const BL ) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BL ) { return ( 2.0/ (mu(x , y , z ) + mu(x+1, y , z ) + @@ -73,7 +73,7 @@ class SSGElasticStencil : public ElasticStencilBase { mu(x+1, y , z+1)) ); } - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z, const TR ) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TR ) { return ( 2.0/ (mu(x , y , z ) + mu(x+1, y , z ) + @@ -82,7 +82,7 @@ class SSGElasticStencil : public ElasticStencilBase { } template - GridValue interp_mu( GridIndex x, GridIndex y, GridIndex z ) + yc_number_node_ptr interp_mu( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { return interp_mu( x, y, z, N() ); } @@ -97,37 +97,37 @@ class SSGElasticStencil : public ElasticStencilBase { // appropriately. template - void define_str(GridIndex t, GridIndex x, GridIndex y, GridIndex z, - Grid &s, Grid &va, Grid &vb) { + void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_grid_var &s, yc_grid_var &va, yc_grid_var &vb) { - GridValue lcoeff = interp_mu( x, y, z ); + yc_number_node_ptr lcoeff = interp_mu( x, y, z ); - GridValue vta = stencil_O8( t+1, x, y, z, va ); - GridValue vtb = stencil_O8( t+1, x, y, z, vb ); + yc_number_node_ptr vta = stencil_O8( t+1, x, y, z, va ); + yc_number_node_ptr vtb = stencil_O8( t+1, x, y, z, vb ); - GridValue next_s = s(t, x, y, z) + ((vta + vtb) * lcoeff) * delta_t; + yc_number_node_ptr next_s = s(t, x, y, z) + ((vta + vtb) * lcoeff) * delta_t; // define the value at t+1. s(t+1, x, y, z) EQUALS next_s; } - void define_str_TL(GridIndex t, GridIndex x, GridIndex y, GridIndex z ) + void define_str_TL(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { - GridValue ilambdamu2 = 1.0 / lambdamu2(x,y,z); - GridValue ilambda = 1.0 / lambda (x,y,z); + yc_number_node_ptr ilambdamu2 = 1.0 / lambdamu2(x,y,z); + yc_number_node_ptr ilambda = 1.0 / lambda (x,y,z); - GridValue vtx = stencil_O8( t+1, x, y, z, v_tr_u ); - GridValue vty = stencil_O8( t+1, x, y, z, v_tl_v ); - GridValue vtz = stencil_O8( t+1, x, y, z, v_bl_w ); + yc_number_node_ptr vtx = stencil_O8( t+1, x, y, z, v_tr_u ); + yc_number_node_ptr vty = stencil_O8( t+1, x, y, z, v_tl_v ); + yc_number_node_ptr vtz = stencil_O8( t+1, x, y, z, v_bl_w ); - GridValue next_xx = s_tl_xx(t, x, y, z) + ilambdamu2 * vtx * delta_t + yc_number_node_ptr next_xx = s_tl_xx(t, x, y, z) + ilambdamu2 * vtx * delta_t + ilambda * vty * delta_t + ilambda * vtz * delta_t; - GridValue next_yy = s_tl_yy(t, x, y, z) + ilambda * vtx * delta_t + yc_number_node_ptr next_yy = s_tl_yy(t, x, y, z) + ilambda * vtx * delta_t + ilambdamu2 * vty * delta_t + ilambda * vtz * delta_t; - GridValue next_zz = s_tl_zz(t, x, y, z) + ilambda * vtx * delta_t + yc_number_node_ptr next_zz = s_tl_zz(t, x, y, z) + ilambda * vtx * delta_t + ilambda * vty * delta_t + ilambdamu2 * vtz * delta_t; @@ -154,4 +154,7 @@ class SSGElasticStencil : public ElasticStencilBase { } }; -REGISTER_STENCIL(SSGElasticStencil); +// Create an object of type 'SSGElasticStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static SSGElasticStencil SSGElasticStencil_instance; diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/SimpleTestStencils.cpp index c3bd9887..064f101e 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/SimpleTestStencils.cpp @@ -23,33 +23,34 @@ IN THE SOFTWARE. *****************************************************************************/ -// Some very simple tests. +// Tests for various YASK DSL features. -#include "Soln.hpp" - -// Simple tests for various YASK DSL features. +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; // A base class for stencil tests. -class TestBase : public StencilRadiusBase { +class TestBase : public yc_solution_with_radius_base { protected: // Indices & dimensions. // Not all these will be used in all tests. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(w); // spatial dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr w = _node_factory.new_domain_index("w"); // spatial dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. // Define some stencils in different dimensions. // These will be asymmetrical if any of the '*_ext' params are not 0; // Define simple stencil from var 'V' at 't0' centered around 'x0'. // Extend given radius left and/or right w/'*_ext'. - virtual GridValue def_1d(Grid& V, const GridIndex& t0, const GridIndex& x0, + virtual yc_number_node_ptr def_1d(yc_grid_var& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, int left_ext, int right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 1; for (int i = -_radius - left_ext; i <= _radius + right_ext; i++, n++) v += V(t0, x0+i); @@ -58,9 +59,9 @@ class TestBase : public StencilRadiusBase { // Define simple stencil from scratch or read-only var 'V' centered // around 'x0'. Similar to 'def_1d()', but doesn't use step var. - virtual GridValue def_no_t_1d(Grid& V, const GridIndex& x0, + virtual yc_number_node_ptr def_no_t_1d(yc_grid_var& V, const yc_number_node_ptr& x0, int left_ext, int right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 1; for (int i = -_radius - left_ext; i <= _radius + right_ext; i++, n++) v += V(x0+i); @@ -70,12 +71,12 @@ class TestBase : public StencilRadiusBase { // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0'. // Extend given radius left and/or right w/'*_ext'. // Use some points from the entire rectangle, not just on the axes. - virtual GridValue def_2d(Grid& V, const GridIndex& t0, - const GridIndex& x0, + virtual yc_number_node_ptr def_2d(yc_grid_var& V, const yc_number_node_ptr& t0, + const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, - const GridIndex& y0, + const yc_number_node_ptr& y0, int y_left_ext, int y_right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 0; for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++, n++) @@ -87,12 +88,12 @@ class TestBase : public StencilRadiusBase { // Define simple stencil from scratch or read-only var 'V' at 't0' // centered around 'x0', 'y0'. Extend given radius left and/or right // w/'*_ext'. - virtual GridValue def_no_t_2d(Grid& V, - const GridIndex& x0, + virtual yc_number_node_ptr def_no_t_2d(yc_grid_var& V, + const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, - const GridIndex& y0, + const yc_number_node_ptr& y0, int y_left_ext, int y_right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 0; for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++, n++) @@ -104,14 +105,14 @@ class TestBase : public StencilRadiusBase { // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0', 'z0'. // Extend given radius left and/or right w/'*_ext'. // Use some points from the entire rectangular polytope, not just on the axes. - virtual GridValue def_3d(Grid& V, const GridIndex& t0, - const GridIndex& x0, + virtual yc_number_node_ptr def_3d(yc_grid_var& V, const yc_number_node_ptr& t0, + const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, - const GridIndex& y0, + const yc_number_node_ptr& y0, int y_left_ext, int y_right_ext, - const GridIndex& z0, + const yc_number_node_ptr& z0, int z_left_ext, int z_right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 0; for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++) @@ -124,14 +125,14 @@ class TestBase : public StencilRadiusBase { // Define simple stencil from scratch or read-only var 'V' centered // around 'x0', 'y0', 'z0'. Extend given radius left and/or right // w/'*_ext'. - virtual GridValue def_no_t_3d(Grid& V, - const GridIndex& x0, + virtual yc_number_node_ptr def_no_t_3d(yc_grid_var& V, + const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, - const GridIndex& y0, + const yc_number_node_ptr& y0, int y_left_ext, int y_right_ext, - const GridIndex& z0, + const yc_number_node_ptr& z0, int z_left_ext, int z_right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 0; for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++) @@ -144,16 +145,16 @@ class TestBase : public StencilRadiusBase { // Define simple stencil from var 'V' at 't0' centered around 'w0', 'x0', 'y0', 'z0'. // Extend given radius left and/or right w/'*_ext'. // Use some points from the entire rectangular polytope, not just on the axes. - virtual GridValue def_4d(Grid& V, const GridIndex& t0, - const GridIndex& w0, + virtual yc_number_node_ptr def_4d(yc_grid_var& V, const yc_number_node_ptr& t0, + const yc_number_node_ptr& w0, int w_left_ext, int w_right_ext, - const GridIndex& x0, + const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, - const GridIndex& y0, + const yc_number_node_ptr& y0, int y_left_ext, int y_right_ext, - const GridIndex& z0, + const yc_number_node_ptr& z0, int z_left_ext, int z_right_ext) { - GridValue v; + yc_number_node_ptr v; int n = 0; for (int h : { -_radius - w_left_ext, 0, _radius + w_right_ext }) for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) @@ -168,8 +169,8 @@ class TestBase : public StencilRadiusBase { public: - TestBase(const string& name, StencilList& stencils, int radius) : - StencilRadiusBase(name, stencils, radius) { } + TestBase(const string& name, int radius) : + yc_solution_with_radius_base(name, radius) { } }; // Simple 1D test. @@ -178,12 +179,12 @@ class Test1dStencil : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. public: - Test1dStencil(StencilList& stencils, int radius=2) : - TestBase("test_1d", stencils, radius) { } + Test1dStencil(int radius=2) : + TestBase("test_1d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -193,7 +194,10 @@ class Test1dStencil : public TestBase { } }; -REGISTER_STENCIL(Test1dStencil); +// Create an object of type 'Test1dStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static Test1dStencil Test1dStencil_instance; // Simple 2D test. class Test2dStencil : public TestBase { @@ -201,12 +205,12 @@ class Test2dStencil : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. public: - Test2dStencil(StencilList& stencils, int radius=2) : - TestBase("test_2d", stencils, radius) { } + Test2dStencil(int radius=2) : + TestBase("test_2d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -216,7 +220,10 @@ class Test2dStencil : public TestBase { } }; -REGISTER_STENCIL(Test2dStencil); +// Create an object of type 'Test2dStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static Test2dStencil Test2dStencil_instance; // Simple 3D test. class Test3dStencil : public TestBase { @@ -224,12 +231,12 @@ class Test3dStencil : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. public: - Test3dStencil(StencilList& stencils, int radius=2) : - TestBase("test_3d", stencils, radius) { } + Test3dStencil(int radius=2) : + TestBase("test_3d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -239,7 +246,10 @@ class Test3dStencil : public TestBase { } }; -REGISTER_STENCIL(Test3dStencil); +// Create an object of type 'Test3dStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static Test3dStencil Test3dStencil_instance; // Simple 4D test. class Test4dStencil : public TestBase { @@ -247,12 +257,12 @@ class Test4dStencil : public TestBase { protected: // Vars. - MAKE_GRID(A, t, w, x, y, z); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, w, x, y, z }); // time-varying grid. public: - Test4dStencil(StencilList& stencils, int radius=1) : - TestBase("test_4d", stencils, radius) { } + Test4dStencil(int radius=1) : + TestBase("test_4d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -262,7 +272,10 @@ class Test4dStencil : public TestBase { } }; -REGISTER_STENCIL(Test4dStencil); +// Create an object of type 'Test4dStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static Test4dStencil Test4dStencil_instance; // Test vars that don't cover all domain dims. class TestPartialStencil3 : public TestBase { @@ -270,20 +283,20 @@ class TestPartialStencil3 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying grid. - MAKE_GRID(B, x); - MAKE_GRID(C, y); - MAKE_GRID(D, z); - MAKE_GRID(E, x, y); - MAKE_GRID(F, y, z); - MAKE_GRID(G, z, y); - MAKE_GRID(H, y, z, x); // different order. - MAKE_SCALAR(I); + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_solution(), { x }); + yc_grid_var C = yc_grid_var("C", get_solution(), { y }); + yc_grid_var D = yc_grid_var("D", get_solution(), { z }); + yc_grid_var E = yc_grid_var("E", get_solution(), { x, y }); + yc_grid_var F = yc_grid_var("F", get_solution(), { y, z }); + yc_grid_var G = yc_grid_var("G", get_solution(), { z, y }); + yc_grid_var H = yc_grid_var("H", get_solution(), { y, z, x }); // different order. + yc_grid_var I = yc_grid_var("I", get_solution(), { }); public: - TestPartialStencil3(StencilList& stencils, int radius=2) : - TestBase("test_partial_3d", stencils, radius) { } + TestPartialStencil3(int radius=2) : + TestBase("test_partial_3d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -301,36 +314,39 @@ class TestPartialStencil3 : public TestBase { } }; -REGISTER_STENCIL(TestPartialStencil3); +// Create an object of type 'TestPartialStencil3', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestPartialStencil3 TestPartialStencil3_instance; // Test misc indices. -class TestMisc2dStencil : public StencilRadiusBase { +class TestMisc2dStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_MISC_INDEX(a); - MAKE_MISC_INDEX(b); - MAKE_MISC_INDEX(c); + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr a = _node_factory.new_misc_index("a"); + yc_index_node_ptr b = _node_factory.new_misc_index("b"); + yc_index_node_ptr c = _node_factory.new_misc_index("c"); // Time-varying grid. Intermix last domain dim with misc dims to make // sure compiler creates correct layout. - MAKE_GRID(A, t, x, a, y, b, c); + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, a, y, b, c }); public: - TestMisc2dStencil(StencilList& stencils, int radius=2) : - StencilRadiusBase("test_misc_2d", stencils, radius) { } + TestMisc2dStencil(int radius=2) : + yc_solution_with_radius_base("test_misc_2d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { // Define the value at t+1 using asymmetric stencil // with various pos & neg indices in misc dims. - GridValue v = A(t, x, 0, y, -1, 2) + 1.0; + yc_number_node_ptr v = A(t, x, 0, y, -1, 2) + 1.0; for (int r = 1; r <= _radius; r++) v += A(t, x + r, 3, y, 0, 1); for (int r = 1; r <= _radius + 1; r++) @@ -343,7 +359,10 @@ class TestMisc2dStencil : public StencilRadiusBase { } }; -REGISTER_STENCIL(TestMisc2dStencil); +// Create an object of type 'TestMisc2dStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestMisc2dStencil TestMisc2dStencil_instance; // A "stream-like" stencil that just reads and writes @@ -352,29 +371,29 @@ REGISTER_STENCIL(TestMisc2dStencil); // Running with radius=2 should give performance comparable to // (but not identical to) the stream 'triad' benchmark. -class StreamStencil : public StencilRadiusBase { +class StreamStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX(t); // step in time dim. - MAKE_DOMAIN_INDEX(x); // spatial dim. - MAKE_DOMAIN_INDEX(y); // spatial dim. - MAKE_DOMAIN_INDEX(z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying 3D grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying 3D grid. public: - StreamStencil(StencilList& stencils, int radius=2) : - StencilRadiusBase("test_stream_3d", stencils, radius) { } + StreamStencil(int radius=2) : + yc_solution_with_radius_base("test_stream_3d", radius) { } virtual ~StreamStencil() { } // Define equation to read '_radius' values and write one. virtual void define() { - GridValue v = constNum(1.0); + yc_number_node_ptr v = _node_factory.new_number_node(1.0); // Add '_radius' values from past time-steps. for (int r = 0; r < _radius; r++) @@ -385,7 +404,10 @@ class StreamStencil : public StencilRadiusBase { } }; -REGISTER_STENCIL(StreamStencil); +// Create an object of type 'StreamStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static StreamStencil StreamStencil_instance; // Reverse-time stencil. // In this test, A(t-1) depends on A(t). @@ -395,12 +417,12 @@ class TestReverseStencil : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y); + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); public: - TestReverseStencil(StencilList& stencils, int radius=2) : - TestBase("test_reverse_2d", stencils, radius) { } + TestReverseStencil(int radius=2) : + TestBase("test_reverse_2d", radius) { } // Define equation to do simple test. virtual void define() { @@ -410,7 +432,10 @@ class TestReverseStencil : public TestBase { } }; -REGISTER_STENCIL(TestReverseStencil); +// Create an object of type 'TestReverseStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestReverseStencil TestReverseStencil_instance; // Test dependent equations. // These will create 2 stencil packs that will be applied in sequence @@ -420,13 +445,13 @@ class TestDepStencil1 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x); // time-varying grid. - MAKE_GRID(B, t, x); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_solution(), { t, x }); // time-varying grid. public: - TestDepStencil1(StencilList& stencils, int radius=2) : - TestBase("test_dep_1d", stencils, radius) { } + TestDepStencil1(int radius=2) : + TestBase("test_dep_1d", radius) { } // Define equation to apply to all points in 'A' and 'B' grids. virtual void define() { @@ -439,20 +464,23 @@ class TestDepStencil1 : public TestBase { } }; -REGISTER_STENCIL(TestDepStencil1); +// Create an object of type 'TestDepStencil1', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestDepStencil1 TestDepStencil1_instance; class TestDepStencil2 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y); // time-varying grid. - MAKE_GRID(B, t, x, y); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_solution(), { t, x, y }); // time-varying grid. public: - TestDepStencil2(StencilList& stencils, int radius=2) : - TestBase("test_dep_2d", stencils, radius) { } + TestDepStencil2(int radius=2) : + TestBase("test_dep_2d", radius) { } // Define equation to apply to all points in 'A' and 'B' grids. virtual void define() { @@ -465,20 +493,23 @@ class TestDepStencil2 : public TestBase { } }; -REGISTER_STENCIL(TestDepStencil2); +// Create an object of type 'TestDepStencil2', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestDepStencil2 TestDepStencil2_instance; class TestDepStencil3 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying grid. - MAKE_GRID(B, t, x, y, z); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_solution(), { t, x, y, z }); // time-varying grid. public: - TestDepStencil3(StencilList& stencils, int radius=2) : - TestBase("test_dep_3d", stencils, radius) { } + TestDepStencil3(int radius=2) : + TestBase("test_dep_3d", radius) { } // Define equation to apply to all points in 'A' and 'B' grids. virtual void define() { @@ -493,7 +524,10 @@ class TestDepStencil3 : public TestBase { } }; -REGISTER_STENCIL(TestDepStencil3); +// Create an object of type 'TestDepStencil3', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestDepStencil3 TestDepStencil3_instance; // Test the use of scratch-pad grids. @@ -502,15 +536,15 @@ class TestScratchStencil1 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. // Temporary storage. - MAKE_SCRATCH_GRID(B, x); + yc_grid_var B = yc_grid_var("B", get_solution(), { x }, true); public: - TestScratchStencil1(StencilList& stencils, int radius=2) : - TestBase("test_scratch_1d", stencils, radius) { } + TestScratchStencil1(int radius=2) : + TestBase("test_scratch_1d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -523,24 +557,27 @@ class TestScratchStencil1 : public TestBase { } }; -REGISTER_STENCIL(TestScratchStencil1); +// Create an object of type 'TestScratchStencil1', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestScratchStencil1 TestScratchStencil1_instance; class TestScratchStencil3 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. // Temporary storage. - MAKE_SCRATCH_GRID(t1, x, y, z); - MAKE_SCRATCH_GRID(t2, x, y, z); - MAKE_SCRATCH_GRID(t3, x, y, z); + yc_grid_var t1 = yc_grid_var("t1", get_solution(), { x, y, z }, true); + yc_grid_var t2 = yc_grid_var("t2", get_solution(), { x, y, z }, true); + yc_grid_var t3 = yc_grid_var("t3", get_solution(), { x, y, z }, true); public: - TestScratchStencil3(StencilList& stencils, int radius=2) : - TestBase("test_scratch_3d", stencils, radius) { } + TestScratchStencil3(int radius=2) : + TestBase("test_scratch_3d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -559,7 +596,10 @@ class TestScratchStencil3 : public TestBase { } }; -REGISTER_STENCIL(TestScratchStencil3); +// Create an object of type 'TestScratchStencil3', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestScratchStencil3 TestScratchStencil3_instance; // Test the use of boundary code in sub-domains. class TestBoundaryStencil1 : public TestBase { @@ -567,86 +607,95 @@ class TestBoundaryStencil1 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. public: - TestBoundaryStencil1(StencilList& stencils, int radius=2) : - TestBase("test_boundary_1d", stencils, radius) { } + TestBoundaryStencil1(int radius=2) : + TestBase("test_boundary_1d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { // Define interior sub-domain. - Condition sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3); + yc_bool_node_ptr sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3); // Define interior points. - GridValue u = def_1d(A, t, x, 0, 1); - A(t+1, x) EQUALS u IF sd0; + yc_number_node_ptr u = def_1d(A, t, x, 0, 1); + A(t+1, x) EQUALS u IF_DOMAIN sd0; // Define exterior points. - A(t+1, x) EQUALS -u IF !sd0; + A(t+1, x) EQUALS -u IF_DOMAIN !sd0; } }; -REGISTER_STENCIL(TestBoundaryStencil1); +// Create an object of type 'TestBoundaryStencil1', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestBoundaryStencil1 TestBoundaryStencil1_instance; class TestBoundaryStencil2 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. public: - TestBoundaryStencil2(StencilList& stencils, int radius=2) : - TestBase("test_boundary_2d", stencils, radius) { } + TestBoundaryStencil2(int radius=2) : + TestBase("test_boundary_2d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { // Sub-domain is rectangle interior. - Condition sd0 = + yc_bool_node_ptr sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3) && (y >= first_index(y) + 4) && (y <= last_index(y) - 6); // Set A w/different stencils depending on condition. - A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 1, 0) IF sd0; - A(t+1, x, y) EQUALS def_2d(A, t, x, 1, 0, y, 0, 2) IF !sd0; + A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 1, 0) IF_DOMAIN sd0; + A(t+1, x, y) EQUALS def_2d(A, t, x, 1, 0, y, 0, 2) IF_DOMAIN !sd0; } }; -REGISTER_STENCIL(TestBoundaryStencil2); +// Create an object of type 'TestBoundaryStencil2', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestBoundaryStencil2 TestBoundaryStencil2_instance; class TestBoundaryStencil3 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y, z); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. public: - TestBoundaryStencil3(StencilList& stencils, int radius=2) : - TestBase("test_boundary_3d", stencils, radius) { } + TestBoundaryStencil3(int radius=2) : + TestBase("test_boundary_3d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { // Sub-domain is rectangle interior. - Condition sd0 = + yc_bool_node_ptr sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3) && (y >= first_index(y) + 4) && (y <= last_index(y) - 6) && (z >= first_index(z) + 6) && (z <= last_index(z) - 4); // Set A w/different stencils depending on condition. - A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 1, 0, z, 0, 1) IF sd0; - A(t+1, x, y, z) EQUALS def_3d(A, t, x, 1, 0, y, 0, 2, z, 1, 0) IF !sd0; + A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 1, 0, z, 0, 1) IF_DOMAIN sd0; + A(t+1, x, y, z) EQUALS def_3d(A, t, x, 1, 0, y, 0, 2, z, 1, 0) IF_DOMAIN !sd0; } }; -REGISTER_STENCIL(TestBoundaryStencil3); +// Create an object of type 'TestBoundaryStencil3', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestBoundaryStencil3 TestBoundaryStencil3_instance; // Test step condition. class TestStepCondStencil1 : public TestBase { @@ -654,25 +703,25 @@ class TestStepCondStencil1 : public TestBase { protected: // Indices. - MAKE_MISC_INDEX(b); + yc_index_node_ptr b = _node_factory.new_misc_index("b"); // Vars. - MAKE_GRID(A, t, x); // time-varying grid. - MAKE_ARRAY(B, b); + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_solution(), { b }); public: - TestStepCondStencil1(StencilList& stencils, int radius=2) : - TestBase("test_step_cond_1d", stencils, radius) { } + TestStepCondStencil1(int radius=2) : + TestBase("test_step_cond_1d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { // Time condition. - Condition tc0 = (t % 2 == 0); + yc_bool_node_ptr tc0 = (t % 2 == 0); // Var condition. - Condition vc0 = (B(0) > B(1)); + yc_bool_node_ptr vc0 = (B(0) > B(1)); // Set A w/different stencils depending on the conditions. It is // the programmer's responsibility to ensure that the conditions are @@ -690,7 +739,10 @@ class TestStepCondStencil1 : public TestBase { } }; -REGISTER_STENCIL(TestStepCondStencil1); +// Create an object of type 'TestStepCondStencil1', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestStepCondStencil1 TestStepCondStencil1_instance; // Test the use of conditional updates with scratch-pad grids. class TestScratchBoundaryStencil1 : public TestBase { @@ -698,15 +750,15 @@ class TestScratchBoundaryStencil1 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. // Temporary storage. - MAKE_SCRATCH_GRID(B, x); + yc_grid_var B = yc_grid_var("B", get_solution(), { x }, true); public: - TestScratchBoundaryStencil1(StencilList& stencils, int radius=2) : - TestBase("test_scratch_boundary_1d", stencils, radius) { } + TestScratchBoundaryStencil1(int radius=2) : + TestBase("test_scratch_boundary_1d", radius) { } // Define equation to apply to all points in 'A' grid. virtual void define() { @@ -715,16 +767,19 @@ class TestScratchBoundaryStencil1 : public TestBase { B(x) EQUALS def_1d(A, t, x, 1, 0); // Define sub-domain. - Condition sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3); + yc_bool_node_ptr sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3); // Define next values for 'A' from scratch var values. auto v = def_no_t_1d(B, x-6, 2, 3) - def_no_t_1d(B, x+7, 0, 2); - A(t+1, x) EQUALS v IF sd0; - A(t+1, x) EQUALS -v IF !sd0; + A(t+1, x) EQUALS v IF_DOMAIN sd0; + A(t+1, x) EQUALS -v IF_DOMAIN !sd0; } }; -REGISTER_STENCIL(TestScratchBoundaryStencil1); +// Create an object of type 'TestScratchBoundaryStencil1', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestScratchBoundaryStencil1 TestScratchBoundaryStencil1_instance; // A stencil that uses svml math functions. class TestFuncStencil1 : public TestBase { @@ -732,14 +787,14 @@ class TestFuncStencil1 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x); - MAKE_GRID(B, t, x); - MAKE_GRID(C, t, x); + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); + yc_grid_var B = yc_grid_var("B", get_solution(), { t, x }); + yc_grid_var C = yc_grid_var("C", get_solution(), { t, x }); public: - TestFuncStencil1(StencilList& stencils, int radius=1) : - TestBase("test_func_1d", stencils, radius) { } + TestFuncStencil1(int radius=1) : + TestBase("test_func_1d", radius) { } virtual void define() { A(t+1, x) EQUALS cos(A(t, x)) - 2 * sin(A(t, x)); @@ -748,7 +803,10 @@ class TestFuncStencil1 : public TestBase { } }; -REGISTER_STENCIL(TestFuncStencil1); +// Create an object of type 'TestFuncStencil1', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestFuncStencil1 TestFuncStencil1_instance; // A stencil that has grids but no stencil equation. class TestEmptyStencil2 : public TestBase { @@ -756,17 +814,20 @@ class TestEmptyStencil2 : public TestBase { protected: // Vars. - MAKE_GRID(A, t, x, y); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. public: - TestEmptyStencil2(StencilList& stencils, int radius=1) : - TestBase("test_empty_2d", stencils, radius) { } + TestEmptyStencil2(int radius=1) : + TestBase("test_empty_2d", radius) { } virtual void define() { } }; -REGISTER_STENCIL(TestEmptyStencil2); +// Create an object of type 'TestEmptyStencil2', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestEmptyStencil2 TestEmptyStencil2_instance; // A stencil that no grids and no stencil equation. // Kernel must be built with domain_dims and step_dim options. @@ -776,10 +837,13 @@ class TestEmptyStencil0: public TestBase { public: - TestEmptyStencil0(StencilList& stencils, int radius=1) : - TestBase("test_empty", stencils, radius) { } + TestEmptyStencil0(int radius=1) : + TestBase("test_empty", radius) { } virtual void define() { } }; -REGISTER_STENCIL(TestEmptyStencil0); +// Create an object of type 'TestEmptyStencil0', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TestEmptyStencil0 TestEmptyStencil0_instance; diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index f14e428e..e47e055a 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -26,41 +26,44 @@ IN THE SOFTWARE. // Implement TTI stencil using formulation from Devito project. // TODO: provide a more readable TTI formulation. -#include "Soln.hpp" +// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. +#include "yask_compiler_utility_api.hpp" +using namespace std; +using namespace yask; -class TTIStencil:public StencilRadiusBase +class TTIStencil:public yc_solution_with_radius_base { protected: // Indices & dimensions. - MAKE_STEP_INDEX (t); // step in time dim. - MAKE_DOMAIN_INDEX (x); // spatial dim. - MAKE_DOMAIN_INDEX (y); // spatial dim. - MAKE_DOMAIN_INDEX (z); // spatial dim. + yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. + yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. - // Grids. - MAKE_GRID (u, t, x, y, z); // Time-varying 3D wavefield grid. - MAKE_GRID (v, t, x, y, z); // Time-varying 3D wavefield grid. - MAKE_GRID (m, x, y, z); // Square slowness of the model. - MAKE_GRID (damp, x, y, z); // Boundary damping. - MAKE_GRID (phi, x, y, z); - MAKE_GRID (theta, x, y, z); - MAKE_GRID (delta, x, y, z); - MAKE_GRID (epsilon, x, y, z); + // Grid vars. + yc_grid_var u = yc_grid_var("u", get_solution(), { t, x, y, z }); // Time-varying 3D wavefield grid. + yc_grid_var v = yc_grid_var("v", get_solution(), { t, x, y, z }); // Time-varying 3D wavefield grid. + yc_grid_var m = yc_grid_var("m", get_solution(), { x, y, z }); // Square slowness of the model. + yc_grid_var damp = yc_grid_var("damp", get_solution(), { x, y, z }); // Boundary damping. + yc_grid_var phi = yc_grid_var("phi", get_solution(), { x, y, z }); + yc_grid_var theta = yc_grid_var("theta", get_solution(), { x, y, z }); + yc_grid_var delta = yc_grid_var("delta", get_solution(), { x, y, z }); + yc_grid_var epsilon = yc_grid_var("epsilon", get_solution(), { x, y, z }); // Hoisted misc time-invariant data. - MAKE_GRID (ti0, x, y, z); - MAKE_GRID (ti1, x, y, z); - MAKE_GRID (ti2, x, y, z); - MAKE_GRID (ti3, x, y, z); + yc_grid_var ti0 = yc_grid_var("ti0", get_solution(), { x, y, z }); + yc_grid_var ti1 = yc_grid_var("ti1", get_solution(), { x, y, z }); + yc_grid_var ti2 = yc_grid_var("ti2", get_solution(), { x, y, z }); + yc_grid_var ti3 = yc_grid_var("ti3", get_solution(), { x, y, z }); public: // For this stencil, the 'radius' is the number of FD coefficients on // either side of center in each spatial dimension. -TTIStencil (StencilList & stencils, int radius = 2): - StencilRadiusBase ("tti", stencils, radius) +TTIStencil (int radius = 2): + yc_solution_with_radius_base ("tti", radius) { } @@ -71,25 +74,25 @@ TTIStencil (StencilList & stencils, int radius = 2): virtual void define_so4 () { - GridValue temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); - GridValue temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, + yc_number_node_ptr temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); + yc_number_node_ptr temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, z); - GridValue temp192 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 1, + yc_number_node_ptr temp192 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 1, z) - 2.5e-2 * u (t, x, y + 1, z); - GridValue temp183 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x - 2, y, + yc_number_node_ptr temp183 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x - 2, y, z) + 1.0e-1 * u (t, x - 1, y, z); - GridValue temp168 = + yc_number_node_ptr temp168 = -7.5e-2 * u (t, x, y + 1, z) + 1.0e-1 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 1, z); - GridValue temp197 = + yc_number_node_ptr temp197 = 3.75e-2 * (temp161 * ti1 (x, y, z) * ti2 (x, y, z) + temp163 * ti2 (x, y, z) * ti3 (x, y, z) - (-7.5e-2 * u (t, x, y, @@ -100,45 +103,45 @@ TTIStencil (StencilList & stencils, int radius = 2): z + 2)) * ti0 (x, y, z)); - GridValue temp171 = + yc_number_node_ptr temp171 = -7.5e-2 * u (t, x + 1, y, z) + 1.0e-1 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 1, y + 2, z); - GridValue temp178 = 2.5e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)); - GridValue temp182 = + yc_number_node_ptr temp178 = 2.5e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)); + yc_number_node_ptr temp182 = 2.5e-2 * (-u (t, x - 2, y - 1, z) + u (t, x - 2, y + 1, z)); - GridValue temp190 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x - 1, y, + yc_number_node_ptr temp190 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x - 1, y, z) - 2.5e-2 * u (t, x + 1, y, z); - GridValue temp173 = 2.5e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)); - GridValue temp188 = + yc_number_node_ptr temp173 = 2.5e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)); + yc_number_node_ptr temp188 = 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x - 1, y + 1, z)); - GridValue temp154 = 2.5e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); - GridValue temp186 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 2, + yc_number_node_ptr temp154 = 2.5e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); + yc_number_node_ptr temp186 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 2, z) + 1.0e-1 * u (t, x, y - 1, z); - GridValue temp158 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x + 1, y, + yc_number_node_ptr temp158 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x + 1, y, z) - 2.5e-2 * u (t, x + 2, y, z); - GridValue temp191 = + yc_number_node_ptr temp191 = 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x + 1, y - 1, z)); - GridValue temp184 = + yc_number_node_ptr temp184 = 2.5e-2 * (-u (t, x - 1, y - 2, z) + u (t, x + 1, y - 2, z)); - GridValue temp181 = + yc_number_node_ptr temp181 = -7.5e-2 * u (t, x - 1, y, z) + 1.0e-1 * u (t, x - 1, y + 1, z) - 2.5e-2 * u (t, x - 1, y + 2, z); - GridValue temp176 = + yc_number_node_ptr temp176 = -7.5e-2 * u (t, x, y - 1, z) + 1.0e-1 * u (t, x + 1, y - 1, z) - 2.5e-2 * u (t, x + 2, y - 1, z); - GridValue temp123 = + yc_number_node_ptr temp123 = (2.5e-2 * ((v (t, x, y, z) - v (t, x, y - 2, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, @@ -149,7 +152,7 @@ TTIStencil (StencilList & stencils, int radius = 2): 2.5e-2 * v (t, x + 2, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); - GridValue temp102 = + yc_number_node_ptr temp102 = (2.5e-2 * ((-v (t, x - 1, y, z - 1) + v (t, x - 1, y, z + 1)) * ti2 (x - 1, y, z) + (-v (t, @@ -174,7 +177,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z) * ti1 (x - 1, y, z)) * ti0 (x - 1, y, z) * ti1 (x - 1, y, z); - GridValue temp131 = + yc_number_node_ptr temp131 = (2.5e-2 * (-v (t, x - 1, y, z - 2) + v (t, x + 1, y, z - 2)) * ti0 (x, y, z - 2) * ti1 (x, y, z - 2) + (-2.5e-2 * v (t, x, y, @@ -191,7 +194,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z - 2)) * ti2 (x, y, z - 2); - GridValue temp87 = + yc_number_node_ptr temp87 = (2.5e-2 * ((-v (t, x - 2, y, z - 1) + v (t, x - 2, y, z + 1)) * ti2 (x - 2, y, z) + (-v (t, @@ -216,7 +219,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z) * ti1 (x - 2, y, z)) * ti0 (x - 2, y, z) * ti1 (x - 2, y, z); - GridValue temp47 = + yc_number_node_ptr temp47 = 2.5e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z)) * ti0 (x, y, z) * ti1 (x, y, @@ -232,7 +235,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y + 2, z)) * ti0 (x, y, z) * ti3 (x, y, z); - GridValue temp110 = + yc_number_node_ptr temp110 = (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y + 2, z)) * ti0 (x, y + 1, z) * ti3 (x, y + 1, @@ -243,7 +246,7 @@ TTIStencil (StencilList & stencils, int radius = 2): 2.5e-2 * v (t, x + 2, y + 1, z)) * ti0 (x, y + 1, z) * ti1 (x, y + 1, z)) * ti0 (x, y + 1, z) * ti3 (x, y + 1, z); - GridValue temp140 = + yc_number_node_ptr temp140 = (2.5e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) * ti0 (x + 1, y, z) * ti1 (x + 1, y, z) + (-7.5e-2 * v (t, x + 1, y, z) + 1.0e-1 * v (t, x + 1, y, @@ -257,7 +260,7 @@ TTIStencil (StencilList & stencils, int radius = 2): ti0 (x + 1, y, z) * ti1 (x + 1, y, z); - GridValue temp149 = + yc_number_node_ptr temp149 = (2.5e-2 * (-v (t, x - 1, y - 2, z) + v (t, x + 1, y - 2, z)) * ti0 (x, y - 2, z) * ti1 (x, y - 2, z) + (-2.5e-2 * v (t, x, y, @@ -276,7 +279,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y - 2, z) * ti3 (x, y - 2, z); - GridValue temp39 = + yc_number_node_ptr temp39 = (2.5e-2 * ((-v (t, x, y, z - 1) + v (t, x, y, z + 1)) * ti2 (x, y, z) + (-v (t, x, @@ -296,7 +299,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z)) * ti0 (x, y, z) * ti1 (x, y, z)) * ti0 (x, y, z) * ti1 (x, y, z); - GridValue temp132 = + yc_number_node_ptr temp132 = (2.5e-2 * (-v (t, x - 1, y, z - 1) + v (t, x + 1, y, z - 1)) * ti0 (x, y, z - 1) * ti1 (x, y, z - 1) + (1.0e-1 * v (t, x, y, @@ -312,9 +315,9 @@ TTIStencil (StencilList & stencils, int radius = 2): z - 1)) * ti2 (x, y, z - 1); - GridValue temp6 = + yc_number_node_ptr temp6 = 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); - GridValue temp141 = + yc_number_node_ptr temp141 = (2.5e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) * ti0 (x - 1, y, z) * ti1 (x - 1, y, z) + (-7.5e-2 * v (t, x - 1, y, z) + 1.0e-1 * v (t, x - 1, y, @@ -328,9 +331,9 @@ TTIStencil (StencilList & stencils, int radius = 2): ti0 (x - 1, y, z) * ti1 (x - 1, y, z); - GridValue temp10 = + yc_number_node_ptr temp10 = 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); - GridValue temp215 = + yc_number_node_ptr temp215 = 3.75e-2 * (-temp154 * ti1 (x, y, z) + temp158 * ti3 (x, y, z)) * ti3 (x, y, z) @@ -692,7 +695,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z - 2)) * ti0 (x, y, z - 2)); - GridValue temp77 = + yc_number_node_ptr temp77 = (2.5e-2 * ((v (t, x, y, z) - v (t, x, y, z - 2)) * ti2 (x, y, z - 1) + (-v (t, x, @@ -726,7 +729,7 @@ TTIStencil (StencilList & stencils, int radius = 2): ti0 (x, y, z - 1) * ti1 (x, y, z - 1)) * ti2 (x, y, z - 1); - GridValue temp61 = + yc_number_node_ptr temp61 = (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y, z + 2)) * ti2 (x, y, z + 1) + (-v (t, x, @@ -761,7 +764,7 @@ TTIStencil (StencilList & stencils, int radius = 2): ti0 (x, y, z + 1) * ti1 (x, y, z + 1)) * ti2 (x, y, z + 1); - GridValue temp150 = + yc_number_node_ptr temp150 = (2.5e-2 * (-v (t, x - 1, y - 1, z) + v (t, x + 1, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, z) + (1.0e-1 * v (t, x, y, @@ -827,19 +830,19 @@ TTIStencil (StencilList & stencils, int radius = 2): virtual void define_so8 () { - GridValue temp330 = + yc_number_node_ptr temp330 = 4.16666666666667e-3 * (u (t, x - 2, y, z) - u (t, x + 2, y, z)) + 3.33333333333333e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); - GridValue temp333 = + yc_number_node_ptr temp333 = -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 1, z) + 7.5e-2 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, z) + 4.16666666666667e-3 * u (t, x, y + 3, z); - GridValue temp336 = + yc_number_node_ptr temp336 = 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x, y + 2, z)) + 4.16666666666667e-3 * (u (t, x, y - 1, z) - u (t, x, y + 3, z)); - GridValue temp395 = + yc_number_node_ptr temp395 = 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x + 2, y - 2, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -848,26 +851,26 @@ TTIStencil (StencilList & stencils, int radius = 2): x + 1, y - 2, z)); - GridValue temp365 = + yc_number_node_ptr temp365 = -4.16666666666667e-2 * u (t, x - 2, y, z) - 1.25e-2 * u (t, x - 2, y - 1, z) + 7.5e-2 * u (t, x - 2, y + 1, z) - 2.5e-2 * u (t, x - 2, y + 2, z) + 4.16666666666667e-3 * u (t, x - 2, y + 3, z); - GridValue temp375 = + yc_number_node_ptr temp375 = -4.16666666666667e-2 * u (t, x + 2, y, z) - 1.25e-2 * u (t, x + 2, y - 1, z) + 7.5e-2 * u (t, x + 2, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 2, z) + 4.16666666666667e-3 * u (t, x + 2, y + 3, z); - GridValue temp394 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 3, y, + yc_number_node_ptr temp394 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 3, y, z) - 4.16666666666667e-2 * u (t, x - 2, y, z) + 7.5e-2 * u (t, x - 1, y, z) + 4.16666666666667e-3 * u (t, x + 1, y, z); - GridValue temp407 = + yc_number_node_ptr temp407 = 4.16666666666667e-3 * (u (t, x - 1, y - 2, z) - u (t, x - 1, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -876,17 +879,17 @@ TTIStencil (StencilList & stencils, int radius = 2): x - 1, y + 1, z)); - GridValue temp352 = + yc_number_node_ptr temp352 = 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x, y - 4, z)) + 3.33333333333333e-2 * (-u (t, x, y - 3, z) + u (t, x, y - 1, z)); - GridValue temp347 = + yc_number_node_ptr temp347 = -4.16666666666667e-2 * u (t, x + 1, y, z) - 1.25e-2 * u (t, x + 1, y - 1, z) + 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 1, y + 2, z) + 4.16666666666667e-3 * u (t, x + 1, y + 3, z); - GridValue temp409 = + yc_number_node_ptr temp409 = 4.16666666666667e-3 * (u (t, x + 1, y - 2, z) - u (t, x + 1, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x + 1, @@ -895,58 +898,58 @@ TTIStencil (StencilList & stencils, int radius = 2): x + 1, y + 1, z)); - GridValue temp318 = + yc_number_node_ptr temp318 = 4.16666666666667e-3 * (u (t, x, y - 2, z) - u (t, x, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); - GridValue temp381 = + yc_number_node_ptr temp381 = -4.16666666666667e-2 * u (t, x, y - 1, z) - 1.25e-2 * u (t, x - 1, y - 1, z) + 7.5e-2 * u (t, x + 1, y - 1, z) - 2.5e-2 * u (t, x + 2, y - 1, z) + 4.16666666666667e-3 * u (t, x + 3, y - 1, z); - GridValue temp408 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 2, y, + yc_number_node_ptr temp408 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 2, y, z) - 4.16666666666667e-2 * u (t, x - 1, y, z) - 2.5e-2 * u (t, x + 1, y, z) + 4.16666666666667e-3 * u (t, x + 2, y, z); - GridValue temp390 = + yc_number_node_ptr temp390 = 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 4, z) - 4.16666666666667e-2 * u (t, x, y - 3, z) + 7.5e-2 * u (t, x, y - 2, z) - 2.5e-2 * u (t, x, y - 1, z); - GridValue temp360 = + yc_number_node_ptr temp360 = 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x - 4, y, z)) + 3.33333333333333e-2 * (-u (t, x - 3, y, z) + u (t, x - 1, y, z)); - GridValue temp370 = + yc_number_node_ptr temp370 = -4.16666666666667e-2 * u (t, x, y + 2, z) - 1.25e-2 * u (t, x - 1, y + 2, z) + 7.5e-2 * u (t, x + 1, y + 2, z) - 2.5e-2 * u (t, x + 2, y + 2, z) + 4.16666666666667e-3 * u (t, x + 3, y + 2, z); - GridValue temp357 = + yc_number_node_ptr temp357 = -4.16666666666667e-2 * u (t, x, y - 2, z) - 1.25e-2 * u (t, x - 1, y - 2, z) + 7.5e-2 * u (t, x + 1, y - 2, z) - 2.5e-2 * u (t, x + 2, y - 2, z) + 4.16666666666667e-3 * u (t, x + 3, y - 2, z); - GridValue temp385 = + yc_number_node_ptr temp385 = -4.16666666666667e-2 * u (t, x - 1, y, z) - 1.25e-2 * u (t, x - 1, y - 1, z) + 7.5e-2 * u (t, x - 1, y + 1, z) - 2.5e-2 * u (t, x - 1, y + 2, z) + 4.16666666666667e-3 * u (t, x - 1, y + 3, z); - GridValue temp377 = + yc_number_node_ptr temp377 = 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)) + 4.16666666666667e-3 * (u (t, x, y - 3, z) - u (t, x, y + 1, z)); - GridValue temp343 = + yc_number_node_ptr temp343 = 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x + 2, y, z)) + 4.16666666666667e-3 * (u (t, x - 1, y, z) - u (t, x + 3, y, z)); - GridValue temp388 = + yc_number_node_ptr temp388 = 4.16666666666667e-3 * (u (t, x - 2, y - 3, z) - u (t, x + 2, y - 3, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -955,13 +958,13 @@ TTIStencil (StencilList & stencils, int radius = 2): x + 1, y - 3, z)); - GridValue temp406 = + yc_number_node_ptr temp406 = -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x, y + 1, z) + 7.5e-2 * u (t, x, y + 2, z) - 2.5e-2 * u (t, x, y + 3, z) + 4.16666666666667e-3 * u (t, x, y + 4, z); - GridValue temp404 = + yc_number_node_ptr temp404 = 4.16666666666667e-3 * (u (t, x - 2, y + 1, z) - u (t, x + 2, y + 1, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -970,23 +973,23 @@ TTIStencil (StencilList & stencils, int radius = 2): x + 1, y + 1, z)); - GridValue temp342 = + yc_number_node_ptr temp342 = -4.16666666666667e-2 * u (t, x, y + 1, z) - 1.25e-2 * u (t, x - 1, y + 1, z) + 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 1, z) + 4.16666666666667e-3 * u (t, x + 3, y + 1, z); - GridValue temp410 = + yc_number_node_ptr temp410 = -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x + 1, y, z) + 7.5e-2 * u (t, x + 2, y, z) - 2.5e-2 * u (t, x + 3, y, z) + 4.16666666666667e-3 * u (t, x + 4, y, z); - GridValue temp367 = + yc_number_node_ptr temp367 = 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x, y + 4, z)) + 3.33333333333333e-2 * (-u (t, x, y + 1, z) + u (t, x, y + 3, z)); - GridValue temp399 = + yc_number_node_ptr temp399 = 4.16666666666667e-3 * (u (t, x - 2, y - 1, z) - u (t, x + 2, y - 1, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -995,13 +998,13 @@ TTIStencil (StencilList & stencils, int radius = 2): x + 1, y - 1, z)); - GridValue temp325 = + yc_number_node_ptr temp325 = -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 1, y, z) + 7.5e-2 * u (t, x + 1, y, z) - 2.5e-2 * u (t, x + 2, y, z) + 4.16666666666667e-3 * u (t, x + 3, y, z); - GridValue temp386 = + yc_number_node_ptr temp386 = 4.16666666666667e-3 * (u (t, x - 3, y - 2, z) - u (t, x - 3, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x - 3, @@ -1010,20 +1013,20 @@ TTIStencil (StencilList & stencils, int radius = 2): x - 3, y + 1, z)); - GridValue temp396 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 3, + yc_number_node_ptr temp396 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 3, z) - 4.16666666666667e-2 * u (t, x, y - 2, z) + 7.5e-2 * u (t, x, y - 1, z) + 4.16666666666667e-3 * u (t, x, y + 1, z); - GridValue temp401 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 2, + yc_number_node_ptr temp401 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 2, z) - 4.16666666666667e-2 * u (t, x, y - 1, z) - 2.5e-2 * u (t, x, y + 1, z) + 4.16666666666667e-3 * u (t, x, y + 2, z); - GridValue temp372 = + yc_number_node_ptr temp372 = 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x + 4, y, z)) + 3.33333333333333e-2 * (-u (t, x + 1, y, z) + u (t, x + 3, y, z)); - GridValue temp420 = + yc_number_node_ptr temp420 = 2.08333333333333e-2 * ((temp330 * ti1 (x, y, z) + temp333 * ti3 (x, y, z)) * ti2 (x, y, z) - @@ -1035,16 +1038,16 @@ TTIStencil (StencilList & stencils, int radius = 2): z + 2) + 4.16666666666667e-3 * u (t, x, y, z + 3)) * ti0 (x, y, z)); - GridValue temp387 = + yc_number_node_ptr temp387 = 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x - 4, y, z) - 4.16666666666667e-2 * u (t, x - 3, y, z) + 7.5e-2 * u (t, x - 2, y, z) - 2.5e-2 * u (t, x - 1, y, z); - GridValue temp383 = + yc_number_node_ptr temp383 = 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)) + 4.16666666666667e-3 * (u (t, x - 3, y, z) - u (t, x + 1, y, z)); - GridValue temp392 = + yc_number_node_ptr temp392 = 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x - 2, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x - 2, @@ -1053,7 +1056,7 @@ TTIStencil (StencilList & stencils, int radius = 2): x - 2, y + 1, z)); - GridValue temp284 = + yc_number_node_ptr temp284 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 2) - v (t, x + 2, y, z - 2)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 2) + @@ -1085,7 +1088,7 @@ TTIStencil (StencilList & stencils, int radius = 2): + 1)) * ti2 (x, y, z - 2)) * ti2 (x, y, z - 2); - GridValue temp308 = + yc_number_node_ptr temp308 = (((4.16666666666667e-3 * (v (t, x - 2, y - 2, z) - v (t, x + 2, y - 2, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 2, z) + @@ -1106,7 +1109,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z + 3)) * ti2 (x, y - 2, z)) * ti0 (x, y - 2, z) * ti3 (x, y - 2, z); - GridValue temp92 = + yc_number_node_ptr temp92 = (((4.16666666666667e-3 * (v (t, x, y - 2, z + 1) - v (t, x, y + 2, z + 1)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z + 1) + @@ -1129,7 +1132,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z + 1); - GridValue temp185 = + yc_number_node_ptr temp185 = (((4.16666666666667e-3 * (v (t, x - 2, y - 2, z) - v (t, x - 2, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 2, y - 1, z) + @@ -1151,7 +1154,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x - 2, y, z); - GridValue temp283 = + yc_number_node_ptr temp283 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 3) - v (t, x + 2, y, z - 3)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 3) + @@ -1184,7 +1187,7 @@ TTIStencil (StencilList & stencils, int radius = 2): - 3)) * ti2 (x, y, z - 3); - GridValue temp309 = + yc_number_node_ptr temp309 = (((4.16666666666667e-3 * (v (t, x - 2, y - 1, z) - v (t, x + 2, y - 1, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + @@ -1205,7 +1208,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z + 3)) * ti2 (x, y - 1, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); - GridValue temp310 = + yc_number_node_ptr temp310 = (((4.16666666666667e-3 * (v (t, x - 2, y + 1, z) - v (t, x + 2, y + 1, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y + 1, z) + @@ -1235,7 +1238,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y + 1, z) * ti3 (x, y + 1, z); - GridValue temp307 = + yc_number_node_ptr temp307 = (((4.16666666666667e-3 * (v (t, x - 2, y - 3, z) - v (t, x + 2, y - 3, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 3, z) + @@ -1259,7 +1262,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z + 3)) * ti2 (x, y - 3, z)) * ti0 (x, y - 3, z) * ti3 (x, y - 3, z); - GridValue temp298 = + yc_number_node_ptr temp298 = (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x + 4, y, z)) + 3.33333333333333e-2 * (-v (t, x + 1, y, z) + v (t, x + 3, y, z))) * ti1 (x + 2, y, @@ -1287,7 +1290,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x + 2, y, z); - GridValue temp165 = + yc_number_node_ptr temp165 = (((4.16666666666667e-3 * (v (t, x - 3, y - 2, z) - v (t, x - 3, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 3, y - 1, z) + @@ -1313,7 +1316,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x - 3, y, z); - GridValue temp154 = + yc_number_node_ptr temp154 = (((4.16666666666667e-3 * (v (t, x, y - 2, z - 1) - v (t, x, y + 2, z - 1)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 1) + @@ -1336,7 +1339,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z - 1); - GridValue temp299 = + yc_number_node_ptr temp299 = (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) + 4.16666666666667e-3 * (v (t, x - 3, y, z) - v (t, x + 1, y, z))) * ti1 (x - 1, y, @@ -1364,7 +1367,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x - 1, y, z); - GridValue temp289 = + yc_number_node_ptr temp289 = (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) + 4.16666666666667e-3 * (v (t, x - 1, y, z) - v (t, x + 3, y, z))) * ti1 (x + 1, y, @@ -1392,7 +1395,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x + 1, y, z); - GridValue temp116 = + yc_number_node_ptr temp116 = (((4.16666666666667e-3 * (v (t, x, y - 2, z - 2) - v (t, x, y + 2, z - 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 2) + @@ -1415,7 +1418,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z - 2); - GridValue temp56 = + yc_number_node_ptr temp56 = (((4.16666666666667e-3 * (v (t, x, y - 2, z) - v (t, x, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z) + v (t, x, y + 1, z))) * ti3 (x, y, @@ -1435,7 +1438,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z)) * ti0 (x, y, z) * ti1 (x, y, z); - GridValue temp204 = + yc_number_node_ptr temp204 = (((4.16666666666667e-3 * (v (t, x - 1, y - 2, z) - v (t, x - 1, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + @@ -1457,7 +1460,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x - 1, y, z); - GridValue temp288 = + yc_number_node_ptr temp288 = (((4.16666666666667e-3 * (v (t, x - 2, y, z + 1) - v (t, x + 2, y, z + 1)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z + 1) + @@ -1489,9 +1492,9 @@ TTIStencil (StencilList & stencils, int radius = 2): + 4)) * ti2 (x, y, z + 1)) * ti2 (x, y, z + 1); - GridValue temp10 = + yc_number_node_ptr temp10 = 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); - GridValue temp133 = + yc_number_node_ptr temp133 = (((4.16666666666667e-3 * (v (t, x, y - 2, z + 2) - v (t, x, y + 2, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z + 2) + @@ -1514,7 +1517,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z + 2); - GridValue temp286 = + yc_number_node_ptr temp286 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 1) - v (t, x + 2, y, z - 1)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 1) + @@ -1546,7 +1549,7 @@ TTIStencil (StencilList & stencils, int radius = 2): + 2)) * ti2 (x, y, z - 1)) * ti2 (x, y, z - 1); - GridValue temp252 = + yc_number_node_ptr temp252 = (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x, y - 4, z)) + 3.33333333333333e-2 * (-v (t, x, y - 3, z) + v (t, x, y - 1, z))) * ti3 (x, y - 2, @@ -1573,7 +1576,7 @@ TTIStencil (StencilList & stencils, int radius = 2): 2, z) * ti3 (x, y - 2, z); - GridValue temp487 = temp420 * ti2 (x, y, z) * ti3 (x, y, + yc_number_node_ptr temp487 = temp420 * ti2 (x, y, z) * ti3 (x, y, z) + 2.08333333333333e-2 * ((-temp318 * ti1 (x, y, z) + temp325 * ti3 (x, y, z)) * ti3 (x, y, @@ -2271,7 +2274,7 @@ TTIStencil (StencilList & stencils, int radius = 2): z + 1)) * ti0 (x, y, z + 1)); - GridValue temp290 = + yc_number_node_ptr temp290 = (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x - 4, y, z)) + 3.33333333333333e-2 * (-v (t, x - 3, y, z) + v (t, x - 1, y, z))) * ti1 (x - 2, y, @@ -2299,7 +2302,7 @@ TTIStencil (StencilList & stencils, int radius = 2): y, z) * ti1 (x - 2, y, z); - GridValue temp275 = + yc_number_node_ptr temp275 = (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x, y - 2, z)) + 4.16666666666667e-3 * (v (t, x, y - 3, z) - v (t, x, y + 1, z))) * ti3 (x, y - 1, @@ -2326,7 +2329,7 @@ TTIStencil (StencilList & stencils, int radius = 2): 1, z) * ti3 (x, y - 1, z); - GridValue temp237 = + yc_number_node_ptr temp237 = (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x, y + 2, z)) + 4.16666666666667e-3 * (v (t, x, y - 1, z) - v (t, x, y + 3, z))) * ti3 (x, y + 1, @@ -2353,7 +2356,7 @@ TTIStencil (StencilList & stencils, int radius = 2): 1, z) * ti3 (x, y + 1, z); - GridValue temp262 = + yc_number_node_ptr temp262 = (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x, y + 4, z)) + 3.33333333333333e-2 * (-v (t, x, y + 1, z) + v (t, x, y + 3, z))) * ti3 (x, y + 2, @@ -2380,7 +2383,7 @@ TTIStencil (StencilList & stencils, int radius = 2): 2, z) * ti3 (x, y + 2, z); - GridValue temp68 = + yc_number_node_ptr temp68 = ((4.16666666666667e-3 * (v (t, x - 2, y, z) - v (t, x + 2, y, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z))) * ti1 (x, y, @@ -2402,9 +2405,9 @@ TTIStencil (StencilList & stencils, int radius = 2): + 2) + 4.16666666666667e-3 * v (t, x, y, z + 3)) * ti2 (x, y, z); - GridValue temp6 = + yc_number_node_ptr temp6 = 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); - GridValue temp225 = + yc_number_node_ptr temp225 = (((4.16666666666667e-3 * (v (t, x + 1, y - 2, z) - v (t, x + 1, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x + 1, y - 1, z) + @@ -2500,4 +2503,7 @@ TTIStencil (StencilList & stencils, int radius = 2): } }; -REGISTER_STENCIL (TTIStencil); +// Create an object of type 'TTIStencil', +// making it available in the YASK compiler utility via the +// '-stencil' commmand-line option or the 'stencil=' build option. +static TTIStencil TTIStencil_instance; diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index 81802cd6..c469082a 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -61,15 +61,17 @@ ($) # Capture class name. if (/class\s+([_\w]+)/) { $class_name = $1; + warn " class $class_name...\n" if $OPT{verbose}; } # Capture stencilList parameter name. if (/StencilList\s*&\s*([_\w]+)/) { $list_var = $1; + warn " StencilList $list_var...\n" if $OPT{verbose}; } # Register solution. - if (/REGISTER_STENCIL[(](.*)[)]/) { + if (/REGISTER_STENCIL\s*[(](.*)[)]/) { my $cname = $1; $result .= @@ -82,30 +84,35 @@ ($) # Include file. elsif (/[#]include.*Soln[.]hpp/) { $result .= "// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility.\n". - "#include \"yask_compiler_utility_api.hpp\"\n"; + "#include \"yask_compiler_utility_api.hpp\"\n". + "using namespace std;\n". + "using namespace yask;\n"; } # For other code, make substitutions and append changes. else { # Ctor: remove StencilList parameter. - s/$class_name\s*[(]\s*StencilList\s*&\s*$list_var\s*,\s*/$class_name(/ - if defined $class_name; - s/$list_var\s*,\s*//g - if defined $list_var; + if (defined $class_name && defined $list_var) { + s/\bStencilList\s*&\s*//g; + s/([(,]\s*)$list_var\s*,\s*/$1/g; # '(a,list,b)' -> '(a,b)' + s/([,]\s*)$list_var\s*([)])/$2/g; # '(a,list)' -> '(a)' + s/([(]\s*)$list_var\s*([)])/$1$2/g; # '(list)' -> '()' + } - # Index creation. - s/MAKE_STEP_INDEX[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_step_index("$1")/g; - s/MAKE_DOMAIN_INDEX[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_domain_index("$1")/g; - s/MAKE_MISC_INDEX[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_misc_index("$1")/g; + # Node creation. + s/MAKE_STEP_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_step_index("$1")/g; + s/MAKE_DOMAIN_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_domain_index("$1")/g; + s/MAKE_MISC_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_misc_index("$1")/g; + s/constNum\s*[(]([^,]+)[)]/_node_factory.new_number_node($1)/g; # Grid creation. - s/MAKE_GRID[(]([^,]+),\s*([^)]+)[)]/auto $1 = yc_grid_var("$1", get_solution(), { $2 })/g; - s/MAKE_ARRAY[(]([^,]+),\s*([^)]+)[)]/auto $1 = yc_grid_var("$1", get_solution(), { $2 })/g; - s/MAKE_SCALAR[(]([^,]+)[)]/auto $1 = yc_grid_var("$1", get_solution(), { })/g; - s/MAKE_SCRATCH_GRID[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; - s/MAKE_SCRATCH_ARRAY[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; - s/MAKE_SCRATCH_SCALAR[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { }, true)/g; + s/MAKE_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 })/g; + s/MAKE_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 })/g; + s/MAKE_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { })/g; + s/MAKE_SCRATCH_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; + s/MAKE_SCRATCH_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; + s/MAKE_SCRATCH_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { }, true)/g; # Typenames. s/\bStencilBase\b/yc_solution_base/g; @@ -138,12 +145,14 @@ ($) close INF; if ($OPT{in_place}) { - open OUTF, ">$fname" or die("error: cannot write back to '$fname'\n"); + # Backup original. my $fbak = $fname."~"; rename "$fname", $fbak or die("error: cannot rename original file to '$fbak'\n"); warn " Original code saved in '$fbak'.\n"; + # Write new code to original filename. + open OUTF, ">$fname" or die("error: cannot write back to '$fname'\n"); print OUTF $result; close OUTF; warn " Converted code written back to '$fname'.\n". From 9d7a0f6ff5e3df7da26fa7538339afa50b6bb4a2 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 7 May 2019 08:37:08 -0700 Subject: [PATCH 16/62] Add more wrappers to yc_solution_base. --- include/Soln.hpp | 27 ++----- include/yask_compiler_utility_api.hpp | 79 ++++++++++++++----- src/stencils/AwpElasticStencil.cpp | 10 +-- src/stencils/AwpStencil.cpp | 8 +- .../ElasticStencil/Elastic2Stencil.hpp | 34 ++++---- .../ElasticStencil/ElasticStencil.hpp | 16 ++-- src/stencils/ExampleStencil.cpp | 8 +- src/stencils/FSGElastic2Stencil.cpp | 42 +++++----- src/stencils/FSGElasticStencil.cpp | 6 +- src/stencils/Iso3dfdStencil.cpp | 8 +- src/stencils/SSGElastic2Stencil.cpp | 8 +- src/stencils/SimpleTestStencils.cpp | 48 +++++------ src/stencils/TTIStencil.cpp | 8 +- utils/bin/convert_v2_stencil.pl | 10 ++- 14 files changed, 171 insertions(+), 141 deletions(-) diff --git a/include/Soln.hpp b/include/Soln.hpp index 8c814603..ef7ab231 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -55,16 +55,6 @@ namespace yask { /// Backward-compatibility contructor. StencilBase(const std::string& name, StencilList& stencils) : yc_solution_base(name) { } - - /// Create a constant expression. - /** - Usually not needed due to operator overloading. - New DSL code should use new_const_number_node() or - simply new_number_node(). - */ - virtual yc_number_node_ptr constNum(double val) { - return _node_factory.new_const_number_node(val); - } }; /// **[Deprecated]** A base class for stencils that have a 'radius'. @@ -75,12 +65,6 @@ namespace yask { /// Backward-compatibility constructor. StencilRadiusBase(const std::string& name, StencilList& stencils, int radius) : yc_solution_with_radius_base(name, radius) { } - - /// Create a constant expression. - /** Usually not needed due to operator overloading. */ - virtual yc_number_node_ptr constNum(double val) { - return _node_factory.new_const_number_node(val); - } }; // Aliases for backward-compatibility. @@ -108,9 +92,9 @@ namespace yask { // Convenience macros for declaring dims in a class derived from \ref StencilBase. // The 'd' arg is the new var name and the dim name. -#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = _node_factory.new_step_index(#d) -#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = _node_factory.new_domain_index(#d) -#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = _node_factory.new_misc_index(#d) +#define MAKE_STEP_INDEX(d) yc_index_node_ptr d = new_step_index(#d) +#define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = new_domain_index(#d) +#define MAKE_MISC_INDEX(d) yc_index_node_ptr d = new_misc_index(#d) // Convenience macros for creating grids in a class implementing get_solution(). // The 'gvar' arg is the var name and the grid name. @@ -124,6 +108,11 @@ namespace yask { #define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) #define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) +// Old namespace-level functions that are now part of yc_solution_base. +#define constNum(n) new_number_node(n) +#define first_index(d) first_domain_index(d) +#define last_index(d) last_domain_index(d) + // Old aliases for operators. #define EQUALS_OPER EQUALS #define IS_EQUIV_TO EQUALS diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index b99cce74..70f040c7 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -54,7 +54,7 @@ namespace yask { call yc_factory::new_solution directly. */ class yc_solution_base { - protected: + private: /// Pointer to the YASK stencil solution. yc_solution_ptr _soln; @@ -106,34 +106,66 @@ namespace yask { could be called from `main()` or any other called function. */ virtual void define() { - std::cout << "Warning: no stencil equations are defined in solution '" << - _soln->get_name() << "'. Implement the 'define()' method in the class " - "derived from 'yc_solution_base'.\n"; + yask_exception e("Error: no stencil equations are defined in solution '" + + get_solution()->get_name() + + "'. Implement the 'define()' method in the class " + "derived from 'yc_solution_base'"); + throw e; } /// Access the underlying solution. - virtual yc_solution_ptr get_solution() { + virtual yc_solution_ptr + get_solution() { return _soln; } - /// Create boundary index expression, e.g., 'first_index(x)'. - virtual yc_number_node_ptr first_index(yc_index_node_ptr dim) { + /// A simple wrapper for yc_node_factory::new_step_index(). + virtual yc_index_node_ptr + new_step_index(const std::string& name) { + return _node_factory.new_step_index(name); + } + + /// A simple wrapper for yc_node_factory::new_domain_index(). + virtual yc_index_node_ptr + new_domain_index(const std::string& name) { + return _node_factory.new_domain_index(name); + } + + /// A simple wrapper for yc_node_factory::new_misc_index(). + virtual yc_index_node_ptr + new_misc_index(const std::string& name) { + return _node_factory.new_misc_index(name); + } + + /// A simple wrapper for yc_node_factory::new_number_node(). + virtual yc_number_node_ptr + new_number_node(yc_number_any_arg arg) { + return _node_factory.new_number_node(arg); + } + + /// A simple wrapper for yc_node_factory::new_first_domain_index(). + virtual yc_number_node_ptr + first_domain_index(yc_index_node_ptr dim) { return _node_factory.new_first_domain_index(dim); } - /// Create boundary index expression, e.g., 'last_index(x)'. - virtual yc_number_node_ptr last_index(yc_index_node_ptr dim) { + /// A simple wrapper for yc_node_factory::new_last_domain_index(). + virtual yc_number_node_ptr + last_domain_index(yc_index_node_ptr dim) { return _node_factory.new_last_domain_index(dim); } /// This solution does _not_ use the "radius" sizing feature. - virtual bool uses_radius() const { return false; } + virtual bool + uses_radius() const { return false; } /// Dummy function for setting radius. - virtual bool set_radius(int radius) { return false; } + virtual bool + set_radius(int radius) { return false; } /// Dummy function for accessing radius. - virtual int get_radius() const { return 0; } + virtual int + get_radius() const { return 0; } }; /// A base class for stencils that have a 'radius'. @@ -161,25 +193,32 @@ namespace yask { /** See yc_solution_base::define(). */ - virtual void define() override { - std::cout << "Warning: no stencil equations are defined in solution '" << - _soln->get_name() << "'. Implement the 'define()' method in the class " - "derived from 'yc_solution_with_radius_base'.\n"; + virtual void + define() override { + yask_exception e("Error: no stencil equations are defined in solution '" + + get_solution()->get_name() + + "'. Implement the 'define()' method in the class " + "derived from 'yc_solution_with_radius_base'"); + throw e; } /// This object does use radius. - virtual bool uses_radius() const override { return true; } + virtual bool + uses_radius() const override { return true; } /// Set radius. /** @returns `true` if successful. */ - virtual bool set_radius(int radius) override { + virtual bool + set_radius(int radius) override { _radius = radius; - _soln->set_description(_soln->get_name() + " radius " + std::to_string(radius)); + auto soln = get_solution(); + soln->set_description(soln->get_name() + " radius " + std::to_string(radius)); return radius >= 0; // support only non-neg. radius. } /// Get radius. - virtual int get_radius() const override { return _radius; } + virtual int + get_radius() const override { return _radius; } }; /** @}*/ diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp index 7e71e642..6313e858 100644 --- a/src/stencils/AwpElasticStencil.cpp +++ b/src/stencils/AwpElasticStencil.cpp @@ -54,10 +54,10 @@ class AwpElasticStencil : public yc_solution_base { protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Time-varying 3D-spatial velocity grids. yc_grid_var vel_x = yc_grid_var("vel_x", get_solution(), { t, x, y, z }); @@ -99,7 +99,7 @@ class AwpElasticStencil : public yc_solution_base { // above the surface. Since we can only write into the "domain", we // will define the surface index to be 2 points before the last domain // index. Thus, there will be two layers in the domain above the surface. -#define SURFACE_IDX (last_index(z) - 2) +#define SURFACE_IDX (last_domain_index(z) - 2) // Define some sub-domains related to the surface. #define IF_BELOW_SURFACE IF_DOMAIN (z < SURFACE_IDX) diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index db2ed75b..0eb8a8f4 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -40,10 +40,10 @@ class AwpStencil : public yc_solution_base { protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Time-varying 3D-spatial velocity grids. yc_grid_var vel_x = yc_grid_var("vel_x", get_solution(), { t, x, y, z }); diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index fba44f35..56cdeca2 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -36,16 +36,16 @@ class Elastic2BoundaryCondition : public yc_solution_base protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // yc_grid_var selectors. - yc_index_node_ptr vidx = _node_factory.new_misc_index("vidx"); - yc_index_node_ptr sidx = _node_factory.new_misc_index("sidx"); - yc_index_node_ptr cidx = _node_factory.new_misc_index("cidx"); - yc_index_node_ptr spidx = _node_factory.new_misc_index("spidx"); + yc_index_node_ptr vidx = new_misc_index("vidx"); + yc_index_node_ptr sidx = new_misc_index("sidx"); + yc_index_node_ptr cidx = new_misc_index("cidx"); + yc_index_node_ptr spidx = new_misc_index("spidx"); public: Elastic2BoundaryCondition(yc_solution_base& base) : @@ -62,15 +62,15 @@ class Elastic2StencilBase : public yc_solution_base { protected: // Dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // yc_grid_var selectors. - yc_index_node_ptr vidx = _node_factory.new_misc_index("vidx"); - yc_index_node_ptr sidx = _node_factory.new_misc_index("sidx"); - yc_index_node_ptr cidx = _node_factory.new_misc_index("cidx"); + yc_index_node_ptr vidx = new_misc_index("vidx"); + yc_index_node_ptr sidx = new_misc_index("sidx"); + yc_index_node_ptr cidx = new_misc_index("cidx"); // 3D-spatial coefficients. yc_grid_var coef = yc_grid_var("coef", get_solution(), { x, y, z, cidx }); @@ -255,8 +255,8 @@ class Elastic2StencilBase : public yc_solution_base { yc_grid_var& v, int vidx, yc_grid_var& s, int sx_idx, int sy_idx, int sz_idx) { define_vel(t, x, y, z, - v, _node_factory.new_number_node(vidx), - s, _node_factory.new_number_node(sx_idx), _node_factory.new_number_node(sy_idx), _node_factory.new_number_node(sz_idx)); + v, new_number_node(vidx), + s, new_number_node(sx_idx), new_number_node(sy_idx), new_number_node(sz_idx)); } yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index 44a83107..1f478042 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -54,10 +54,10 @@ class ElasticBoundaryCondition : public yc_solution_base protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. public: ElasticBoundaryCondition(yc_solution_base& base) : @@ -74,10 +74,10 @@ class ElasticStencilBase : public yc_solution_base { protected: // Dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // 3D-spatial coefficients. yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); diff --git a/src/stencils/ExampleStencil.cpp b/src/stencils/ExampleStencil.cpp index c568dfe3..47aa8b0c 100644 --- a/src/stencils/ExampleStencil.cpp +++ b/src/stencils/ExampleStencil.cpp @@ -38,10 +38,10 @@ class AvePtsStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying 3D grid. diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index dda732bc..13724dbd 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -121,7 +121,7 @@ namespace fsg { template yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, int cidx) { - return cell_coeff(x, y, z, c, _node_factory.new_number_node(cidx)); + return cell_coeff(x, y, z, c, new_number_node(cidx)); } yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, @@ -163,7 +163,7 @@ namespace fsg { yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, int cidx) { - return cell_coeff_artm( x, y, z, c, _node_factory.new_number_node(cidx)); + return cell_coeff_artm( x, y, z, c, new_number_node(cidx)); } yc_number_node_ptr stress_update( yc_number_node_ptr c1, yc_number_node_ptr c2, yc_number_node_ptr c3, @@ -273,11 +273,11 @@ namespace fsg { int vyu_idx, int vyv_idx, int vyw_idx, int vzu_idx, int vzv_idx, int vzw_idx) { define_str(t, x, y, z, - _node_factory.new_number_node(sxx_idx), _node_factory.new_number_node(syy_idx), _node_factory.new_number_node(szz_idx), - _node_factory.new_number_node(sxy_idx), _node_factory.new_number_node(sxz_idx), _node_factory.new_number_node(syz_idx), - _node_factory.new_number_node(vxu_idx), _node_factory.new_number_node(vxv_idx), _node_factory.new_number_node(vxw_idx), - _node_factory.new_number_node(vyu_idx), _node_factory.new_number_node(vyv_idx), _node_factory.new_number_node(vyw_idx), - _node_factory.new_number_node(vzu_idx), _node_factory.new_number_node(vzv_idx), _node_factory.new_number_node(vzw_idx)); + new_number_node(sxx_idx), new_number_node(syy_idx), new_number_node(szz_idx), + new_number_node(sxy_idx), new_number_node(sxz_idx), new_number_node(syz_idx), + new_number_node(vxu_idx), new_number_node(vxv_idx), new_number_node(vxw_idx), + new_number_node(vyu_idx), new_number_node(vyv_idx), new_number_node(vyw_idx), + new_number_node(vzu_idx), new_number_node(vzv_idx), new_number_node(vzw_idx)); } // Call all the define_* functions. @@ -341,9 +341,9 @@ namespace fsg { yc_bool_node_ptr is_at_boundary() { yc_bool_node_ptr bc = - (z < first_index(z)+abc_width || z > last_index(z)-abc_width) || - (y < first_index(y)+abc_width || y > last_index(y)-abc_width) || - (x < first_index(x)+abc_width || x > last_index(x)-abc_width); + (z < first_domain_index(z)+abc_width || z > last_domain_index(z)-abc_width) || + (y < first_domain_index(y)+abc_width || y > last_domain_index(y)-abc_width) || + (x < first_domain_index(x)+abc_width || x > last_domain_index(x)-abc_width); return bc; } yc_bool_node_ptr is_not_at_boundary() @@ -383,10 +383,10 @@ namespace fsg { int abc_x_idx, int abc_y_idx, int abc_z_idx, int abc_sq_x_idx, int abc_sq_y_idx, int abc_sq_z_idx) { define_vel_abc(t, x, y, z, - _node_factory.new_number_node(vidx), - _node_factory.new_number_node(sx_idx), _node_factory.new_number_node(sy_idx), _node_factory.new_number_node(sz_idx), - _node_factory.new_number_node(abc_x_idx), _node_factory.new_number_node(abc_y_idx), _node_factory.new_number_node(abc_z_idx), - _node_factory.new_number_node(abc_sq_x_idx), _node_factory.new_number_node(abc_sq_y_idx), _node_factory.new_number_node(abc_sq_z_idx)); + new_number_node(vidx), + new_number_node(sx_idx), new_number_node(sy_idx), new_number_node(sz_idx), + new_number_node(abc_x_idx), new_number_node(abc_y_idx), new_number_node(abc_z_idx), + new_number_node(abc_sq_x_idx), new_number_node(abc_sq_y_idx), new_number_node(abc_sq_z_idx)); } void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) @@ -500,13 +500,13 @@ namespace fsg { int abc_x_idx, int abc_y_idx, int abc_z_idx, int abc_sq_x_idx, int abc_sq_y_idx, int abc_sq_z_idx) { define_str_abc(t, x, y, z, - _node_factory.new_number_node(sxx_idx), _node_factory.new_number_node(syy_idx), _node_factory.new_number_node(szz_idx), - _node_factory.new_number_node(sxy_idx), _node_factory.new_number_node(sxz_idx), _node_factory.new_number_node(syz_idx), - _node_factory.new_number_node(vxu_idx), _node_factory.new_number_node(vxv_idx), _node_factory.new_number_node(vxw_idx), - _node_factory.new_number_node(vyu_idx), _node_factory.new_number_node(vyv_idx), _node_factory.new_number_node(vyw_idx), - _node_factory.new_number_node(vzu_idx), _node_factory.new_number_node(vzv_idx), _node_factory.new_number_node(vzw_idx), - _node_factory.new_number_node(abc_x_idx), _node_factory.new_number_node(abc_y_idx), _node_factory.new_number_node(abc_z_idx), - _node_factory.new_number_node(abc_sq_x_idx), _node_factory.new_number_node(abc_sq_y_idx), _node_factory.new_number_node(abc_sq_z_idx)); + new_number_node(sxx_idx), new_number_node(syy_idx), new_number_node(szz_idx), + new_number_node(sxy_idx), new_number_node(sxz_idx), new_number_node(syz_idx), + new_number_node(vxu_idx), new_number_node(vxv_idx), new_number_node(vxw_idx), + new_number_node(vyu_idx), new_number_node(vyv_idx), new_number_node(vyw_idx), + new_number_node(vzu_idx), new_number_node(vzv_idx), new_number_node(vzw_idx), + new_number_node(abc_x_idx), new_number_node(abc_y_idx), new_number_node(abc_z_idx), + new_number_node(abc_sq_x_idx), new_number_node(abc_sq_y_idx), new_number_node(abc_sq_z_idx)); } void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index 8e7f4eec..33180733 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -346,9 +346,9 @@ namespace fsg { yc_bool_node_ptr is_at_boundary() { yc_bool_node_ptr bc = - ( z < first_index(z)+abc_width || z > last_index(z)-abc_width ) || - ( y < first_index(y)+abc_width || y > last_index(y)-abc_width ) || - ( x < first_index(x)+abc_width || x > last_index(x)-abc_width ); + ( z < first_domain_index(z)+abc_width || z > last_domain_index(z)-abc_width ) || + ( y < first_domain_index(y)+abc_width || y > last_domain_index(y)-abc_width ) || + ( x < first_domain_index(x)+abc_width || x > last_domain_index(x)-abc_width ); return bc; } yc_bool_node_ptr is_not_at_boundary() diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index a0d0693f..5ba5900e 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -37,10 +37,10 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Grid vars. yc_grid_var pressure = diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index a56559a8..d6a19984 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -106,7 +106,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, int sidx, int va_idx, int vb_idx) { define_str(t, x, y, z, - _node_factory.new_number_node(sidx), _node_factory.new_number_node(va_idx), _node_factory.new_number_node(vb_idx)); + new_number_node(sidx), new_number_node(va_idx), new_number_node(vb_idx)); } void define_str_TL(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) @@ -115,9 +115,9 @@ class SSGElastic2Stencil : public Elastic2StencilBase { yc_number_node_ptr ilambdamu2 = 1.0 / coef(x,y,z, C_LAMBDA_MU2); yc_number_node_ptr ilambda = 1.0 / coef(x,y,z, C_LAMBDA); - yc_number_node_ptr vtx = stencil_O8( t+1, x, y, z, v, _node_factory.new_number_node(V_TR_U) ); - yc_number_node_ptr vty = stencil_O8( t+1, x, y, z, v, _node_factory.new_number_node(V_TL_V) ); - yc_number_node_ptr vtz = stencil_O8( t+1, x, y, z, v, _node_factory.new_number_node(V_BL_W) ); + yc_number_node_ptr vtx = stencil_O8( t+1, x, y, z, v, new_number_node(V_TR_U) ); + yc_number_node_ptr vty = stencil_O8( t+1, x, y, z, v, new_number_node(V_TL_V) ); + yc_number_node_ptr vtz = stencil_O8( t+1, x, y, z, v, new_number_node(V_BL_W) ); yc_number_node_ptr next_xx = s(t, x, y, z, S_TL_XX) + ilambdamu2 * vtx * delta_t + ilambda * vty * delta_t diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/SimpleTestStencils.cpp index 064f101e..6206396f 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/SimpleTestStencils.cpp @@ -37,11 +37,11 @@ class TestBase : public yc_solution_with_radius_base { // Indices & dimensions. // Not all these will be used in all tests. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr w = _node_factory.new_domain_index("w"); // spatial dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr w = new_domain_index("w"); // spatial dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Define some stencils in different dimensions. // These will be asymmetrical if any of the '*_ext' params are not 0; @@ -325,12 +325,12 @@ class TestMisc2dStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr a = _node_factory.new_misc_index("a"); - yc_index_node_ptr b = _node_factory.new_misc_index("b"); - yc_index_node_ptr c = _node_factory.new_misc_index("c"); + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr a = new_misc_index("a"); + yc_index_node_ptr b = new_misc_index("b"); + yc_index_node_ptr c = new_misc_index("c"); // Time-varying grid. Intermix last domain dim with misc dims to make // sure compiler creates correct layout. @@ -376,10 +376,10 @@ class StreamStencil : public yc_solution_with_radius_base { protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying 3D grid. @@ -393,7 +393,7 @@ class StreamStencil : public yc_solution_with_radius_base { // Define equation to read '_radius' values and write one. virtual void define() { - yc_number_node_ptr v = _node_factory.new_number_node(1.0); + yc_number_node_ptr v = new_number_node(1.0); // Add '_radius' values from past time-steps. for (int r = 0; r < _radius; r++) @@ -618,7 +618,7 @@ class TestBoundaryStencil1 : public TestBase { virtual void define() { // Define interior sub-domain. - yc_bool_node_ptr sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3); + yc_bool_node_ptr sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); // Define interior points. yc_number_node_ptr u = def_1d(A, t, x, 0, 1); @@ -651,8 +651,8 @@ class TestBoundaryStencil2 : public TestBase { // Sub-domain is rectangle interior. yc_bool_node_ptr sd0 = - (x >= first_index(x) + 5) && (x <= last_index(x) - 3) && - (y >= first_index(y) + 4) && (y <= last_index(y) - 6); + (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && + (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6); // Set A w/different stencils depending on condition. A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 1, 0) IF_DOMAIN sd0; @@ -682,9 +682,9 @@ class TestBoundaryStencil3 : public TestBase { // Sub-domain is rectangle interior. yc_bool_node_ptr sd0 = - (x >= first_index(x) + 5) && (x <= last_index(x) - 3) && - (y >= first_index(y) + 4) && (y <= last_index(y) - 6) && - (z >= first_index(z) + 6) && (z <= last_index(z) - 4); + (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && + (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6) && + (z >= first_domain_index(z) + 6) && (z <= last_domain_index(z) - 4); // Set A w/different stencils depending on condition. A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 1, 0, z, 0, 1) IF_DOMAIN sd0; @@ -703,7 +703,7 @@ class TestStepCondStencil1 : public TestBase { protected: // Indices. - yc_index_node_ptr b = _node_factory.new_misc_index("b"); + yc_index_node_ptr b = new_misc_index("b"); // Vars. yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. @@ -767,7 +767,7 @@ class TestScratchBoundaryStencil1 : public TestBase { B(x) EQUALS def_1d(A, t, x, 1, 0); // Define sub-domain. - yc_bool_node_ptr sd0 = (x >= first_index(x) + 5) && (x <= last_index(x) - 3); + yc_bool_node_ptr sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); // Define next values for 'A' from scratch var values. auto v = def_no_t_1d(B, x-6, 2, 3) - def_no_t_1d(B, x+7, 0, 2); diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index e47e055a..9fddfe21 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -37,10 +37,10 @@ class TTIStencil:public yc_solution_with_radius_base protected: // Indices & dimensions. - yc_index_node_ptr t = _node_factory.new_step_index("t"); // step in time dim. - yc_index_node_ptr x = _node_factory.new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = _node_factory.new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = _node_factory.new_domain_index("z"); // spatial dim. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Grid vars. yc_grid_var u = yc_grid_var("u", get_solution(), { t, x, y, z }); // Time-varying 3D wavefield grid. diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index c469082a..1159a099 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -101,10 +101,12 @@ ($) } # Node creation. - s/MAKE_STEP_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_step_index("$1")/g; - s/MAKE_DOMAIN_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_domain_index("$1")/g; - s/MAKE_MISC_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = _node_factory.new_misc_index("$1")/g; - s/constNum\s*[(]([^,]+)[)]/_node_factory.new_number_node($1)/g; + s/MAKE_STEP_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = new_step_index("$1")/g; + s/MAKE_DOMAIN_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = new_domain_index("$1")/g; + s/MAKE_MISC_INDEX\s*[(]([^)]+)[)]/yc_index_node_ptr $1 = new_misc_index("$1")/g; + s/\bconstNum\b/new_number_node/g; + s/\bfirst_index\b/first_domain_index/g; + s/\blast_index\b/last_domain_index/g; # Grid creation. s/MAKE_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 })/g; From 9b6fb3bd61b30aa2942b375ec33a53117bea927b Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 7 May 2019 11:43:42 -0700 Subject: [PATCH 17/62] Shorten 'get_solution()' to 'get_soln()' and use 'auto' in stencils where possible. --- README.md | 2 +- include/Soln.hpp | 6 +- include/yask_compiler_utility_api.hpp | 32 +- src/compiler/compiler_main.cpp | 20 +- src/stencils/AwpElasticStencil.cpp | 104 +++--- src/stencils/AwpStencil.cpp | 164 +++++----- .../ElasticStencil/Elastic2Stencil.hpp | 2 +- .../ElasticStencil/ElasticStencil.hpp | 12 +- src/stencils/ExampleStencil.cpp | 2 +- src/stencils/FSGElastic2Stencil.cpp | 169 +++++----- src/stencils/FSGElasticStencil.cpp | 298 +++++++++--------- src/stencils/Iso3dfdStencil.cpp | 18 +- src/stencils/SSGElastic2Stencil.cpp | 28 +- src/stencils/SSGElasticStencil.cpp | 48 +-- src/stencils/SimpleTestStencils.cpp | 92 +++--- src/stencils/TTIStencil.cpp | 228 +++++++------- utils/bin/convert_v2_stencil.pl | 12 +- 17 files changed, 613 insertions(+), 624 deletions(-) diff --git a/README.md b/README.md index 759d7981..3a6b4e1c 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ YASK contains a domain-specific compiler to convert scalar stencil code to SIMD- ## Backward-compatibility notices, including changes in default behavior ### Version 3 * Version 3.00.00 implemented a unification of the old (v2) internal DSL with the YASK compiler API. -Most v2 DSL code should still work using the "Soln.hpp" backward-compatibility header file. +Canonical v2 DSL code should still work using the `Soln.hpp` backward-compatibility header file. To convert v2 DSL code to v3 format, use the `./utils/bin/convert_v2_stencil.pl` utility. ### Version 2 diff --git a/include/Soln.hpp b/include/Soln.hpp index ef7ab231..20f0dad9 100644 --- a/include/Soln.hpp +++ b/include/Soln.hpp @@ -96,15 +96,15 @@ namespace yask { #define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = new_domain_index(#d) #define MAKE_MISC_INDEX(d) yc_index_node_ptr d = new_misc_index(#d) -// Convenience macros for creating grids in a class implementing get_solution(). +// Convenience macros for creating grids in a class implementing get_soln(). // The 'gvar' arg is the var name and the grid name. // The remaining args are the dimension names. #define MAKE_GRID(gvar, ...) \ - yc_grid_var gvar = yc_grid_var(#gvar, get_solution(), { __VA_ARGS__ }, false) + yc_grid_var gvar = yc_grid_var(#gvar, get_soln(), { __VA_ARGS__ }, false) #define MAKE_SCALAR(gvar) MAKE_GRID(gvar) #define MAKE_ARRAY(gvar, d1) MAKE_GRID(gvar, d1) #define MAKE_SCRATCH_GRID(gvar, ...) \ - yc_grid_var gvar = yc_grid_var(#gvar, get_solution(), { __VA_ARGS__ }, true) + yc_grid_var gvar = yc_grid_var(#gvar, get_soln(), { __VA_ARGS__ }, true) #define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) #define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index 70f040c7..d14166cc 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -84,7 +84,7 @@ namespace yask { explicitly. */ yc_solution_base(yc_solution_base& base) { - _soln = base.get_solution(); + _soln = base.get_soln(); } /// Destructor. @@ -107,7 +107,7 @@ namespace yask { */ virtual void define() { yask_exception e("Error: no stencil equations are defined in solution '" + - get_solution()->get_name() + + get_soln()->get_name() + "'. Implement the 'define()' method in the class " "derived from 'yc_solution_base'"); throw e; @@ -115,7 +115,7 @@ namespace yask { /// Access the underlying solution. virtual yc_solution_ptr - get_solution() { + get_soln() { return _soln; } @@ -154,21 +154,9 @@ namespace yask { last_domain_index(yc_index_node_ptr dim) { return _node_factory.new_last_domain_index(dim); } - - /// This solution does _not_ use the "radius" sizing feature. - virtual bool - uses_radius() const { return false; } - - /// Dummy function for setting radius. - virtual bool - set_radius(int radius) { return false; } - - /// Dummy function for accessing radius. - virtual int - get_radius() const { return 0; } }; - /// A base class for stencils that have a 'radius'. + /// A base class for stencils that have a 'radius' size parameter. class yc_solution_with_radius_base : public yc_solution_base { protected: @@ -196,29 +184,25 @@ namespace yask { virtual void define() override { yask_exception e("Error: no stencil equations are defined in solution '" + - get_solution()->get_name() + + get_soln()->get_name() + "'. Implement the 'define()' method in the class " "derived from 'yc_solution_with_radius_base'"); throw e; } - /// This object does use radius. - virtual bool - uses_radius() const override { return true; } - /// Set radius. /** @returns `true` if successful. */ virtual bool - set_radius(int radius) override { + set_radius(int radius) { _radius = radius; - auto soln = get_solution(); + auto soln = get_soln(); soln->set_description(soln->get_name() + " radius " + std::to_string(radius)); return radius >= 0; // support only non-neg. radius. } /// Get radius. virtual int - get_radius() const override { return _radius; } + get_radius() const { return _radius; } }; /** @}*/ diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 738da0f2..32cb705a 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -98,9 +98,12 @@ void usage(const string& cmd) { for (auto si : stencils) { auto name = si.first; if ((name.rfind("test_", 0) == 0) == show_test) { - auto sp = si.second; + auto* sp = si.second; cout << " " << name; - if (sp->uses_radius()) + + // Add asterisk for solns with a radius. + auto* srp = dynamic_cast(sp); + if (srp) cout << " *"; cout << endl; } @@ -385,19 +388,22 @@ void parseOpts(int argc, const char* argv[]) } stencilSoln = stencilIter->second; assert(stencilSoln); - auto soln = stencilSoln->get_solution(); + auto soln = stencilSoln->get_soln(); cout << "Stencil-solution name: " << soln->get_name() << endl; - if (stencilSoln->uses_radius()) { + + // Set radius if applicable. + auto* srp = dynamic_cast(stencilSoln); + if (srp) { if (radius >= 0) { - bool rOk = stencilSoln->set_radius(radius); + bool rOk = srp->set_radius(radius); if (!rOk) { cerr << "Error: invalid radius=" << radius << " for stencil type '" << solutionName << "'." << endl; usage(argv[0]); } } - cout << "Stencil radius: " << stencilSoln->get_radius() << endl; + cout << "Stencil radius: " << srp->get_radius() << endl; } cout << "Stencil-solution description: " << soln->get_description() << endl; @@ -439,7 +445,7 @@ int main(int argc, const char* argv[]) { os = ofac.new_stdout_output(); else os = ofac.new_file_output(fname); - stencilSoln->get_solution()->format(type, os); + stencilSoln->get_soln()->format(type, os); } } catch (yask_exception& e) { cerr << "YASK Stencil Compiler: " << e.get_message() << ".\n"; diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp index 6313e858..db294a51 100644 --- a/src/stencils/AwpElasticStencil.cpp +++ b/src/stencils/AwpElasticStencil.cpp @@ -60,31 +60,31 @@ class AwpElasticStencil : public yc_solution_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Time-varying 3D-spatial velocity grids. - yc_grid_var vel_x = yc_grid_var("vel_x", get_solution(), { t, x, y, z }); - yc_grid_var vel_y = yc_grid_var("vel_y", get_solution(), { t, x, y, z }); - yc_grid_var vel_z = yc_grid_var("vel_z", get_solution(), { t, x, y, z }); + yc_grid_var vel_x = yc_grid_var("vel_x", get_soln(), { t, x, y, z }); + yc_grid_var vel_y = yc_grid_var("vel_y", get_soln(), { t, x, y, z }); + yc_grid_var vel_z = yc_grid_var("vel_z", get_soln(), { t, x, y, z }); // Time-varying 3D-spatial Stress grids. - yc_grid_var stress_xx = yc_grid_var("stress_xx", get_solution(), { t, x, y, z }); - yc_grid_var stress_yy = yc_grid_var("stress_yy", get_solution(), { t, x, y, z }); - yc_grid_var stress_zz = yc_grid_var("stress_zz", get_solution(), { t, x, y, z }); - yc_grid_var stress_xy = yc_grid_var("stress_xy", get_solution(), { t, x, y, z }); - yc_grid_var stress_xz = yc_grid_var("stress_xz", get_solution(), { t, x, y, z }); - yc_grid_var stress_yz = yc_grid_var("stress_yz", get_solution(), { t, x, y, z }); + yc_grid_var stress_xx = yc_grid_var("stress_xx", get_soln(), { t, x, y, z }); + yc_grid_var stress_yy = yc_grid_var("stress_yy", get_soln(), { t, x, y, z }); + yc_grid_var stress_zz = yc_grid_var("stress_zz", get_soln(), { t, x, y, z }); + yc_grid_var stress_xy = yc_grid_var("stress_xy", get_soln(), { t, x, y, z }); + yc_grid_var stress_xz = yc_grid_var("stress_xz", get_soln(), { t, x, y, z }); + yc_grid_var stress_yz = yc_grid_var("stress_yz", get_soln(), { t, x, y, z }); // 3D-spatial Lame' coefficients. - yc_grid_var lambda = yc_grid_var("lambda", get_solution(), { x, y, z }); - yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); - yc_grid_var mu = yc_grid_var("mu", get_solution(), { x, y, z }); + yc_grid_var lambda = yc_grid_var("lambda", get_soln(), { x, y, z }); + yc_grid_var rho = yc_grid_var("rho", get_soln(), { x, y, z }); + yc_grid_var mu = yc_grid_var("mu", get_soln(), { x, y, z }); // Sponge coefficients. // (Most of these will be 1.0.) #ifdef FULL_SPONGE_GRID - yc_grid_var sponge = yc_grid_var("sponge", get_solution(), { x, y, z }); + yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z }); #else - yc_grid_var cr_x = yc_grid_var("cr_x", get_solution(), { x }); - yc_grid_var cr_y = yc_grid_var("cr_y", get_solution(), { y }); - yc_grid_var cr_z = yc_grid_var("cr_z", get_solution(), { z }); + yc_grid_var cr_x = yc_grid_var("cr_x", get_soln(), { x }); + yc_grid_var cr_y = yc_grid_var("cr_y", get_soln(), { y }); + yc_grid_var cr_z = yc_grid_var("cr_z", get_soln(), { z }); #endif // Spatial FD coefficients. @@ -92,8 +92,8 @@ class AwpElasticStencil : public yc_solution_base { const double c2 = -1.0/24.0; // Physical dimensions in time and space. - yc_grid_var delta_t = yc_grid_var("delta_t", get_solution(), { }); - yc_grid_var h = yc_grid_var("h", get_solution(), { }); + yc_grid_var delta_t = yc_grid_var("delta_t", get_soln(), { }); + yc_grid_var h = yc_grid_var("h", get_soln(), { }); // For the surface stress conditions, we need to write into 2 points // above the surface. Since we can only write into the "domain", we @@ -109,9 +109,9 @@ class AwpElasticStencil : public yc_solution_base { #define IF_TWO_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 2) #ifdef USE_SCRATCH_GRIDS - yc_grid_var tmp_vel_x = yc_grid_var("tmp_vel_x", get_solution(), { x, y, z }, true); - yc_grid_var tmp_vel_y = yc_grid_var("tmp_vel_y", get_solution(), { x, y, z }, true); - yc_grid_var tmp_vel_z = yc_grid_var("tmp_vel_z", get_solution(), { x, y, z }, true); + yc_grid_var tmp_vel_x = yc_grid_var("tmp_vel_x", get_soln(), { x, y, z }, true); + yc_grid_var tmp_vel_y = yc_grid_var("tmp_vel_y", get_soln(), { x, y, z }, true); + yc_grid_var tmp_vel_z = yc_grid_var("tmp_vel_z", get_soln(), { x, y, z }, true); #endif public: @@ -136,54 +136,54 @@ class AwpElasticStencil : public yc_solution_base { // appropriately. yc_number_node_ptr get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - yc_number_node_ptr rho_val = (rho(x, y, z ) + + auto rho_val = (rho(x, y, z ) + rho(x, y-1, z ) + rho(x, y, z-1) + rho(x, y-1, z-1)) * (1.0 / 4.0); - yc_number_node_ptr d_val = + auto d_val = c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - yc_number_node_ptr next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_x); // Return the value at t+1. return next_vel_x; } yc_number_node_ptr get_next_vel_y(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - yc_number_node_ptr rho_val = (rho(x, y, z ) + + auto rho_val = (rho(x, y, z ) + rho(x+1, y, z ) + rho(x, y, z-1) + rho(x+1, y, z-1)) * (1.0 / 4.0); - yc_number_node_ptr d_val = + auto d_val = c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - yc_number_node_ptr next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_y); // Return the value at t+1. return next_vel_y; } yc_number_node_ptr get_next_vel_z(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - yc_number_node_ptr rho_val = (rho(x, y, z) + + auto rho_val = (rho(x, y, z) + rho(x+1, y, z) + rho(x, y-1, z) + rho(x+1, y-1, z)) * (1.0 / 4.0); - yc_number_node_ptr d_val = + auto d_val = c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - yc_number_node_ptr next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_z); // Return the value at t+1. @@ -195,7 +195,7 @@ class AwpElasticStencil : public yc_solution_base { // Since we're defining points when z == surface + 1, // the surface itself will be at z - 1; - yc_number_node_ptr surf = z - 1; + auto surf = z - 1; #ifdef USE_SCRATCH_GRIDS @@ -222,17 +222,17 @@ class AwpElasticStencil : public yc_solution_base { #endif // A couple of intermediate values. - yc_number_node_ptr d_x_val = VEL_X(x+1, y, surf) - + auto d_x_val = VEL_X(x+1, y, surf) - (VEL_Z(x+1, y, surf) - VEL_Z(x, y, surf)); - yc_number_node_ptr d_y_val = VEL_Y(x, y-1, surf) - + auto d_y_val = VEL_Y(x, y-1, surf) - (VEL_Z(x, y, surf) - VEL_Z(x, y-1, surf)); // Following values are valid one layer above the free surface. - yc_number_node_ptr plus1_vel_x = VEL_X(x, y, surf) - + auto plus1_vel_x = VEL_X(x, y, surf) - (VEL_Z(x, y, surf) - VEL_Z(x-1, y, surf)); - yc_number_node_ptr plus1_vel_y = VEL_Y(x, y, surf) - + auto plus1_vel_y = VEL_Y(x, y, surf) - (VEL_Z(x, y+1, surf) - VEL_Z(x, y, surf)); - yc_number_node_ptr plus1_vel_z = VEL_Z(x, y, surf) - + auto plus1_vel_z = VEL_Z(x, y, surf) - ((d_x_val - plus1_vel_x) + (VEL_X(x+1, y, surf) - VEL_X(x, y, surf)) + (plus1_vel_y - d_y_val) + @@ -294,7 +294,7 @@ class AwpElasticStencil : public yc_solution_base { yc_number_node_ptr get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - yc_number_node_ptr next_stress_xx = stress_xx(t, x, y, z) + + auto next_stress_xx = stress_xx(t, x, y, z) + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_x_val(x, y, z)) + (ave8(lambda, x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); @@ -305,7 +305,7 @@ class AwpElasticStencil : public yc_solution_base { } yc_number_node_ptr get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - yc_number_node_ptr next_stress_yy = stress_yy(t, x, y, z) + + auto next_stress_yy = stress_yy(t, x, y, z) + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_y_val(x, y, z)) + (ave8(lambda, x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); @@ -316,7 +316,7 @@ class AwpElasticStencil : public yc_solution_base { } yc_number_node_ptr get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - yc_number_node_ptr next_stress_zz = stress_zz(t, x, y, z) + + auto next_stress_zz = stress_zz(t, x, y, z) + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_z_val(x, y, z)) + (ave8(lambda, x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); @@ -328,18 +328,18 @@ class AwpElasticStencil : public yc_solution_base { yc_number_node_ptr get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { // Compute average of 2 neighbors. - yc_number_node_ptr mu2 = 2.0 / + auto mu2 = 2.0 / (mu(x, y, z ) + mu(x, y, z-1)); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_xy_val = + auto d_xy_val = c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - yc_number_node_ptr d_yx_val = + auto d_yx_val = c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - yc_number_node_ptr next_stress_xy = stress_xy(t, x, y, z) + + auto next_stress_xy = stress_xy(t, x, y, z) + ((mu2 * delta_t / h) * (d_xy_val + d_yx_val)); adjust_for_sponge(next_stress_xy); @@ -349,18 +349,18 @@ class AwpElasticStencil : public yc_solution_base { yc_number_node_ptr get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { // Compute average of 2 neighbors. - yc_number_node_ptr mu2 = 2.0 / + auto mu2 = 2.0 / (mu(x, y, z ) + mu(x, y-1, z )); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_xz_val = + auto d_xz_val = c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - yc_number_node_ptr d_zx_val = + auto d_zx_val = c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - yc_number_node_ptr next_stress_xz = stress_xz(t, x, y, z) + + auto next_stress_xz = stress_xz(t, x, y, z) + ((mu2 * delta_t / h) * (d_xz_val + d_zx_val)); adjust_for_sponge(next_stress_xz); @@ -370,18 +370,18 @@ class AwpElasticStencil : public yc_solution_base { yc_number_node_ptr get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { // Compute average of 2 neighbors. - yc_number_node_ptr mu2 = 2.0 / + auto mu2 = 2.0 / (mu(x, y, z ) + mu(x+1, y, z )); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_yz_val = + auto d_yz_val = c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - yc_number_node_ptr d_zy_val = + auto d_zy_val = c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - yc_number_node_ptr next_stress_yz = stress_yz(t, x, y, z) + + auto next_stress_yz = stress_yz(t, x, y, z) + ((mu2 * delta_t / h) * (d_yz_val + d_zy_val)); adjust_for_sponge(next_stress_yz); @@ -393,7 +393,7 @@ class AwpElasticStencil : public yc_solution_base { void define_free_surface_stress() { // When z == surface + 1, the surface will be at z - 1; - yc_number_node_ptr surf = z - 1; + auto surf = z - 1; stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf) IF_ONE_ABOVE_SURFACE; stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index 0eb8a8f4..a7192296 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -46,48 +46,48 @@ class AwpStencil : public yc_solution_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Time-varying 3D-spatial velocity grids. - yc_grid_var vel_x = yc_grid_var("vel_x", get_solution(), { t, x, y, z }); - yc_grid_var vel_y = yc_grid_var("vel_y", get_solution(), { t, x, y, z }); - yc_grid_var vel_z = yc_grid_var("vel_z", get_solution(), { t, x, y, z }); + yc_grid_var vel_x = yc_grid_var("vel_x", get_soln(), { t, x, y, z }); + yc_grid_var vel_y = yc_grid_var("vel_y", get_soln(), { t, x, y, z }); + yc_grid_var vel_z = yc_grid_var("vel_z", get_soln(), { t, x, y, z }); // Time-varying 3D-spatial Stress grids. - yc_grid_var stress_xx = yc_grid_var("stress_xx", get_solution(), { t, x, y, z }); - yc_grid_var stress_yy = yc_grid_var("stress_yy", get_solution(), { t, x, y, z }); - yc_grid_var stress_zz = yc_grid_var("stress_zz", get_solution(), { t, x, y, z }); - yc_grid_var stress_xy = yc_grid_var("stress_xy", get_solution(), { t, x, y, z }); - yc_grid_var stress_xz = yc_grid_var("stress_xz", get_solution(), { t, x, y, z }); - yc_grid_var stress_yz = yc_grid_var("stress_yz", get_solution(), { t, x, y, z }); + yc_grid_var stress_xx = yc_grid_var("stress_xx", get_soln(), { t, x, y, z }); + yc_grid_var stress_yy = yc_grid_var("stress_yy", get_soln(), { t, x, y, z }); + yc_grid_var stress_zz = yc_grid_var("stress_zz", get_soln(), { t, x, y, z }); + yc_grid_var stress_xy = yc_grid_var("stress_xy", get_soln(), { t, x, y, z }); + yc_grid_var stress_xz = yc_grid_var("stress_xz", get_soln(), { t, x, y, z }); + yc_grid_var stress_yz = yc_grid_var("stress_yz", get_soln(), { t, x, y, z }); // Time-varying attenuation memory grids. - yc_grid_var stress_mem_xx = yc_grid_var("stress_mem_xx", get_solution(), { t, x, y, z }); - yc_grid_var stress_mem_yy = yc_grid_var("stress_mem_yy", get_solution(), { t, x, y, z }); - yc_grid_var stress_mem_zz = yc_grid_var("stress_mem_zz", get_solution(), { t, x, y, z }); - yc_grid_var stress_mem_xy = yc_grid_var("stress_mem_xy", get_solution(), { t, x, y, z }); - yc_grid_var stress_mem_xz = yc_grid_var("stress_mem_xz", get_solution(), { t, x, y, z }); - yc_grid_var stress_mem_yz = yc_grid_var("stress_mem_yz", get_solution(), { t, x, y, z }); + yc_grid_var stress_mem_xx = yc_grid_var("stress_mem_xx", get_soln(), { t, x, y, z }); + yc_grid_var stress_mem_yy = yc_grid_var("stress_mem_yy", get_soln(), { t, x, y, z }); + yc_grid_var stress_mem_zz = yc_grid_var("stress_mem_zz", get_soln(), { t, x, y, z }); + yc_grid_var stress_mem_xy = yc_grid_var("stress_mem_xy", get_soln(), { t, x, y, z }); + yc_grid_var stress_mem_xz = yc_grid_var("stress_mem_xz", get_soln(), { t, x, y, z }); + yc_grid_var stress_mem_yz = yc_grid_var("stress_mem_yz", get_soln(), { t, x, y, z }); // 3D grids used for anelastic attenuation - yc_grid_var weight = yc_grid_var("weight", get_solution(), { x, y, z }); - yc_grid_var tau2 = yc_grid_var("tau2", get_solution(), { x, y, z }); - yc_grid_var anelastic_ap = yc_grid_var("anelastic_ap", get_solution(), { x, y, z }); - yc_grid_var anelastic_as_diag = yc_grid_var("anelastic_as_diag", get_solution(), { x, y, z }); - yc_grid_var anelastic_xy = yc_grid_var("anelastic_xy", get_solution(), { x, y, z }); - yc_grid_var anelastic_xz = yc_grid_var("anelastic_xz", get_solution(), { x, y, z }); - yc_grid_var anelastic_yz = yc_grid_var("anelastic_yz", get_solution(), { x, y, z }); + yc_grid_var weight = yc_grid_var("weight", get_soln(), { x, y, z }); + yc_grid_var tau2 = yc_grid_var("tau2", get_soln(), { x, y, z }); + yc_grid_var anelastic_ap = yc_grid_var("anelastic_ap", get_soln(), { x, y, z }); + yc_grid_var anelastic_as_diag = yc_grid_var("anelastic_as_diag", get_soln(), { x, y, z }); + yc_grid_var anelastic_xy = yc_grid_var("anelastic_xy", get_soln(), { x, y, z }); + yc_grid_var anelastic_xz = yc_grid_var("anelastic_xz", get_soln(), { x, y, z }); + yc_grid_var anelastic_yz = yc_grid_var("anelastic_yz", get_soln(), { x, y, z }); // 3D-spatial Lame' coefficients. - yc_grid_var lambda = yc_grid_var("lambda", get_solution(), { x, y, z }); - yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); - yc_grid_var mu = yc_grid_var("mu", get_solution(), { x, y, z }); + yc_grid_var lambda = yc_grid_var("lambda", get_soln(), { x, y, z }); + yc_grid_var rho = yc_grid_var("rho", get_soln(), { x, y, z }); + yc_grid_var mu = yc_grid_var("mu", get_soln(), { x, y, z }); // Sponge coefficients. // (Most of these will be 1.0.) #ifdef FULL_SPONGE_GRID - yc_grid_var sponge = yc_grid_var("sponge", get_solution(), { x, y, z }); + yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z }); #else - yc_grid_var cr_x = yc_grid_var("cr_x", get_solution(), { x }); - yc_grid_var cr_y = yc_grid_var("cr_y", get_solution(), { y }); - yc_grid_var cr_z = yc_grid_var("cr_z", get_solution(), { z }); + yc_grid_var cr_x = yc_grid_var("cr_x", get_soln(), { x }); + yc_grid_var cr_y = yc_grid_var("cr_y", get_soln(), { y }); + yc_grid_var cr_z = yc_grid_var("cr_z", get_soln(), { z }); #endif // Spatial FD coefficients. @@ -95,8 +95,8 @@ class AwpStencil : public yc_solution_base { const double c2 = -1.0/24.0; // Physical dimensions in time and space. - yc_grid_var delta_t = yc_grid_var("delta_t", get_solution(), { }); - yc_grid_var h = yc_grid_var("h", get_solution(), { }); + yc_grid_var delta_t = yc_grid_var("delta_t", get_soln(), { }); + yc_grid_var h = yc_grid_var("h", get_soln(), { }); public: @@ -120,54 +120,54 @@ class AwpStencil : public yc_solution_base { // appropriately. void define_vel_x() { - yc_number_node_ptr rho_val = (rho(x, y, z ) + - rho(x, y-1, z ) + - rho(x, y, z-1) + - rho(x, y-1, z-1)) * (1.0 / 4.0); - yc_number_node_ptr d_val = + auto rho_val = (rho(x, y, z ) + + rho(x, y-1, z ) + + rho(x, y, z-1) + + rho(x, y-1, z-1)) * (1.0 / 4.0); + auto d_val = c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - yc_number_node_ptr next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_x); // define the value at t+1. vel_x(t+1, x, y, z) EQUALS next_vel_x; } void define_vel_y() { - yc_number_node_ptr rho_val = (rho(x, y, z ) + - rho(x+1, y, z ) + - rho(x, y, z-1) + - rho(x+1, y, z-1)) * (1.0 / 4.0); - yc_number_node_ptr d_val = + auto rho_val = (rho(x, y, z ) + + rho(x+1, y, z ) + + rho(x, y, z-1) + + rho(x+1, y, z-1)) * (1.0 / 4.0); + auto d_val = c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - yc_number_node_ptr next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_y); // define the value at t+1. vel_y(t+1, x, y, z) EQUALS next_vel_y; } void define_vel_z() { - yc_number_node_ptr rho_val = (rho(x, y, z) + - rho(x+1, y, z) + - rho(x, y-1, z) + - rho(x+1, y-1, z)) * (1.0 / 4.0); - yc_number_node_ptr d_val = + auto rho_val = (rho(x, y, z) + + rho(x+1, y, z) + + rho(x, y-1, z) + + rho(x+1, y-1, z)) * (1.0 / 4.0); + auto d_val = c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - yc_number_node_ptr next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_z); // define the value at t+1. @@ -186,14 +186,14 @@ class AwpStencil : public yc_solution_base { yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, yc_number_node_ptr tau1) { - yc_number_node_ptr stress_mem_xx_old = stress_mem_xx(t, x, y, z); + auto stress_mem_xx_old = stress_mem_xx(t, x, y, z); - yc_number_node_ptr next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + + auto next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + (1.0 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_as_diag(x, y, z) * (d_y_val + d_z_val) - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - yc_number_node_ptr next_stress_xx = stress_xx(t, x, y, z) + + auto next_stress_xx = stress_xx(t, x, y, z) + ((delta_t / h) * ((2. * mu_val * d_x_val) + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + delta_t * (next_stress_mem_xx + stress_mem_xx_old); @@ -208,14 +208,14 @@ class AwpStencil : public yc_solution_base { yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, yc_number_node_ptr tau1) { - yc_number_node_ptr stress_mem_yy_old = stress_mem_yy(t, x, y, z); + auto stress_mem_yy_old = stress_mem_yy(t, x, y, z); - yc_number_node_ptr next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + + auto next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + (1 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_z_val) - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - yc_number_node_ptr next_stress_yy = stress_yy(t, x, y, z) + + auto next_stress_yy = stress_yy(t, x, y, z) + ((delta_t / h) * ((2. * mu_val * d_y_val) + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + delta_t * (next_stress_mem_yy + stress_mem_yy_old); @@ -230,14 +230,14 @@ class AwpStencil : public yc_solution_base { yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, yc_number_node_ptr tau1) { - yc_number_node_ptr stress_mem_zz_old = stress_mem_zz(t, x, y, z); + auto stress_mem_zz_old = stress_mem_zz(t, x, y, z); - yc_number_node_ptr next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + + auto next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + (1 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_y_val) - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - yc_number_node_ptr next_stress_zz = stress_zz(t, x, y, z) + + auto next_stress_zz = stress_zz(t, x, y, z) + ((delta_t / h) * ((2. * mu_val * d_z_val) + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + delta_t * (next_stress_mem_zz + stress_mem_zz_old); @@ -250,24 +250,24 @@ class AwpStencil : public yc_solution_base { } void define_stress_xy(yc_number_node_ptr tau1) { - yc_number_node_ptr mu_val = 2.0 / + auto mu_val = 2.0 / (mu(x, y, z ) + mu(x, y, z-1)); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_xy_val = + auto d_xy_val = c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - yc_number_node_ptr d_yx_val = + auto d_yx_val = c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - yc_number_node_ptr stress_mem_xy_old = stress_mem_xy(t, x, y, z); + auto stress_mem_xy_old = stress_mem_xy(t, x, y, z); - yc_number_node_ptr next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - + auto next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - (0.5 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_xy(x, y, z) * (d_xy_val + d_yx_val)); - yc_number_node_ptr next_stress_xy = stress_xy(t, x, y, z) + + auto next_stress_xy = stress_xy(t, x, y, z) + ((mu_val * delta_t / h) * (d_xy_val + d_yx_val)) + delta_t * (next_stress_mem_xy + stress_mem_xy_old); @@ -279,24 +279,24 @@ class AwpStencil : public yc_solution_base { } void define_stress_xz(yc_number_node_ptr tau1) { - yc_number_node_ptr mu_val = 2.0 / + auto mu_val = 2.0 / (mu(x, y, z ) + mu(x, y-1, z )); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_xz_val = + auto d_xz_val = c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - yc_number_node_ptr d_zx_val = + auto d_zx_val = c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - yc_number_node_ptr stress_mem_xz_old = stress_mem_xz(t, x, y, z); + auto stress_mem_xz_old = stress_mem_xz(t, x, y, z); - yc_number_node_ptr next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - + auto next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - (0.5 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_xz(x, y, z) * (d_xz_val + d_zx_val)); - yc_number_node_ptr next_stress_xz = stress_xz(t, x, y, z) + + auto next_stress_xz = stress_xz(t, x, y, z) + ((mu_val * delta_t / h) * (d_xz_val + d_zx_val)) + delta_t * (next_stress_mem_xz + stress_mem_xz_old); @@ -308,24 +308,24 @@ class AwpStencil : public yc_solution_base { } void define_stress_yz(yc_number_node_ptr tau1) { - yc_number_node_ptr mu_val = 2.0 / + auto mu_val = 2.0 / (mu(x, y, z ) + mu(x+1, y, z )); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_yz_val = + auto d_yz_val = c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - yc_number_node_ptr d_zy_val = + auto d_zy_val = c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - yc_number_node_ptr stress_mem_yz_old = stress_mem_yz(t, x, y, z); + auto stress_mem_yz_old = stress_mem_yz(t, x, y, z); - yc_number_node_ptr next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - + auto next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - (0.5 / h) * tau1 * weight(x, y, z) * (mu_val * anelastic_yz(x, y, z) * (d_yz_val + d_zy_val)); - yc_number_node_ptr next_stress_yz = stress_yz(t, x, y, z) + + auto next_stress_yz = stress_yz(t, x, y, z) + ((mu_val * delta_t / h) * (d_yz_val + d_zy_val)) + delta_t * (next_stress_mem_yz + stress_mem_yz_old); @@ -345,29 +345,29 @@ class AwpStencil : public yc_solution_base { define_vel_z(); // Define some values common to the diagonal stress equations. - yc_number_node_ptr lambda_val = 8.0 / + auto lambda_val = 8.0 / (lambda(x, y, z ) + lambda(x+1, y, z ) + lambda(x, y-1, z ) + lambda(x+1, y-1, z ) + lambda(x, y, z-1) + lambda(x+1, y, z-1) + lambda(x, y-1, z-1) + lambda(x+1, y-1, z-1)); - yc_number_node_ptr mu_val = 8.0 / + auto mu_val = 8.0 / (mu(x, y, z ) + mu(x+1, y, z ) + mu(x, y-1, z ) + mu(x+1, y-1, z ) + mu(x, y, z-1) + mu(x+1, y, z-1) + mu(x, y-1, z-1) + mu(x+1, y-1, z-1)); // Note that we are using the velocity values at t+1. - yc_number_node_ptr d_x_val = + auto d_x_val = c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); - yc_number_node_ptr d_y_val = + auto d_y_val = c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); - yc_number_node_ptr d_z_val = + auto d_z_val = c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); - yc_number_node_ptr tau1 = 1.0 - tau2(x, y, z); + auto tau1 = 1.0 - tau2(x, y, z); // Define stress components. define_stress_xx(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index 56cdeca2..29ddbb76 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -73,7 +73,7 @@ class Elastic2StencilBase : public yc_solution_base { yc_index_node_ptr cidx = new_misc_index("cidx"); // 3D-spatial coefficients. - yc_grid_var coef = yc_grid_var("coef", get_solution(), { x, y, z, cidx }); + yc_grid_var coef = yc_grid_var("coef", get_soln(), { x, y, z, cidx }); enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2, C_RHO }; // Spatial FD coefficients. diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index 1f478042..0c72051f 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -80,7 +80,7 @@ class ElasticStencilBase : public yc_solution_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // 3D-spatial coefficients. - yc_grid_var rho = yc_grid_var("rho", get_solution(), { x, y, z }); + yc_grid_var rho = yc_grid_var("rho", get_soln(), { x, y, z }); // Spatial FD coefficients. const double c0_8 = 1.2; @@ -230,13 +230,13 @@ class ElasticStencilBase : public yc_solution_base { void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &v, yc_grid_var &sx, yc_grid_var &sy, yc_grid_var &sz) { - yc_number_node_ptr lrho = interp_rho( x, y, z ); + auto lrho = interp_rho( x, y, z ); - yc_number_node_ptr stx = stencil_O8( t, x, y, z, sx ); - yc_number_node_ptr sty = stencil_O8( t, x, y, z, sy ); - yc_number_node_ptr stz = stencil_O8( t, x, y, z, sz ); + auto stx = stencil_O8( t, x, y, z, sx ); + auto sty = stencil_O8( t, x, y, z, sy ); + auto stz = stencil_O8( t, x, y, z, sz ); - yc_number_node_ptr next_v = v(t, x, y, z) + ((stx + sty + stz) * delta_t * lrho); + auto next_v = v(t, x, y, z) + ((stx + sty + stz) * delta_t * lrho); // define the value at t+1. if ( hasBoundaryCondition() ) { diff --git a/src/stencils/ExampleStencil.cpp b/src/stencils/ExampleStencil.cpp index 47aa8b0c..75213597 100644 --- a/src/stencils/ExampleStencil.cpp +++ b/src/stencils/ExampleStencil.cpp @@ -44,7 +44,7 @@ class AvePtsStencil : public yc_solution_with_radius_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying 3D grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying 3D grid. // Add additional points to expression v. // Returns number of points added. diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index 13724dbd..0d4fed77 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -53,20 +53,20 @@ namespace fsg { protected: // Velocity and stress grids. - yc_grid_var v = yc_grid_var("v", get_solution(), { t, x, y, z, vidx }); + yc_grid_var v = yc_grid_var("v", get_soln(), { t, x, y, z, vidx }); enum VIDX { V_BL_U, V_BL_V, V_BL_W, V_BR_U, V_BR_V, V_BR_W, V_TL_U, V_TL_V, V_TL_W, V_TR_U, V_TR_V, V_TR_W }; - yc_grid_var s = yc_grid_var("s", get_solution(), { t, x, y, z, sidx }); + yc_grid_var s = yc_grid_var("s", get_soln(), { t, x, y, z, sidx }); enum SIDX { S_BL_XX, S_BL_YY, S_BL_ZZ, S_BL_YZ, S_BL_XZ, S_BL_XY, S_BR_XX, S_BR_YY, S_BR_ZZ, S_BR_YZ, S_BR_XZ, S_BR_XY, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TL_YZ, S_TL_XZ, S_TL_XY, S_TR_XX, S_TR_YY, S_TR_ZZ, S_TR_YZ, S_TR_XZ, S_TR_XY }; // 3D-spatial coefficients. - yc_grid_var c = yc_grid_var("c", get_solution(), { x, y, z, cidx }); + yc_grid_var c = yc_grid_var("c", get_soln(), { x, y, z, cidx }); enum CIDX { C11, C12, C13, C14, C15, C16, C22, C23, C24, C25, C26, C33, C34, C35, C36, @@ -198,53 +198,53 @@ namespace fsg { yc_number_node_ptr vzu_idx, yc_number_node_ptr vzv_idx, yc_number_node_ptr vzw_idx) { // Interpolate coeffs. - yc_number_node_ptr ic11 = cell_coeff (x, y, z, c, C11); - yc_number_node_ptr ic12 = cell_coeff (x, y, z, c, C12); - yc_number_node_ptr ic13 = cell_coeff (x, y, z, c, C13); - yc_number_node_ptr ic14 = cell_coeff_artm(x, y, z, c, C14); - yc_number_node_ptr ic15 = cell_coeff_artm(x, y, z, c, C15); - yc_number_node_ptr ic16 = cell_coeff_artm(x, y, z, c, C16); - yc_number_node_ptr ic22 = cell_coeff (x, y, z, c, C22); - yc_number_node_ptr ic23 = cell_coeff (x, y, z, c, C23); - yc_number_node_ptr ic24 = cell_coeff_artm(x, y, z, c, C24); - yc_number_node_ptr ic25 = cell_coeff_artm(x, y, z, c, C25); - yc_number_node_ptr ic26 = cell_coeff_artm(x, y, z, c, C26); - yc_number_node_ptr ic33 = cell_coeff (x, y, z, c, C33); - yc_number_node_ptr ic34 = cell_coeff_artm(x, y, z, c, C34); - yc_number_node_ptr ic35 = cell_coeff_artm(x, y, z, c, C35); - yc_number_node_ptr ic36 = cell_coeff_artm(x, y, z, c, C36); - yc_number_node_ptr ic44 = cell_coeff (x, y, z, c, C44); - yc_number_node_ptr ic45 = cell_coeff_artm(x, y, z, c, C45); - yc_number_node_ptr ic46 = cell_coeff_artm(x, y, z, c, C46); - yc_number_node_ptr ic55 = cell_coeff (x, y, z, c, C55); - yc_number_node_ptr ic56 = cell_coeff_artm(x, y, z, c, C56); - yc_number_node_ptr ic66 = cell_coeff (x, y, z, c, C66); + auto ic11 = cell_coeff (x, y, z, c, C11); + auto ic12 = cell_coeff (x, y, z, c, C12); + auto ic13 = cell_coeff (x, y, z, c, C13); + auto ic14 = cell_coeff_artm(x, y, z, c, C14); + auto ic15 = cell_coeff_artm(x, y, z, c, C15); + auto ic16 = cell_coeff_artm(x, y, z, c, C16); + auto ic22 = cell_coeff (x, y, z, c, C22); + auto ic23 = cell_coeff (x, y, z, c, C23); + auto ic24 = cell_coeff_artm(x, y, z, c, C24); + auto ic25 = cell_coeff_artm(x, y, z, c, C25); + auto ic26 = cell_coeff_artm(x, y, z, c, C26); + auto ic33 = cell_coeff (x, y, z, c, C33); + auto ic34 = cell_coeff_artm(x, y, z, c, C34); + auto ic35 = cell_coeff_artm(x, y, z, c, C35); + auto ic36 = cell_coeff_artm(x, y, z, c, C36); + auto ic44 = cell_coeff (x, y, z, c, C44); + auto ic45 = cell_coeff_artm(x, y, z, c, C45); + auto ic46 = cell_coeff_artm(x, y, z, c, C46); + auto ic55 = cell_coeff (x, y, z, c, C55); + auto ic56 = cell_coeff_artm(x, y, z, c, C56); + auto ic66 = cell_coeff (x, y, z, c, C66); // Compute stencils. Note that we are using the velocity values at t+1. - yc_number_node_ptr u_z = stencil_O8( t+1, x, y, z, v, vzu_idx); - yc_number_node_ptr v_z = stencil_O8( t+1, x, y, z, v, vzv_idx); - yc_number_node_ptr w_z = stencil_O8( t+1, x, y, z, v, vzw_idx); + auto u_z = stencil_O8( t+1, x, y, z, v, vzu_idx); + auto v_z = stencil_O8( t+1, x, y, z, v, vzv_idx); + auto w_z = stencil_O8( t+1, x, y, z, v, vzw_idx); - yc_number_node_ptr u_x = stencil_O8( t+1, x, y, z, v, vxu_idx); - yc_number_node_ptr v_x = stencil_O8( t+1, x, y, z, v, vxv_idx); - yc_number_node_ptr w_x = stencil_O8( t+1, x, y, z, v, vxw_idx); + auto u_x = stencil_O8( t+1, x, y, z, v, vxu_idx); + auto v_x = stencil_O8( t+1, x, y, z, v, vxv_idx); + auto w_x = stencil_O8( t+1, x, y, z, v, vxw_idx); - yc_number_node_ptr u_y = stencil_O8( t+1, x, y, z, v, vyu_idx); - yc_number_node_ptr v_y = stencil_O8( t+1, x, y, z, v, vyv_idx); - yc_number_node_ptr w_y = stencil_O8( t+1, x, y, z, v, vyw_idx); + auto u_y = stencil_O8( t+1, x, y, z, v, vyu_idx); + auto v_y = stencil_O8( t+1, x, y, z, v, vyv_idx); + auto w_y = stencil_O8( t+1, x, y, z, v, vyw_idx); // Compute next stress value - yc_number_node_ptr next_sxx = s(t, x, y, z, sxx_idx) + + auto next_sxx = s(t, x, y, z, sxx_idx) + stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_syy = s(t, x, y, z, syy_idx) + + auto next_syy = s(t, x, y, z, syy_idx) + stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_szz = s(t, x, y, z, szz_idx) + + auto next_szz = s(t, x, y, z, szz_idx) + stress_update(ic13,ic23,ic33,ic34,ic35,ic36,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_syz = s(t, x, y, z, syz_idx) + + auto next_syz = s(t, x, y, z, syz_idx) + stress_update(ic14,ic24,ic34,ic44,ic45,ic46,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_sxz = s(t, x, y, z, sxz_idx) + + auto next_sxz = s(t, x, y, z, sxz_idx) + stress_update(ic15,ic25,ic35,ic45,ic55,ic56,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_sxy = s(t, x, y, z, sxy_idx) + + auto next_sxy = s(t, x, y, z, sxy_idx) + stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); // define the value at t+1. @@ -323,7 +323,7 @@ namespace fsg { const int abc_width = 20; // Sponge coefficients. - yc_grid_var sponge = yc_grid_var("sponge", get_solution(), { x, y, z, spidx }); + yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z, spidx }); enum SPONGE_IDX { SPONGE_LX, SPONGE_RX, SPONGE_BZ, SPONGE_TZ, SPONGE_FY, SPONGE_BY, SPONGE_SQ_LX, SPONGE_SQ_RX, SPONGE_SQ_BZ, @@ -357,17 +357,16 @@ namespace fsg { yc_number_node_ptr sx_idx, yc_number_node_ptr sy_idx, yc_number_node_ptr sz_idx, yc_number_node_ptr abc_x_idx, yc_number_node_ptr abc_y_idx, yc_number_node_ptr abc_z_idx, yc_number_node_ptr abc_sq_x_idx, yc_number_node_ptr abc_sq_y_idx, yc_number_node_ptr abc_sq_z_idx) { + auto at_abc = is_at_boundary(); - yc_bool_node_ptr at_abc = is_at_boundary(); - - yc_number_node_ptr next_v = fsg.v(t, x, y, z, vidx) * sponge(x,y,z, abc_x_idx) * + auto next_v = fsg.v(t, x, y, z, vidx) * sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); - yc_number_node_ptr lrho = fsg.interp_rho( x, y, z); + auto lrho = fsg.interp_rho( x, y, z); - yc_number_node_ptr stx = fsg.stencil_O2_X( t, x, y, z, fsg.s, sx_idx); - yc_number_node_ptr sty = fsg.stencil_O2_Y( t, x, y, z, fsg.s, sy_idx); - yc_number_node_ptr stz = fsg.stencil_O2_Z( t, x, y, z, fsg.s, sz_idx); + auto stx = fsg.stencil_O2_X( t, x, y, z, fsg.s, sx_idx); + auto sty = fsg.stencil_O2_Y( t, x, y, z, fsg.s, sy_idx); + auto stz = fsg.stencil_O2_Z( t, x, y, z, fsg.s, sz_idx); next_v += ((stx + sty + stz) * fsg.delta_t * lrho); next_v *= sponge(x,y,z, abc_sq_x_idx) * sponge(x,y,z, abc_sq_y_idx) * @@ -427,52 +426,52 @@ namespace fsg { yc_number_node_ptr abc_x_idx, yc_number_node_ptr abc_y_idx, yc_number_node_ptr abc_z_idx, yc_number_node_ptr abc_sq_x_idx, yc_number_node_ptr abc_sq_y_idx, yc_number_node_ptr abc_sq_z_idx) { - yc_number_node_ptr abc = sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); - yc_number_node_ptr next_sxx = fsg.s(t, x, y, z, sxx_idx) * abc; - yc_number_node_ptr next_syy = fsg.s(t, x, y, z, syy_idx) * abc; - yc_number_node_ptr next_szz = fsg.s(t, x, y, z, szz_idx) * abc; - yc_number_node_ptr next_syz = fsg.s(t, x, y, z, syz_idx) * abc; - yc_number_node_ptr next_sxz = fsg.s(t, x, y, z, sxz_idx) * abc; - yc_number_node_ptr next_sxy = fsg.s(t, x, y, z, sxy_idx) * abc; + auto abc = sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); + auto next_sxx = fsg.s(t, x, y, z, sxx_idx) * abc; + auto next_syy = fsg.s(t, x, y, z, syy_idx) * abc; + auto next_szz = fsg.s(t, x, y, z, szz_idx) * abc; + auto next_syz = fsg.s(t, x, y, z, syz_idx) * abc; + auto next_sxz = fsg.s(t, x, y, z, sxz_idx) * abc; + auto next_sxy = fsg.s(t, x, y, z, sxy_idx) * abc; // Interpolate coeffs. - yc_number_node_ptr ic11 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C11); - yc_number_node_ptr ic12 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C12); - yc_number_node_ptr ic13 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C13); - yc_number_node_ptr ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C14); - yc_number_node_ptr ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C15); - yc_number_node_ptr ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C16); - yc_number_node_ptr ic22 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C22); - yc_number_node_ptr ic23 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C23); - yc_number_node_ptr ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C24); - yc_number_node_ptr ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C25); - yc_number_node_ptr ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C26); - yc_number_node_ptr ic33 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C33); - yc_number_node_ptr ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C34); - yc_number_node_ptr ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C35); - yc_number_node_ptr ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C36); - yc_number_node_ptr ic44 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C44); - yc_number_node_ptr ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C45); - yc_number_node_ptr ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C46); - yc_number_node_ptr ic55 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C55); - yc_number_node_ptr ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C56); - yc_number_node_ptr ic66 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C66); + auto ic11 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C11); + auto ic12 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C12); + auto ic13 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C13); + auto ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C14); + auto ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C15); + auto ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C16); + auto ic22 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C22); + auto ic23 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C23); + auto ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C24); + auto ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C25); + auto ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C26); + auto ic33 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C33); + auto ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C34); + auto ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C35); + auto ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C36); + auto ic44 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C44); + auto ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C45); + auto ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C46); + auto ic55 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C55); + auto ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c, fsg.C56); + auto ic66 = fsg.cell_coeff (x, y, z, fsg.c, fsg.C66); // Compute stencils. Note that we are using the velocity values at t+1. - yc_number_node_ptr u_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzu_idx); - yc_number_node_ptr v_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzv_idx); - yc_number_node_ptr w_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzw_idx); + auto u_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzu_idx); + auto v_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzv_idx); + auto w_z = fsg.stencil_O2_Z( t+1, x, y, z, fsg.v, vzw_idx); - yc_number_node_ptr u_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxu_idx); - yc_number_node_ptr v_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxv_idx); - yc_number_node_ptr w_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxw_idx); + auto u_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxu_idx); + auto v_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxv_idx); + auto w_x = fsg.stencil_O2_X( t+1, x, y, z, fsg.v, vxw_idx); - yc_number_node_ptr u_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyu_idx); - yc_number_node_ptr v_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyv_idx); - yc_number_node_ptr w_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyw_idx); + auto u_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyu_idx); + auto v_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyv_idx); + auto w_y = fsg.stencil_O2_Y( t+1, x, y, z, fsg.v, vyw_idx); // Compute next stress value - yc_number_node_ptr abc_sq = sponge(x,y,z, abc_sq_x_idx) * + auto abc_sq = sponge(x,y,z, abc_sq_x_idx) * sponge(x,y,z, abc_sq_y_idx) * sponge(x,y,z, abc_sq_z_idx); next_sxx += fsg.stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; next_syy += fsg.stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index 33180733..65584b40 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -50,66 +50,66 @@ namespace fsg { protected: - yc_grid_var v_bl_u = yc_grid_var("v_bl_u", get_solution(), { t, x, y, z }); - yc_grid_var v_bl_v = yc_grid_var("v_bl_v", get_solution(), { t, x, y, z }); - yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_solution(), { t, x, y, z }); - yc_grid_var v_br_u = yc_grid_var("v_br_u", get_solution(), { t, x, y, z }); - yc_grid_var v_br_v = yc_grid_var("v_br_v", get_solution(), { t, x, y, z }); - yc_grid_var v_br_w = yc_grid_var("v_br_w", get_solution(), { t, x, y, z }); - yc_grid_var v_tl_u = yc_grid_var("v_tl_u", get_solution(), { t, x, y, z }); - yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_solution(), { t, x, y, z }); - yc_grid_var v_tl_w = yc_grid_var("v_tl_w", get_solution(), { t, x, y, z }); - yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_solution(), { t, x, y, z }); - yc_grid_var v_tr_v = yc_grid_var("v_tr_v", get_solution(), { t, x, y, z }); - yc_grid_var v_tr_w = yc_grid_var("v_tr_w", get_solution(), { t, x, y, z }); - - yc_grid_var s_bl_xx = yc_grid_var("s_bl_xx", get_solution(), { t, x, y, z }); - yc_grid_var s_bl_yy = yc_grid_var("s_bl_yy", get_solution(), { t, x, y, z }); - yc_grid_var s_bl_zz = yc_grid_var("s_bl_zz", get_solution(), { t, x, y, z }); - yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_solution(), { t, x, y, z }); - yc_grid_var s_bl_xz = yc_grid_var("s_bl_xz", get_solution(), { t, x, y, z }); - yc_grid_var s_bl_xy = yc_grid_var("s_bl_xy", get_solution(), { t, x, y, z }); - yc_grid_var s_br_xx = yc_grid_var("s_br_xx", get_solution(), { t, x, y, z }); - yc_grid_var s_br_yy = yc_grid_var("s_br_yy", get_solution(), { t, x, y, z }); - yc_grid_var s_br_zz = yc_grid_var("s_br_zz", get_solution(), { t, x, y, z }); - yc_grid_var s_br_yz = yc_grid_var("s_br_yz", get_solution(), { t, x, y, z }); - yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_solution(), { t, x, y, z }); - yc_grid_var s_br_xy = yc_grid_var("s_br_xy", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_yz = yc_grid_var("s_tl_yz", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_xz = yc_grid_var("s_tl_xz", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_xy = yc_grid_var("s_tl_xy", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_xx = yc_grid_var("s_tr_xx", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_yy = yc_grid_var("s_tr_yy", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_zz = yc_grid_var("s_tr_zz", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_yz = yc_grid_var("s_tr_yz", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_xz = yc_grid_var("s_tr_xz", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_solution(), { t, x, y, z }); + yc_grid_var v_bl_u = yc_grid_var("v_bl_u", get_soln(), { t, x, y, z }); + yc_grid_var v_bl_v = yc_grid_var("v_bl_v", get_soln(), { t, x, y, z }); + yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_soln(), { t, x, y, z }); + yc_grid_var v_br_u = yc_grid_var("v_br_u", get_soln(), { t, x, y, z }); + yc_grid_var v_br_v = yc_grid_var("v_br_v", get_soln(), { t, x, y, z }); + yc_grid_var v_br_w = yc_grid_var("v_br_w", get_soln(), { t, x, y, z }); + yc_grid_var v_tl_u = yc_grid_var("v_tl_u", get_soln(), { t, x, y, z }); + yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_soln(), { t, x, y, z }); + yc_grid_var v_tl_w = yc_grid_var("v_tl_w", get_soln(), { t, x, y, z }); + yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_soln(), { t, x, y, z }); + yc_grid_var v_tr_v = yc_grid_var("v_tr_v", get_soln(), { t, x, y, z }); + yc_grid_var v_tr_w = yc_grid_var("v_tr_w", get_soln(), { t, x, y, z }); + + yc_grid_var s_bl_xx = yc_grid_var("s_bl_xx", get_soln(), { t, x, y, z }); + yc_grid_var s_bl_yy = yc_grid_var("s_bl_yy", get_soln(), { t, x, y, z }); + yc_grid_var s_bl_zz = yc_grid_var("s_bl_zz", get_soln(), { t, x, y, z }); + yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_soln(), { t, x, y, z }); + yc_grid_var s_bl_xz = yc_grid_var("s_bl_xz", get_soln(), { t, x, y, z }); + yc_grid_var s_bl_xy = yc_grid_var("s_bl_xy", get_soln(), { t, x, y, z }); + yc_grid_var s_br_xx = yc_grid_var("s_br_xx", get_soln(), { t, x, y, z }); + yc_grid_var s_br_yy = yc_grid_var("s_br_yy", get_soln(), { t, x, y, z }); + yc_grid_var s_br_zz = yc_grid_var("s_br_zz", get_soln(), { t, x, y, z }); + yc_grid_var s_br_yz = yc_grid_var("s_br_yz", get_soln(), { t, x, y, z }); + yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_soln(), { t, x, y, z }); + yc_grid_var s_br_xy = yc_grid_var("s_br_xy", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_yz = yc_grid_var("s_tl_yz", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_xz = yc_grid_var("s_tl_xz", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_xy = yc_grid_var("s_tl_xy", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_xx = yc_grid_var("s_tr_xx", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_yy = yc_grid_var("s_tr_yy", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_zz = yc_grid_var("s_tr_zz", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_yz = yc_grid_var("s_tr_yz", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_xz = yc_grid_var("s_tr_xz", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_soln(), { t, x, y, z }); // 3D-spatial coefficients. - yc_grid_var c11 = yc_grid_var("c11", get_solution(), { x, y, z }); - yc_grid_var c12 = yc_grid_var("c12", get_solution(), { x, y, z }); - yc_grid_var c13 = yc_grid_var("c13", get_solution(), { x, y, z }); - yc_grid_var c14 = yc_grid_var("c14", get_solution(), { x, y, z }); - yc_grid_var c15 = yc_grid_var("c15", get_solution(), { x, y, z }); - yc_grid_var c16 = yc_grid_var("c16", get_solution(), { x, y, z }); - yc_grid_var c22 = yc_grid_var("c22", get_solution(), { x, y, z }); - yc_grid_var c23 = yc_grid_var("c23", get_solution(), { x, y, z }); - yc_grid_var c24 = yc_grid_var("c24", get_solution(), { x, y, z }); - yc_grid_var c25 = yc_grid_var("c25", get_solution(), { x, y, z }); - yc_grid_var c26 = yc_grid_var("c26", get_solution(), { x, y, z }); - yc_grid_var c33 = yc_grid_var("c33", get_solution(), { x, y, z }); - yc_grid_var c34 = yc_grid_var("c34", get_solution(), { x, y, z }); - yc_grid_var c35 = yc_grid_var("c35", get_solution(), { x, y, z }); - yc_grid_var c36 = yc_grid_var("c36", get_solution(), { x, y, z }); - yc_grid_var c44 = yc_grid_var("c44", get_solution(), { x, y, z }); - yc_grid_var c45 = yc_grid_var("c45", get_solution(), { x, y, z }); - yc_grid_var c46 = yc_grid_var("c46", get_solution(), { x, y, z }); - yc_grid_var c55 = yc_grid_var("c55", get_solution(), { x, y, z }); - yc_grid_var c56 = yc_grid_var("c56", get_solution(), { x, y, z }); - yc_grid_var c66 = yc_grid_var("c66", get_solution(), { x, y, z }); + yc_grid_var c11 = yc_grid_var("c11", get_soln(), { x, y, z }); + yc_grid_var c12 = yc_grid_var("c12", get_soln(), { x, y, z }); + yc_grid_var c13 = yc_grid_var("c13", get_soln(), { x, y, z }); + yc_grid_var c14 = yc_grid_var("c14", get_soln(), { x, y, z }); + yc_grid_var c15 = yc_grid_var("c15", get_soln(), { x, y, z }); + yc_grid_var c16 = yc_grid_var("c16", get_soln(), { x, y, z }); + yc_grid_var c22 = yc_grid_var("c22", get_soln(), { x, y, z }); + yc_grid_var c23 = yc_grid_var("c23", get_soln(), { x, y, z }); + yc_grid_var c24 = yc_grid_var("c24", get_soln(), { x, y, z }); + yc_grid_var c25 = yc_grid_var("c25", get_soln(), { x, y, z }); + yc_grid_var c26 = yc_grid_var("c26", get_soln(), { x, y, z }); + yc_grid_var c33 = yc_grid_var("c33", get_soln(), { x, y, z }); + yc_grid_var c34 = yc_grid_var("c34", get_soln(), { x, y, z }); + yc_grid_var c35 = yc_grid_var("c35", get_soln(), { x, y, z }); + yc_grid_var c36 = yc_grid_var("c36", get_soln(), { x, y, z }); + yc_grid_var c44 = yc_grid_var("c44", get_soln(), { x, y, z }); + yc_grid_var c45 = yc_grid_var("c45", get_soln(), { x, y, z }); + yc_grid_var c46 = yc_grid_var("c46", get_soln(), { x, y, z }); + yc_grid_var c55 = yc_grid_var("c55", get_soln(), { x, y, z }); + yc_grid_var c56 = yc_grid_var("c56", get_soln(), { x, y, z }); + yc_grid_var c66 = yc_grid_var("c66", get_soln(), { x, y, z }); public: @@ -210,53 +210,53 @@ namespace fsg { yc_grid_var &vxu, yc_grid_var &vxv, yc_grid_var &vxw, yc_grid_var &vyu, yc_grid_var &vyv, yc_grid_var &vyw, yc_grid_var &vzu, yc_grid_var &vzv, yc_grid_var &vzw ) { // Interpolate coeffs. - yc_number_node_ptr ic11 = cell_coeff (x, y, z, c11); - yc_number_node_ptr ic12 = cell_coeff (x, y, z, c12); - yc_number_node_ptr ic13 = cell_coeff (x, y, z, c13); - yc_number_node_ptr ic14 = cell_coeff_artm(x, y, z, c14); - yc_number_node_ptr ic15 = cell_coeff_artm(x, y, z, c15); - yc_number_node_ptr ic16 = cell_coeff_artm(x, y, z, c16); - yc_number_node_ptr ic22 = cell_coeff (x, y, z, c22); - yc_number_node_ptr ic23 = cell_coeff (x, y, z, c23); - yc_number_node_ptr ic24 = cell_coeff_artm(x, y, z, c24); - yc_number_node_ptr ic25 = cell_coeff_artm(x, y, z, c25); - yc_number_node_ptr ic26 = cell_coeff_artm(x, y, z, c26); - yc_number_node_ptr ic33 = cell_coeff (x, y, z, c33); - yc_number_node_ptr ic34 = cell_coeff_artm(x, y, z, c34); - yc_number_node_ptr ic35 = cell_coeff_artm(x, y, z, c35); - yc_number_node_ptr ic36 = cell_coeff_artm(x, y, z, c36); - yc_number_node_ptr ic44 = cell_coeff (x, y, z, c44); - yc_number_node_ptr ic45 = cell_coeff_artm(x, y, z, c45); - yc_number_node_ptr ic46 = cell_coeff_artm(x, y, z, c46); - yc_number_node_ptr ic55 = cell_coeff (x, y, z, c55); - yc_number_node_ptr ic56 = cell_coeff_artm(x, y, z, c56); - yc_number_node_ptr ic66 = cell_coeff (x, y, z, c66); + auto ic11 = cell_coeff (x, y, z, c11); + auto ic12 = cell_coeff (x, y, z, c12); + auto ic13 = cell_coeff (x, y, z, c13); + auto ic14 = cell_coeff_artm(x, y, z, c14); + auto ic15 = cell_coeff_artm(x, y, z, c15); + auto ic16 = cell_coeff_artm(x, y, z, c16); + auto ic22 = cell_coeff (x, y, z, c22); + auto ic23 = cell_coeff (x, y, z, c23); + auto ic24 = cell_coeff_artm(x, y, z, c24); + auto ic25 = cell_coeff_artm(x, y, z, c25); + auto ic26 = cell_coeff_artm(x, y, z, c26); + auto ic33 = cell_coeff (x, y, z, c33); + auto ic34 = cell_coeff_artm(x, y, z, c34); + auto ic35 = cell_coeff_artm(x, y, z, c35); + auto ic36 = cell_coeff_artm(x, y, z, c36); + auto ic44 = cell_coeff (x, y, z, c44); + auto ic45 = cell_coeff_artm(x, y, z, c45); + auto ic46 = cell_coeff_artm(x, y, z, c46); + auto ic55 = cell_coeff (x, y, z, c55); + auto ic56 = cell_coeff_artm(x, y, z, c56); + auto ic66 = cell_coeff (x, y, z, c66); // Compute stencils. Note that we are using the velocity values at t+1. - yc_number_node_ptr u_z = stencil_O8( t+1, x, y, z, vzu ); - yc_number_node_ptr v_z = stencil_O8( t+1, x, y, z, vzv ); - yc_number_node_ptr w_z = stencil_O8( t+1, x, y, z, vzw ); + auto u_z = stencil_O8( t+1, x, y, z, vzu ); + auto v_z = stencil_O8( t+1, x, y, z, vzv ); + auto w_z = stencil_O8( t+1, x, y, z, vzw ); - yc_number_node_ptr u_x = stencil_O8( t+1, x, y, z, vxu ); - yc_number_node_ptr v_x = stencil_O8( t+1, x, y, z, vxv ); - yc_number_node_ptr w_x = stencil_O8( t+1, x, y, z, vxw ); + auto u_x = stencil_O8( t+1, x, y, z, vxu ); + auto v_x = stencil_O8( t+1, x, y, z, vxv ); + auto w_x = stencil_O8( t+1, x, y, z, vxw ); - yc_number_node_ptr u_y = stencil_O8( t+1, x, y, z, vyu ); - yc_number_node_ptr v_y = stencil_O8( t+1, x, y, z, vyv ); - yc_number_node_ptr w_y = stencil_O8( t+1, x, y, z, vyw ); + auto u_y = stencil_O8( t+1, x, y, z, vyu ); + auto v_y = stencil_O8( t+1, x, y, z, vyv ); + auto w_y = stencil_O8( t+1, x, y, z, vyw ); // Compute next stress value - yc_number_node_ptr next_sxx = sxx(t, x, y, z) + + auto next_sxx = sxx(t, x, y, z) + stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_syy = syy(t, x, y, z) + + auto next_syy = syy(t, x, y, z) + stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_szz = szz(t, x, y, z) + + auto next_szz = szz(t, x, y, z) + stress_update(ic13,ic23,ic33,ic34,ic35,ic36,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_syz = syz(t, x, y, z) + + auto next_syz = syz(t, x, y, z) + stress_update(ic14,ic24,ic34,ic44,ic45,ic46,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_sxz = sxz(t, x, y, z) + + auto next_sxz = sxz(t, x, y, z) + stress_update(ic15,ic25,ic35,ic45,ic55,ic56,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); - yc_number_node_ptr next_sxy = sxy(t, x, y, z) + + auto next_sxy = sxy(t, x, y, z) + stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y); // define the value at t+1. @@ -321,18 +321,18 @@ namespace fsg { const int abc_width = 20; // Sponge coefficients. - yc_grid_var sponge_lx = yc_grid_var("sponge_lx", get_solution(), { x, y, z }); - yc_grid_var sponge_rx = yc_grid_var("sponge_rx", get_solution(), { x, y, z }); - yc_grid_var sponge_bz = yc_grid_var("sponge_bz", get_solution(), { x, y, z }); - yc_grid_var sponge_tz = yc_grid_var("sponge_tz", get_solution(), { x, y, z }); - yc_grid_var sponge_fy = yc_grid_var("sponge_fy", get_solution(), { x, y, z }); - yc_grid_var sponge_by = yc_grid_var("sponge_by", get_solution(), { x, y, z }); - yc_grid_var sponge_sq_lx = yc_grid_var("sponge_sq_lx", get_solution(), { x, y, z }); - yc_grid_var sponge_sq_rx = yc_grid_var("sponge_sq_rx", get_solution(), { x, y, z }); - yc_grid_var sponge_sq_bz = yc_grid_var("sponge_sq_bz", get_solution(), { x, y, z }); - yc_grid_var sponge_sq_tz = yc_grid_var("sponge_sq_tz", get_solution(), { x, y, z }); - yc_grid_var sponge_sq_fy = yc_grid_var("sponge_sq_fy", get_solution(), { x, y, z }); - yc_grid_var sponge_sq_by = yc_grid_var("sponge_sq_by", get_solution(), { x, y, z }); + yc_grid_var sponge_lx = yc_grid_var("sponge_lx", get_soln(), { x, y, z }); + yc_grid_var sponge_rx = yc_grid_var("sponge_rx", get_soln(), { x, y, z }); + yc_grid_var sponge_bz = yc_grid_var("sponge_bz", get_soln(), { x, y, z }); + yc_grid_var sponge_tz = yc_grid_var("sponge_tz", get_soln(), { x, y, z }); + yc_grid_var sponge_fy = yc_grid_var("sponge_fy", get_soln(), { x, y, z }); + yc_grid_var sponge_by = yc_grid_var("sponge_by", get_soln(), { x, y, z }); + yc_grid_var sponge_sq_lx = yc_grid_var("sponge_sq_lx", get_soln(), { x, y, z }); + yc_grid_var sponge_sq_rx = yc_grid_var("sponge_sq_rx", get_soln(), { x, y, z }); + yc_grid_var sponge_sq_bz = yc_grid_var("sponge_sq_bz", get_soln(), { x, y, z }); + yc_grid_var sponge_sq_tz = yc_grid_var("sponge_sq_tz", get_soln(), { x, y, z }); + yc_grid_var sponge_sq_fy = yc_grid_var("sponge_sq_fy", get_soln(), { x, y, z }); + yc_grid_var sponge_sq_by = yc_grid_var("sponge_sq_by", get_soln(), { x, y, z }); FSGElasticStencilBase &fsg; @@ -363,13 +363,13 @@ namespace fsg { yc_bool_node_ptr at_abc = is_at_boundary(); - yc_number_node_ptr next_v = v(t, x, y, z) * abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); + auto next_v = v(t, x, y, z) * abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); - yc_number_node_ptr lrho = fsg.interp_rho( x, y, z ); + auto lrho = fsg.interp_rho( x, y, z ); - yc_number_node_ptr stx = fsg.stencil_O2_X( t, x, y, z, sx ); - yc_number_node_ptr sty = fsg.stencil_O2_Y( t, x, y, z, sy ); - yc_number_node_ptr stz = fsg.stencil_O2_Z( t, x, y, z, sz ); + auto stx = fsg.stencil_O2_X( t, x, y, z, sx ); + auto sty = fsg.stencil_O2_Y( t, x, y, z, sy ); + auto stz = fsg.stencil_O2_Z( t, x, y, z, sz ); next_v += ((stx + sty + stz) * fsg.delta_t * lrho); next_v *= abc_sq_x(x,y,z) * abc_sq_y(x,y,z) * abc_sq_z(x,y,z); @@ -412,52 +412,52 @@ namespace fsg { yc_grid_var &vxu, yc_grid_var &vxv, yc_grid_var &vxw, yc_grid_var &vyu, yc_grid_var &vyv, yc_grid_var &vyw, yc_grid_var &vzu, yc_grid_var &vzv, yc_grid_var &vzw, yc_grid_var &abc_x, yc_grid_var &abc_y, yc_grid_var &abc_z, yc_grid_var &abc_sq_x, yc_grid_var &abc_sq_y, yc_grid_var &abc_sq_z) { - yc_number_node_ptr abc = abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); - yc_number_node_ptr next_sxx = sxx(t, x, y, z) * abc; - yc_number_node_ptr next_syy = syy(t, x, y, z) * abc; - yc_number_node_ptr next_szz = szz(t, x, y, z) * abc; - yc_number_node_ptr next_syz = syz(t, x, y, z) * abc; - yc_number_node_ptr next_sxz = sxz(t, x, y, z) * abc; - yc_number_node_ptr next_sxy = sxy(t, x, y, z) * abc; + auto abc = abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); + auto next_sxx = sxx(t, x, y, z) * abc; + auto next_syy = syy(t, x, y, z) * abc; + auto next_szz = szz(t, x, y, z) * abc; + auto next_syz = syz(t, x, y, z) * abc; + auto next_sxz = sxz(t, x, y, z) * abc; + auto next_sxy = sxy(t, x, y, z) * abc; // Interpolate coeffs. - yc_number_node_ptr ic11 = fsg.cell_coeff (x, y, z, fsg.c11); - yc_number_node_ptr ic12 = fsg.cell_coeff (x, y, z, fsg.c12); - yc_number_node_ptr ic13 = fsg.cell_coeff (x, y, z, fsg.c13); - yc_number_node_ptr ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c14); - yc_number_node_ptr ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c15); - yc_number_node_ptr ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c16); - yc_number_node_ptr ic22 = fsg.cell_coeff (x, y, z, fsg.c22); - yc_number_node_ptr ic23 = fsg.cell_coeff (x, y, z, fsg.c23); - yc_number_node_ptr ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c24); - yc_number_node_ptr ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c25); - yc_number_node_ptr ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c26); - yc_number_node_ptr ic33 = fsg.cell_coeff (x, y, z, fsg.c33); - yc_number_node_ptr ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c34); - yc_number_node_ptr ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c35); - yc_number_node_ptr ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c36); - yc_number_node_ptr ic44 = fsg.cell_coeff (x, y, z, fsg.c44); - yc_number_node_ptr ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c45); - yc_number_node_ptr ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c46); - yc_number_node_ptr ic55 = fsg.cell_coeff (x, y, z, fsg.c55); - yc_number_node_ptr ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c56); - yc_number_node_ptr ic66 = fsg.cell_coeff (x, y, z, fsg.c66); + auto ic11 = fsg.cell_coeff (x, y, z, fsg.c11); + auto ic12 = fsg.cell_coeff (x, y, z, fsg.c12); + auto ic13 = fsg.cell_coeff (x, y, z, fsg.c13); + auto ic14 = fsg.cell_coeff_artm(x, y, z, fsg.c14); + auto ic15 = fsg.cell_coeff_artm(x, y, z, fsg.c15); + auto ic16 = fsg.cell_coeff_artm(x, y, z, fsg.c16); + auto ic22 = fsg.cell_coeff (x, y, z, fsg.c22); + auto ic23 = fsg.cell_coeff (x, y, z, fsg.c23); + auto ic24 = fsg.cell_coeff_artm(x, y, z, fsg.c24); + auto ic25 = fsg.cell_coeff_artm(x, y, z, fsg.c25); + auto ic26 = fsg.cell_coeff_artm(x, y, z, fsg.c26); + auto ic33 = fsg.cell_coeff (x, y, z, fsg.c33); + auto ic34 = fsg.cell_coeff_artm(x, y, z, fsg.c34); + auto ic35 = fsg.cell_coeff_artm(x, y, z, fsg.c35); + auto ic36 = fsg.cell_coeff_artm(x, y, z, fsg.c36); + auto ic44 = fsg.cell_coeff (x, y, z, fsg.c44); + auto ic45 = fsg.cell_coeff_artm(x, y, z, fsg.c45); + auto ic46 = fsg.cell_coeff_artm(x, y, z, fsg.c46); + auto ic55 = fsg.cell_coeff (x, y, z, fsg.c55); + auto ic56 = fsg.cell_coeff_artm(x, y, z, fsg.c56); + auto ic66 = fsg.cell_coeff (x, y, z, fsg.c66); // Compute stencils. Note that we are using the velocity values at t+1. - yc_number_node_ptr u_z = fsg.stencil_O2_Z( t+1, x, y, z, vzu ); - yc_number_node_ptr v_z = fsg.stencil_O2_Z( t+1, x, y, z, vzv ); - yc_number_node_ptr w_z = fsg.stencil_O2_Z( t+1, x, y, z, vzw ); + auto u_z = fsg.stencil_O2_Z( t+1, x, y, z, vzu ); + auto v_z = fsg.stencil_O2_Z( t+1, x, y, z, vzv ); + auto w_z = fsg.stencil_O2_Z( t+1, x, y, z, vzw ); - yc_number_node_ptr u_x = fsg.stencil_O2_X( t+1, x, y, z, vxu ); - yc_number_node_ptr v_x = fsg.stencil_O2_X( t+1, x, y, z, vxv ); - yc_number_node_ptr w_x = fsg.stencil_O2_X( t+1, x, y, z, vxw ); + auto u_x = fsg.stencil_O2_X( t+1, x, y, z, vxu ); + auto v_x = fsg.stencil_O2_X( t+1, x, y, z, vxv ); + auto w_x = fsg.stencil_O2_X( t+1, x, y, z, vxw ); - yc_number_node_ptr u_y = fsg.stencil_O2_Y( t+1, x, y, z, vyu ); - yc_number_node_ptr v_y = fsg.stencil_O2_Y( t+1, x, y, z, vyv ); - yc_number_node_ptr w_y = fsg.stencil_O2_Y( t+1, x, y, z, vyw ); + auto u_y = fsg.stencil_O2_Y( t+1, x, y, z, vyu ); + auto v_y = fsg.stencil_O2_Y( t+1, x, y, z, vyv ); + auto w_y = fsg.stencil_O2_Y( t+1, x, y, z, vyw ); // Compute next stress value - yc_number_node_ptr abc_sq = abc_sq_x(x,y,z) * abc_sq_y(x,y,z) * abc_sq_z(x,y,z); + auto abc_sq = abc_sq_x(x,y,z) * abc_sq_y(x,y,z) * abc_sq_z(x,y,z); next_sxx += fsg.stress_update(ic11,ic12,ic13,ic14,ic15,ic16,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; next_syy += fsg.stress_update(ic12,ic22,ic23,ic24,ic25,ic26,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; next_szz += fsg.stress_update(ic13,ic23,ic33,ic34,ic35,ic36,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 5ba5900e..d265fcd7 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -44,9 +44,9 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Grid vars. yc_grid_var pressure = - yc_grid_var("pressure", get_solution(), { t, x, y, z }); // time-varying 3D pressure grid. + yc_grid_var("pressure", get_soln(), { t, x, y, z }); // time-varying 3D pressure grid. yc_grid_var vel = - yc_grid_var("vel", get_solution(), { x, y, z }); // constant 3D vel grid (c(x,y,z)^2 * delta_t^2). + yc_grid_var("vel", get_soln(), { x, y, z }); // constant 3D vel grid (c(x,y,z)^2 * delta_t^2). public: @@ -83,7 +83,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Calculate FDx + FDy + FDz. // Start with center value multiplied by coeff 0. - yc_number_node_ptr fd_sum = pressure(t, x, y, z) * coeff[c0i]; + auto fd_sum = pressure(t, x, y, z) * coeff[c0i]; // Add values from x, y, and z axes multiplied by the // coeff for the given radius. @@ -127,7 +127,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // p(t+1) = 2 * p(t) - p(t-1) + c^2 * fd_sum * delta_t^2. // Let vel = c^2 * delta_t^2 for each grid point. - yc_number_node_ptr next_p = (2.0 * pressure(t, x, y, z)) - + auto next_p = (2.0 * pressure(t, x, y, z)) - pressure(t-1, x, y, z) + (fd_sum * vel(x, y, z)); return next_p; @@ -137,7 +137,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { virtual void define() { // Get equation for RHS. - yc_number_node_ptr next_p = get_next_p(); + auto next_p = get_next_p(); // Define the value at t+1 to be equal to next_p. // Since this implements the finite-difference method, this @@ -159,9 +159,9 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { // In practice, the interior values would be set to 1.0, // and values nearer the boundary would be set to values // increasingly approaching 0.0. - yc_grid_var cr_x = yc_grid_var("cr_x", get_solution(), { x }); - yc_grid_var cr_y = yc_grid_var("cr_y", get_solution(), { y }); - yc_grid_var cr_z = yc_grid_var("cr_z", get_solution(), { z }); + yc_grid_var cr_x = yc_grid_var("cr_x", get_soln(), { x }); + yc_grid_var cr_y = yc_grid_var("cr_y", get_soln(), { y }); + yc_grid_var cr_z = yc_grid_var("cr_z", get_soln(), { z }); public: Iso3dfdSpongeStencil(int radius=8) : @@ -172,7 +172,7 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { virtual void define() { // Get equation for RHS. - yc_number_node_ptr next_p = get_next_p(); + auto next_p = get_next_p(); // Apply sponge absorption. next_p *= cr_x(x) * cr_y(y) * cr_z(z); diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index d6a19984..4d056f0a 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -35,11 +35,11 @@ class SSGElastic2Stencil : public Elastic2StencilBase { protected: // Time-varying 3D-spatial velocity grids. - yc_grid_var v = yc_grid_var("v", get_solution(), { t, x, y, z, vidx }); + yc_grid_var v = yc_grid_var("v", get_soln(), { t, x, y, z, vidx }); enum VIDX { V_BL_W, V_TL_V, V_TR_U }; // Time-varying 3D-spatial Stress grids. - yc_grid_var s = yc_grid_var("s", get_solution(), { t, x, y, z, sidx }); + yc_grid_var s = yc_grid_var("s", get_soln(), { t, x, y, z, sidx }); enum SIDX { S_BL_YZ, S_BR_XZ, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TR_XY }; public: @@ -92,12 +92,12 @@ class SSGElastic2Stencil : public Elastic2StencilBase { void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_number_node_ptr sidx, yc_number_node_ptr va_idx, yc_number_node_ptr vb_idx) { - yc_number_node_ptr lcoeff = interp_mu( x, y, z ); + auto lcoeff = interp_mu( x, y, z ); - yc_number_node_ptr vta = stencil_O8( t+1, x, y, z, v, va_idx ); - yc_number_node_ptr vtb = stencil_O8( t+1, x, y, z, v, vb_idx ); + auto vta = stencil_O8( t+1, x, y, z, v, va_idx ); + auto vtb = stencil_O8( t+1, x, y, z, v, vb_idx ); - yc_number_node_ptr next_s = s(t, x, y, z, sidx) + ((vta + vtb) * lcoeff) * delta_t; + auto next_s = s(t, x, y, z, sidx) + ((vta + vtb) * lcoeff) * delta_t; // define the value at t+1. s(t+1, x, y, z, sidx) EQUALS next_s; @@ -112,20 +112,20 @@ class SSGElastic2Stencil : public Elastic2StencilBase { void define_str_TL(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { - yc_number_node_ptr ilambdamu2 = 1.0 / coef(x,y,z, C_LAMBDA_MU2); - yc_number_node_ptr ilambda = 1.0 / coef(x,y,z, C_LAMBDA); + auto ilambdamu2 = 1.0 / coef(x,y,z, C_LAMBDA_MU2); + auto ilambda = 1.0 / coef(x,y,z, C_LAMBDA); - yc_number_node_ptr vtx = stencil_O8( t+1, x, y, z, v, new_number_node(V_TR_U) ); - yc_number_node_ptr vty = stencil_O8( t+1, x, y, z, v, new_number_node(V_TL_V) ); - yc_number_node_ptr vtz = stencil_O8( t+1, x, y, z, v, new_number_node(V_BL_W) ); + auto vtx = stencil_O8( t+1, x, y, z, v, new_number_node(V_TR_U) ); + auto vty = stencil_O8( t+1, x, y, z, v, new_number_node(V_TL_V) ); + auto vtz = stencil_O8( t+1, x, y, z, v, new_number_node(V_BL_W) ); - yc_number_node_ptr next_xx = s(t, x, y, z, S_TL_XX) + ilambdamu2 * vtx * delta_t + auto next_xx = s(t, x, y, z, S_TL_XX) + ilambdamu2 * vtx * delta_t + ilambda * vty * delta_t + ilambda * vtz * delta_t; - yc_number_node_ptr next_yy = s(t, x, y, z, S_TL_YY) + ilambda * vtx * delta_t + auto next_yy = s(t, x, y, z, S_TL_YY) + ilambda * vtx * delta_t + ilambdamu2 * vty * delta_t + ilambda * vtz * delta_t; - yc_number_node_ptr next_zz = s(t, x, y, z, S_TL_ZZ) + ilambda * vtx * delta_t + auto next_zz = s(t, x, y, z, S_TL_ZZ) + ilambda * vtx * delta_t + ilambda * vty * delta_t + ilambdamu2 * vtz * delta_t; diff --git a/src/stencils/SSGElasticStencil.cpp b/src/stencils/SSGElasticStencil.cpp index 3ccd83d8..a8371bb1 100644 --- a/src/stencils/SSGElasticStencil.cpp +++ b/src/stencils/SSGElasticStencil.cpp @@ -33,22 +33,22 @@ class SSGElasticStencil : public ElasticStencilBase { protected: // Time-varying 3D-spatial velocity grids. - yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_solution(), { t, x, y, z }); - yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_solution(), { t, x, y, z }); - yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_solution(), { t, x, y, z }); + yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_soln(), { t, x, y, z }); + yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_soln(), { t, x, y, z }); + yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_soln(), { t, x, y, z }); // Time-varying 3D-spatial Stress grids. - yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_solution(), { t, x, y, z }); - yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_solution(), { t, x, y, z }); - yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_solution(), { t, x, y, z }); - yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_solution(), { t, x, y, z }); + yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_soln(), { t, x, y, z }); + yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_soln(), { t, x, y, z }); + yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_soln(), { t, x, y, z }); + yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_soln(), { t, x, y, z }); // 3D-spatial coefficients. - yc_grid_var mu = yc_grid_var("mu", get_solution(), { x, y, z }); - yc_grid_var lambda = yc_grid_var("lambda", get_solution(), { x, y, z }); - yc_grid_var lambdamu2 = yc_grid_var("lambdamu2", get_solution(), { x, y, z }); + yc_grid_var mu = yc_grid_var("mu", get_soln(), { x, y, z }); + yc_grid_var lambda = yc_grid_var("lambda", get_soln(), { x, y, z }); + yc_grid_var lambdamu2 = yc_grid_var("lambdamu2", get_soln(), { x, y, z }); public: @@ -100,12 +100,12 @@ class SSGElasticStencil : public ElasticStencilBase { void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &s, yc_grid_var &va, yc_grid_var &vb) { - yc_number_node_ptr lcoeff = interp_mu( x, y, z ); + auto lcoeff = interp_mu( x, y, z ); - yc_number_node_ptr vta = stencil_O8( t+1, x, y, z, va ); - yc_number_node_ptr vtb = stencil_O8( t+1, x, y, z, vb ); + auto vta = stencil_O8( t+1, x, y, z, va ); + auto vtb = stencil_O8( t+1, x, y, z, vb ); - yc_number_node_ptr next_s = s(t, x, y, z) + ((vta + vtb) * lcoeff) * delta_t; + auto next_s = s(t, x, y, z) + ((vta + vtb) * lcoeff) * delta_t; // define the value at t+1. s(t+1, x, y, z) EQUALS next_s; @@ -114,20 +114,20 @@ class SSGElasticStencil : public ElasticStencilBase { void define_str_TL(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { - yc_number_node_ptr ilambdamu2 = 1.0 / lambdamu2(x,y,z); - yc_number_node_ptr ilambda = 1.0 / lambda (x,y,z); + auto ilambdamu2 = 1.0 / lambdamu2(x,y,z); + auto ilambda = 1.0 / lambda (x,y,z); - yc_number_node_ptr vtx = stencil_O8( t+1, x, y, z, v_tr_u ); - yc_number_node_ptr vty = stencil_O8( t+1, x, y, z, v_tl_v ); - yc_number_node_ptr vtz = stencil_O8( t+1, x, y, z, v_bl_w ); + auto vtx = stencil_O8( t+1, x, y, z, v_tr_u ); + auto vty = stencil_O8( t+1, x, y, z, v_tl_v ); + auto vtz = stencil_O8( t+1, x, y, z, v_bl_w ); - yc_number_node_ptr next_xx = s_tl_xx(t, x, y, z) + ilambdamu2 * vtx * delta_t + auto next_xx = s_tl_xx(t, x, y, z) + ilambdamu2 * vtx * delta_t + ilambda * vty * delta_t + ilambda * vtz * delta_t; - yc_number_node_ptr next_yy = s_tl_yy(t, x, y, z) + ilambda * vtx * delta_t + auto next_yy = s_tl_yy(t, x, y, z) + ilambda * vtx * delta_t + ilambdamu2 * vty * delta_t + ilambda * vtz * delta_t; - yc_number_node_ptr next_zz = s_tl_zz(t, x, y, z) + ilambda * vtx * delta_t + auto next_zz = s_tl_zz(t, x, y, z) + ilambda * vtx * delta_t + ilambda * vty * delta_t + ilambdamu2 * vtz * delta_t; diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/SimpleTestStencils.cpp index 6206396f..fba996df 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/SimpleTestStencils.cpp @@ -179,7 +179,7 @@ class Test1dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. public: @@ -205,7 +205,7 @@ class Test2dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. public: @@ -231,7 +231,7 @@ class Test3dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. public: @@ -257,7 +257,7 @@ class Test4dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, w, x, y, z }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, w, x, y, z }); // time-varying grid. public: @@ -283,15 +283,15 @@ class TestPartialStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_solution(), { x }); - yc_grid_var C = yc_grid_var("C", get_solution(), { y }); - yc_grid_var D = yc_grid_var("D", get_solution(), { z }); - yc_grid_var E = yc_grid_var("E", get_solution(), { x, y }); - yc_grid_var F = yc_grid_var("F", get_solution(), { y, z }); - yc_grid_var G = yc_grid_var("G", get_solution(), { z, y }); - yc_grid_var H = yc_grid_var("H", get_solution(), { y, z, x }); // different order. - yc_grid_var I = yc_grid_var("I", get_solution(), { }); + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_soln(), { x }); + yc_grid_var C = yc_grid_var("C", get_soln(), { y }); + yc_grid_var D = yc_grid_var("D", get_soln(), { z }); + yc_grid_var E = yc_grid_var("E", get_soln(), { x, y }); + yc_grid_var F = yc_grid_var("F", get_soln(), { y, z }); + yc_grid_var G = yc_grid_var("G", get_soln(), { z, y }); + yc_grid_var H = yc_grid_var("H", get_soln(), { y, z, x }); // different order. + yc_grid_var I = yc_grid_var("I", get_soln(), { }); public: @@ -334,7 +334,7 @@ class TestMisc2dStencil : public yc_solution_with_radius_base { // Time-varying grid. Intermix last domain dim with misc dims to make // sure compiler creates correct layout. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, a, y, b, c }); + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, a, y, b, c }); public: @@ -382,7 +382,7 @@ class StreamStencil : public yc_solution_with_radius_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying 3D grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying 3D grid. public: @@ -417,7 +417,7 @@ class TestReverseStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); public: @@ -445,8 +445,8 @@ class TestDepStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_solution(), { t, x }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_soln(), { t, x }); // time-varying grid. public: @@ -474,8 +474,8 @@ class TestDepStencil2 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_solution(), { t, x, y }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_soln(), { t, x, y }); // time-varying grid. public: @@ -503,8 +503,8 @@ class TestDepStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_solution(), { t, x, y, z }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_soln(), { t, x, y, z }); // time-varying grid. public: @@ -536,10 +536,10 @@ class TestScratchStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. // Temporary storage. - yc_grid_var B = yc_grid_var("B", get_solution(), { x }, true); + yc_grid_var B = yc_grid_var("B", get_soln(), { x }, true); public: @@ -567,12 +567,12 @@ class TestScratchStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. // Temporary storage. - yc_grid_var t1 = yc_grid_var("t1", get_solution(), { x, y, z }, true); - yc_grid_var t2 = yc_grid_var("t2", get_solution(), { x, y, z }, true); - yc_grid_var t3 = yc_grid_var("t3", get_solution(), { x, y, z }, true); + yc_grid_var t1 = yc_grid_var("t1", get_soln(), { x, y, z }, true); + yc_grid_var t2 = yc_grid_var("t2", get_soln(), { x, y, z }, true); + yc_grid_var t3 = yc_grid_var("t3", get_soln(), { x, y, z }, true); public: @@ -607,7 +607,7 @@ class TestBoundaryStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. public: @@ -618,10 +618,10 @@ class TestBoundaryStencil1 : public TestBase { virtual void define() { // Define interior sub-domain. - yc_bool_node_ptr sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); + auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); // Define interior points. - yc_number_node_ptr u = def_1d(A, t, x, 0, 1); + auto u = def_1d(A, t, x, 0, 1); A(t+1, x) EQUALS u IF_DOMAIN sd0; // Define exterior points. @@ -639,7 +639,7 @@ class TestBoundaryStencil2 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. public: @@ -650,7 +650,7 @@ class TestBoundaryStencil2 : public TestBase { virtual void define() { // Sub-domain is rectangle interior. - yc_bool_node_ptr sd0 = + auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6); @@ -670,7 +670,7 @@ class TestBoundaryStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y, z }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. public: @@ -681,7 +681,7 @@ class TestBoundaryStencil3 : public TestBase { virtual void define() { // Sub-domain is rectangle interior. - yc_bool_node_ptr sd0 = + auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6) && (z >= first_domain_index(z) + 6) && (z <= last_domain_index(z) - 4); @@ -706,8 +706,8 @@ class TestStepCondStencil1 : public TestBase { yc_index_node_ptr b = new_misc_index("b"); // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_solution(), { b }); + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. + yc_grid_var B = yc_grid_var("B", get_soln(), { b }); public: @@ -718,10 +718,10 @@ class TestStepCondStencil1 : public TestBase { virtual void define() { // Time condition. - yc_bool_node_ptr tc0 = (t % 2 == 0); + auto tc0 = (t % 2 == 0); // Var condition. - yc_bool_node_ptr vc0 = (B(0) > B(1)); + auto vc0 = (B(0) > B(1)); // Set A w/different stencils depending on the conditions. It is // the programmer's responsibility to ensure that the conditions are @@ -750,10 +750,10 @@ class TestScratchBoundaryStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. // Temporary storage. - yc_grid_var B = yc_grid_var("B", get_solution(), { x }, true); + yc_grid_var B = yc_grid_var("B", get_soln(), { x }, true); public: @@ -767,7 +767,7 @@ class TestScratchBoundaryStencil1 : public TestBase { B(x) EQUALS def_1d(A, t, x, 1, 0); // Define sub-domain. - yc_bool_node_ptr sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); + auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); // Define next values for 'A' from scratch var values. auto v = def_no_t_1d(B, x-6, 2, 3) - def_no_t_1d(B, x+7, 0, 2); @@ -787,9 +787,9 @@ class TestFuncStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x }); - yc_grid_var B = yc_grid_var("B", get_solution(), { t, x }); - yc_grid_var C = yc_grid_var("C", get_solution(), { t, x }); + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); + yc_grid_var B = yc_grid_var("B", get_soln(), { t, x }); + yc_grid_var C = yc_grid_var("C", get_soln(), { t, x }); public: @@ -814,7 +814,7 @@ class TestEmptyStencil2 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_solution(), { t, x, y }); // time-varying grid. + yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. public: diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index 9fddfe21..ffa56e04 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -43,20 +43,20 @@ class TTIStencil:public yc_solution_with_radius_base yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Grid vars. - yc_grid_var u = yc_grid_var("u", get_solution(), { t, x, y, z }); // Time-varying 3D wavefield grid. - yc_grid_var v = yc_grid_var("v", get_solution(), { t, x, y, z }); // Time-varying 3D wavefield grid. - yc_grid_var m = yc_grid_var("m", get_solution(), { x, y, z }); // Square slowness of the model. - yc_grid_var damp = yc_grid_var("damp", get_solution(), { x, y, z }); // Boundary damping. - yc_grid_var phi = yc_grid_var("phi", get_solution(), { x, y, z }); - yc_grid_var theta = yc_grid_var("theta", get_solution(), { x, y, z }); - yc_grid_var delta = yc_grid_var("delta", get_solution(), { x, y, z }); - yc_grid_var epsilon = yc_grid_var("epsilon", get_solution(), { x, y, z }); + yc_grid_var u = yc_grid_var("u", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield grid. + yc_grid_var v = yc_grid_var("v", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield grid. + yc_grid_var m = yc_grid_var("m", get_soln(), { x, y, z }); // Square slowness of the model. + yc_grid_var damp = yc_grid_var("damp", get_soln(), { x, y, z }); // Boundary damping. + yc_grid_var phi = yc_grid_var("phi", get_soln(), { x, y, z }); + yc_grid_var theta = yc_grid_var("theta", get_soln(), { x, y, z }); + yc_grid_var delta = yc_grid_var("delta", get_soln(), { x, y, z }); + yc_grid_var epsilon = yc_grid_var("epsilon", get_soln(), { x, y, z }); // Hoisted misc time-invariant data. - yc_grid_var ti0 = yc_grid_var("ti0", get_solution(), { x, y, z }); - yc_grid_var ti1 = yc_grid_var("ti1", get_solution(), { x, y, z }); - yc_grid_var ti2 = yc_grid_var("ti2", get_solution(), { x, y, z }); - yc_grid_var ti3 = yc_grid_var("ti3", get_solution(), { x, y, z }); + yc_grid_var ti0 = yc_grid_var("ti0", get_soln(), { x, y, z }); + yc_grid_var ti1 = yc_grid_var("ti1", get_soln(), { x, y, z }); + yc_grid_var ti2 = yc_grid_var("ti2", get_soln(), { x, y, z }); + yc_grid_var ti3 = yc_grid_var("ti3", get_soln(), { x, y, z }); public: @@ -74,25 +74,25 @@ TTIStencil (int radius = 2): virtual void define_so4 () { - yc_number_node_ptr temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); - yc_number_node_ptr temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, + auto temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); + auto temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, z); - yc_number_node_ptr temp192 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 1, + auto temp192 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 1, z) - 2.5e-2 * u (t, x, y + 1, z); - yc_number_node_ptr temp183 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x - 2, y, + auto temp183 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x - 2, y, z) + 1.0e-1 * u (t, x - 1, y, z); - yc_number_node_ptr temp168 = + auto temp168 = -7.5e-2 * u (t, x, y + 1, z) + 1.0e-1 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 1, z); - yc_number_node_ptr temp197 = + auto temp197 = 3.75e-2 * (temp161 * ti1 (x, y, z) * ti2 (x, y, z) + temp163 * ti2 (x, y, z) * ti3 (x, y, z) - (-7.5e-2 * u (t, x, y, @@ -103,45 +103,45 @@ TTIStencil (int radius = 2): z + 2)) * ti0 (x, y, z)); - yc_number_node_ptr temp171 = + auto temp171 = -7.5e-2 * u (t, x + 1, y, z) + 1.0e-1 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 1, y + 2, z); - yc_number_node_ptr temp178 = 2.5e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)); - yc_number_node_ptr temp182 = + auto temp178 = 2.5e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)); + auto temp182 = 2.5e-2 * (-u (t, x - 2, y - 1, z) + u (t, x - 2, y + 1, z)); - yc_number_node_ptr temp190 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x - 1, y, + auto temp190 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x - 1, y, z) - 2.5e-2 * u (t, x + 1, y, z); - yc_number_node_ptr temp173 = 2.5e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)); - yc_number_node_ptr temp188 = + auto temp173 = 2.5e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)); + auto temp188 = 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x - 1, y + 1, z)); - yc_number_node_ptr temp154 = 2.5e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); - yc_number_node_ptr temp186 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 2, + auto temp154 = 2.5e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); + auto temp186 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 2, z) + 1.0e-1 * u (t, x, y - 1, z); - yc_number_node_ptr temp158 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x + 1, y, + auto temp158 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x + 1, y, z) - 2.5e-2 * u (t, x + 2, y, z); - yc_number_node_ptr temp191 = + auto temp191 = 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x + 1, y - 1, z)); - yc_number_node_ptr temp184 = + auto temp184 = 2.5e-2 * (-u (t, x - 1, y - 2, z) + u (t, x + 1, y - 2, z)); - yc_number_node_ptr temp181 = + auto temp181 = -7.5e-2 * u (t, x - 1, y, z) + 1.0e-1 * u (t, x - 1, y + 1, z) - 2.5e-2 * u (t, x - 1, y + 2, z); - yc_number_node_ptr temp176 = + auto temp176 = -7.5e-2 * u (t, x, y - 1, z) + 1.0e-1 * u (t, x + 1, y - 1, z) - 2.5e-2 * u (t, x + 2, y - 1, z); - yc_number_node_ptr temp123 = + auto temp123 = (2.5e-2 * ((v (t, x, y, z) - v (t, x, y - 2, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, @@ -152,7 +152,7 @@ TTIStencil (int radius = 2): 2.5e-2 * v (t, x + 2, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); - yc_number_node_ptr temp102 = + auto temp102 = (2.5e-2 * ((-v (t, x - 1, y, z - 1) + v (t, x - 1, y, z + 1)) * ti2 (x - 1, y, z) + (-v (t, @@ -177,7 +177,7 @@ TTIStencil (int radius = 2): z) * ti1 (x - 1, y, z)) * ti0 (x - 1, y, z) * ti1 (x - 1, y, z); - yc_number_node_ptr temp131 = + auto temp131 = (2.5e-2 * (-v (t, x - 1, y, z - 2) + v (t, x + 1, y, z - 2)) * ti0 (x, y, z - 2) * ti1 (x, y, z - 2) + (-2.5e-2 * v (t, x, y, @@ -194,7 +194,7 @@ TTIStencil (int radius = 2): z - 2)) * ti2 (x, y, z - 2); - yc_number_node_ptr temp87 = + auto temp87 = (2.5e-2 * ((-v (t, x - 2, y, z - 1) + v (t, x - 2, y, z + 1)) * ti2 (x - 2, y, z) + (-v (t, @@ -219,7 +219,7 @@ TTIStencil (int radius = 2): z) * ti1 (x - 2, y, z)) * ti0 (x - 2, y, z) * ti1 (x - 2, y, z); - yc_number_node_ptr temp47 = + auto temp47 = 2.5e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z)) * ti0 (x, y, z) * ti1 (x, y, @@ -235,7 +235,7 @@ TTIStencil (int radius = 2): y + 2, z)) * ti0 (x, y, z) * ti3 (x, y, z); - yc_number_node_ptr temp110 = + auto temp110 = (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y + 2, z)) * ti0 (x, y + 1, z) * ti3 (x, y + 1, @@ -246,7 +246,7 @@ TTIStencil (int radius = 2): 2.5e-2 * v (t, x + 2, y + 1, z)) * ti0 (x, y + 1, z) * ti1 (x, y + 1, z)) * ti0 (x, y + 1, z) * ti3 (x, y + 1, z); - yc_number_node_ptr temp140 = + auto temp140 = (2.5e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) * ti0 (x + 1, y, z) * ti1 (x + 1, y, z) + (-7.5e-2 * v (t, x + 1, y, z) + 1.0e-1 * v (t, x + 1, y, @@ -260,7 +260,7 @@ TTIStencil (int radius = 2): ti0 (x + 1, y, z) * ti1 (x + 1, y, z); - yc_number_node_ptr temp149 = + auto temp149 = (2.5e-2 * (-v (t, x - 1, y - 2, z) + v (t, x + 1, y - 2, z)) * ti0 (x, y - 2, z) * ti1 (x, y - 2, z) + (-2.5e-2 * v (t, x, y, @@ -279,7 +279,7 @@ TTIStencil (int radius = 2): y - 2, z) * ti3 (x, y - 2, z); - yc_number_node_ptr temp39 = + auto temp39 = (2.5e-2 * ((-v (t, x, y, z - 1) + v (t, x, y, z + 1)) * ti2 (x, y, z) + (-v (t, x, @@ -299,7 +299,7 @@ TTIStencil (int radius = 2): z)) * ti0 (x, y, z) * ti1 (x, y, z)) * ti0 (x, y, z) * ti1 (x, y, z); - yc_number_node_ptr temp132 = + auto temp132 = (2.5e-2 * (-v (t, x - 1, y, z - 1) + v (t, x + 1, y, z - 1)) * ti0 (x, y, z - 1) * ti1 (x, y, z - 1) + (1.0e-1 * v (t, x, y, @@ -315,9 +315,9 @@ TTIStencil (int radius = 2): z - 1)) * ti2 (x, y, z - 1); - yc_number_node_ptr temp6 = + auto temp6 = 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); - yc_number_node_ptr temp141 = + auto temp141 = (2.5e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) * ti0 (x - 1, y, z) * ti1 (x - 1, y, z) + (-7.5e-2 * v (t, x - 1, y, z) + 1.0e-1 * v (t, x - 1, y, @@ -331,9 +331,9 @@ TTIStencil (int radius = 2): ti0 (x - 1, y, z) * ti1 (x - 1, y, z); - yc_number_node_ptr temp10 = + auto temp10 = 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); - yc_number_node_ptr temp215 = + auto temp215 = 3.75e-2 * (-temp154 * ti1 (x, y, z) + temp158 * ti3 (x, y, z)) * ti3 (x, y, z) @@ -695,7 +695,7 @@ TTIStencil (int radius = 2): z - 2)) * ti0 (x, y, z - 2)); - yc_number_node_ptr temp77 = + auto temp77 = (2.5e-2 * ((v (t, x, y, z) - v (t, x, y, z - 2)) * ti2 (x, y, z - 1) + (-v (t, x, @@ -729,7 +729,7 @@ TTIStencil (int radius = 2): ti0 (x, y, z - 1) * ti1 (x, y, z - 1)) * ti2 (x, y, z - 1); - yc_number_node_ptr temp61 = + auto temp61 = (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y, z + 2)) * ti2 (x, y, z + 1) + (-v (t, x, @@ -764,7 +764,7 @@ TTIStencil (int radius = 2): ti0 (x, y, z + 1) * ti1 (x, y, z + 1)) * ti2 (x, y, z + 1); - yc_number_node_ptr temp150 = + auto temp150 = (2.5e-2 * (-v (t, x - 1, y - 1, z) + v (t, x + 1, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, z) + (1.0e-1 * v (t, x, y, @@ -830,19 +830,19 @@ TTIStencil (int radius = 2): virtual void define_so8 () { - yc_number_node_ptr temp330 = + auto temp330 = 4.16666666666667e-3 * (u (t, x - 2, y, z) - u (t, x + 2, y, z)) + 3.33333333333333e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); - yc_number_node_ptr temp333 = + auto temp333 = -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 1, z) + 7.5e-2 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, z) + 4.16666666666667e-3 * u (t, x, y + 3, z); - yc_number_node_ptr temp336 = + auto temp336 = 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x, y + 2, z)) + 4.16666666666667e-3 * (u (t, x, y - 1, z) - u (t, x, y + 3, z)); - yc_number_node_ptr temp395 = + auto temp395 = 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x + 2, y - 2, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -851,26 +851,26 @@ TTIStencil (int radius = 2): x + 1, y - 2, z)); - yc_number_node_ptr temp365 = + auto temp365 = -4.16666666666667e-2 * u (t, x - 2, y, z) - 1.25e-2 * u (t, x - 2, y - 1, z) + 7.5e-2 * u (t, x - 2, y + 1, z) - 2.5e-2 * u (t, x - 2, y + 2, z) + 4.16666666666667e-3 * u (t, x - 2, y + 3, z); - yc_number_node_ptr temp375 = + auto temp375 = -4.16666666666667e-2 * u (t, x + 2, y, z) - 1.25e-2 * u (t, x + 2, y - 1, z) + 7.5e-2 * u (t, x + 2, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 2, z) + 4.16666666666667e-3 * u (t, x + 2, y + 3, z); - yc_number_node_ptr temp394 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 3, y, + auto temp394 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 3, y, z) - 4.16666666666667e-2 * u (t, x - 2, y, z) + 7.5e-2 * u (t, x - 1, y, z) + 4.16666666666667e-3 * u (t, x + 1, y, z); - yc_number_node_ptr temp407 = + auto temp407 = 4.16666666666667e-3 * (u (t, x - 1, y - 2, z) - u (t, x - 1, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -879,17 +879,17 @@ TTIStencil (int radius = 2): x - 1, y + 1, z)); - yc_number_node_ptr temp352 = + auto temp352 = 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x, y - 4, z)) + 3.33333333333333e-2 * (-u (t, x, y - 3, z) + u (t, x, y - 1, z)); - yc_number_node_ptr temp347 = + auto temp347 = -4.16666666666667e-2 * u (t, x + 1, y, z) - 1.25e-2 * u (t, x + 1, y - 1, z) + 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 1, y + 2, z) + 4.16666666666667e-3 * u (t, x + 1, y + 3, z); - yc_number_node_ptr temp409 = + auto temp409 = 4.16666666666667e-3 * (u (t, x + 1, y - 2, z) - u (t, x + 1, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x + 1, @@ -898,58 +898,58 @@ TTIStencil (int radius = 2): x + 1, y + 1, z)); - yc_number_node_ptr temp318 = + auto temp318 = 4.16666666666667e-3 * (u (t, x, y - 2, z) - u (t, x, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); - yc_number_node_ptr temp381 = + auto temp381 = -4.16666666666667e-2 * u (t, x, y - 1, z) - 1.25e-2 * u (t, x - 1, y - 1, z) + 7.5e-2 * u (t, x + 1, y - 1, z) - 2.5e-2 * u (t, x + 2, y - 1, z) + 4.16666666666667e-3 * u (t, x + 3, y - 1, z); - yc_number_node_ptr temp408 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 2, y, + auto temp408 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 2, y, z) - 4.16666666666667e-2 * u (t, x - 1, y, z) - 2.5e-2 * u (t, x + 1, y, z) + 4.16666666666667e-3 * u (t, x + 2, y, z); - yc_number_node_ptr temp390 = + auto temp390 = 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 4, z) - 4.16666666666667e-2 * u (t, x, y - 3, z) + 7.5e-2 * u (t, x, y - 2, z) - 2.5e-2 * u (t, x, y - 1, z); - yc_number_node_ptr temp360 = + auto temp360 = 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x - 4, y, z)) + 3.33333333333333e-2 * (-u (t, x - 3, y, z) + u (t, x - 1, y, z)); - yc_number_node_ptr temp370 = + auto temp370 = -4.16666666666667e-2 * u (t, x, y + 2, z) - 1.25e-2 * u (t, x - 1, y + 2, z) + 7.5e-2 * u (t, x + 1, y + 2, z) - 2.5e-2 * u (t, x + 2, y + 2, z) + 4.16666666666667e-3 * u (t, x + 3, y + 2, z); - yc_number_node_ptr temp357 = + auto temp357 = -4.16666666666667e-2 * u (t, x, y - 2, z) - 1.25e-2 * u (t, x - 1, y - 2, z) + 7.5e-2 * u (t, x + 1, y - 2, z) - 2.5e-2 * u (t, x + 2, y - 2, z) + 4.16666666666667e-3 * u (t, x + 3, y - 2, z); - yc_number_node_ptr temp385 = + auto temp385 = -4.16666666666667e-2 * u (t, x - 1, y, z) - 1.25e-2 * u (t, x - 1, y - 1, z) + 7.5e-2 * u (t, x - 1, y + 1, z) - 2.5e-2 * u (t, x - 1, y + 2, z) + 4.16666666666667e-3 * u (t, x - 1, y + 3, z); - yc_number_node_ptr temp377 = + auto temp377 = 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)) + 4.16666666666667e-3 * (u (t, x, y - 3, z) - u (t, x, y + 1, z)); - yc_number_node_ptr temp343 = + auto temp343 = 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x + 2, y, z)) + 4.16666666666667e-3 * (u (t, x - 1, y, z) - u (t, x + 3, y, z)); - yc_number_node_ptr temp388 = + auto temp388 = 4.16666666666667e-3 * (u (t, x - 2, y - 3, z) - u (t, x + 2, y - 3, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -958,13 +958,13 @@ TTIStencil (int radius = 2): x + 1, y - 3, z)); - yc_number_node_ptr temp406 = + auto temp406 = -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x, y + 1, z) + 7.5e-2 * u (t, x, y + 2, z) - 2.5e-2 * u (t, x, y + 3, z) + 4.16666666666667e-3 * u (t, x, y + 4, z); - yc_number_node_ptr temp404 = + auto temp404 = 4.16666666666667e-3 * (u (t, x - 2, y + 1, z) - u (t, x + 2, y + 1, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -973,23 +973,23 @@ TTIStencil (int radius = 2): x + 1, y + 1, z)); - yc_number_node_ptr temp342 = + auto temp342 = -4.16666666666667e-2 * u (t, x, y + 1, z) - 1.25e-2 * u (t, x - 1, y + 1, z) + 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 1, z) + 4.16666666666667e-3 * u (t, x + 3, y + 1, z); - yc_number_node_ptr temp410 = + auto temp410 = -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x + 1, y, z) + 7.5e-2 * u (t, x + 2, y, z) - 2.5e-2 * u (t, x + 3, y, z) + 4.16666666666667e-3 * u (t, x + 4, y, z); - yc_number_node_ptr temp367 = + auto temp367 = 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x, y + 4, z)) + 3.33333333333333e-2 * (-u (t, x, y + 1, z) + u (t, x, y + 3, z)); - yc_number_node_ptr temp399 = + auto temp399 = 4.16666666666667e-3 * (u (t, x - 2, y - 1, z) - u (t, x + 2, y - 1, z)) + 3.33333333333333e-2 * (-u (t, x - 1, @@ -998,13 +998,13 @@ TTIStencil (int radius = 2): x + 1, y - 1, z)); - yc_number_node_ptr temp325 = + auto temp325 = -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 1, y, z) + 7.5e-2 * u (t, x + 1, y, z) - 2.5e-2 * u (t, x + 2, y, z) + 4.16666666666667e-3 * u (t, x + 3, y, z); - yc_number_node_ptr temp386 = + auto temp386 = 4.16666666666667e-3 * (u (t, x - 3, y - 2, z) - u (t, x - 3, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x - 3, @@ -1013,20 +1013,20 @@ TTIStencil (int radius = 2): x - 3, y + 1, z)); - yc_number_node_ptr temp396 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 3, + auto temp396 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 3, z) - 4.16666666666667e-2 * u (t, x, y - 2, z) + 7.5e-2 * u (t, x, y - 1, z) + 4.16666666666667e-3 * u (t, x, y + 1, z); - yc_number_node_ptr temp401 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 2, + auto temp401 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 2, z) - 4.16666666666667e-2 * u (t, x, y - 1, z) - 2.5e-2 * u (t, x, y + 1, z) + 4.16666666666667e-3 * u (t, x, y + 2, z); - yc_number_node_ptr temp372 = + auto temp372 = 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x + 4, y, z)) + 3.33333333333333e-2 * (-u (t, x + 1, y, z) + u (t, x + 3, y, z)); - yc_number_node_ptr temp420 = + auto temp420 = 2.08333333333333e-2 * ((temp330 * ti1 (x, y, z) + temp333 * ti3 (x, y, z)) * ti2 (x, y, z) - @@ -1038,16 +1038,16 @@ TTIStencil (int radius = 2): z + 2) + 4.16666666666667e-3 * u (t, x, y, z + 3)) * ti0 (x, y, z)); - yc_number_node_ptr temp387 = + auto temp387 = 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x - 4, y, z) - 4.16666666666667e-2 * u (t, x - 3, y, z) + 7.5e-2 * u (t, x - 2, y, z) - 2.5e-2 * u (t, x - 1, y, z); - yc_number_node_ptr temp383 = + auto temp383 = 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)) + 4.16666666666667e-3 * (u (t, x - 3, y, z) - u (t, x + 1, y, z)); - yc_number_node_ptr temp392 = + auto temp392 = 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x - 2, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x - 2, @@ -1056,7 +1056,7 @@ TTIStencil (int radius = 2): x - 2, y + 1, z)); - yc_number_node_ptr temp284 = + auto temp284 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 2) - v (t, x + 2, y, z - 2)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 2) + @@ -1088,7 +1088,7 @@ TTIStencil (int radius = 2): + 1)) * ti2 (x, y, z - 2)) * ti2 (x, y, z - 2); - yc_number_node_ptr temp308 = + auto temp308 = (((4.16666666666667e-3 * (v (t, x - 2, y - 2, z) - v (t, x + 2, y - 2, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 2, z) + @@ -1109,7 +1109,7 @@ TTIStencil (int radius = 2): z + 3)) * ti2 (x, y - 2, z)) * ti0 (x, y - 2, z) * ti3 (x, y - 2, z); - yc_number_node_ptr temp92 = + auto temp92 = (((4.16666666666667e-3 * (v (t, x, y - 2, z + 1) - v (t, x, y + 2, z + 1)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z + 1) + @@ -1132,7 +1132,7 @@ TTIStencil (int radius = 2): y, z + 1); - yc_number_node_ptr temp185 = + auto temp185 = (((4.16666666666667e-3 * (v (t, x - 2, y - 2, z) - v (t, x - 2, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 2, y - 1, z) + @@ -1154,7 +1154,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x - 2, y, z); - yc_number_node_ptr temp283 = + auto temp283 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 3) - v (t, x + 2, y, z - 3)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 3) + @@ -1187,7 +1187,7 @@ TTIStencil (int radius = 2): - 3)) * ti2 (x, y, z - 3); - yc_number_node_ptr temp309 = + auto temp309 = (((4.16666666666667e-3 * (v (t, x - 2, y - 1, z) - v (t, x + 2, y - 1, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + @@ -1208,7 +1208,7 @@ TTIStencil (int radius = 2): z + 3)) * ti2 (x, y - 1, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); - yc_number_node_ptr temp310 = + auto temp310 = (((4.16666666666667e-3 * (v (t, x - 2, y + 1, z) - v (t, x + 2, y + 1, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y + 1, z) + @@ -1238,7 +1238,7 @@ TTIStencil (int radius = 2): y + 1, z) * ti3 (x, y + 1, z); - yc_number_node_ptr temp307 = + auto temp307 = (((4.16666666666667e-3 * (v (t, x - 2, y - 3, z) - v (t, x + 2, y - 3, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 3, z) + @@ -1262,7 +1262,7 @@ TTIStencil (int radius = 2): z + 3)) * ti2 (x, y - 3, z)) * ti0 (x, y - 3, z) * ti3 (x, y - 3, z); - yc_number_node_ptr temp298 = + auto temp298 = (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x + 4, y, z)) + 3.33333333333333e-2 * (-v (t, x + 1, y, z) + v (t, x + 3, y, z))) * ti1 (x + 2, y, @@ -1290,7 +1290,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x + 2, y, z); - yc_number_node_ptr temp165 = + auto temp165 = (((4.16666666666667e-3 * (v (t, x - 3, y - 2, z) - v (t, x - 3, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 3, y - 1, z) + @@ -1316,7 +1316,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x - 3, y, z); - yc_number_node_ptr temp154 = + auto temp154 = (((4.16666666666667e-3 * (v (t, x, y - 2, z - 1) - v (t, x, y + 2, z - 1)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 1) + @@ -1339,7 +1339,7 @@ TTIStencil (int radius = 2): y, z - 1); - yc_number_node_ptr temp299 = + auto temp299 = (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) + 4.16666666666667e-3 * (v (t, x - 3, y, z) - v (t, x + 1, y, z))) * ti1 (x - 1, y, @@ -1367,7 +1367,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x - 1, y, z); - yc_number_node_ptr temp289 = + auto temp289 = (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) + 4.16666666666667e-3 * (v (t, x - 1, y, z) - v (t, x + 3, y, z))) * ti1 (x + 1, y, @@ -1395,7 +1395,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x + 1, y, z); - yc_number_node_ptr temp116 = + auto temp116 = (((4.16666666666667e-3 * (v (t, x, y - 2, z - 2) - v (t, x, y + 2, z - 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 2) + @@ -1418,7 +1418,7 @@ TTIStencil (int radius = 2): y, z - 2); - yc_number_node_ptr temp56 = + auto temp56 = (((4.16666666666667e-3 * (v (t, x, y - 2, z) - v (t, x, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z) + v (t, x, y + 1, z))) * ti3 (x, y, @@ -1438,7 +1438,7 @@ TTIStencil (int radius = 2): z)) * ti0 (x, y, z) * ti1 (x, y, z); - yc_number_node_ptr temp204 = + auto temp204 = (((4.16666666666667e-3 * (v (t, x - 1, y - 2, z) - v (t, x - 1, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + @@ -1460,7 +1460,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x - 1, y, z); - yc_number_node_ptr temp288 = + auto temp288 = (((4.16666666666667e-3 * (v (t, x - 2, y, z + 1) - v (t, x + 2, y, z + 1)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z + 1) + @@ -1492,9 +1492,9 @@ TTIStencil (int radius = 2): + 4)) * ti2 (x, y, z + 1)) * ti2 (x, y, z + 1); - yc_number_node_ptr temp10 = + auto temp10 = 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); - yc_number_node_ptr temp133 = + auto temp133 = (((4.16666666666667e-3 * (v (t, x, y - 2, z + 2) - v (t, x, y + 2, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z + 2) + @@ -1517,7 +1517,7 @@ TTIStencil (int radius = 2): y, z + 2); - yc_number_node_ptr temp286 = + auto temp286 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 1) - v (t, x + 2, y, z - 1)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 1) + @@ -1549,7 +1549,7 @@ TTIStencil (int radius = 2): + 2)) * ti2 (x, y, z - 1)) * ti2 (x, y, z - 1); - yc_number_node_ptr temp252 = + auto temp252 = (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x, y - 4, z)) + 3.33333333333333e-2 * (-v (t, x, y - 3, z) + v (t, x, y - 1, z))) * ti3 (x, y - 2, @@ -1576,7 +1576,7 @@ TTIStencil (int radius = 2): 2, z) * ti3 (x, y - 2, z); - yc_number_node_ptr temp487 = temp420 * ti2 (x, y, z) * ti3 (x, y, + auto temp487 = temp420 * ti2 (x, y, z) * ti3 (x, y, z) + 2.08333333333333e-2 * ((-temp318 * ti1 (x, y, z) + temp325 * ti3 (x, y, z)) * ti3 (x, y, @@ -2274,7 +2274,7 @@ TTIStencil (int radius = 2): z + 1)) * ti0 (x, y, z + 1)); - yc_number_node_ptr temp290 = + auto temp290 = (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x - 4, y, z)) + 3.33333333333333e-2 * (-v (t, x - 3, y, z) + v (t, x - 1, y, z))) * ti1 (x - 2, y, @@ -2302,7 +2302,7 @@ TTIStencil (int radius = 2): y, z) * ti1 (x - 2, y, z); - yc_number_node_ptr temp275 = + auto temp275 = (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x, y - 2, z)) + 4.16666666666667e-3 * (v (t, x, y - 3, z) - v (t, x, y + 1, z))) * ti3 (x, y - 1, @@ -2329,7 +2329,7 @@ TTIStencil (int radius = 2): 1, z) * ti3 (x, y - 1, z); - yc_number_node_ptr temp237 = + auto temp237 = (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x, y + 2, z)) + 4.16666666666667e-3 * (v (t, x, y - 1, z) - v (t, x, y + 3, z))) * ti3 (x, y + 1, @@ -2356,7 +2356,7 @@ TTIStencil (int radius = 2): 1, z) * ti3 (x, y + 1, z); - yc_number_node_ptr temp262 = + auto temp262 = (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x, y + 4, z)) + 3.33333333333333e-2 * (-v (t, x, y + 1, z) + v (t, x, y + 3, z))) * ti3 (x, y + 2, @@ -2383,7 +2383,7 @@ TTIStencil (int radius = 2): 2, z) * ti3 (x, y + 2, z); - yc_number_node_ptr temp68 = + auto temp68 = ((4.16666666666667e-3 * (v (t, x - 2, y, z) - v (t, x + 2, y, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z))) * ti1 (x, y, @@ -2405,9 +2405,9 @@ TTIStencil (int radius = 2): + 2) + 4.16666666666667e-3 * v (t, x, y, z + 3)) * ti2 (x, y, z); - yc_number_node_ptr temp6 = + auto temp6 = 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); - yc_number_node_ptr temp225 = + auto temp225 = (((4.16666666666667e-3 * (v (t, x + 1, y - 2, z) - v (t, x + 1, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x + 1, y - 1, z) + diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index 1159a099..abeed353 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -109,12 +109,12 @@ ($) s/\blast_index\b/last_domain_index/g; # Grid creation. - s/MAKE_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 })/g; - s/MAKE_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 })/g; - s/MAKE_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { })/g; - s/MAKE_SCRATCH_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; - s/MAKE_SCRATCH_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { $2 }, true)/g; - s/MAKE_SCRATCH_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_solution(), { }, true)/g; + s/MAKE_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 })/g; + s/MAKE_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 })/g; + s/MAKE_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { })/g; + s/MAKE_SCRATCH_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 }, true)/g; + s/MAKE_SCRATCH_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 }, true)/g; + s/MAKE_SCRATCH_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { }, true)/g; # Typenames. s/\bStencilBase\b/yc_solution_base/g; From 13775d30ef0976b378b823a657d21cb55efe0ecf Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 9 May 2019 15:24:27 -0700 Subject: [PATCH 18/62] More API and stencil cleanup. --- README.md | 14 +- include/yask_compiler_api.hpp | 73 +++++-- include/yask_compiler_utility_api.hpp | 7 +- include/yask_kernel_api.hpp | 2 +- src/compiler/compiler_main.cpp | 17 +- .../ElasticStencil/Elastic2Stencil.hpp | 164 +++------------ .../ElasticStencil/ElasticStencil.hpp | 193 +++++++++++++++--- src/stencils/FSGElastic2Stencil.cpp | 125 ++++-------- src/stencils/Iso3dfdStencil.cpp | 16 +- src/stencils/SSGElastic2Stencil.cpp | 20 +- src/stencils/SimpleTestStencils.cpp | 6 +- 11 files changed, 330 insertions(+), 307 deletions(-) diff --git a/README.md b/README.md index 3a6b4e1c..6244565e 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,15 @@ ## Overview YASK is a framework to rapidly create high-performance stencil code including optimizations and features such as -* Vector-folding to increase data reuse via non-traditional data layout, -* Multi-level OpenMP parallelism to exploit multiple cores and threads, -* Scaling to multiple sockets and nodes via MPI with overlapped communication and compute, and -* Spatial tiling with automatically-tuned block sizes, -* Temporal tiling in multiple dimensions to further increase cache locality, +* Support for boundary layers and staggered-grid stencils. +* Vector-folding to increase data reuse via non-traditional data layout. +* Multi-level OpenMP parallelism to exploit multiple cores and threads. +* Scaling to multiple sockets and nodes via MPI with overlapped communication and compute. +* Spatial tiling with automatically-tuned block sizes. +* Temporal tiling in multiple dimensions to further increase cache locality. * APIs for C++ and Python: [API documentation](https://rawgit.com/intel/yask/api-docs/html/index.html). -YASK contains a domain-specific compiler to convert scalar stencil code to SIMD-optimized code for Intel(R) Xeon Phi(TM) and Intel(R) Xeon(R) processors. +YASK contains a domain-specific compiler to convert stencil-equation specifications to SIMD-optimized code for Intel(R) Xeon Phi(TM) and Intel(R) Xeon(R) processors. ### Supported Platforms and Processors: * 64-bit Linux. @@ -40,6 +41,7 @@ YASK contains a domain-specific compiler to convert scalar stencil code to SIMD- Older Gnu C++ compilers can produce kernels that run many times slower. * Gnu C++ compiler, g++ (4.9.0 or later; 8.2.0 or later recommended). + Even when using Intel compilers, they rely on functionality provided by a g++ installation. * Linux libraries `librt` and `libnuma`. * Perl (5.010 or later). * Awk. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 1830ce27..15e55c4c 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -117,6 +117,7 @@ namespace yask { /** Objects of this type contain all the grids and equations that comprise a solution. + Must be created via yc_factory::new_solution(). */ class yc_solution { public: @@ -185,6 +186,20 @@ namespace yask { At least one grid must be defined with at least one domain-index node. + Example code to create a solution with a grid equation: + ~~~{.cpp} + yc_factory ycfac; + yc_node_factory nfac; + auto my_soln = ycfac.new_solution("my_stencil"); + auto t = nfac.new_step_index("t"); + auto x = nfac.new_domain_index("x"); + auto y = nfac.new_domain_index("y"); + auto a = ycfac.new_grid("A", { t, x, y }); + a->new_grid_point({t+1, x, y}) EQUALS (a->new_grid_point({t, x, y}) + + a->new_grid_point({t, x+1, y}) + + a->new_grid_point({t, x, y+1})) * (1.0/3.0); + ~~~ + @returns Pointer to the new \ref yc_grid object. */ virtual yc_grid_ptr @@ -504,7 +519,9 @@ namespace yask { A compile-time grid is a variable used for constructing equations. It does not contain any data. Data is only stored during run-time, using a \ref yk_grid. - Created via yc_solution::new_grid(). */ + + Created via yc_solution::new_grid() or implicitly via the \ref yc_grid_var constructor. + */ class yc_grid { public: virtual ~yc_grid() {} @@ -531,13 +548,6 @@ namespace yask { Each expression in `index_exprs` describes how to access an element in the corresponding dimension of the grid. - Example: if a grid was created via - `g = new_grid("A", {t, x, y, n})` with step-dimension `t`, - domain-dimensions `x` and `y`, and misc-dimension `n`, - `g->new_grid_point({t + 1, x - 1, y + 1, 2})` refers to the specified - element for the values of `t`, `x`, and `y` set dynamically - during stencil evaluation and the constant value `2` for `n`. - @returns Pointer to AST node used to read from or write to point in grid. */ virtual yc_grid_point_node_ptr new_grid_point(const std::vector& index_exprs @@ -550,8 +560,12 @@ namespace yask { /** C++ initializer-list version with same semantics as the vector version of new_grid_point(). + + See example code shown in yc_solution::new_grid(). + @note This version is not available (or needed) in the Python API. - @returns Pointer to AST node used to read or write from point in grid. */ + @returns Pointer to AST node used to read or write from point in grid. + */ virtual yc_grid_point_node_ptr new_grid_point(const std::initializer_list& index_exprs) = 0; #endif @@ -625,7 +639,27 @@ namespace yask { /// A wrapper class around a \ref yc_grid pointer. /** Using this class provides a syntactic alternative to calling yc_solution::new_grid() - and/or yc_solution::new_scratch_grid() followed by yc_grid::new_grid_point(). + (or yc_solution::new_scratch_grid()) followed by yc_grid::new_grid_point(). + + To use this wrapper class, construct an object of type \ref yc_grid_var by + passing a \ref yc_solution pointer to it. + Then, expressions for points in the grid can be created with a more + intuitive syntax. + + Example code to create a solution with a grid equation: + ~~~{.cpp} + yc_factory ycfac; + yc_node_factory nfac; + auto my_soln = ycfac.new_solution("my_stencil"); + auto t = nfac.new_step_index("t"); + auto x = nfac.new_domain_index("x"); + auto y = nfac.new_domain_index("y"); + yc_grid_var a("A", my_soln, { t, x, y }); + a({t+1, x, y}) EQUALS (a({t, x, y}) + + a({t, x+1, y}) + + a({t, x, y+1})) * (1.0/3.0); + ~~~ + Compare to the example shown in yc_solution::new_grid(). *Scoping and lifetime:* Since the \ref yc_grid pointer in a \ref yc_grid_var object is a shared pointer also owned by the \ref @@ -686,6 +720,18 @@ namespace yask { } #endif + /// Contructor for a simple scalar value. + /** + A wrapper around yc_solution::new_grid(). + */ + yc_grid_var(const std::string& name + /**< [in] Name of the new grid; must be a valid C++ + identifier and unique across grids. */, + yc_solution_ptr soln + /**< [in] Pointer to solution that will own the grid. */) { + _grid = soln->new_grid(name, { }); + } + /// Contructor taking an existing grid. /** Creates a new \ref yc_grid_var wrapper around an @@ -712,7 +758,6 @@ namespace yask { The number of arguments must match the dimensionality of the grid. Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, - where `vec` is a 2-element vector of \ref yc_number_node pointers. */ virtual yc_grid_point_node_ptr operator()(const std::vector& index_exprs) { @@ -757,15 +802,13 @@ namespace yask { return _grid->new_grid_point({i1}); } - /// **[Deprecated]** Create an expression for a point in a 1-6 dim grid. + /// Create an expression for a point in a 1-6 dim grid. /** A wrapper around yc_grid::new_grid_point(). - The number of arguments must match the dimensionality of the grid. + The number of non-null arguments must match the dimensionality of the grid. Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. @note Not available in Python API. Use vector version. - - Deprecated: The vector or initializer-list version is recommended instead. */ virtual yc_grid_point_node_ptr operator()(const yc_number_any_arg i1 = nullptr, const yc_number_any_arg i2 = nullptr, diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index d14166cc..d09457ac 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -39,7 +39,11 @@ namespace yask { /** * \defgroup ycu YASK Compiler Utility - * Types, clases, and functions used in the provided `yask_compiler.exe` binary utility. + * Wrappers around \ref yc_solution pointers used to create solutions that will + * be integrated into the provided `yask_compiler.exe` binary utility. + * Not to be used by YASK stencil code that is _not_ to be used with the compiler + * utility. In other words, if you write your own binary to generate optimized + * YASK stencil code, use the APIs in \ref sec_yc only. * @{ */ @@ -85,6 +89,7 @@ namespace yask { */ yc_solution_base(yc_solution_base& base) { _soln = base.get_soln(); + assert(_soln.get()); } /// Destructor. diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index a8c3b604..386e9417 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -130,7 +130,7 @@ namespace yask { MPI must be enabled and initialized before calling this function following the usage notes for new_env(). - @note `#include "mpi.h"` should precede `#include "yask_kernel_api.hpp"` + @note #`include "mpi.h"` should precede #`include "yask_kernel_api.hpp"` to ensure proper MPI type definitions. */ virtual yk_env_ptr diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 32cb705a..d81f712e 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -64,20 +64,17 @@ namespace yask { // Dummy object for backward-compatibility with old stencil DSL. StencilList stub_stencils; + // Constructor from the DSL API. // Create new solution and register it. - yc_solution_ptr yc_new_solution(const std::string& name, - yc_solution_base* base_ptr) { + yc_solution_base::yc_solution_base(const std::string& name) { if (stencils.count(name)) THROW_YASK_EXCEPTION("Error: stencil '" + name + "' already defined"); - auto soln = factory.new_solution(name); - stencils[name] = base_ptr; - return soln; - } + _soln = factory.new_solution(name); + assert(_soln.get()); - // Constructor from the DSL API. - yc_solution_base::yc_solution_base(const std::string& name) { - _soln = yc_new_solution(name, this); + // Add this new 'yc_solution_base' to the map. + stencils[name] = this; } } // yask namespace. @@ -423,7 +420,7 @@ void parseOpts(int argc, const char* argv[]) int main(int argc, const char* argv[]) { cout << "YASK -- Yet Another Stencil Kernel\n" - "YASK Stencil Compiler\n" + "YASK Stencil Compiler Utility\n" "Copyright (c) 2014-2019, Intel Corporation.\n" "Version: " << yask_get_version_string() << endl; diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index 29ddbb76..4605ec5f 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -29,118 +29,24 @@ IN THE SOFTWARE. #include "ElasticStencil.hpp" -// This class implements yc_solution_base but is not the main solution. -// The main solution is provided during construction. -class Elastic2BoundaryCondition : public yc_solution_base -{ -protected: - - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - - // yc_grid_var selectors. - yc_index_node_ptr vidx = new_misc_index("vidx"); - yc_index_node_ptr sidx = new_misc_index("sidx"); - yc_index_node_ptr cidx = new_misc_index("cidx"); - yc_index_node_ptr spidx = new_misc_index("spidx"); - - public: - Elastic2BoundaryCondition(yc_solution_base& base) : - yc_solution_base(base) { } - virtual ~Elastic2BoundaryCondition() {} - - // Determine whether current indices are at boundary. - virtual yc_bool_node_ptr is_at_boundary() =0; - virtual yc_bool_node_ptr is_not_at_boundary() =0; -}; - -class Elastic2StencilBase : public yc_solution_base { +// This class extends ElasticStencilBase to provide methods to make +// stencils with merged grids. +class Elastic2StencilBase : public ElasticStencilBase { protected: - // Dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // yc_grid_var selectors. yc_index_node_ptr vidx = new_misc_index("vidx"); yc_index_node_ptr sidx = new_misc_index("sidx"); yc_index_node_ptr cidx = new_misc_index("cidx"); - // 3D-spatial coefficients. - yc_grid_var coef = yc_grid_var("coef", get_soln(), { x, y, z, cidx }); - enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2, C_RHO }; - - // Spatial FD coefficients. - const double c0_8 = 1.2; - const double c1_8 = 1.4; - const double c2_8 = 1.6; - const double c3_8 = 1.8; - - // Physical dimensions in time and space. - const double delta_t = 0.002452; - - // Inverse of discretization. - const double dxi = 36.057693; - const double dyi = 36.057693; - const double dzi = 36.057693; - - Elastic2BoundaryCondition *bc = NULL; - public: - Elastic2StencilBase(const string& name, - Elastic2BoundaryCondition *_bc = NULL) : - yc_solution_base(name), bc(_bc) - { } - - bool hasBoundaryCondition() - { - return bc != NULL; - } - - yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TL) - { - return (2.0/ (coef(x , y , z, C_RHO) + - coef(x+1, y , z, C_RHO))); - } - - yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TR) - { - return (2.0/ (coef(x , y , z, C_RHO) + - coef(x , y+1, z, C_RHO))); - } - - yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BL) - { - return (2.0/ (coef(x , y , z, C_RHO) + - coef(x , y , z+1, C_RHO))); - } - - yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BR) - { - return (8.0/ (coef(x , y , z, C_RHO) + - coef(x , y , z+1, C_RHO) + - coef(x , y+1, z, C_RHO) + - coef(x+1, y , z, C_RHO) + - coef(x+1, y+1, z, C_RHO) + - coef(x , y+1, z+1, C_RHO) + - coef(x+1, y , z+1, C_RHO) + - coef(x+1, y+1, z+1, C_RHO))); - } - - template - yc_number_node_ptr interp_rho(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) - { - return interp_rho(x, y, z, N()); - } + Elastic2StencilBase(const string& name, + ElasticBoundaryCondition *_bc = NULL) : + ElasticStencilBase(name, _bc) { } yc_number_node_ptr stencil_O8_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const int offset) + yc_grid_var &g, yc_number_any_arg gidx, const int offset) { return (c0_8 * (g(t,x,y,z +offset, gidx) - @@ -154,19 +60,19 @@ class Elastic2StencilBase : public yc_solution_base { } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const Z, const B) + yc_grid_var &g, yc_number_any_arg gidx, const Z, const B) { return stencil_O8_Z(t, x, y, z, g, gidx, 0); } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const Z, const F) + yc_grid_var &g, yc_number_any_arg gidx, const Z, const F) { return stencil_O8_Z(t, x, y, z, g, gidx, 1); } yc_number_node_ptr stencil_O8_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const int offset) + yc_grid_var &g, yc_number_any_arg gidx, const int offset) { return (c0_8 * (g(t,x,y +offset,z, gidx) - @@ -180,18 +86,18 @@ class Elastic2StencilBase : public yc_solution_base { } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const Y, const B) + yc_grid_var &g, yc_number_any_arg gidx, const Y, const B) { return stencil_O8_Y(t, x, y, z, g, gidx, 0); } - yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, yc_number_node_ptr gidx, const Y, const F) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, yc_number_any_arg gidx, const Y, const F) { return stencil_O8_Y(t, x, y, z, g, gidx, 1); } yc_number_node_ptr stencil_O8_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const int offset) + yc_grid_var &g, yc_number_any_arg gidx, const int offset) { return (c0_8 * (g(t,x +offset,y,z, gidx) - @@ -205,13 +111,13 @@ class Elastic2StencilBase : public yc_solution_base { } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const X, const B) + yc_grid_var &g, yc_number_any_arg gidx, const X, const B) { return stencil_O8_X(t, x, y, z, g, gidx, 0); } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, + yc_grid_var &g, yc_number_any_arg gidx, const X, const F) { return stencil_O8_X(t, x, y, z, g, gidx, 1); @@ -219,7 +125,7 @@ class Elastic2StencilBase : public yc_solution_base { template yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx) + yc_grid_var &g, yc_number_any_arg gidx) { return stencil_O8(t, x, y, z, g, gidx, Dim(), Dir()); } @@ -232,8 +138,8 @@ class Elastic2StencilBase : public yc_solution_base { template void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var& v, yc_number_node_ptr vidx, - yc_grid_var& s, yc_number_node_ptr sx_idx, yc_number_node_ptr sy_idx, yc_number_node_ptr sz_idx) { + yc_grid_var& v, yc_number_any_arg vidx, + yc_grid_var& s, yc_number_any_arg sx_idx, yc_number_any_arg sy_idx, yc_number_any_arg sz_idx) { yc_number_node_ptr lrho = interp_rho(x, y, z); @@ -250,17 +156,9 @@ class Elastic2StencilBase : public yc_solution_base { } else v(t+1, x, y, z, vidx) EQUALS next_v; } - template - void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var& v, int vidx, - yc_grid_var& s, int sx_idx, int sy_idx, int sz_idx) { - define_vel(t, x, y, z, - v, new_number_node(vidx), - s, new_number_node(sx_idx), new_number_node(sy_idx), new_number_node(sz_idx)); - } - + yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const int offset) + yc_grid_var &g, yc_number_any_arg gidx, const int offset) { return (g(t,x,y,z, gidx) - @@ -268,26 +166,26 @@ class Elastic2StencilBase : public yc_solution_base { } yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const B) + yc_grid_var &g, yc_number_any_arg gidx, const B) { return stencil_O2_Z(t, x, y, z, g, gidx, -1); } yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const F) + yc_grid_var &g, yc_number_any_arg gidx, const F) { return stencil_O2_Z(t, x, y, z, g, gidx, 1); } template yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx) + yc_grid_var &g, yc_number_any_arg gidx) { return stencil_O2_Z(t, x, y, z, g, gidx, D()); } yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const int offset) + yc_grid_var &g, yc_number_any_arg gidx, const int offset) { return (g(t,x,y ,z, gidx) - @@ -295,26 +193,26 @@ class Elastic2StencilBase : public yc_solution_base { } yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const B) + yc_grid_var &g, yc_number_any_arg gidx, const B) { return stencil_O2_Y(t, x, y, z, g, gidx,-1); } yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const F) + yc_grid_var &g, yc_number_any_arg gidx, const F) { return stencil_O2_Y(t, x, y, z, g, gidx, 1); } template yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx) + yc_grid_var &g, yc_number_any_arg gidx) { return stencil_O2_Y(t, x, y, z, g, gidx, D()); } yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const int offset) + yc_grid_var &g, yc_number_any_arg gidx, const int offset) { return (g(t,x ,y,z, gidx) - @@ -322,20 +220,20 @@ class Elastic2StencilBase : public yc_solution_base { } yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const B) + yc_grid_var &g, yc_number_any_arg gidx, const B) { return stencil_O2_X(t, x, y, z, g, gidx,-1); } yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx, const F) + yc_grid_var &g, yc_number_any_arg gidx, const F) { return stencil_O2_X(t, x, y, z, g, gidx, 1); } template yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_node_ptr gidx) + yc_grid_var &g, yc_number_any_arg gidx) { return stencil_O2_X(t, x, y, z, g, gidx, D()); } diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index 0c72051f..0bc2a22d 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -53,13 +53,13 @@ class ElasticBoundaryCondition : public yc_solution_base { protected: - // Indices & dimensions. + // Dimensions. yc_index_node_ptr t = new_step_index("t"); // step in time dim. yc_index_node_ptr x = new_domain_index("x"); // spatial dim. yc_index_node_ptr y = new_domain_index("y"); // spatial dim. yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - public: +public: ElasticBoundaryCondition(yc_solution_base& base) : yc_solution_base(base) { } virtual ~ElasticBoundaryCondition() {} @@ -69,6 +69,8 @@ class ElasticBoundaryCondition : public yc_solution_base virtual yc_bool_node_ptr is_not_at_boundary() =0; }; +// This class implements yc_solution_base but is not the main solution. +// The main solution is provided during construction. class ElasticStencilBase : public yc_solution_base { protected: @@ -109,25 +111,37 @@ class ElasticStencilBase : public yc_solution_base { return bc != NULL; } - yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TL ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + const TL ) { return ( 2.0/ (rho(x , y , z ) + rho(x+1, y , z )) ); } - yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const TR ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + const TR ) { return ( 2.0/ (rho(x , y , z ) + rho(x , y+1, z )) ); } - yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BL ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + const BL ) { return ( 2.0/ (rho(x , y , z ) + rho(x , y , z+1)) ); } - yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, const BR ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + const BR ) { return ( 8.0/ (rho(x , y , z ) + rho(x , y , z+1) + @@ -139,13 +153,21 @@ class ElasticStencilBase : public yc_solution_base { rho(x+1, y+1, z+1)) ); } + // Call the interp_rho() function above depending on N. template - yc_number_node_ptr interp_rho( yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) + yc_number_node_ptr interp_rho( yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z ) { return interp_rho( x, y, z, N() ); } - yc_number_node_ptr stencil_O8_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) + yc_number_node_ptr stencil_O8_Z( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const int offset ) { return (c0_8 * (g(t,x,y,z +offset) - @@ -158,17 +180,32 @@ class ElasticStencilBase : public yc_solution_base { g(t,x,y,z-4+offset)))*dzi; } - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Z, const B ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const Z, const B ) { return stencil_O8_Z( t, x, y, z, g, 0 ); } - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Z, const F ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const Z, const F ) { return stencil_O8_Z( t, x, y, z, g, 1 ); } - yc_number_node_ptr stencil_O8_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) + yc_number_node_ptr stencil_O8_Y( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const int offset ) { return (c0_8 * (g(t,x,y +offset,z) - @@ -181,17 +218,32 @@ class ElasticStencilBase : public yc_solution_base { g(t,x,y-4+offset,z)))*dyi; } - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Y, const B ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const Y, const B ) { return stencil_O8_Y( t, x, y, z, g, 0 ); } - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const Y, const F ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const Y, const F ) { return stencil_O8_Y( t, x, y, z, g, 1 ); } - yc_number_node_ptr stencil_O8_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) + yc_number_node_ptr stencil_O8_X( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const int offset ) { return (c0_8 * (g(t,x +offset,y,z) - @@ -204,18 +256,33 @@ class ElasticStencilBase : public yc_solution_base { g(t,x-4+offset,y,z)))*dxi; } - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const X, const B ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const X, const B ) { return stencil_O8_X( t, x, y, z, g, 0 ); } - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const X, const F ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const X, const F ) { return stencil_O8_X( t, x, y, z, g, 1 ); } + // Call the stencil_O8() function above depending on Dim & Dir. template - yc_number_node_ptr stencil_O8( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) + yc_number_node_ptr stencil_O8( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g ) { return stencil_O8( t, x, y, z, g, Dim(), Dir() ); } @@ -227,8 +294,14 @@ class ElasticStencilBase : public yc_solution_base { // appropriately. template - void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &v, yc_grid_var &sx, yc_grid_var &sy, yc_grid_var &sz) { + void define_vel(yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &v, + yc_grid_var &sx, + yc_grid_var &sy, + yc_grid_var &sz) { auto lrho = interp_rho( x, y, z ); @@ -246,71 +319,129 @@ class ElasticStencilBase : public yc_solution_base { v(t+1, x, y, z) EQUALS next_v; } - yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const int offset ) { return (g(t,x,y,z ) - g(t,x,y,z+offset))*dzi; } - yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const B ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const B ) { return stencil_O2_Z( t, x, y, z, g,-1 ); } - yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const F ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const F ) { return stencil_O2_Z( t, x, y, z, g, 1 ); } template - yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) + yc_number_node_ptr stencil_O2_Z( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g ) { return stencil_O2_Z( t, x, y, z, g, D() ); } - yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const int offset ) { return (g(t,x,y ,z) - g(t,x,y+offset,z))*dyi; } - yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const B ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const B ) { return stencil_O2_Y( t, x, y, z, g,-1 ); } - yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const F ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const F ) { return stencil_O2_Y( t, x, y, z, g, 1 ); } template - yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) + yc_number_node_ptr stencil_O2_Y( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g ) { return stencil_O2_Y( t, x, y, z, g, D() ); } - yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const int offset ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const int offset ) { return (g(t,x ,y,z) - g(t,x+offset,y,z))*dxi; } - yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const B ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const B ) { return stencil_O2_X( t, x, y, z, g,-1 ); } - yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, const F ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g, + const F ) { return stencil_O2_X( t, x, y, z, g, 1 ); } + // Call the stencil_O2() function above depending on D. template - yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g ) + yc_number_node_ptr stencil_O2_X( yc_number_node_ptr t, + yc_number_node_ptr x, + yc_number_node_ptr y, + yc_number_node_ptr z, + yc_grid_var &g ) { return stencil_O2_X( t, x, y, z, g, D() ); } diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index 0d4fed77..4477d12c 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -38,11 +38,13 @@ namespace fsg { class FSG2_ABC; - class FSG2BoundaryCondition : public Elastic2BoundaryCondition + class FSG2BoundaryCondition : public ElasticBoundaryCondition { + protected: + public: FSG2BoundaryCondition(yc_solution_base& base) : - Elastic2BoundaryCondition(base) {} + ElasticBoundaryCondition(base) {} virtual void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) {} virtual void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) {} }; @@ -114,15 +116,10 @@ namespace fsg { } template yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx) + yc_grid_var &c, yc_number_any_arg cidx) { return cell_coeff( x, y, z, c, cidx, N()); } - template - yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, int cidx) { - return cell_coeff(x, y, z, c, new_number_node(cidx)); - } yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, yc_number_node_ptr cidx, const BR) @@ -155,16 +152,10 @@ namespace fsg { } template yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx) + yc_grid_var &c, yc_number_any_arg cidx) { return cell_coeff_artm( x, y, z, c, cidx, N()); } - template - yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, int cidx) - { - return cell_coeff_artm( x, y, z, c, new_number_node(cidx)); - } yc_number_node_ptr stress_update( yc_number_node_ptr c1, yc_number_node_ptr c2, yc_number_node_ptr c3, yc_number_node_ptr c4, yc_number_node_ptr c5, yc_number_node_ptr c6, @@ -191,11 +182,11 @@ namespace fsg { template void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_number_node_ptr sxx_idx, yc_number_node_ptr syy_idx, yc_number_node_ptr szz_idx, - yc_number_node_ptr sxy_idx, yc_number_node_ptr sxz_idx, yc_number_node_ptr syz_idx, - yc_number_node_ptr vxu_idx, yc_number_node_ptr vxv_idx, yc_number_node_ptr vxw_idx, - yc_number_node_ptr vyu_idx, yc_number_node_ptr vyv_idx, yc_number_node_ptr vyw_idx, - yc_number_node_ptr vzu_idx, yc_number_node_ptr vzv_idx, yc_number_node_ptr vzw_idx) { + yc_number_any_arg sxx_idx, yc_number_any_arg syy_idx, yc_number_any_arg szz_idx, + yc_number_any_arg sxy_idx, yc_number_any_arg sxz_idx, yc_number_any_arg syz_idx, + yc_number_any_arg vxu_idx, yc_number_any_arg vxv_idx, yc_number_any_arg vxw_idx, + yc_number_any_arg vyu_idx, yc_number_any_arg vyv_idx, yc_number_any_arg vyw_idx, + yc_number_any_arg vzu_idx, yc_number_any_arg vzv_idx, yc_number_any_arg vzw_idx) { // Interpolate coeffs. auto ic11 = cell_coeff (x, y, z, c, C11); @@ -249,7 +240,7 @@ namespace fsg { // define the value at t+1. if(hasBoundaryCondition()) { - yc_bool_node_ptr not_at_bc = bc->is_not_at_boundary(); + auto not_at_bc = bc->is_not_at_boundary(); s(t+1, x, y, z, sxx_idx) EQUALS next_sxx IF_DOMAIN not_at_bc; s(t+1, x, y, z, syy_idx) EQUALS next_syy IF_DOMAIN not_at_bc; s(t+1, x, y, z, szz_idx) EQUALS next_szz IF_DOMAIN not_at_bc; @@ -265,20 +256,6 @@ namespace fsg { s(t+1, x, y, z, sxy_idx) EQUALS next_sxy; } } - template - void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - int sxx_idx, int syy_idx, int szz_idx, - int sxy_idx, int sxz_idx, int syz_idx, - int vxu_idx, int vxv_idx, int vxw_idx, - int vyu_idx, int vyv_idx, int vyw_idx, - int vzu_idx, int vzv_idx, int vzw_idx) { - define_str(t, x, y, z, - new_number_node(sxx_idx), new_number_node(syy_idx), new_number_node(szz_idx), - new_number_node(sxy_idx), new_number_node(sxz_idx), new_number_node(syz_idx), - new_number_node(vxu_idx), new_number_node(vxv_idx), new_number_node(vxw_idx), - new_number_node(vyu_idx), new_number_node(vyv_idx), new_number_node(vyw_idx), - new_number_node(vzu_idx), new_number_node(vzv_idx), new_number_node(vzw_idx)); - } // Call all the define_* functions. virtual void define() { @@ -323,6 +300,7 @@ namespace fsg { const int abc_width = 20; // Sponge coefficients. + yc_index_node_ptr spidx = new_misc_index("spidx"); yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z, spidx }); enum SPONGE_IDX { SPONGE_LX, SPONGE_RX, SPONGE_BZ, SPONGE_TZ, SPONGE_FY, SPONGE_BY, @@ -353,10 +331,10 @@ namespace fsg { template void define_vel_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_number_node_ptr vidx, - yc_number_node_ptr sx_idx, yc_number_node_ptr sy_idx, yc_number_node_ptr sz_idx, - yc_number_node_ptr abc_x_idx, yc_number_node_ptr abc_y_idx, yc_number_node_ptr abc_z_idx, - yc_number_node_ptr abc_sq_x_idx, yc_number_node_ptr abc_sq_y_idx, yc_number_node_ptr abc_sq_z_idx) { + yc_number_any_arg vidx, + yc_number_any_arg sx_idx, yc_number_any_arg sy_idx, yc_number_any_arg sz_idx, + yc_number_any_arg abc_x_idx, yc_number_any_arg abc_y_idx, yc_number_any_arg abc_z_idx, + yc_number_any_arg abc_sq_x_idx, yc_number_any_arg abc_sq_y_idx, yc_number_any_arg abc_sq_z_idx) { auto at_abc = is_at_boundary(); auto next_v = fsg.v(t, x, y, z, vidx) * sponge(x,y,z, abc_x_idx) * @@ -375,18 +353,6 @@ namespace fsg { // define the value at t+1. fsg.v(t+1, x, y, z, vidx) EQUALS next_v IF_DOMAIN at_abc; } - template - void define_vel_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - int vidx, - int sx_idx, int sy_idx, int sz_idx, - int abc_x_idx, int abc_y_idx, int abc_z_idx, - int abc_sq_x_idx, int abc_sq_y_idx, int abc_sq_z_idx) { - define_vel_abc(t, x, y, z, - new_number_node(vidx), - new_number_node(sx_idx), new_number_node(sy_idx), new_number_node(sz_idx), - new_number_node(abc_x_idx), new_number_node(abc_y_idx), new_number_node(abc_z_idx), - new_number_node(abc_sq_x_idx), new_number_node(abc_sq_y_idx), new_number_node(abc_sq_z_idx)); - } void velocity (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { @@ -418,13 +384,13 @@ namespace fsg { template void define_str_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_number_node_ptr sxx_idx, yc_number_node_ptr syy_idx, yc_number_node_ptr szz_idx, - yc_number_node_ptr sxy_idx, yc_number_node_ptr sxz_idx, yc_number_node_ptr syz_idx, - yc_number_node_ptr vxu_idx, yc_number_node_ptr vxv_idx, yc_number_node_ptr vxw_idx, - yc_number_node_ptr vyu_idx, yc_number_node_ptr vyv_idx, yc_number_node_ptr vyw_idx, - yc_number_node_ptr vzu_idx, yc_number_node_ptr vzv_idx, yc_number_node_ptr vzw_idx, - yc_number_node_ptr abc_x_idx, yc_number_node_ptr abc_y_idx, yc_number_node_ptr abc_z_idx, - yc_number_node_ptr abc_sq_x_idx, yc_number_node_ptr abc_sq_y_idx, yc_number_node_ptr abc_sq_z_idx) { + yc_number_any_arg sxx_idx, yc_number_any_arg syy_idx, yc_number_any_arg szz_idx, + yc_number_any_arg sxy_idx, yc_number_any_arg sxz_idx, yc_number_any_arg syz_idx, + yc_number_any_arg vxu_idx, yc_number_any_arg vxv_idx, yc_number_any_arg vxw_idx, + yc_number_any_arg vyu_idx, yc_number_any_arg vyv_idx, yc_number_any_arg vyw_idx, + yc_number_any_arg vzu_idx, yc_number_any_arg vzv_idx, yc_number_any_arg vzw_idx, + yc_number_any_arg abc_x_idx, yc_number_any_arg abc_y_idx, yc_number_any_arg abc_z_idx, + yc_number_any_arg abc_sq_x_idx, yc_number_any_arg abc_sq_y_idx, yc_number_any_arg abc_sq_z_idx) { auto abc = sponge(x,y,z, abc_x_idx) * sponge(x,y,z, abc_y_idx) * sponge(x,y,z, abc_z_idx); auto next_sxx = fsg.s(t, x, y, z, sxx_idx) * abc; @@ -481,7 +447,7 @@ namespace fsg { next_sxy += fsg.stress_update(ic16,ic26,ic36,ic46,ic56,ic66,u_z,u_x,u_y,v_z,v_x,v_y,w_z,w_x,w_y) * abc_sq; // define the value at t+1. - yc_bool_node_ptr at_abc = is_at_boundary(); + auto at_abc = is_at_boundary(); fsg.s(t+1, x, y, z, sxx_idx) EQUALS next_sxx IF_DOMAIN at_abc; fsg.s(t+1, x, y, z, syy_idx) EQUALS next_syy IF_DOMAIN at_abc; fsg.s(t+1, x, y, z, szz_idx) EQUALS next_szz IF_DOMAIN at_abc; @@ -489,24 +455,6 @@ namespace fsg { fsg.s(t+1, x, y, z, sxz_idx) EQUALS next_sxz IF_DOMAIN at_abc; fsg.s(t+1, x, y, z, sxy_idx) EQUALS next_sxy IF_DOMAIN at_abc; } - template - void define_str_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - int sxx_idx, int syy_idx, int szz_idx, - int sxy_idx, int sxz_idx, int syz_idx, - int vxu_idx, int vxv_idx, int vxw_idx, - int vyu_idx, int vyv_idx, int vyw_idx, - int vzu_idx, int vzv_idx, int vzw_idx, - int abc_x_idx, int abc_y_idx, int abc_z_idx, - int abc_sq_x_idx, int abc_sq_y_idx, int abc_sq_z_idx) { - define_str_abc(t, x, y, z, - new_number_node(sxx_idx), new_number_node(syy_idx), new_number_node(szz_idx), - new_number_node(sxy_idx), new_number_node(sxz_idx), new_number_node(syz_idx), - new_number_node(vxu_idx), new_number_node(vxv_idx), new_number_node(vxw_idx), - new_number_node(vyu_idx), new_number_node(vyv_idx), new_number_node(vyw_idx), - new_number_node(vzu_idx), new_number_node(vzv_idx), new_number_node(vzw_idx), - new_number_node(abc_x_idx), new_number_node(abc_y_idx), new_number_node(abc_z_idx), - new_number_node(abc_sq_x_idx), new_number_node(abc_sq_y_idx), new_number_node(abc_sq_z_idx)); - } void stress (yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { @@ -533,24 +481,25 @@ namespace fsg { struct FSGElastic2Stencil : public FSGElastic2StencilBase { FSGElastic2Stencil() : - FSGElastic2StencilBase("fsg2") { } + FSGElastic2StencilBase("fsg_merged") { } }; struct FSG2ABCElasticStencil : public FSGElastic2StencilBase { - FSG2_ABC abc; // Absorbing Boundary yc_bool_node_ptr + FSG2_ABC abc; // Absorbing Boundary Condition. FSG2ABCElasticStencil() : - FSGElastic2StencilBase("fsg2_abc", &abc), + FSGElastic2StencilBase("fsg_merged_abc", &abc), abc(*this) { } }; -// Create an object of type 'FSGElastic2Stencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static FSGElastic2Stencil FSGElastic2Stencil_instance; -// Create an object of type 'FSG2ABCElasticStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static FSG2ABCElasticStencil FSG2ABCElasticStencil_instance; + // Create an object of type 'FSGElastic2Stencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static FSGElastic2Stencil FSGElastic2Stencil_instance; + + // Create an object of type 'FSG2ABCElasticStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static FSG2ABCElasticStencil FSG2ABCElasticStencil_instance; } diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index d265fcd7..7ad84634 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -155,14 +155,6 @@ static Iso3dfdStencil Iso3dfdStencil_instance; class Iso3dfdSpongeStencil : public Iso3dfdStencil { protected: - // Sponge coefficients. - // In practice, the interior values would be set to 1.0, - // and values nearer the boundary would be set to values - // increasingly approaching 0.0. - yc_grid_var cr_x = yc_grid_var("cr_x", get_soln(), { x }); - yc_grid_var cr_y = yc_grid_var("cr_y", get_soln(), { y }); - yc_grid_var cr_z = yc_grid_var("cr_z", get_soln(), { z }); - public: Iso3dfdSpongeStencil(int radius=8) : Iso3dfdStencil("_sponge", radius) { } @@ -171,6 +163,14 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { // Define equation for pressure at t+1 based on values from vel and pressure at t. virtual void define() { + // Sponge coefficients. + // In practice, the interior values would be set to 1.0, + // and values nearer the boundary would be set to values + // increasingly approaching 0.0. + yc_grid_var cr_x("cr_x", get_soln(), { x }); + yc_grid_var cr_y("cr_y", get_soln(), { y }); + yc_grid_var cr_z("cr_z", get_soln(), { z }); + // Get equation for RHS. auto next_p = get_next_p(); diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index 4d056f0a..8b9c7784 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -42,10 +42,14 @@ class SSGElastic2Stencil : public Elastic2StencilBase { yc_grid_var s = yc_grid_var("s", get_soln(), { t, x, y, z, sidx }); enum SIDX { S_BL_YZ, S_BR_XZ, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TR_XY }; + // Merged. + yc_grid_var coef = yc_grid_var("c", get_soln(), { t, x, y, z, cidx }); + enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2 }; + public: SSGElastic2Stencil( ) : - Elastic2StencilBase("ssg2") + Elastic2StencilBase("ssg_merged") { } @@ -90,7 +94,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { template void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_number_node_ptr sidx, yc_number_node_ptr va_idx, yc_number_node_ptr vb_idx) { + yc_number_any_arg sidx, yc_number_any_arg va_idx, yc_number_any_arg vb_idx) { auto lcoeff = interp_mu( x, y, z ); @@ -102,12 +106,6 @@ class SSGElastic2Stencil : public Elastic2StencilBase { // define the value at t+1. s(t+1, x, y, z, sidx) EQUALS next_s; } - template - void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - int sidx, int va_idx, int vb_idx) { - define_str(t, x, y, z, - new_number_node(sidx), new_number_node(va_idx), new_number_node(vb_idx)); - } void define_str_TL(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z ) { @@ -115,9 +113,9 @@ class SSGElastic2Stencil : public Elastic2StencilBase { auto ilambdamu2 = 1.0 / coef(x,y,z, C_LAMBDA_MU2); auto ilambda = 1.0 / coef(x,y,z, C_LAMBDA); - auto vtx = stencil_O8( t+1, x, y, z, v, new_number_node(V_TR_U) ); - auto vty = stencil_O8( t+1, x, y, z, v, new_number_node(V_TL_V) ); - auto vtz = stencil_O8( t+1, x, y, z, v, new_number_node(V_BL_W) ); + auto vtx = stencil_O8( t+1, x, y, z, v, V_TR_U ); + auto vty = stencil_O8( t+1, x, y, z, v, V_TL_V ); + auto vtz = stencil_O8( t+1, x, y, z, v, V_BL_W ); auto next_xx = s(t, x, y, z, S_TL_XX) + ilambdamu2 * vtx * delta_t + ilambda * vty * delta_t diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/SimpleTestStencils.cpp index fba996df..dac0b3cc 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/SimpleTestStencils.cpp @@ -393,14 +393,14 @@ class StreamStencil : public yc_solution_with_radius_base { // Define equation to read '_radius' values and write one. virtual void define() { - yc_number_node_ptr v = new_number_node(1.0); + yc_number_node_ptr v; // Add '_radius' values from past time-steps. for (int r = 0; r < _radius; r++) v += A(t-r, x, y, z); - // define the value at t+1 to be equivalent to v. - A(t+1, x, y, z) EQUALS v; + // define the value at t+1 to be equivalent to v + 1. + A(t+1, x, y, z) EQUALS v + 1; } }; From 723f6f378cefe0c497113ab5392242088817906a Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 9 May 2019 15:49:18 -0700 Subject: [PATCH 19/62] Move non-documented include files to other dirs. --- Makefile | 2 +- README.md | 1 + docs/api/doxygen_config.txt | 2 +- include/{ => aux}/yc_node_api.hpp | 0 include/{ => aux}/yk_grid_api.hpp | 0 include/{ => aux}/yk_solution_api.hpp | 0 include/yask_compiler_api.hpp | 2 +- include/yask_kernel_api.hpp | 4 ++-- src/compiler/Makefile | 2 +- src/compiler/swig/yask_compiler_api.i | 2 +- src/kernel/swig/yask_kernel_api.i | 4 ++-- {include => src/stencils/v2}/Soln.hpp | 0 12 files changed, 10 insertions(+), 9 deletions(-) rename include/{ => aux}/yc_node_api.hpp (100%) rename include/{ => aux}/yk_grid_api.hpp (100%) rename include/{ => aux}/yk_solution_api.hpp (100%) rename {include => src/stencils/v2}/Soln.hpp (100%) diff --git a/Makefile b/Makefile index e4b018be..3ff7b81d 100644 --- a/Makefile +++ b/Makefile @@ -130,7 +130,7 @@ api: $(YK_MAKE) $@ # Format API documents. -docs/api/html/index.html: include/*.hpp docs/api/*.* +docs/api/html/index.html: include/*.hpp include/*/*.hpp docs/api/*.* doxygen -v cd docs/api; doxygen doxygen_config.txt diff --git a/README.md b/README.md index 6244565e..59f37081 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ YASK contains a domain-specific compiler to convert stencil-equation specificati * Version 3.00.00 implemented a unification of the old (v2) internal DSL with the YASK compiler API. Canonical v2 DSL code should still work using the `Soln.hpp` backward-compatibility header file. To convert v2 DSL code to v3 format, use the `./utils/bin/convert_v2_stencil.pl` utility. +DSL or kernel code that has used any undocumented files, data, or types may have to be updated. ### Version 2 * Version 2.22.00 changed the heuristic to determine vector-folding sizes when some diff --git a/docs/api/doxygen_config.txt b/docs/api/doxygen_config.txt index 461f0542..6bd9ee97 100644 --- a/docs/api/doxygen_config.txt +++ b/docs/api/doxygen_config.txt @@ -809,7 +809,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../../include \ +INPUT = ../../include ../../include/aux \ mainpage.txt # This tag can be used to specify the character encoding of the source files diff --git a/include/yc_node_api.hpp b/include/aux/yc_node_api.hpp similarity index 100% rename from include/yc_node_api.hpp rename to include/aux/yc_node_api.hpp diff --git a/include/yk_grid_api.hpp b/include/aux/yk_grid_api.hpp similarity index 100% rename from include/yk_grid_api.hpp rename to include/aux/yk_grid_api.hpp diff --git a/include/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp similarity index 100% rename from include/yk_solution_api.hpp rename to include/aux/yk_solution_api.hpp diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 15e55c4c..7c4062fb 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -82,7 +82,7 @@ namespace yask { /** @}*/ } -#include "yc_node_api.hpp" +#include "aux/yc_node_api.hpp" namespace yask { diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 386e9417..16ff5099 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -68,8 +68,8 @@ namespace yask { /** @}*/ } // namespace yask. -#include "yk_solution_api.hpp" -#include "yk_grid_api.hpp" +#include "aux/yk_solution_api.hpp" +#include "aux/yk_grid_api.hpp" namespace yask { diff --git a/src/compiler/Makefile b/src/compiler/Makefile index 7d4c126d..9251f39e 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -110,7 +110,7 @@ $(YC_LIB): $(YC_OBJS) $(YC_EXEC): compiler_main.cpp $(YC_STENCIL_OBJS) $(YC_LIB) $(MKDIR) $(dir $@) - $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) $^ $(YC_LFLAGS) -o $@ + $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) -I$(YC_STENCIL_DIR)/v2 $^ $(YC_LFLAGS) -o $@ @ls -l $@ $(MAKE) echo-settings diff --git a/src/compiler/swig/yask_compiler_api.i b/src/compiler/swig/yask_compiler_api.i index 6109d88c..4dcdaed7 100644 --- a/src/compiler/swig/yask_compiler_api.i +++ b/src/compiler/swig/yask_compiler_api.i @@ -201,4 +201,4 @@ BOOL_OP(__le__, <=); %include "yask_common_api.hpp" %include "yask_compiler_api.hpp" -%include "yc_node_api.hpp" +%include "aux/yc_node_api.hpp" diff --git a/src/kernel/swig/yask_kernel_api.i b/src/kernel/swig/yask_kernel_api.i index f4a33215..8bc04ef7 100644 --- a/src/kernel/swig/yask_kernel_api.i +++ b/src/kernel/swig/yask_kernel_api.i @@ -69,5 +69,5 @@ IN THE SOFTWARE. %include "yask_common_api.hpp" %include "yask_kernel_api.hpp" -%include "yk_solution_api.hpp" -%include "yk_grid_api.hpp" +%include "aux/yk_solution_api.hpp" +%include "aux/yk_grid_api.hpp" diff --git a/include/Soln.hpp b/src/stencils/v2/Soln.hpp similarity index 100% rename from include/Soln.hpp rename to src/stencils/v2/Soln.hpp From f7b8f482b95ef6a1af3acadbf5fc5d0e2499ddbf Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 9 May 2019 16:04:12 -0700 Subject: [PATCH 20/62] Move Soln.hpp for backward-compatibility. --- {src/stencils/v2 => include/aux}/Soln.hpp | 0 src/common/common.mk | 2 +- src/compiler/Makefile | 2 +- src/compiler/compiler_main.cpp | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename {src/stencils/v2 => include/aux}/Soln.hpp (100%) diff --git a/src/stencils/v2/Soln.hpp b/include/aux/Soln.hpp similarity index 100% rename from src/stencils/v2/Soln.hpp rename to include/aux/Soln.hpp diff --git a/src/common/common.mk b/src/common/common.mk index 9869418d..b41446c4 100644 --- a/src/common/common.mk +++ b/src/common/common.mk @@ -60,7 +60,7 @@ COEFF_DIR := $(SRC_DIR)/contrib/coefficients # Globs and flags. INC_GLOB := $(wildcard $(addsuffix /*.hpp,$(INC_DIR))) -INC_CXXFLAGS := $(addprefix -I,$(INC_DIR)) +INC_CXXFLAGS := $(addprefix -I,$(INC_DIR) $(INC_DIR)/aux) # YASK stencil compiler. # This is here because both the compiler and kernel diff --git a/src/compiler/Makefile b/src/compiler/Makefile index 9251f39e..7d4c126d 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -110,7 +110,7 @@ $(YC_LIB): $(YC_OBJS) $(YC_EXEC): compiler_main.cpp $(YC_STENCIL_OBJS) $(YC_LIB) $(MKDIR) $(dir $@) - $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) -I$(YC_STENCIL_DIR)/v2 $^ $(YC_LFLAGS) -o $@ + $(CXX_PREFIX) $(YC_LD) $(YC_CXXFLAGS) $(YC_INC_CXXFLAGS) $^ $(YC_LFLAGS) -o $@ @ls -l $@ $(MAKE) echo-settings diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index d81f712e..e2fed922 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -32,7 +32,7 @@ IN THE SOFTWARE. #include "yask_compiler_utility_api.hpp" // Backward-compatible API. -#include "Soln.hpp" +#include "aux/Soln.hpp" // YASK compiler-solution code. // TODO: remove these non-API includes. From 45c9b2442f6af788c66071056d58b999d98e4c49 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 10 May 2019 11:14:26 -0700 Subject: [PATCH 21/62] Change "grid" to "var" everywhere. --- README.md | 5 +- docs/api/mainpage.txt | 50 +- include/aux/Soln.hpp | 14 +- include/aux/yc_node_api.hpp | 68 +-- include/aux/yk_solution_api.hpp | 317 +++++++----- .../aux/{yk_grid_api.hpp => yk_var_api.hpp} | 351 +++++++------ include/yask_compiler_api.hpp | 484 ++++++++++-------- include/yask_compiler_utility_api.hpp | 2 +- include/yask_kernel_api.hpp | 20 +- src/common/fd_coeff2.cpp | 2 +- src/compiler/Makefile | 2 +- src/compiler/compiler_main.cpp | 40 +- src/compiler/lib/Cpp.cpp | 128 ++--- src/compiler/lib/Cpp.hpp | 64 +-- src/compiler/lib/CppIntrin.cpp | 8 +- src/compiler/lib/CppIntrin.hpp | 16 +- src/compiler/lib/Eqs.cpp | 350 ++++++------- src/compiler/lib/Eqs.hpp | 52 +- src/compiler/lib/Expr.cpp | 108 ++-- src/compiler/lib/Expr.hpp | 104 ++-- src/compiler/lib/ExprUtils.hpp | 6 +- src/compiler/lib/Print.cpp | 40 +- src/compiler/lib/Print.hpp | 34 +- src/compiler/lib/Settings.cpp | 18 +- src/compiler/lib/Settings.hpp | 6 +- src/compiler/lib/Solution.cpp | 22 +- src/compiler/lib/Solution.hpp | 44 +- src/compiler/lib/{Grid.cpp => Var.cpp} | 82 +-- src/compiler/lib/{Grid.hpp => Var.hpp} | 72 +-- src/compiler/lib/Vec.cpp | 44 +- src/compiler/lib/Vec.hpp | 62 +-- src/compiler/lib/Visitor.hpp | 8 +- src/compiler/lib/YaskKernel.cpp | 176 +++---- src/compiler/swig/yask_compiler_api.i | 6 +- .../yask_compiler_api_exception_test.cpp | 20 +- .../tests/yask_compiler_api_exception_test.py | 34 +- src/compiler/tests/yask_compiler_api_test.cpp | 30 +- src/compiler/tests/yask_compiler_api_test.py | 58 +-- src/contrib/coefficients/fd_coeff_test.cpp | 14 +- src/kernel/Makefile | 36 +- src/kernel/lib/alloc.cpp | 188 +++---- src/kernel/lib/auto_tuner.cpp | 2 +- src/kernel/lib/context.cpp | 222 ++++---- src/kernel/lib/context.hpp | 164 +++--- .../{generic_grids.cpp => generic_var.cpp} | 36 +- .../{generic_grids.hpp => generic_var.hpp} | 100 ++-- src/kernel/lib/indices.hpp | 12 +- src/kernel/lib/{new_grid.cpp => new_var.cpp} | 44 +- src/kernel/lib/settings.cpp | 14 +- src/kernel/lib/settings.hpp | 30 +- src/kernel/lib/setup.cpp | 46 +- src/kernel/lib/soln_apis.cpp | 66 +-- src/kernel/lib/stencil_calc.cpp | 58 +-- src/kernel/lib/stencil_calc.hpp | 22 +- src/kernel/lib/yask_stencil.hpp | 8 +- .../lib/{realv_grids.cpp => yk_var.cpp} | 82 +-- .../lib/{realv_grids.hpp => yk_var.hpp} | 312 +++++------ .../lib/{grid_apis.cpp => yk_var_apis.cpp} | 164 +++--- src/kernel/swig/yask_kernel_api.i | 6 +- .../tests/{grid_test.cpp => var_test.cpp} | 28 +- .../tests/yask_kernel_api_exception_test.cpp | 72 +-- .../tests/yask_kernel_api_exception_test.py | 106 ++-- src/kernel/tests/yask_kernel_api_test.cpp | 102 ++-- src/kernel/tests/yask_kernel_api_test.py | 138 ++--- src/kernel/yask_main.cpp | 18 +- src/stencils/AwpElasticStencil.cpp | 96 ++-- src/stencils/AwpStencil.cpp | 102 ++-- .../ElasticStencil/Elastic2Stencil.hpp | 60 +-- .../ElasticStencil/ElasticStencil.hpp | 62 +-- src/stencils/FSGElastic2Stencil.cpp | 44 +- src/stencils/FSGElasticStencil.cpp | 184 +++---- src/stencils/Iso3dfdStencil.cpp | 20 +- src/stencils/SSGElastic2Stencil.cpp | 24 +- src/stencils/SSGElasticStencil.cpp | 42 +- ...{ExampleStencil.cpp => SimpleStencils.cpp} | 4 +- src/stencils/TTIStencil.cpp | 26 +- ...impleTestStencils.cpp => TestStencils.cpp} | 134 ++--- utils/bin/analyze_trace.pl | 30 +- utils/bin/convert_v2_stencil.pl | 18 +- utils/bin/gen_layouts.pl | 8 +- utils/bin/gen_loops.pl | 6 +- utils/bin/yask_tuner.pl | 32 +- utils/lib/YaskUtils.pm | 2 + 83 files changed, 3041 insertions(+), 2890 deletions(-) rename include/aux/{yk_grid_api.hpp => yk_var_api.hpp} (81%) rename src/compiler/lib/{Grid.cpp => Var.cpp} (84%) rename src/compiler/lib/{Grid.hpp => Var.hpp} (78%) rename src/kernel/lib/{generic_grids.cpp => generic_var.cpp} (82%) rename src/kernel/lib/{generic_grids.hpp => generic_var.hpp} (78%) rename src/kernel/lib/{new_grid.cpp => new_var.cpp} (82%) rename src/kernel/lib/{realv_grids.cpp => yk_var.cpp} (90%) rename src/kernel/lib/{realv_grids.hpp => yk_var.hpp} (84%) rename src/kernel/lib/{grid_apis.cpp => yk_var_apis.cpp} (70%) rename src/kernel/tests/{grid_test.cpp => var_test.cpp} (86%) rename src/stencils/{ExampleStencil.cpp => SimpleStencils.cpp} (98%) rename src/stencils/{SimpleTestStencils.cpp => TestStencils.cpp} (84%) diff --git a/README.md b/README.md index 59f37081..f8671640 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,10 @@ YASK contains a domain-specific compiler to convert stencil-equation specificati * Version 3.00.00 implemented a unification of the old (v2) internal DSL with the YASK compiler API. Canonical v2 DSL code should still work using the `Soln.hpp` backward-compatibility header file. To convert v2 DSL code to v3 format, use the `./utils/bin/convert_v2_stencil.pl` utility. -DSL or kernel code that has used any undocumented files, data, or types may have to be updated. +All references to the term "grid" has been changed to "var"; backward-compatibility APIs should maintain +functionality of v2 DSL and kernel code. +DSL and kernel code and any local output-parsing scripts that has used any undocumented files, +data, or types may have to be updated. ### Version 2 * Version 2.22.00 changed the heuristic to determine vector-folding sizes when some diff --git a/docs/api/mainpage.txt b/docs/api/mainpage.txt index d6d6ddf1..518fb22e 100644 --- a/docs/api/mainpage.txt +++ b/docs/api/mainpage.txt @@ -35,10 +35,10 @@ The following sub-sections describe each of the tasks in the workflow and when t @subsection yc_intro Define a Stencil Solution and Generate Kernel Code -A stencil solution consists of the grid variables containing the problem data -and one or more equations that describe how grid points are calculated. -An equation consists of a grid point to be calculated that "EQUALS" an expression -consisting of other grid points, constants, mathematical operators, etc. +A stencil solution consists of the variables containing the problem data +and one or more equations that describe how points in the variables are calculated. +An equation consists of a point to be calculated that "EQUALS" an expression +consisting of other points, constants, mathematical operators, etc. - Example equation: `u(t+1, x, y) EQUALS (u(t, x, y) + u(t, x+1, y) + u(t, x, y+1)) / 3`. A new stencil solution may be defined in one of the following ways: @@ -90,7 +90,7 @@ This may be done in one of the following ways: - This application may be run via `bin/yask.sh` to obtain a performance measurement of the kernel. -# You can also create your own stencil application using the YASK stencil kernel API. - This approach would be taken to integrate the kernel into a larger application that - would inject real-world initial-state data into the grids and extract the + would inject real-world initial-state data into the YASK variables and extract the final-state data for analysis or further processing. - See `src/kernel/tests/yask_kernel_api_test.cpp` for an example kernel usage in C++. - See `bin/yask_kernel_api_test.py` for an example kernel usage in Python. @@ -114,21 +114,21 @@ The types, classes, and functions are listed in \ref yc. @subsection yc_usage Typical Program Flow using the Compiler API - Create a yc_factory. This is the "bootstrap" object that will be used to create others. - Create a yc_solution object via yc_factory::new_solution(). -- Create one or more \ref yc_grid objects via yc_solution::new_grid() as needed by +- Create one or more \ref yc_var objects via yc_solution::new_var() as needed by the stencil(s) being implemented. - Calls to yc_solution::new_grid() specify the name and dimensions of each grid. - Grids may be read-only (constants) or read-write. - Each grid will be a part of the solution from which it was created. -- Create an equation for each read-write grid. + Calls to yc_solution::new_var() specify the name and dimensions of each var. + Vars may be read-only (constants) or read-write. + Each var will be a part of the solution from which it was created. +- Create an equation for each read-write var. - Create expressions "bottom-up" by creating the leaf nodes first. - - Leaf nodes may be floating-point (FP) constants or references to grid points. - - Constants are created via yc_node_factory::new_const_number_node(). - - References to grid points are created via yc_grid::new_relative_grid_point(), which - specifies the grid indices relative to any point within the grid domain. - - Create operator nodes via calls to yc_node_factory::new_add_node(), etc., to build up + - Leaf nodes may be floating-point (FP) constants or references to var points. + - Constants are created via yc_node_factory::new_number_node(). + - References to points are created via yc_var::new_var_point(), which + specifies the indices relative to the point being evaluated within the problem domain. + - Create operator nodes via normal math operators (`+`, `*`, etc.), to build up larger expressions. - - To complete each equation, use yc_node_factory::new_equation_node() to specify an expression - on the right-hand side (RHS) and the grid point that is defined to be equal + - To complete each equation, use the special `EQUALS` operator to specify an expression + on the right-hand side (RHS) and the point in a variable that is defined to be equal to it on the left-hand side (LHS). - Specify the solution domain dimension via yc_node_factory::new_domain_index(). - Specify the solution step dimension via yc_node_factory::new_step_index(). @@ -156,19 +156,19 @@ The types, classes, and functions are listed in \ref yk. - Create a \ref yk_solution object via yk_factory::new_solution(). A pointer to the environment object is provided. This structure allows you to initialize MPI early in the program. - The solution contains the grids and equations defined by the stencil compiler process. + The solution contains the vars and equations defined by the stencil compiler process. - Use the \ref yk_solution methods to configure options like the size of the problem domain. - Set up internal data structures via yk_solution::prepare_solution(). This adjusts any settings as needed, determines each rank's position in the problem - if MPI is enabled, and allocates data for the grids. + if MPI is enabled, and allocates data for the vars. Be sure to modify any settings before calling yk_solution::prepare_solution(). -- Access the solution grids via yk_solution::get_grid(). - Various properties of each grid may be retrieved or set. - In particular, you should initialize the data in each grid via yk_grid::set_all_elements_same() - and yk_grid::set_element(). -- Apply the stencil(s) to the grids via yk_solution::run_solution(). +- Access the solution vars via yk_solution::get_var(). + Various properties of each var may be retrieved or set. + In particular, you should initialize the data in each var via yk_var::set_all_elements_same() + and yk_var::set_element(). +- Apply the stencil(s) to the vars via yk_solution::run_solution(). There are versions for advancing one or more steps. -- Retrieve the final results via yk_grid::get_element(). +- Retrieve the final results via yk_var::get_element(). @section sec_tests Example Tests diff --git a/include/aux/Soln.hpp b/include/aux/Soln.hpp index 20f0dad9..b85fb3f5 100644 --- a/include/aux/Soln.hpp +++ b/include/aux/Soln.hpp @@ -68,11 +68,11 @@ namespace yask { }; // Aliases for backward-compatibility. - typedef yc_grid_var Grid; + typedef yc_var_proxy Grid; typedef yc_number_node_ptr GridIndex; typedef yc_number_node_ptr GridValue; typedef yc_bool_node_ptr Condition; - typedef yc_grid_point_node_ptr GridPointPtr; + typedef yc_var_point_node_ptr GridPointPtr; typedef yc_expr_node_ptr ExprPtr; typedef yc_number_node_ptr NumExprPtr; typedef yc_index_node_ptr IndexExprPtr; @@ -96,15 +96,15 @@ namespace yask { #define MAKE_DOMAIN_INDEX(d) yc_index_node_ptr d = new_domain_index(#d) #define MAKE_MISC_INDEX(d) yc_index_node_ptr d = new_misc_index(#d) -// Convenience macros for creating grids in a class implementing get_soln(). -// The 'gvar' arg is the var name and the grid name. +// Convenience macros for creating vars in a class implementing get_soln(). +// The 'gvar' arg is the C++ var and YASK var name. // The remaining args are the dimension names. #define MAKE_GRID(gvar, ...) \ - yc_grid_var gvar = yc_grid_var(#gvar, get_soln(), { __VA_ARGS__ }, false) + yc_var_proxy gvar = yc_var_proxy(#gvar, get_soln(), { __VA_ARGS__ }, false) #define MAKE_SCALAR(gvar) MAKE_GRID(gvar) #define MAKE_ARRAY(gvar, d1) MAKE_GRID(gvar, d1) #define MAKE_SCRATCH_GRID(gvar, ...) \ - yc_grid_var gvar = yc_grid_var(#gvar, get_soln(), { __VA_ARGS__ }, true) + yc_var_proxy gvar = yc_var_proxy(#gvar, get_soln(), { __VA_ARGS__ }, true) #define MAKE_SCRATCH_SCALAR(gvar) MAKE_SCRATCH_GRID(gvar) #define MAKE_SCRATCH_ARRAY(gvar, d1) MAKE_SCRATCH_GRID(gvar, d1) @@ -122,7 +122,7 @@ namespace yask { #define IF_STEP_OPER IF_STEP // Namespaces for stencil code. -#ifndef NO_NAMESPACES +#ifndef NO_USING_NAMESPACES using namespace yask; using namespace std; #endif diff --git a/include/aux/yc_node_api.hpp b/include/aux/yc_node_api.hpp index a4ecd496..a2aba73a 100644 --- a/include/aux/yc_node_api.hpp +++ b/include/aux/yc_node_api.hpp @@ -142,7 +142,7 @@ namespace yask { }; /// Equation node. - /** Indicates grid point on LHS is equivalent to expression + /** Indicates var point on LHS is equivalent to expression on RHS. This is NOT a test for equality. Created via yc_node_factory::new_equation_node(). */ @@ -150,8 +150,8 @@ namespace yask { public: /// Get the left-hand-side operand. - /** @returns Grid-point node appearing before the EQUALS operator. */ - virtual yc_grid_point_node_ptr get_lhs() =0; + /** @returns Var-point node appearing before the EQUALS operator. */ + virtual yc_var_point_node_ptr get_lhs() =0; /// Get the right-hand-side operand. /** @returns Expression node appearing after the EQUALS operator. */ @@ -227,7 +227,7 @@ namespace yask { my_expr.set_step_cond(my_step_cond); \endcode - Step conditions may also refer to elements in grid variables including + Step conditions may also refer to elements in variables including scalars (1-D) and arrays (2-D). For non-scalar variables, indices used in a step condition _cannot_ include domain variables like `x` or `y`, but constants are allowed. In this way, equations can be enabled or @@ -276,17 +276,23 @@ namespace yask { get_name() const =0; }; - /// A reference to a point in a grid. + /// A reference to a point in a var. /** - Created via yc_grid::new_relative_grid_point(). + Created via yc_var::new_var_point() or yc_var::new_relative_var_point(). */ - class yc_grid_point_node : public virtual yc_number_node { + class yc_var_point_node : public virtual yc_number_node { public: - /// Get the grid this point is in. - /** @returns Pointer to a \ref yc_grid object. */ - virtual yc_grid_ptr - get_grid() =0; + /// Get the var this point is in. + /** @returns Pointer to a \ref yc_var object. */ + virtual yc_var_ptr + get_var() =0; + + /// **[Deprecated]** Use get_var(). + virtual yc_var_ptr + get_grid() { + return get_var(); + } }; /// A constant numerical value. @@ -494,8 +500,8 @@ namespace yask { yc_number_ptr_arg(yc_index_node_ptr p) : yc_number_node_ptr(p) { } - /// Arg can be a grid-point-node pointer. - yc_number_ptr_arg(yc_grid_point_node_ptr p) : + /// Arg can be a var-point-node pointer. + yc_number_ptr_arg(yc_var_point_node_ptr p) : yc_number_node_ptr(p) { } }; @@ -559,8 +565,8 @@ namespace yask { yc_number_any_arg(yc_index_node_ptr p) : yc_number_node_ptr(p) { } - /// Arg can be a grid-point-node pointer. - yc_number_any_arg(yc_grid_point_node_ptr p) : + /// Arg can be a var-point-node pointer. + yc_number_any_arg(yc_var_point_node_ptr p) : yc_number_node_ptr(p) { } /// Arg can be an index type. @@ -586,7 +592,7 @@ namespace yask { #endif /// Factory to create AST nodes. - /** @note Grid-point reference nodes are created from a \ref yc_grid object + /** @note Var-point reference nodes are created from a \ref yc_var object instead of from a \ref yc_node_factory. */ class yc_node_factory { public: @@ -594,7 +600,7 @@ namespace yask { /// Create a step-index node. /** - Create a variable to be used to index grids in the + Create a variable to be used to index vars in the solution-step dimension. The name usually describes time, e.g. "t". @returns Pointer to new \ref yc_index_node object. @@ -605,7 +611,7 @@ namespace yask { /// Create a domain-index node. /** - Create a variable to be used to index grids in the + Create a variable to be used to index vars in the solution-domain dimension. The name usually describes spatial dimensions, e.g. "x" or "y", but it can be any dimension that is specified at run-time, @@ -622,7 +628,7 @@ namespace yask { /// Create a new miscellaneous index. /** - Create an variable to be used to index grids in the + Create an variable to be used to index vars in the some dimension that is not the step dimension or a domain dimension. The value of these indices are normally compile-time @@ -634,10 +640,10 @@ namespace yask { /**< [in] Index name. */ ) const; /// Create an equation node. - /** Indicates grid point on LHS is equivalent to expression on + /** Indicates var point on LHS is equivalent to expression on RHS. This is NOT a test for equality. When an equation is created, it is automatically added to the list of equations for - the yc_solution that contains the grid that is on the + the yc_solution that contains the var that is on the LHS. An optional domain condition may be provided to define the sub-domain @@ -661,8 +667,8 @@ namespace yask { @returns Pointer to new \ref yc_equation_node object. */ virtual yc_equation_node_ptr - new_equation_node(yc_grid_point_node_ptr lhs - /**< [in] Grid-point before EQUALS operator. */, + new_equation_node(yc_var_point_node_ptr lhs + /**< [in] Var-point before EQUALS operator. */, yc_number_node_ptr rhs /**< [in] Expression after EQUALS operator. */, yc_bool_node_ptr sub_domain_cond = nullptr @@ -1027,25 +1033,25 @@ namespace yask { yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, const yc_index_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ - inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ + inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, const yc_var_point_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_number_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_index_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ - inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ + inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, const yc_var_point_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ - inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_number_node_ptr rhs) { \ + inline yc_bool_node_ptr operator oper(const yc_var_point_node_ptr lhs, const yc_number_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ - inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_index_node_ptr rhs) { \ + inline yc_bool_node_ptr operator oper(const yc_var_point_node_ptr lhs, const yc_index_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ - inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, const yc_grid_point_node_ptr rhs) { \ + inline yc_bool_node_ptr operator oper(const yc_var_point_node_ptr lhs, const yc_var_point_node_ptr rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, rhs); } \ inline yc_bool_node_ptr operator oper(const yc_number_node_ptr lhs, double rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } \ inline yc_bool_node_ptr operator oper(const yc_index_node_ptr lhs, double rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } \ - inline yc_bool_node_ptr operator oper(const yc_grid_point_node_ptr lhs, double rhs) { \ + inline yc_bool_node_ptr operator oper(const yc_var_point_node_ptr lhs, double rhs) { \ yc_node_factory nfac; return nfac.fn(lhs, nfac.new_number_node(rhs)); } BOOL_OPER(==, new_equals_node) @@ -1067,8 +1073,8 @@ namespace yask { */ #define EQUALS << - /// The operator version of yc_node_factory::new_equation_node() used for defining a grid value. - yc_equation_node_ptr operator EQUALS(yc_grid_point_node_ptr gpp, const yc_number_any_arg rhs); + /// The operator version of yc_node_factory::new_equation_node() used for defining a var-point value. + yc_equation_node_ptr operator EQUALS(yc_var_point_node_ptr gpp, const yc_number_any_arg rhs); /// Recommended macro to make the domain-condition operator readable and self-explanatory. /** diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index 0621a519..e3af6f59 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -40,18 +40,18 @@ namespace yask { * @{ */ - /// Allocate grids on local NUMA node. + /// Allocate vars on local NUMA node. /** This is used in yk_solution::set_default_numa_preferred - and yk_grid::set_numa_preferred. + and yk_var::set_numa_preferred. In Python, specify as `yask_kernel.cvar.yask_numa_local`. */ const int yask_numa_local = -1; - /// Allocate grids across all available NUMA nodes. + /// Allocate vars across all available NUMA nodes. /** This is used in yk_solution::set_default_numa_preferred - and yk_grid::set_numa_preferred. + and yk_var::set_numa_preferred. In Python, specify as `yask_kernel.cvar.yask_numa_interleave`. */ const int yask_numa_interleave = -2; @@ -59,14 +59,14 @@ namespace yask { /// Do not specify any NUMA binding. /** This is used in yk_solution::set_default_numa_preferred - and yk_grid::set_numa_preferred. + and yk_var::set_numa_preferred. In Python, specify as `yask_kernel.cvar.yask_numa_none`. */ const int yask_numa_none = -9; /// Stencil solution as defined by the generated code from the YASK stencil compiler. /** - Objects of this type contain all the grids and equations + Objects of this type contain all the vars and equations that comprise a solution. */ class yk_solution { @@ -97,7 +97,7 @@ namespace yask { /** @returns String containing the step-dimension name that was defined by yc_node_factory::new_step_index() - and used in one or more grids. + and used in one or more vars. */ virtual std::string get_step_dim_name() const =0; @@ -116,7 +116,7 @@ namespace yask { /** @returns List of all domain-dimension names that were defined by yc_node_factory::new_domain_index() - and used in one or more grids. + and used in one or more vars. */ virtual std::vector get_domain_dim_names() const =0; @@ -126,9 +126,9 @@ namespace yask { @returns List of all dimension names that were either * Defined by yc_node_factory::new_misc_index() - and used in one or more grids, or + and used in one or more vars, or * Created at run-time by adding a new dimension - via yk_solution::new_grid() or yk_solution::new_fixed_size_grid(). + via yk_solution::new_var() or yk_solution::new_fixed_size_var(). */ virtual std::vector get_misc_dim_names() const =0; @@ -155,9 +155,7 @@ namespace yask { Setting the local-domain size to a non-zero value will clear the global-domain size in that dimension until prepare_solution() is called. - See the "Detailed Description" for \ref yk_grid for more information on grid sizes. - There is no domain-size setting allowed in the - solution-step dimension (e.g., "t"). + See the "Detailed Description" for \ref yk_var for more information on var sizes. */ virtual void set_rank_domain_size(const std::string& dim @@ -190,9 +188,7 @@ namespace yask { local-domain size in that dimension until prepare_solution() is called. See documentation for set_rank_domain_size(). - See the "Detailed Description" for \ref yk_grid for more information on grid sizes. - There is no domain-size setting allowed in the - solution-step dimension (e.g., "t"). + See the "Detailed Description" for \ref yk_var for more information on var sizes. */ virtual void set_overall_domain_size(const std::string& dim @@ -340,35 +336,36 @@ namespace yask { the names from get_domain_dim_names(). */ ) const =0; - /// Get the number of grids in the solution. + /// Get the number of vars in the solution. /** - Grids may be pre-defined by the stencil compiler - (e.g., via yc_solution::new_grid()) - or created explicitly via yk_solution::new_grid() - or yk_solution::new_fixed_size_grid(). - @returns Number of grids that have been created. + Vars may be pre-defined by the stencil compiler + (e.g., via yc_solution::new_var()) + or created explicitly via yk_solution::new_var() + or yk_solution::new_fixed_size_var(). + @returns Number of YASK vars that have been created. */ virtual int - get_num_grids() const =0; + get_num_vars() const =0; - /// Get the specified grid. + /// Get the specified var. /** - This cannot be used to access scratch grids. - @returns Pointer to the specified grid or null pointer if it does not exist. + This cannot be used to access scratch vars. + @returns Pointer to the specified var or null pointer if it does not exist. */ - virtual yk_grid_ptr - get_grid(const std::string& name /**< [in] Name of the grid. */ ) =0; + virtual yk_var_ptr + get_var(const std::string& name + /**< [in] Name of the var. */ ) =0; - /// Get all the grids. + /// Get all the vars. /** - @returns List of all non-scratch grids in the solution. + @returns List of all non-scratch vars in the solution. */ - virtual std::vector - get_grids() =0; + virtual std::vector + get_vars() =0; /// Prepare the solution for stencil application. /** - Allocates data in grids that do not already have storage allocated. + Allocates data in vars that do not already have storage allocated. Calculates the position of each rank in the overall problem domain. Sets many other data structures needed for proper stencil application. Since this function initiates MPI communication, it must be called @@ -417,7 +414,7 @@ namespace yask { /// Run the stencil solution for the specified steps. /** - The stencil(s) in the solution are applied to the grid data, setting the + The stencil(s) in the solution are applied to the var data, setting the index variables as follows: 1. If temporal wave-front tiling is *not* used (the default): - The step index (e.g., `t` for "time") will be sequentially set to values @@ -483,7 +480,7 @@ namespace yask { /// Finish using a solution. /** Performs a final MPI halo exchange. - Releases shared ownership of memory used by the grids. This will + Releases shared ownership of memory used by the vars. This will result in deallocating each memory block that is not referenced by another shared pointer. */ @@ -558,9 +555,9 @@ namespace yask { the names from get_step_dim_name() or get_domain_dim_names(). */) const =0; - /// **[Advanced]** Set the minimum amount of grid padding for all grids. + /// **[Advanced]** Set the minimum amount of padding for all vars. /** - This sets the minimum number of elements in each grid that is + This sets the minimum number of elements in each var that is reserved outside of the rank domain in the given dimension. This padding area can be used for required halo areas. At least the specified number of elements will be added to both @@ -573,15 +570,15 @@ namespace yask { - Value provided by any of the pad-size setting functions. The padding size cannot be changed after data storage - has been allocated for a given grid; attempted changes to the pad size for such - grids will be ignored. - In addition, once a grid's padding is set, it cannot be reduced, only increased. - - Use yk_grid::set_left_min_pad_size and yk_grid::set_right_min_pad_size() - for specific setting of each grid. - Call yk_grid::get_left_pad_size() and yk_grid::get_right_pad_size() - to determine the actual padding sizes for a given grid. - See the "Detailed Description" for \ref yk_grid for more information on grid sizes. + has been allocated for a given var; attempted changes to the pad size for such + vars will be ignored. + In addition, once a var's padding is set, it cannot be reduced, only increased. + + Use yk_var::set_left_min_pad_size and yk_var::set_right_min_pad_size() + for specific setting of each var. + Call yk_var::get_left_pad_size() and yk_var::get_right_pad_size() + to determine the actual padding sizes for a given var. + See the "Detailed Description" for \ref yk_var for more information on var sizes. Padding is only allowed in the domain dimensions. */ virtual void @@ -592,9 +589,9 @@ namespace yask { /**< [in] Elements in this `dim` applied to both sides of the domain. */ ) =0; - /// **[Advanced]** Get the minimum amount of grid padding for all grids. + /// **[Advanced]** Get the minimum amount of padding for all vars. /** - @returns Current setting of minimum amount of grid padding for all grids. + @returns Current setting of minimum amount of padding for all vars. */ virtual idx_t get_min_pad_size(const std::string& dim @@ -634,10 +631,10 @@ namespace yask { for a given number of steps after the best settings are found. This function should be called only *after* calling prepare_solution(). This call must be made on each rank. - @warning Modifies the contents of the grids by calling run_solution() + @warning Modifies the contents of the vars by calling run_solution() an arbitrary number of times, but without halo exchange. (See run_solution() for other restrictions and warnings.) - Thus, grid data should be set *after* calling this function when + Thus, var data should be set *after* calling this function when used in a production or test setting where correct results are expected. */ virtual void @@ -645,158 +642,158 @@ namespace yask { /**< [in] If _true_, print progress information to the debug object set via set_debug_output(). */ ) =0; - /// **[Advanced]** Add a new grid to the solution. + /// **[Advanced]** Add a new var to the solution. /** - This is typically not needed because grids used by the stencils are pre-defined + This is typically not needed because vars used by the stencils are pre-defined by the solution itself via the stencil compiler. - However, a grid may be created explicitly via this function + However, a var may be created explicitly via this function in order to use it for purposes other than by the pre-defined stencils within the current solution. - Grids created by this function will behave [mostly] like a pre-defined grid. + Vars created by this function will behave [mostly] like a pre-defined var. For example, - Step and domain dimensions must the same as those defined by yc_node_factory::new_step_index() and yc_node_factory::new_domain_index(), respectively. - - For each domain dimension of the grid, - the new grid's domain size will be the same as that returned by + - For each domain dimension of the var, + the new var's domain size will be the same as that returned by get_rank_domain_size(). - Calls to set_rank_domain_size() will automatically resize the corresponding domain - size in this grid. - - This grid's first domain index in this rank will be determined + size in this var. + - This var's first domain index in this rank will be determined by the position of this rank. - - This grid's initial padding size will be the same as that returned by + - This var's initial padding size will be the same as that returned by get_min_pad_size(). - - After creating a new grid, you can increase its padding - sizes in the domain dimensions via yk_grid::set_min_pad_size(), + - After creating a new var, you can increase its padding + sizes in the domain dimensions via yk_var::set_min_pad_size(), yk_solution::set_min_pad_size(), etc. - For step and misc dimensions, you can change the desired size - yk_grid::set_alloc_size(). - - Storage may be allocated via yk_grid::alloc_storage() or + yk_var::set_alloc_size(). + - Storage may be allocated via yk_var::alloc_storage() or yk_solution::prepare_solution(). - Some behaviors are different from pre-defined grids. For example, - - You can create new "misc" dimensions during grid creation simply + Some behaviors are different from pre-defined vars. For example, + - You can create new "misc" dimensions during var creation simply by naming them in the `dims` argument. Any dimension name that is not a step or domain dimension will become a misc dimension, whether or not it was defined via yc_node_factory::new_misc_index(). - - Grids created via new_grid() cannot be direct inputs or outputs of - stencil equations. However, data in a grid created via new_grid() - can be merged with a pre-defined grid via yk_grid::fuse_grids() - if the grids are compatible. + - Vars created via new_var() cannot be direct inputs or outputs of + stencil equations. However, data in a var created via new_var() + can be merged with a pre-defined var via yk_var::fuse_vars() + if the vars are compatible. - If you want a grid that is not automatically resized based on the - solution settings, use new_fixed_size_grid() instead. + If you want a var that is not automatically resized based on the + solution settings, use new_fixed_size_var() instead. - @note A new grid contains only the meta-data for the grid; data storage + @note A new var contains only the meta-data for the var; data storage is not yet allocated. Storage may be allocated in any of the methods listed - in the "Detailed Description" for \ref yk_grid. - @returns Pointer to the new grid. + in the "Detailed Description" for \ref yk_var. + @returns Pointer to the new var. */ - virtual yk_grid_ptr - new_grid(const std::string& name - /**< [in] Name of the grid; must be unique + virtual yk_var_ptr + new_var(const std::string& name + /**< [in] Name of the var; must be unique within the solution. */, const std::vector& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */ ) =0; + not repeated within this var. */ ) =0; #ifndef SWIG - /// **[Advanced]** Add a new grid to the solution. + /// **[Advanced]** Add a new var to the solution. /** - See documentation for the version of new_grid() with a vector of dimension names + See documentation for the version of new_var() with a vector of dimension names as a parameter. @note This version is not available (or needed) in the Python API. - @returns Pointer to the new grid. + @returns Pointer to the new var. */ - virtual yk_grid_ptr - new_grid(const std::string& name - /**< [in] Name of the grid; must be unique + virtual yk_var_ptr + new_var(const std::string& name + /**< [in] Name of the var; must be unique within the solution. */, const std::initializer_list& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */ ) =0; + not repeated within this var. */ ) =0; #endif - /// **[Advanced]** Add a new grid to the solution with a specified size. + /// **[Advanced]** Add a new var to the solution with a specified size. /** - This is typically not needed because grids used by the stencils are pre-defined + This is typically not needed because vars used by the stencils are pre-defined by the solution itself via the stencil compiler. - However, a grid may be created explicitly via this function + However, a var may be created explicitly via this function in order to use it for purposes other than by the pre-defined stencils within the current solution. - The following behaviors are different from both pre-defined grids - and those created via new_grid(): + The following behaviors are different from both pre-defined vars + and those created via new_var(): - Calls to set_rank_domain_size() will *not* automatically resize - the corresponding local-domain size in this grid--this is where the term "fixed" applies. - - In contrast, for each domain dimension of the grid, - the new grid's local-domain size can be changed independently of the domain + the corresponding local-domain size in this var--this is where the term "fixed" applies. + - In contrast, for each domain dimension of the var, + the new var's local-domain size can be changed independently of the domain size of the solution. - - This grid's first domain index in this rank will be fixed at zero (0) + - This var's first domain index in this rank will be fixed at zero (0) in each domain dimension regardless of this rank's position. - In other words, this grid does not participate in "domain decomposition". - - This grid's padding size will be affected only by calls to - yk_grid::set_min_pad_size(), etc., i.e., *not* via + In other words, this var does not participate in "domain decomposition". + - This var's padding size will be affected only by calls to + yk_var::set_min_pad_size(), etc., i.e., *not* via yk_solution::set_min_pad_size(). - The following behaviors are the same as those of a pre-defined grid - and those created via new_grid(): + The following behaviors are the same as those of a pre-defined var + and those created via new_var(): - For step and misc dimensions, you can change the desired size - yk_grid::set_alloc_size(). - - Storage may be allocated via yk_grid::alloc_storage() or + yk_var::set_alloc_size(). + - Storage may be allocated via yk_var::alloc_storage() or yk_solution::prepare_solution(). - See yk_grid::set_alloc_size(). + See yk_var::set_alloc_size(). - The following behaviors are different than a pre-defined grid - but the same as those created via new_grid(): - - You can create new "misc" dimensions during grid creation simply + The following behaviors are different than a pre-defined var + but the same as those created via new_var(): + - You can create new "misc" dimensions during var creation simply by naming them in the `dims` argument. Any dimension name that is not a step or domain dimension will become a misc dimension, whether or not it was defined via yc_node_factory::new_misc_index(). - - Grids created via new_fixed_size_grid() cannot be direct inputs or outputs of - stencil equations. However, data in a grid created via new_fixed_size_grid() - can be shared with a pre-defined grid via yk_grid::fuse_grids() - if the grids are compatible. + - Vars created via new_fixed_size_var() cannot be direct inputs or outputs of + stencil equations. However, data in a var created via new_fixed_size_var() + can be shared with a pre-defined var via yk_var::fuse_vars() + if the vars are compatible. - @note A new grid contains only the meta-data for the grid; data storage + @note A new var contains only the meta-data for the var; data storage is not yet allocated. Storage may be allocated in any of the methods listed - in the "Detailed Description" for \ref yk_grid. - @returns Pointer to the new grid. + in the "Detailed Description" for \ref yk_var. + @returns Pointer to the new var. */ - virtual yk_grid_ptr - new_fixed_size_grid(const std::string& name - /**< [in] Name of the grid; must be unique + virtual yk_var_ptr + new_fixed_size_var(const std::string& name + /**< [in] Name of the var; must be unique within the solution. */, const std::vector& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */, + not repeated within this var. */, const std::vector& dim_sizes /**< [in] Initial allocation in each dimension. Must be exatly one size for each dimension. */ ) =0; #ifndef SWIG - /// **[Advanced]** Add a new grid to the solution with a specified size. + /// **[Advanced]** Add a new var to the solution with a specified size. /** - See documentation for the version of new_fixed_size_grid() with a vector of dimension names + See documentation for the version of new_fixed_size_var() with a vector of dimension names as a parameter. @note This version is not available (or needed) in the Python API. - @returns Pointer to the new grid. + @returns Pointer to the new var. */ - virtual yk_grid_ptr - new_fixed_size_grid(const std::string& name - /**< [in] Name of the grid; must be unique + virtual yk_var_ptr + new_fixed_size_var(const std::string& name + /**< [in] Name of the var; must be unique within the solution. */, const std::initializer_list& dims /**< [in] List of names of all dimensions. Names must be valid C++ identifiers and - not repeated within this grid. */, + not repeated within this var. */, const std::initializer_list& dim_sizes /**< [in] Initial allocation in each dimension. Must be exatly one size for each dimension. */ ) =0; @@ -804,13 +801,13 @@ namespace yask { /// **[Advanced]** Set the default preferred NUMA node on which to allocate data. /** - This value is used when allocating grids and MPI buffers. + This value is used when allocating vars and MPI buffers. The NUMA "preferred node allocation" policy is used, meaning that memory will be allocated in an alternative node if the preferred one doesn't have enough space available or is otherwise restricted. Instead of specifying a NUMA node, a special value may be used to specify another policy as listed. - This setting may be overridden for any specific grid. + This setting may be overridden for any specific var. @returns `true` if NUMA preference was set; `false` if NUMA preferences are not enabled. */ @@ -849,15 +846,15 @@ namespace yask { apply_command_line_options(const std::string& args /**< [in] String of arguments to parse. */ ) =0; - /// **[Advanced]** Merge grid variables with another solution. + /// **[Advanced]** Merge YASK variables with another solution. /** - Calls yk_grid::fuse_grids() for each pair of grids that have the same name + Calls yk_var::fuse_vars() for each pair of vars that have the same name in this solution and the source solution. - All conditions listed in yk_grid::fuse_grids() must hold for each pair. + All conditions listed in yk_var::fuse_vars() must hold for each pair. */ virtual void - fuse_grids(yk_solution_ptr source - /**< [in] Solution from which grids will be merged. */) =0; + fuse_vars(yk_solution_ptr source + /**< [in] Solution from which vars will be merged. */) =0; /// **[Advanced]** Set whether invalid step indices alias to valid ones. virtual void @@ -870,6 +867,64 @@ namespace yask { */ virtual bool get_step_wrap() const =0; + + /// **[Deprecated]** Use get_num_vars(). + virtual int + get_num_grids() const { + return get_num_vars(); + } + + /// **[Deprecated]** Use get_var(). + virtual yk_var_ptr + get_grid(const std::string& name) { + return get_var(name); + } + + /// **[Deprecated]** Use get_vars(). + virtual std::vector + get_grids() { + return get_vars(); + } + + /// **[Deprecated]** Use new_var(). + virtual yk_var_ptr + new_grid(const std::string& name, + const std::vector& dims) { + return new_var(name, dims); + } + +#ifndef SWIG + /// **[Deprecated]** Use new_var(). + virtual yk_var_ptr + new_grid(const std::string& name, + const std::initializer_list& dims) { + return new_var(name, dims); + } +#endif + + /// **[Deprecated]** Use new_fixed_size_var(). + virtual yk_var_ptr + new_fixed_size_grid(const std::string& name, + const std::vector& dims, + const std::vector& dim_sizes) { + return new_fixed_size_var(name, dims, dim_sizes); + } + +#ifndef SWIG + /// **[Deprecated]** Use new_fixed_size_var(). + virtual yk_var_ptr + new_fixed_size_grid(const std::string& name, + const std::initializer_list& dims, + const std::vector& dim_sizes) { + return new_fixed_size_var(name, dims, dim_sizes); + } +#endif + + /// **[Deprecated]** Use fuse_vars(). + virtual void + fuse_grids(yk_solution_ptr source) { + fuse_vars(source); + } }; /// Statistics from calls to run_solution(). @@ -902,7 +957,7 @@ namespace yask { /// Get the number of elements written across all steps. /** - @returns Number of elements written, summed over all output grids, + @returns Number of elements written, summed over all output vars, steps executed, and ranks. */ virtual idx_t diff --git a/include/aux/yk_grid_api.hpp b/include/aux/yk_var_api.hpp similarity index 81% rename from include/aux/yk_grid_api.hpp rename to include/aux/yk_var_api.hpp index 91b6d394..9fb35322 100644 --- a/include/aux/yk_grid_api.hpp +++ b/include/aux/yk_var_api.hpp @@ -23,11 +23,11 @@ IN THE SOFTWARE. *****************************************************************************/ -///////// API for the YASK stencil kernel grid. //////////// +///////// API for the YASK stencil kernel var. //////////// // This file uses Doxygen 1.8 markup for API documentation-generation. // See http://www.stack.nl/~dimitri/doxygen. -/** @file yk_grid_api.hpp */ +/** @file yk_var_api.hpp */ #pragma once @@ -40,21 +40,20 @@ namespace yask { * @{ */ - /// A run-time data container. + /// A run-time YASK data container. /** - A run-time YASK variable (usually referred to simply as a "grid", - which is a bit of a misnomer) is a generic term for any n-dimensional - array. A 0-dim grid is a scalar, a 1-dim grid is an array, etc. A - run-time variable actually contains data, unlike yc_grid, a + A run-time YASK variable is a generic term for any n-dimensional + array. A 0-dim var is a scalar, a 1-dim var is an array, etc. A + run-time variable actually contains data, unlike yc_var, a compile-time variable. - Typically, access to each grid is obtained via yk_solution::get_grid(). - You may also use yk_solution::new_grid() or yk_solution::new_fixed_size_grid() - if you need a grid that is not part of the pre-defined solution. + Typically, access to each var is obtained via yk_solution::get_var(). + You may also use yk_solution::new_var() or yk_solution::new_fixed_size_var() + if you need a var that is not part of the pre-defined solution. - # Grid Dimensions # + # Var Dimensions # - Each dimension of a grid is one of the following: + Each dimension of a YASK var is one of the following: - The *step* dimension, typically time (`t`), as returned from yk_solution::get_step_dim_name(). - A *domain* dimension, typically a spatial dimension such as `x` or `y`, @@ -71,9 +70,9 @@ namespace yask { However, there is a finite allocation size, which is the number of values in the step dimension that are stored in memory. The valid indices in the step dimension are always consecutive and change based - on what was last written to the grid. + on what was last written to the var. - For example: If a grid `A` has + For example: If a var `A` has an allocation size of two (2) in the `t` step dimension, its initial valid `t` indices are 0 and 1. Calling `A->get_element({0, x})` or `A->get_element({1, x})` would return a value from `A` assuming `x` @@ -87,20 +86,20 @@ namespace yask { calling `A->get_element({1, x})` or `A->get_element({2, x})` would succeed and `A->get_element({0, x})` would fail. - Calling APIs that set values in a grid such as set_element() will + Calling APIs that set values in a var such as set_element() will also update the valid step index range. The current valid indices in the step dimension can be retrieved via - yk_grid::get_first_valid_step_index() and - yk_grid::get_last_valid_step_index(). + yk_var::get_first_valid_step_index() and + yk_var::get_last_valid_step_index(). If yk_solution::set_step_wrap(true) is called, any invalid value of a step index provided to an API will silently "wrap-around" to a valid value by effectively adding or subtracing multiples of the allocation size as needed. For example, if the valid step indices are 7 and 8 - for a given grid, the indices 0 and 1 will wrap-around to 8 and 7, + for a given var, the indices 0 and 1 will wrap-around to 8 and 7, respectively. This is not recommended for general use because it can hide off-by-one-type errors. However, it may be useful for - applications that need to access a grid using absolute rather than + applications that need to access a var using absolute rather than logical step indices. ## Domain Dimensions # @@ -108,9 +107,11 @@ namespace yask { A domain dimension typically corresponds to a physical spatial dimension, but it can be any dimension that is used for "domain decomposition" in the solution. + The indices in the domain dimensions that correspond to spatial dimensions (e.g., + "x" and "y") often denote locations in the implicit "grid" of the problem domain. In each domain dimension, - grid sizes include the following components: + the number of elements allocated in a given var include the following components: - The *domain* is the elements to which the stencils are applied. - The *left padding* is all the accessible elements before the domain and includes the left halo. - The *right padding* is all the accessible elements after the domain and includes the right halo. @@ -155,7 +156,7 @@ namespace yask { There is a fixed allocation size, and each index must be between its first and last valid value. The valid miscellaneous indices may be retrieved via - yk_grid::get_first_misc_index() and yk_grid::get_last_misc_index(). + yk_var::get_first_misc_index() and yk_var::get_last_misc_index(). # Other Details # @@ -168,38 +169,41 @@ namespace yask { ## Data Storage # - Initially, a grid is not assigned any allocated storage. + Initially, a var is not assigned any allocated storage. This is done to allow modification of domain, padding, and other allocation sizes before allocation. Once the allocation sizes have been set in all dimensions, the data storage itself may be allocated. This can be done in any of the following ways: - - Storage for all grids without data storage will be automatically allocated when + - Storage for all vars without data storage will be automatically allocated when yk_solution::prepare_solution() is called. - - Storage for a specific grid may be allocated before calling yk_solution::prepare_solution() - via yk_grid::alloc_storage(). - - **[Advanced]** A grid may be merged with another grid with existing storage - via yk_grid::fuse_grids(). + - Storage for a specific var may be allocated before calling yk_solution::prepare_solution() + via yk_var::alloc_storage(). + - **[Advanced]** A var may be merged with another var with existing storage + via yk_var::fuse_vars(). */ - class yk_grid { + class yk_var { public: - virtual ~yk_grid() {} + virtual ~yk_var() {} - /// Get the name of the grid. + /// Get the name of the var. /** - @returns String containing name provided via yc_solution::new_grid(). + @returns String containing name provided via yc_solution::new_var(), + yk_solution::new_var(), or yk_solution::new_fixed_size_var().. + @note Recall that scratch vars created via yc_solution::new_scratch_var() + are temporary variables and thus are not accessible via the kernel APIs. */ virtual const std::string& get_name() const =0; - /// Get the number of dimensions used in this grid. + /// Get the number of dimensions used in this var. /** This may include domain, step, and/or miscellaneous dimensions. - @returns Number of dimensions created via yc_solution::new_grid(), - yk_solution::new_grid(), or yk_solution::new_fixed_size_grid(). + @returns Number of dimensions created via yc_solution::new_var(), + yk_solution::new_var(), or yk_solution::new_fixed_size_var(). */ virtual int get_num_dims() const =0; - /// Get all the dimensions in this grid. + /// Get all the dimensions in this var. /** This may include domain, step, and/or miscellaneous dimensions. @returns List of names of all the dimensions. @@ -207,7 +211,7 @@ namespace yask { virtual std::vector get_dim_names() const =0; - /// Determine whether specified dimension exists in this grid. + /// Determine whether specified dimension exists in this var. /** @returns `true` if dimension exists (including step-dimension), `false` otherwise. @@ -215,9 +219,9 @@ namespace yask { virtual bool is_dim_used(const std::string& dim) const =0; - /// Determine whether this grid is *not* automatically resized based on the solution. + /// Determine whether this var is *not* automatically resized based on the solution. /** - @returns `true` if this grid was created via yk_solution::new_fixed_size_grid() + @returns `true` if this var was created via yk_solution::new_fixed_size_var() or `false` otherwise. */ virtual bool is_fixed_size() const =0; @@ -225,7 +229,7 @@ namespace yask { /// Get the first valid index in this rank in the specified dimension. /** This is a convenience function that provides the first possible - index in any grid dimension regardless of the dimension type. + index in any var dimension regardless of the dimension type. It is equivalent to get_first_rank_alloc_index(dim) when `dim` is a domain dimension, get_first_misc_index(dim) @@ -243,7 +247,7 @@ namespace yask { /// Get the last index in this rank in the specified dimension. /** This is a convenience function that provides the last possible - index in any grid dimension regardless of the dimension type. + index in any var dimension regardless of the dimension type. It is equivalent to get_last_rank_alloc_index(dim) when `dim` is a domain dimension, get_last_misc_index(dim) @@ -261,7 +265,7 @@ namespace yask { /// Get the number of elements allocated in the specified dimension. /** For the domain dimensions, this includes the rank-domain and padding sizes. - See the "Detailed Description" for \ref yk_grid for information on grid sizes. + See the "Detailed Description" for \ref yk_var for information on var sizes. For any dimension `dim`, `get_alloc_size(dim) == get_last_local_index(dim) - get_first_local_index(dim) + 1`; @returns allocation in number of elements (not bytes). @@ -273,24 +277,24 @@ namespace yask { /// Get the first valid index in the step dimension. /** - The valid step indices in a grid are updated by calling yk_solution::run_solution() + The valid step indices in a var are updated by calling yk_solution::run_solution() or one of the element-setting API functions. Equivalient to get_first_local_index(dim), where `dim` is the step dimension. @returns the first index in the step dimension that can be used in one of the element-getting API functions. - This grid must use the step index. + This var must use the step index. */ virtual idx_t get_first_valid_step_index() const =0; /// Get the last valid index in the step dimension. /** - The valid step indices in a grid are updated by calling yk_solution::run_solution() + The valid step indices in a var are updated by calling yk_solution::run_solution() or one of the element-setting API functions. Equivalient to get_last_local_index(dim), where `dim` is the step dimension. @returns the last index in the step dimension that can be used in one of the element-getting API functions. - This grid must use the step index. + This var must use the step index. */ virtual idx_t get_last_valid_step_index() const =0; @@ -299,7 +303,7 @@ namespace yask { /** @returns The same value as yk_solution::get_rank_domain_size() if is_fixed_size() returns `false` or the fixed sized provided via - yk_solution::new_fixed_size_grid() otherwise. + yk_solution::new_fixed_size_var() otherwise. */ virtual idx_t get_rank_domain_size(const std::string& dim @@ -324,7 +328,7 @@ namespace yask { because prepare_solution() assigns this rank's position in the problem domain. @returns The same value as yk_solution::get_last_rank_domain_index() if is_fixed_size() returns `false` or one less than the fixed sized provided via - yk_solution::new_fixed_size_grid() otherwise. + yk_solution::new_fixed_size_var() otherwise. */ virtual idx_t get_last_rank_domain_index(const std::string& dim @@ -358,7 +362,7 @@ namespace yask { @note This function should be called only *after* calling prepare_solution() because prepare_solution() assigns this rank's position in the problem domain. @returns The first index of left halo in this rank or - the same value as yk_grid::get_first_rank_domain_index() + the same value as yk_var::get_first_rank_domain_index() if the left halo has zero size. */ virtual idx_t @@ -371,7 +375,7 @@ namespace yask { @note This function should be called only *after* calling prepare_solution() because prepare_solution() assigns this rank's position in the problem domain. @returns The last index of right halo in this rank or - the same value as yk_grid::get_last_rank_domain_index() + the same value as yk_var::get_last_rank_domain_index() if the right halo has zero size. */ virtual idx_t @@ -455,15 +459,15 @@ namespace yask { /// Determine whether the given indices refer to an accessible element in this rank. /** - Provide indices in a list in the same order returned by get_dim_names() for this grid. + Provide indices in a list in the same order returned by get_dim_names() for this var. Domain index values are relative to the *overall* problem domain. @returns `true` if index values fall within the range returned by get_first_local_index(dim) and get_last_local_index(dim) for each dimension - `dim` in the grid; `false` otherwise. + `dim` in the var; `false` otherwise. */ virtual bool are_indices_local(const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each var dimension. */ ) const =0; #ifndef SWIG /// Determine whether the given indices refer to an accessible element in this rank. @@ -472,45 +476,45 @@ namespace yask { */ virtual bool are_indices_local(const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each var dimension. */ ) const =0; #endif - /// Read the value of one element in this grid. + /// Read the value of one element in this var. /** Provide indices in a list in the same order returned by get_dim_names(). Indices are relative to the *overall* problem domain. Index values must fall between the values returned by get_first_local_index() and get_last_local_index(), inclusive, - for each dimension in the grid. - @returns value in grid at given indices. + for each dimension in the var. + @returns value in var at given indices. */ virtual double get_element(const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each var dimension. */ ) const =0; #ifndef SWIG - /// Read the value of one element in this grid. + /// Read the value of one element in this var. /** See get_element(). - @returns value in grid at given indices. + @returns value in var at given indices. */ virtual double get_element(const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each var dimension. */ ) const =0; #endif - /// Set the value of one element in this grid. + /// Set the value of one element in this var. /** Provide indices in a list in the same order returned by get_dim_names(). Indices are relative to the *overall* problem domain. - If the grid uses the step dimension, the value of the step index - will be used to update the current valid step indices in the grid. + If the var uses the step dimension, the value of the step index + will be used to update the current valid step indices in the var. If `strict_indices` is `false` and any non-step index values are invalid as defined by are_indices_local(), the API will have no effect and return zero (0). If `strict_indices` is `true` and any non-step index values are invalid, the API will throw an exception. - If storage has not been allocated for this grid, this will have no effect + If storage has not been allocated for this var, this will have no effect and return zero (0) if `strict_indices` is `false`, or it will throw an exception if `strict_indices` is `true`. @note The parameter value is a double-precision floating-point value, but @@ -520,31 +524,31 @@ namespace yask { are valid and zero (0) if they are not. */ virtual idx_t - set_element(double val /**< [in] Element in grid will be set to this. */, + set_element(double val /**< [in] Element in var will be set to this. */, const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */, + /**< [in] List of indices, one for each var dimension. */, bool strict_indices = true /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) =0; + in no change to var. */ ) =0; #ifndef SWIG - /// Set the value of one element in this grid. + /// Set the value of one element in this var. /** See set_element(). @returns Number of elements set. */ virtual idx_t - set_element(double val /**< [in] Element in grid will be set to this. */, + set_element(double val /**< [in] Element in var will be set to this. */, const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */, + /**< [in] List of indices, one for each var dimension. */, bool strict_indices = true /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) =0; + in no change to var. */ ) =0; #endif - /// Copy elements within specified subset of this grid into a buffer. + /// Copy elements within specified subset of this var into a buffer. /** Reads all elements from `first_indices` to `last_indices` in each dimension and writes them to consecutive memory locations in the buffer. @@ -566,11 +570,11 @@ namespace yask { get_elements_in_slice(void* buffer_ptr /**< [out] Pointer to buffer where values will be written. */, const std::vector& first_indices - /**< [in] List of initial indices, one for each grid dimension. */, + /**< [in] List of initial indices, one for each var dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */ ) const =0; + /**< [in] List of final indices, one for each var dimension. */ ) const =0; - /// Atomically add to the value of one grid element. + /// Atomically add to the value of one var element. /** Provide indices in a list in the same order returned by get_dim_names(). Indices are relative to the *overall* problem domain. @@ -578,7 +582,7 @@ namespace yask { get_first_local_index() and get_last_local_index(), inclusive. Updates are OpenMP atomic, meaning that this function can be called by several OpenMP threads without causing a race condition. - If storage has not been allocated for this grid, this will have no effect + If storage has not been allocated for this var, this will have no effect and return zero (0) if `strict_indices` is `false`, or it will throw an exception if `strict_indices` is `true`. @note The parameter value is a double-precision floating-point value, but @@ -587,31 +591,31 @@ namespace yask { @returns Number of elements updated. */ virtual idx_t - add_to_element(double val /**< [in] This value will be added to element in grid. */, + add_to_element(double val /**< [in] This value will be added to element in var. */, const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */, + /**< [in] List of indices, one for each var dimension. */, bool strict_indices = true /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) =0; + in no change to var. */ ) =0; #ifndef SWIG - /// Atomically add to the value of one grid element. + /// Atomically add to the value of one var element. /** See add_to_element(). @returns Number of elements set. */ virtual idx_t - add_to_element(double val /**< [in] This value will be added to element in grid. */, + add_to_element(double val /**< [in] This value will be added to element in var. */, const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */, + /**< [in] List of indices, one for each var dimension. */, bool strict_indices = true /**< [in] If true, indices must be within domain or padding. If false, indices outside of domain and padding result - in no change to grid. */ ) =0; + in no change to var. */ ) =0; #endif - /// Initialize all grid elements to the same value. + /// Initialize all var elements to the same value. /** Sets all allocated elements, including those in the domain and padding area to the same specified value. @@ -623,7 +627,7 @@ namespace yask { virtual void set_all_elements_same(double val /**< [in] All elements will be set to this. */ ) =0; - /// Initialize grid elements within specified subset of the grid to the same value. + /// Initialize var elements within specified subset of the var to the same value. /** Sets all elements from `first_indices` to `last_indices` in each dimension to the specified value. @@ -632,7 +636,7 @@ namespace yask { Index values must fall between the values returned by get_first_local_index() and get_last_local_index(), inclusive, if `strict_indices` is `true`. - If storage has not been allocated for this grid, this will have no effect + If storage has not been allocated for this var, this will have no effect and return zero (0) if `strict_indices` is `false`, or it will throw an exception if `strict_indices` is `true`. @returns Number of elements set. @@ -640,15 +644,15 @@ namespace yask { virtual idx_t set_elements_in_slice_same(double val /**< [in] All elements in the slice will be set to this. */, const std::vector& first_indices - /**< [in] List of initial indices, one for each grid dimension. */, + /**< [in] List of initial indices, one for each var dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */, + /**< [in] List of final indices, one for each var dimension. */, bool strict_indices = true /**< [in] If true, indices must be within domain or padding. - If false, only elements within the allocation of this grid + If false, only elements within the allocation of this var will be set, and elements outside will be ignored. */ ) =0; - /// Set grid elements within specified subset of the grid from values in a buffer. + /// Set var elements within specified subset of the var from values in a buffer. /** Reads elements from consecutive memory locations, starting at `buffer_ptr` @@ -664,7 +668,7 @@ namespace yask { Indices are relative to the *overall* problem domain. Index values must fall between the values returned by get_first_local_index() and get_last_local_index(), inclusive. - If storage has not been allocated for this grid, this will + If storage has not been allocated for this var, this will throw an exception. @returns Number of elements written. */ @@ -672,62 +676,62 @@ namespace yask { set_elements_in_slice(const void* buffer_ptr /**< [out] Pointer to buffer where values will be read. */, const std::vector& first_indices - /**< [in] List of initial indices, one for each grid dimension. */, + /**< [in] List of initial indices, one for each var dimension. */, const std::vector& last_indices - /**< [in] List of final indices, one for each grid dimension. */ ) =0; + /**< [in] List of final indices, one for each var dimension. */ ) =0; #ifdef COPY_SLICE_IMPLEMENTED - /// Copy specified grid elements from another (source) grid into this (target) grid. + /// Copy specified var elements from another (source) var into this (target) var. /** - Reads elements starting at `first_source_indices` in the `source` grid and + Reads elements starting at `first_source_indices` in the `source` var and writes them starting at `first_target_indices` and ending - at `last_target_indices` in this grid. + at `last_target_indices` in this var. The size of the copy is determined by the differences bewteen `first_target_indices` and `last_target_indices` in each dimension. Provide indices in the same order returned by get_dim_names(). Indices are relative to the *overall* problem domain. Index values must fall between the values returned by get_first_local_index() and get_last_local_index(), inclusive, for - each dimension in both grids. + each dimension in both vars. @returns Number of elements copied. */ virtual idx_t - set_elements_in_slice(const yk_grid_ptr source - /**< [in] Grid from which elements will be read. */, + set_elements_in_slice(const yk_var_ptr source + /**< [in] Var from which elements will be read. */, const std::vector& first_source_indices - /**< [in] List of starting indices in the source grid, - one for each grid dimension. */, + /**< [in] List of starting indices in the source var, + one for each var dimension. */, const std::vector& first_target_indices - /**< [in] List of starting indices in this (target) grid, - one for each grid dimension. */, + /**< [in] List of starting indices in this (target) var, + one for each var dimension. */, const std::vector& last_target_indices - /**< [in] List of final indices in this (target) grid, - one for each grid dimension. */ ) =0; + /**< [in] List of final indices in this (target) var, + one for each var dimension. */ ) =0; #endif /// Format the indices for pretty-printing. /** Provide indices in a list in the same order returned by get_dim_names(). - @returns A string containing the grid name and the index values. + @returns A string containing the var name and the index values. */ virtual std::string format_indices(const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each var dimension. */ ) const =0; #ifndef SWIG /// Format the indices for pretty-printing. /** See format_indices(). - @returns A string containing the grid name and the index values. + @returns A string containing the var name and the index values. */ virtual std::string format_indices(const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */ ) const =0; + /**< [in] List of indices, one for each var dimension. */ ) const =0; #endif - /* Advanced APIs for yk_grid found below are not needed for most applications. */ + /* Advanced APIs for yk_var found below are not needed for most applications. */ - /// **[Advanced]** Get whether the allocation of the step dimension of this grid can be modified at run-time. + /// **[Advanced]** Get whether the allocation of the step dimension of this var can be modified at run-time. /** See set_alloc_size(). */ @@ -736,7 +740,7 @@ namespace yask { /// **[Advanced]** Set the default preferred NUMA node on which to allocate data. /** - This value is used when allocating data for this grid. + This value is used when allocating data for this var. Thus, the desired NUMA policy must be set before calling alloc_data() or yk_solution::prepare_solution(). @returns `true` if NUMA preference was set; @@ -749,21 +753,21 @@ namespace yask { /// **[Advanced]** Get the default preferred NUMA node on which to allocate data. /** - @returns Current setting of preferred NUMA node for this grid. + @returns Current setting of preferred NUMA node for this var. */ virtual int get_numa_preferred() const =0; /// **[Advanced]** Set the minimum left padding in the specified dimension. /** - This sets the minimum number of elements in this grid in the left padding area. + This sets the minimum number of elements in this var in the left padding area. This padding area can be used for required halo areas. This function may be useful in the unusual case where the final halo size is unknown when the storage is allocated. - Call get_left_pad_size() to determine the actual padding size for the grid. + Call get_left_pad_size() to determine the actual padding size for the var. See additional behavior related to setting pad size under yk_solution::set_min_pad_size(). - See the "Detailed Description" for \ref yk_grid for information on grid sizes. + See the "Detailed Description" for \ref yk_var for information on var sizes. */ virtual void set_left_min_pad_size(const std::string& dim @@ -776,14 +780,14 @@ namespace yask { /// **[Advanced]** Set the minimum right padding in the specified dimension. /** - This sets the minimum number of elements in this grid in the right padding area. + This sets the minimum number of elements in this var in the right padding area. This padding area can be used for required halo areas. This function may be useful in the unusual case where the final halo size is unknown when the storage is allocated. - Call get_right_pad_size() to determine the actual padding size for the grid. + Call get_right_pad_size() to determine the actual padding size for the var. See additional behavior related to setting pad size under yk_solution::set_min_pad_size(). - See the "Detailed Description" for \ref yk_grid for information on grid sizes. + See the "Detailed Description" for \ref yk_var for information on var sizes. */ virtual void set_right_min_pad_size(const std::string& dim @@ -859,34 +863,34 @@ namespace yask { /// **[Advanced]** Set the number of elements to allocate in the specified dimension. /** Setting an allocation is only allowed in the following cases. - Grids created via yc_solution::new_grid() are defined at YASK - compile time, and grids created via \ref yk_solution methods + Vars created via yc_solution::new_var() are defined at YASK + compile time, and vars created via \ref yk_solution methods are defined at YASK kernel run time. - Grid creation time | Grid creation method | Step dim | Domain dim | Misc dim | + Var creation time | Var creation method | Step dim | Domain dim | Misc dim | -------------------|----------------------|----------|------------|----------| - Compile-time | yc_solution::new_grid() + yc_grid::set_dynamic_step_alloc (false) [1] | No | No | Yes [2] | - Compile-time | yc_solution::new_grid() + yc_grid::set_dynamic_step_alloc (true) [1] | Yes | No | Yes [2] | - Run-time | yk_solution::new_grid() | Yes | No | Yes | - Run-time | yk_solution::new_fixed_size_grid() [3] | Yes | Yes | Yes | + Compile-time | yc_solution::new_var() + yc_var::set_dynamic_step_alloc (false) [1] | No | No | Yes [2] | + Compile-time | yc_solution::new_var() + yc_var::set_dynamic_step_alloc (true) [1] | Yes | No | Yes [2] | + Run-time | yk_solution::new_var() | Yes | No | Yes | + Run-time | yk_solution::new_fixed_size_var() [3] | Yes | Yes | Yes | - @note [1] By default, grid variables created via yc_solution::new_grid() + @note [1] By default, variables created via yc_solution::new_var() do _not_ allow dynamic step allocation. - @note [2] Misc dim allocations cannot be changed for compile-time grids if the YASK + @note [2] Misc dim allocations cannot be changed for compile-time vars if the YASK compiler was run with the "-interleave-misc" option. - @note [3] The term "fixed" in yk_solution::new_fixed_size_grid() means that the + @note [3] The term "fixed" in yk_solution::new_fixed_size_var() means that the domain size will not change automatically when its solution domain size changes. It does not mean that the sizes cannot be changed via the APIs--quite the opposite. The allocation size cannot be changed after data storage - has been allocated for this grid. + has been allocated for this var. */ virtual void set_alloc_size(const std::string& dim /**< [in] Name of dimension to set. Must be a domain dimension or - a misc dimension for user-created grids. */, + a misc dimension for user-created vars. */, idx_t size /**< [in] Number of elements to allocate. */ ) =0; /// **[Advanced]** Set the first index of a specified miscellaneous dimension. @@ -903,10 +907,10 @@ namespace yask { idx_t idx /**< [in] New value for first index. May be negative. */ ) =0; - /// **[Advanced]** Get the first accessible index in this grid in this rank in the specified domain dimension. + /// **[Advanced]** Get the first accessible index in this var in this rank in the specified domain dimension. /** Equivalent to get_first_local_index(dim), where `dim` is a domain dimension. - @returns First valid index in this grid. + @returns First valid index in this var. */ virtual idx_t get_first_rank_alloc_index(const std::string& dim @@ -914,10 +918,10 @@ namespace yask { Must be one of the names from yk_solution::get_domain_dim_names(). */ ) const =0; - /// **[Advanced]** Get the last accessible index in this grid in this rank in the specified domain dimension. + /// **[Advanced]** Get the last accessible index in this var in this rank in the specified domain dimension. /** Equivalent to get_last_local_index(dim), where `dim` is a domain dimension. - @returns Last valid index in this grid. + @returns Last valid index in this var. */ virtual idx_t get_last_rank_alloc_index(const std::string& dim @@ -948,25 +952,25 @@ namespace yask { virtual idx_t get_num_storage_elements() const =0; - /// **[Advanced]** Explicitly allocate data-storage memory for this grid. + /// **[Advanced]** Explicitly allocate data-storage memory for this var. /** Amount of allocation is calculated based on domain, padding, and step-dimension allocation sizes. Any pre-existing storage will be released before allocation as via release_storage(). - See allocation options in the "Detailed Description" for \ref yk_grid. + See allocation options in the "Detailed Description" for \ref yk_var. */ virtual void alloc_storage() =0; - /// **[Advanced]** Explicitly release any allocated data-storage for this grid. + /// **[Advanced]** Explicitly release any allocated data-storage for this var. /** This will release storage allocated via any of the options - described in the "Detailed Description" for \ref yk_grid. + described in the "Detailed Description" for \ref yk_var. */ virtual void release_storage() =0; - /// **[Advanced]** Determines whether storage layout is the same as another grid. + /// **[Advanced]** Determines whether storage layout is the same as another var. /** In order for the storage layout to be identical, the following must be the same: @@ -980,42 +984,42 @@ namespace yask { The following do not have to be identical: - Halo size. - @returns `true` if storage for this grid has the same layout as + @returns `true` if storage for this var has the same layout as `other` or `false` otherwise. */ virtual bool - is_storage_layout_identical(const yk_grid_ptr other) const =0; + is_storage_layout_identical(const yk_var_ptr other) const =0; - /// **[Advanced]** Merge this grid with another grid. + /// **[Advanced]** Merge this var with another var. /** - After calling this API, this grid - grid will effectively become another reference to the `source` grid. - Any subsequent API applied to this grid or the - `source` grid will access the same data and/or + After calling this API, this var + var will effectively become another reference to the `source` var. + Any subsequent API applied to this var or the + `source` var will access the same data and/or effect the same changes. Storage implications: - - Any pre-existing storage in this grid will be released. - - The storage of the this grid will become - allocated or unallocated depending on that of the source grid. - - After fusing, calling release_storage() on this grid - or the `source` grid will apply to both. + - Any pre-existing storage in this var will be released. + - The storage of the this var will become + allocated or unallocated depending on that of the source var. + - After fusing, calling release_storage() on this var + or the `source` var will apply to both. To ensure that the kernels created by the YASK compiler work - properly, if this grid is used in a kernel, the dimensions and - fold-lengths of the `source` grid must be identical or an - exception will the thrown. If the `source` grid is a fixed-size - grid, the storage, local domain sizes, halos, etc. of the grid + properly, if this var is used in a kernel, the dimensions and + fold-lengths of the `source` var must be identical or an + exception will the thrown. If the `source` var is a fixed-size + var, the storage, local domain sizes, halos, etc. of the var must be set to be compatible with the solution before calling yk_solution::prepare_solution(). Otherwise, yk_solution::prepare_solution() will throw an exception. - See allocation options and more information about grid sizes - in the "Detailed Description" for \ref yk_grid. + See allocation options and more information about var sizes + in the "Detailed Description" for \ref yk_var. */ virtual void - fuse_grids(yk_grid_ptr source - /**< [in] Grid to be merged with this grid. */) =0; + fuse_vars(yk_var_ptr source + /**< [in] Var to be merged with this var. */) =0; /// **[Advanced]** Get pointer to raw data storage buffer. /** @@ -1027,18 +1031,18 @@ namespace yask { - A call to set_all_elements_same() will initialize all elements within get_num_storage_bytes() bytes from the beginning of the buffer. - If is_storage_layout_identical() returns `true` between this - and some other grid, any given element index applied to both grids + and some other var, any given element index applied to both vars will refer to an element at the same offset into their respective data buffers. Thus, - You can perform element-wise unary mathematical operations on - all elements of a grid via its raw buffer, e.g., add some constant + all elements of a var via its raw buffer, e.g., add some constant value to all elements. - - If the layouts of two grids are identical, you can use their - raw buffers to copy or compare the grid contents for equality or + - If the layouts of two vars are identical, you can use their + raw buffers to copy or compare the var contents for equality or perform element-wise binary mathematical operations on them, - e.g., add all elements from one grid to another. + e.g., add all elements from one var to another. The following assumptions are not safe: - Any expectations regarding the relationship between an element @@ -1056,7 +1060,7 @@ namespace yask { */ virtual void* get_raw_storage_buffer() =0; - /* Deprecated APIs for yk_grid found below should be avoided. + /* Deprecated APIs for yk_var found below should be avoided. Use the more explicit form found in the documentation. */ /// **[Deprecated]** Get the left halo size in the specified dimension. @@ -1096,7 +1100,7 @@ namespace yask { /// **[Deprecated]** Use are_indices_local() instead. virtual bool is_element_allocated(const std::vector& indices - /**< [in] List of indices, one for each grid dimension. */ ) const { + /**< [in] List of indices, one for each var dimension. */ ) const { return are_indices_local(indices); } @@ -1104,12 +1108,21 @@ namespace yask { /// **[Deprecated]** Use are_indices_local() instead. virtual bool is_element_allocated(const std::initializer_list& indices - /**< [in] List of indices, one for each grid dimension. */ ) const { + /**< [in] List of indices, one for each var dimension. */ ) const { return are_indices_local(indices); } #endif - }; + /// **[Deprecated]** Use fuse_vars(). + virtual void + fuse_grids(yk_var_ptr source) { + fuse_vars(source); + } + + }; // yk_var. + /// **[Deprecated]** Use yk_var. + typedef yk_var yk_grid; + /** @}*/ } // namespace yask. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 7c4062fb..7bf1a769 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -49,9 +49,9 @@ namespace yask { /// Shared pointer to \ref yc_solution typedef std::shared_ptr yc_solution_ptr; - class yc_grid; - /// Pointer to \ref yc_grid - typedef yc_grid* yc_grid_ptr; + class yc_var; + /// Pointer to \ref yc_var + typedef yc_var* yc_var_ptr; // Forward declarations of expression nodes and their pointers. @@ -75,9 +75,9 @@ namespace yask { /// Shared pointer to \ref yc_equation_node typedef std::shared_ptr yc_equation_node_ptr; - class yc_grid_point_node; - /// Shared pointer to \ref yc_grid_point_node - typedef std::shared_ptr yc_grid_point_node_ptr; + class yc_var_point_node; + /// Shared pointer to \ref yc_var_point_node + typedef std::shared_ptr yc_var_point_node_ptr; /** @}*/ } @@ -105,7 +105,7 @@ namespace yask { /// Create a stencil solution. /** - A stencil solution contains all the grids and equations. + A stencil solution contains all the vars and equations. @returns Pointer to new solution object. */ virtual yc_solution_ptr @@ -115,7 +115,7 @@ namespace yask { /// Stencil solution. /** - Objects of this type contain all the grids and equations + Objects of this type contain all the vars and equations that comprise a solution. Must be created via yc_factory::new_solution(). */ @@ -173,20 +173,22 @@ namespace yask { set_element_bytes(int nbytes /**< [in] Number of bytes in a FP number. Should be 4 or 8. */ ) =0; - /// Create an n-dimensional grid variable in the solution. + /// Create an n-dimensional variable in the solution. /** - "Grid" is a generic term for any n-dimensional variable. A 0-dim - grid is a scalar, a 1-dim grid is a vector, a 2-dim grid is a + "Var" is a generic term for any n-dimensional variable. A 0-dim + var is a scalar, a 1-dim var is a vector, a 2-dim var is a matrix, etc. - At least one grid must be defined with a step-index - node, and it must be the first dimension listed. - If more than one grid uses a step-index node, the step-indices - must have the same name across all such grids. + The dimensions of a variable are defined by providing a list + of indices created via yc_node_factory::new_step_index(), + yc_node_factory::new_domain_index(), and/or + yc_node_factory::new_misc_index(). + When a step index is used, it must be the first index. + If more than one var uses a step-index, the step-indices + must have the same name. For example, you cannot have + one var with step-index "t" and one with step-index "time". - At least one grid must be defined with at least one domain-index node. - - Example code to create a solution with a grid equation: + Example code to create a solution with an equation for a variable named "A": ~~~{.cpp} yc_factory ycfac; yc_node_factory nfac; @@ -194,95 +196,97 @@ namespace yask { auto t = nfac.new_step_index("t"); auto x = nfac.new_domain_index("x"); auto y = nfac.new_domain_index("y"); - auto a = ycfac.new_grid("A", { t, x, y }); - a->new_grid_point({t+1, x, y}) EQUALS (a->new_grid_point({t, x, y}) + - a->new_grid_point({t, x+1, y}) + - a->new_grid_point({t, x, y+1})) * (1.0/3.0); + auto a = ycfac.new_var("A", { t, x, y }); + a->new_var_point({t+1, x, y}) EQUALS (a->new_var_point({t, x, y}) + + a->new_var_point({t, x+1, y}) + + a->new_var_point({t, x, y+1})) * (1.0/3.0); ~~~ - @returns Pointer to the new \ref yc_grid object. + @returns Pointer to the new \ref yc_var object. */ - virtual yc_grid_ptr - new_grid(const std::string& name - /**< [in] Name of the new grid; must be a valid C++ - identifier and unique across grids. */, + virtual yc_var_ptr + new_var(const std::string& name + /**< [in] Name of the new var; must be a valid C++ + identifier and unique across vars. */, const std::vector& dims - /**< [in] Dimensions of the grid. + /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */ ) =0; #ifndef SWIG - /// Create an n-dimensional grid variable in the solution. + /// Create an n-dimensional variable in the solution. /** C++ initializer-list version with same semantics as - the vector version of new_grid(). + the vector version of new_var(). @note This version is not available (or needed) in the Python API. - @returns Pointer to the new \ref yc_grid object. + @returns Pointer to the new \ref yc_var object. */ - virtual yc_grid_ptr - new_grid(const std::string& name /**< [in] Name of the new grid; must be + virtual yc_var_ptr + new_var(const std::string& name /**< [in] Name of the new var; must be a valid C++ identifier and unique - across grids. */, + across vars. */, const std::initializer_list& dims - /**< [in] Dimensions of the grid. + /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */ ) =0; #endif - /// Create an n-dimensional scratch-grid variable in the solution. + /// Create an n-dimensional scratch variable in the solution. /** - A scratch grid is a temporary variable used in the - definition of a non-scratch grid. - - Scratch grids are not accessible via kernel APIs. + A scratch variable is a temporary variable used as an + intermediate value in an equation. + - Scratch vars are not accessible via kernel APIs. Thus, they cannot be programmatically read from or written to. - - Scratch grid values must be defined from equations ultimately - referencing only non-scratch grid values, optionally referencing - other intermediate scratch-grids. - - Scratch grids cannot use the step-index as a dimension. + - Scratch var values must be defined from equations ultimately + referencing only non-scratch var values, optionally referencing + other intermediate scratch-vars. + - Scratch vars cannot use the step-index as a dimension. See `TestScratchStencil*` classes in `src/stencils/SimpleTestStencils.hpp` for usage examples. - @returns Pointer to the new \ref yc_grid object. + @returns Pointer to the new \ref yc_var object. */ - virtual yc_grid_ptr - new_scratch_grid(const std::string& name - /**< [in] Name of the new grid; must be a valid C++ - identifier and unique across grids. */, + virtual yc_var_ptr + new_scratch_var(const std::string& name + /**< [in] Name of the new var; must be a valid C++ + identifier and unique across vars. */, const std::vector& dims - /**< [in] Dimensions of the grid. + /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */ ) =0; #ifndef SWIG - /// Create an n-dimensional scratch-grid variable in the solution. + /// Create an n-dimensional scratch variable in the solution. /** C++ initializer-list version with same semantics as - the vector version of new_scratch_grid(). + the vector version of new_scratch_var(). @note This version is not available (or needed) in the Python API. - @returns Pointer to the new \ref yc_grid object. + @returns Pointer to the new \ref yc_var object. */ - virtual yc_grid_ptr - new_scratch_grid(const std::string& name - /**< [in] Name of the new grid; must be + virtual yc_var_ptr + new_scratch_var(const std::string& name + /**< [in] Name of the new var; must be a valid C++ identifier and unique - across grids. */, + across vars. */, const std::initializer_list& dims - /**< [in] Dimensions of the grid. + /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */ ) =0; #endif - /// Get the number of grids in the solution. - /** @returns Number of grids that have been created via new_grid(). */ + /// Get the number of vars in the solution. + /** + @returns Number of vars that have been created via new_var() or + new_scratch_var(). */ virtual int - get_num_grids() const =0; + get_num_vars() const =0; - /// Get all the grids in the solution. - /** @returns Vector containing pointer to all grids. */ - virtual std::vector - get_grids() =0; + /// Get all the vars in the solution. + /** @returns Vector containing pointer to all vars. */ + virtual std::vector + get_vars() =0; - /// Get the specified grid. - /** @returns Pointer to the specified grid or null pointer if it does not exist. */ - virtual yc_grid_ptr - get_grid(const std::string& name /**< [in] Name of the grid. */ ) =0; + /// Get the specified var. + /** @returns Pointer to the specified var or null pointer if it does not exist. */ + virtual yc_var_ptr + get_var(const std::string& name /**< [in] Name of the var. */ ) =0; /// Set the vectorization length in given dimension. /** For YASK-code generation, the product of the fold lengths should @@ -351,7 +355,7 @@ namespace yask { avx512 | YASK stencil classes for CORE AVX-512 & MIC AVX-512 ISAs. knc | YASK stencil classes for Knights Corner ISA. dot | DOT-language description. - dot-lite| DOT-language description of grid accesses only. + dot-lite| DOT-language description of var accesses only. pseudo | Human-readable pseudo-code (for debug). pseudo-long | Human-readable pseudo-code with intermediate variables. @@ -371,14 +375,14 @@ namespace yask { /// **[Advanced]** Explicitly list the domain dimensions in the solution. /** - In addition, domain dimension(s) are added when new_grid() or - new_scratch_grid() is called with one or more domain dimensions. + In addition, domain dimension(s) are added when new_var(), + new_scratch_var() is called with one or more domain dimensions. Either way, the last unique domain dimension specified will become the 'inner' or 'unit-stride' dimension in memory layouts. Thus, this option can be used to override the default layout order. It also allows specification of the domain dimensions in the unusual case where a solution is defined without any - grids containing all of the domain dimensions. + vars containing all of the domain dimensions. */ virtual void set_domain_dims(const std::vector& dims @@ -388,7 +392,7 @@ namespace yask { /// **[Advanced]** Explicitly list the domain dimensions in the solution. /** C++ initializer-list version with same semantics as - the vector version of new_grid(). + the vector version of new_var(). @note This version is not available (or needed) in the Python API. */ virtual void @@ -398,11 +402,11 @@ namespace yask { /// **[Advanced]** Explicitly identify the step dimension in the solution. /** - By default, the step dimension is defined when new_grid() or - new_scratch_grid() is called with the step dimension. - This allows specification of the step dimension in the + By default, the step dimension is defined when new_var() + is called with a step index. + This API allows specification of the step dimension in the unusual case where a solution is defined without any - grids containing the step dimension. + vars containing the step dimension. */ virtual void set_step_dim(const yc_index_node_ptr dim @@ -480,10 +484,10 @@ namespace yask { about a circular dependency. This exception may not be thrown until format() is called. - - If using scratch grids, dependencies among scratch grids - and between scratch-grid equations and non-scratch-grid - equations should also be added. Each scratch grid equation - should ultimately depend on non-scratch-grid values. + - If using scratch vars, dependencies among scratch vars + and between scratch equations and non-scratch + equations should also be added. Each scratch equation + should ultimately depend on non-scratch values. - This function can be used in cooperation with or instead of the built-in automatic dependency checker. @@ -511,112 +515,165 @@ namespace yask { */ virtual void clear_dependencies() =0; + + /// **[Deprecated]** Use new_var(). + virtual yc_var_ptr + new_grid(const std::string& name, + const std::vector& dims) { + return new_var(name, dims); + } + +#ifndef SWIG + /// **[Deprecated]** Use new_var(). + virtual yc_var_ptr + new_grid(const std::string& name, + const std::initializer_list& dims) { + return new_var(name, dims); + } +#endif + + /// **[Deprecated]** Use new_scratch_var(). + virtual yc_var_ptr + new_scratch_grid(const std::string& name, + const std::vector& dims) { + return new_scratch_var(name, dims); + } + +#ifndef SWIG + /// **[Deprecated]** Use new_scratch_var(). + virtual yc_var_ptr + new_scratch_grid(const std::string& name, + const std::initializer_list& dims) { + return new_scratch_var(name, dims); + } +#endif + + /// **[Deprecated]** Use get_num_vars(). + virtual int + get_num_grids() const { + return get_num_vars(); + } + + /// **[Deprecated]** Use get_vars(). + virtual std::vector + get_grids() { + return get_vars(); + } + + /// **[Deprecated]** Use get_var(). + virtual yc_var_ptr + get_grid(const std::string& name) { + return get_var(name); + } }; /// A compile-time data variable. - /** "Grid" is a generic term for any n-dimensional array. A 0-dim grid - is a scalar, a 1-dim grid is an array, etc. - A compile-time grid is a variable used for constructing equations. + /** "Var" is a generic term for any n-dimensional variable. A 0-dim var + is a scalar, a 1-dim var is an array, etc. + A compile-time variable is used for constructing stencil equations. It does not contain any data. - Data is only stored during run-time, using a \ref yk_grid. + Data is only stored during run-time, using a \ref yk_var. - Created via yc_solution::new_grid() or implicitly via the \ref yc_grid_var constructor. + Created via yc_solution::new_var() or yc_solution::new_scratch_var() + or implicitly via the \ref yc_var_proxy constructor. */ - class yc_grid { + class yc_var { public: - virtual ~yc_grid() {} + virtual ~yc_var() {} - /// Get the name of the grid. - /** @returns String containing name provided via new_grid(). */ + /// Get the name of the var. + /** @returns String containing name provided via + yc_solution::new_var() or yc_solution::new_scratch_var(). */ virtual const std::string& get_name() const =0; /// Get the number of dimensions. - /** @returns Number of dimensions created via new_grid(). */ + /** @returns Number of dimensions created via + yc_solution::new_var() or yc_solution::new_scratch_var(). */ virtual int get_num_dims() const =0; - /// Get all the dimensions in this grid. + /// Get all the dimensions in this var. /** - Includes step dimension if it is a dimension of this grid. - May be different than values returned from yc_solution::get_domain_dim_names(). - @returns List of names of all the dimensions. + This is not necessarily a list of all the dimensions used + in the \ref yc_solution. + @returns List of names of all the dimensions used in this var. */ virtual std::vector get_dim_names() const =0; - /// Create a reference to a point in this grid. + /// Create a reference to a point in this var. /** Each expression in `index_exprs` describes how to access - an element in the corresponding dimension of the grid. + an element in the corresponding dimension of the var. - @returns Pointer to AST node used to read from or write to point in grid. */ - virtual yc_grid_point_node_ptr - new_grid_point(const std::vector& index_exprs + @returns Pointer to AST node used to read from or write to point in var. */ + virtual yc_var_point_node_ptr + new_var_point(const std::vector& index_exprs /**< [in] Index expressions. These must appear in the same order as when the - grid was created. */ ) =0; + var was created. */ ) =0; #ifndef SWIG - /// Create a reference to a point in this grid. + /// Create a reference to a point in this var. /** C++ initializer-list version with same semantics as - the vector version of new_grid_point(). + the vector version of new_var_point(). - See example code shown in yc_solution::new_grid(). + See example code shown in yc_solution::new_var(). @note This version is not available (or needed) in the Python API. - @returns Pointer to AST node used to read or write from point in grid. + @returns Pointer to AST node used to read or write from point in var. */ - virtual yc_grid_point_node_ptr - new_grid_point(const std::initializer_list& index_exprs) = 0; + virtual yc_var_point_node_ptr + new_var_point(const std::initializer_list& index_exprs) = 0; #endif - /// Create a reference to a point in this grid using relative offsets. + /// Create a reference to a point in this var using relative offsets. /** - A shorthand function for calling new_grid_point() when + A shorthand function for calling new_var_point() when all index expressions are constant offsets. Each offset refers to the dimensions defined when the - grid was created via stencil_solution::new_grid(). + var was created via yc_solution::new_var(). - Example: if `g = new_grid("data", {t, x, y})` with step-dimension `t` + Example: if `g = new_var("data", {t, x, y})` with step-dimension `t` and domain-dimensions `x` and `y`, - `g->new_relative_grid_point({1, -1, 0})` refers to the same point as - `g->new_grid_point({t + 1, x - 1, y})`. + `g->new_relative_var_point({1, -1, 0})` refers to the same point as + `g->new_var_point({t + 1, x - 1, y})`. @warning This convenience function can only be used when every - dimension of the grid is either the step dimension or a domain dimension. - If this is not the case, use new_grid_point(). - @returns Pointer to AST node used to read from or write to point in grid. */ - virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::vector& dim_offsets + dimension of the var is either the step dimension or a domain dimension. + If this is not the case, use new_var_point(). + @returns Pointer to AST node used to read from or write to point in var. */ + virtual yc_var_point_node_ptr + new_relative_var_point(const std::vector& dim_offsets /**< [in] offset from evaluation index in each dim. */ ) =0; #ifndef SWIG - /// Create a reference to a point in this grid using relative offsets. + /// Create a reference to a point in this var using relative offsets. /** C++ initializer-list version with same semantics as - the vector version of new_relative_grid_point(). + the vector version of new_relative_var_point(). @note This version is not available (or needed) in the Python API. - @returns Pointer to AST node used to read or write from point in grid. */ - virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::initializer_list& dim_offsets) = 0; + @returns Pointer to AST node used to read or write from point in var. */ + virtual yc_var_point_node_ptr + new_relative_var_point(const std::initializer_list& dim_offsets) = 0; #endif - /// **[Advanced]** Get whether the allocation of the step dimension of this grid can be modified at run-time. + /// **[Advanced]** Get whether the allocation of the step dimension of this var can be modified at run-time. /** - See yk_grid::set_alloc_size(). + See yk_var::set_alloc_size(). */ virtual bool is_dynamic_step_alloc() const =0; - /// **[Advanced]** Set whether the allocation of the step dimension of this grid can be modified at run-time. + /// **[Advanced]** Set whether the allocation of the step dimension of this var can be modified at run-time. /** - See yk_grid::set_alloc_size(). + See yk_var::set_alloc_size(). */ virtual void set_dynamic_step_alloc(bool is_dynamic /**< [in] `true` to enable or `false` to disable. */) =0; - /// **[Advanced]** Get the current allocation in the step dimension of this grid. + /// **[Advanced]** Get the current allocation in the step dimension of this var. /** If set_step_alloc_size() has been called, that setting will be returned. If set_step_alloc_size() has not been called, the default setting determined @@ -626,7 +683,7 @@ namespace yask { virtual idx_t get_step_alloc_size() const =0; - /// **[Advanced]** Set the current allocation in the step dimension of this grid. + /// **[Advanced]** Set the current allocation in the step dimension of this var. /** Override the default setting determined by the YASK compiler for allocation in the step dimension. @@ -636,17 +693,17 @@ namespace yask { /**< [in] Number of elements to allocate in the step dimension. */) =0; }; - /// A wrapper class around a \ref yc_grid pointer. + /// A wrapper class around a \ref yc_var pointer. /** - Using this class provides a syntactic alternative to calling yc_solution::new_grid() - (or yc_solution::new_scratch_grid()) followed by yc_grid::new_grid_point(). + Using this class provides a syntactic alternative to calling yc_solution::new_var() + (or yc_solution::new_scratch_var()) followed by yc_var::new_var_point(). - To use this wrapper class, construct an object of type \ref yc_grid_var by + To use this wrapper class, construct an object of type \ref yc_var_proxy by passing a \ref yc_solution pointer to it. - Then, expressions for points in the grid can be created with a more + Then, expressions for points in the var can be created with a more intuitive syntax. - Example code to create a solution with a grid equation: + Example code to create a solution with an equation for a variable named "A": ~~~{.cpp} yc_factory ycfac; yc_node_factory nfac; @@ -654,163 +711,163 @@ namespace yask { auto t = nfac.new_step_index("t"); auto x = nfac.new_domain_index("x"); auto y = nfac.new_domain_index("y"); - yc_grid_var a("A", my_soln, { t, x, y }); + yc_var_proxy a("A", my_soln, { t, x, y }); a({t+1, x, y}) EQUALS (a({t, x, y}) + a({t, x+1, y}) + a({t, x, y+1})) * (1.0/3.0); ~~~ - Compare to the example shown in yc_solution::new_grid(). + Compare to the example shown in yc_solution::new_var(). - *Scoping and lifetime:* Since the \ref yc_grid pointer in a \ref - yc_grid_var object is a shared pointer also owned by the \ref - yc_solution object used to construct the \ref yc_grid_var object, the - underlying grid will not be destroyed until both the \ref yc_grid_var + *Scoping and lifetime:* Since the \ref yc_var pointer in a \ref + yc_var_proxy object is a shared pointer also owned by the \ref + yc_solution object used to construct the \ref yc_var_proxy object, the + underlying var will not be destroyed until both the \ref yc_var_proxy object and the \ref yc_solution object are destroyed. - A \ref yc_grid_var object created from an existing \ref yc_grid + A \ref yc_var_proxy object created from an existing \ref yc_var object will have the same properties. */ - class yc_grid_var { + class yc_var_proxy { private: - yc_grid_ptr _grid; + yc_var_ptr _var; public: /// Contructor taking a vector of index vars. /** - A wrapper around yc_solution::new_grid() and - yc_solution::new_scratch_grid(). + A wrapper around yc_solution::new_var() and + yc_solution::new_scratch_var(). */ - yc_grid_var(const std::string& name - /**< [in] Name of the new grid; must be a valid C++ - identifier and unique across grids. */, + yc_var_proxy(const std::string& name + /**< [in] Name of the new var; must be a valid C++ + identifier and unique across vars. */, yc_solution_ptr soln - /**< [in] Pointer to solution that will own the grid. */, + /**< [in] Pointer to solution that will own the var. */, const std::vector< yc_index_node_ptr > &dims - /**< [in] Dimensions of the grid. + /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */, bool is_scratch = false - /**< [in] Whether to make a scratch grid. */) { + /**< [in] Whether to make a scratch var. */) { if (is_scratch) - _grid = soln->new_scratch_grid(name, dims); + _var = soln->new_scratch_var(name, dims); else - _grid = soln->new_grid(name, dims); + _var = soln->new_var(name, dims); } #ifndef SWIG /// Contructor taking an initializer_list of index vars. /** - A wrapper around yc_solution::new_grid() and - yc_solution::new_scratch_grid(). + A wrapper around yc_solution::new_var() and + yc_solution::new_scratch_var(). @note Not available in the Python API. Use the vector version. */ - yc_grid_var(const std::string& name - /**< [in] Name of the new grid; must be a valid C++ - identifier and unique across grids. */, + yc_var_proxy(const std::string& name + /**< [in] Name of the new var; must be a valid C++ + identifier and unique across vars. */, yc_solution_ptr soln - /**< [in] Pointer to solution that will own the grid. */, + /**< [in] Pointer to solution that will own the var. */, const std::initializer_list< yc_index_node_ptr > &dims - /**< [in] Dimensions of the grid. + /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */, bool is_scratch = false - /**< [in] Whether to make a scratch grid. */) { + /**< [in] Whether to make a scratch var. */) { if (is_scratch) - _grid = soln->new_scratch_grid(name, dims); + _var = soln->new_scratch_var(name, dims); else - _grid = soln->new_grid(name, dims); + _var = soln->new_var(name, dims); } #endif /// Contructor for a simple scalar value. /** - A wrapper around yc_solution::new_grid(). + A wrapper around yc_solution::new_var(). */ - yc_grid_var(const std::string& name - /**< [in] Name of the new grid; must be a valid C++ - identifier and unique across grids. */, + yc_var_proxy(const std::string& name + /**< [in] Name of the new var; must be a valid C++ + identifier and unique across vars. */, yc_solution_ptr soln - /**< [in] Pointer to solution that will own the grid. */) { - _grid = soln->new_grid(name, { }); + /**< [in] Pointer to solution that will own the var. */) { + _var = soln->new_var(name, { }); } - /// Contructor taking an existing grid. + /// Contructor taking an existing var. /** - Creates a new \ref yc_grid_var wrapper around an - existing grid. + Creates a new \ref yc_var_proxy wrapper around an + existing var. */ - yc_grid_var(yc_grid_ptr& grid) : _grid(grid) { } + yc_var_proxy(yc_var_ptr& var) : _var(var) { } /// Provide a virtual destructor. - virtual ~yc_grid_var() { } + virtual ~yc_var_proxy() { } - /// Get the underlying \ref yc_grid pointer. - virtual yc_grid_ptr get_grid() { - return _grid; + /// Get the underlying \ref yc_var pointer. + virtual yc_var_ptr get_var() { + return _var; } - /// Get the underlying \ref yc_grid pointer. - virtual const yc_grid_ptr get_grid() const { - return _grid; + /// Get the underlying \ref yc_var pointer. + virtual const yc_var_ptr get_var() const { + return _var; } - /// Create an expression for a point in a grid. + /// Create an expression for a point in a var. /** - A wrapper around yc_grid::new_grid_point(). - The number of arguments must match the dimensionality of the grid. + A wrapper around yc_var::new_var_point(). + The number of arguments must match the dimensionality of the var. - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, + Example w/2D var `B`: `A(t+1, x) EQUALS A(t, x) + B(vec)`, */ - virtual yc_grid_point_node_ptr + virtual yc_var_point_node_ptr operator()(const std::vector& index_exprs) { - return _grid->new_grid_point(index_exprs); + return _var->new_var_point(index_exprs); } #ifndef SWIG - /// Create an expression for a point in a grid. + /// Create an expression for a point in a var. /** - A wrapper around yc_grid::new_grid_point(). - The number of arguments must match the dimensionality of the grid. + A wrapper around yc_var::new_var_point(). + The number of arguments must match the dimensionality of the var. - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. + Example w/2D var `B`: `A(t+1, x) EQUALS A(t, x) + B({x, 3})`. @note Not available in Python API. Use vector version. */ - virtual yc_grid_point_node_ptr + virtual yc_var_point_node_ptr operator()(const std::initializer_list& index_exprs) { - return _grid->new_grid_point(index_exprs); + return _var->new_var_point(index_exprs); } - /// Create an expression for a point in a zero-dim (scalar) grid using implicit conversion. + /// Create an expression for a point in a zero-dim (scalar) var using implicit conversion. /** - A wrapper around yc_grid::new_grid_point(). + A wrapper around yc_var::new_var_point(). - Example w/0D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B`. + Example w/0D var `B`: `A(t+1, x) EQUALS A(t, x) + B`. @note Not available in Python API. Use vector version with empty vector. */ virtual operator yc_number_ptr_arg() { - return _grid->new_grid_point({}); + return _var->new_var_point({}); } - /// Create an expression for a point in a one-dim (array) grid. + /// Create an expression for a point in a one-dim (array) var. /** - A wrapper around yc_grid::new_grid_point(). + A wrapper around yc_var::new_var_point(). - Example w/1D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. + Example w/1D var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. @note Not available in Python API. Use vector version with 1-element vector. */ - virtual yc_grid_point_node_ptr operator[](const yc_number_any_arg i1) { - return _grid->new_grid_point({i1}); + virtual yc_var_point_node_ptr operator[](const yc_number_any_arg i1) { + return _var->new_var_point({i1}); } - /// Create an expression for a point in a 1-6 dim grid. + /// Create an expression for a point in a 1-6 dim var. /** - A wrapper around yc_grid::new_grid_point(). - The number of non-null arguments must match the dimensionality of the grid. + A wrapper around yc_var::new_var_point(). + The number of non-null arguments must match the dimensionality of the var. - Example w/2D grid var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. + Example w/2D var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. @note Not available in Python API. Use vector version. */ - virtual yc_grid_point_node_ptr operator()(const yc_number_any_arg i1 = nullptr, + virtual yc_var_point_node_ptr operator()(const yc_number_any_arg i1 = nullptr, const yc_number_any_arg i2 = nullptr, const yc_number_any_arg i3 = nullptr, const yc_number_any_arg i4 = nullptr, @@ -829,12 +886,21 @@ namespace yask { args.push_back(i5); if (i6) args.push_back(i6); - return _grid->new_grid_point(args); + return _var->new_var_point(args); } #endif - + }; /** @}*/ + /// **[Deprecated]** Use yc_var. + typedef yc_var yc_grid; + /// **[Deprecated]** Use yc_var_ptr. + typedef yc_var_ptr yc_grid_ptr; + /// **[Deprecated]** Use yc_var_point_node. + typedef yc_var_point_node yc_grid_point_node; + /// **[Deprecated]** Use yc_var_point_node_ptr. + typedef yc_var_point_node_ptr yc_grid_point_node_ptr; + } // namespace yask. diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index d09457ac..4d4c951f 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -102,7 +102,7 @@ namespace yask { command-line, this function in the named solution will be called. This function must be implemented by each concrete stencil solution to - add grids and grid-value equations as needed to define the stencil. + add vars and equations as needed to define the stencil. In general, any YASK compiler API functions may be called from this function. diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 16ff5099..0ae80f22 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -57,9 +57,9 @@ namespace yask { /// Shared pointer to \ref yk_solution. typedef std::shared_ptr yk_solution_ptr; - class yk_grid; - /// Shared pointer to \ref yk_grid. - typedef std::shared_ptr yk_grid_ptr; + class yk_var; + /// Shared pointer to \ref yk_var. + typedef std::shared_ptr yk_var_ptr; class yk_stats; /// Shared pointer to \ref yk_stats. @@ -69,7 +69,7 @@ namespace yask { } // namespace yask. #include "aux/yk_solution_api.hpp" -#include "aux/yk_grid_api.hpp" +#include "aux/yk_var_api.hpp" namespace yask { @@ -138,7 +138,7 @@ namespace yask { /// Create a stencil solution. /** - A stencil solution contains all the grids and equations + A stencil solution contains all the vars and equations that were created during stencil compilation. @returns Pointer to new solution object. */ @@ -149,8 +149,8 @@ namespace yask { /** All the settings that were specified via the `yk_solution::set_*()` functions in the source solution will be copied to the new solution. - This does *not* copy any grids, grid settings, or grid data; - see yk_solution::share_grid_storage(). + This does *not* copy any vars, var settings, or var data; + see yk_solution::fuse_vars(). @returns Pointer to new solution object. */ virtual yk_solution_ptr @@ -186,5 +186,11 @@ namespace yask { global_barrier() const =0; }; + /// **[Deprecated]** Use yk_var. + typedef yk_var yk_grid; + /// **[Deprecated]** Use yk_var_ptr. + typedef yk_var_ptr yk_grid_ptr; + /** @}*/ + } // namespace yask. diff --git a/src/common/fd_coeff2.cpp b/src/common/fd_coeff2.cpp index 9a356e76..e93a76b4 100644 --- a/src/common/fd_coeff2.cpp +++ b/src/common/fd_coeff2.cpp @@ -45,7 +45,7 @@ namespace yask { return coeffs; } - // Common FD forms for uniform grid spacing. + // Common FD forms for uniform var spacing. vector get_center_fd_coefficients(int derivative_order, int radius) { if (radius < 1) THROW_YASK_EXCEPTION("get_center_fd_coefficients() called with less than radius 1"); diff --git a/src/compiler/Makefile b/src/compiler/Makefile index 7d4c126d..14287e26 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -46,7 +46,7 @@ YC_PY_LIB := $(PY_OUT_DIR)/_$(YC_MODULE)$(SO_SUFFIX) YC_PY_MOD := $(PY_OUT_DIR)/$(YC_MODULE).py YC_TEST_EXEC := $(BIN_OUT_DIR)/$(YC_BASE)_api_test.exe YC_TEST_EXEC_WITH_EXCEPTION := $(BIN_OUT_DIR)/$(YC_BASE)_api_exception_test.exe -YC_SRC_NAMES := Expr ExprUtils Grid Settings Eqs Print Vec Cpp CppIntrin YaskKernel Solution +YC_SRC_NAMES := Expr ExprUtils Var Settings Eqs Print Vec Cpp CppIntrin YaskKernel Solution YC_STENCIL_NAMES:= $(notdir $(patsubst %.cpp,%,$(wildcard $(YC_STENCIL_DIR)/*.cpp))) YC_OBJS := $(addprefix $(YC_OBJ_DIR)/,$(addsuffix .o,$(YC_SRC_NAMES) $(COMM_SRC_NAMES))) YC_STENCIL_OBJS := $(addprefix $(YC_OBJ_DIR)/,$(addsuffix .o,$(YC_STENCIL_NAMES))) diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index e2fed922..847aaa1f 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -115,7 +115,7 @@ void usage(const string& cmd) { " Currently, only 4 (single-precision) and 8 (double) are allowed.\n" " -domain-dims ,,...\n" " Explicitly name the domain dimensions and set their order.\n" - " In addition, domain dimensions are added when grid variables are encountered\n" + " In addition, domain dimensions are added when YASK variables are encountered\n" " in the stencil DSL code.\n" " Either way, the last unique domain dimension specified will become the 'inner' or\n" " 'unit-stride' dimension in memory layouts. Thus, this option can be used to override\n" @@ -123,7 +123,7 @@ void usage(const string& cmd) { " The domain-dimension order also affects loop nesting and default rank layout.\n" " -step-dim \n" " Explicitly set the step dimension.\n" - " By default, the step dimension is defined when grid variables are encountered\n" + " By default, the step dimension is defined when YASK variables are encountered\n" " in the stencil DSL code.\n" " -fold =,...\n" " Set number of elements in each given dimension in a vector block.\n" @@ -132,11 +132,11 @@ void usage(const string& cmd) { " formats with explicit lengths, lengths will adjusted as needed.\n" " -cluster =,...\n" " Set number of vectors to evaluate in each dimension.\n" - " -grids \n" - " Only process updates to grids whose names match .\n" + " -vars \n" + " Only process updates to vars whose names match .\n" " This can be used to generate code for a subset of the stencil equations.\n" " -eq-bundles =,...\n" - " Put updates to grids matching in equation-bundle with base-name .\n" + " Put updates to vars matching in equation-bundle with base-name .\n" " By default, eq-bundles are created as needed based on dependencies between equations:\n" " equations that do not depend on each other are bundled together into bundles with the\n" " base-name '" << settings._eq_bundle_basename_default << "'.\n" @@ -145,23 +145,23 @@ void usage(const string& cmd) { settings._eq_bundle_basename_default << "_1', etc.\n" " This option allows more control over this bundling.\n" " Example: \"-eq-bundles a=foo,b=b[aeiou]r\" creates one or more eq-bundles named 'a_0', 'a_1', etc.\n" - " containing updates to each grid whose name contains 'foo' and one or more eq-bundles\n" - " named 'b_0', 'b_1', etc. containing updates to each grid whose name matches 'b[aeiou]r'.\n" + " containing updates to each var whose name contains 'foo' and one or more eq-bundles\n" + " named 'b_0', 'b_1', etc. containing updates to each var whose name matches 'b[aeiou]r'.\n" " Standard regex-format tokens in will be replaced based on matches to .\n" - " Example: \"-eq-bundles 'g_$&=b[aeiou]r'\" with grids 'bar_x', 'bar_y', 'ber_x', and 'ber_y'\n" - " would create eq-bundle 'g_bar_0' for grids 'bar_x' and 'bar_y' and eq-bundle 'g_ber_0' for\n" - " grids 'ber_x' and 'ber_y' because '$&' is substituted by the string that matches the regex.\n" + " Example: \"-eq-bundles 'g_$&=b[aeiou]r'\" with vars 'bar_x', 'bar_y', 'ber_x', and 'ber_y'\n" + " would create eq-bundle 'g_bar_0' for vars 'bar_x' and 'bar_y' and eq-bundle 'g_ber_0' for\n" + " vars 'ber_x' and 'ber_y' because '$&' is substituted by the string that matches the regex.\n" " [-no]-bundle-scratch\n" - " Bundle scratch equations even if the sizes of their scratch grids must be increased\n" + " Bundle scratch equations even if the sizes of their scratch vars must be increased\n" " to do so (default=" << settings._bundleScratch << ").\n" " -halo \n" - " Specify the size of the halos on all grids.\n" - " By default, halos are calculated automatically for each grid.\n" + " Specify the size of the halos on all vars.\n" + " By default, halos are calculated automatically for each var.\n" " -step-alloc \n" - " Specify the size of the step-dimension memory allocation on all grids.\n" - " By default, allocations are calculated automatically for each grid.\n" + " Specify the size of the step-dimension memory allocation on all vars.\n" + " By default, allocations are calculated automatically for each var.\n" " [-no]-interleave-misc\n" - " Allocate grid vars with the 'misc' dims as the inner-most dims (default=" << settings._innerMisc << ").\n" + " Allocate YASK vars with the 'misc' dims as the inner-most dims (default=" << settings._innerMisc << ").\n" " This disallows dynamcally changing the 'misc' dim sizes during run-time.\n" " -fus\n" " Make first dimension of fold unit stride (default=" << settings._firstInner << ").\n" @@ -202,7 +202,7 @@ void usage(const string& cmd) { " pseudo Human-readable scalar pseudo-code.\n" " pseudo-long Human-readable scalar pseudo-code with intermediate variables.\n" " dot DOT-language description.\n" - " dot-lite DOT-language description of grid accesses only.\n" + " dot-lite DOT-language description of var accesses only.\n" //" pov-ray POV-Ray code.\n" //" -ps Print stats for all folding options for given vector length.\n" "\n" @@ -285,8 +285,8 @@ void parseOpts(int argc, const char* argv[]) // options w/a string value. if (opt == "-stencil") solutionName = argop; - else if (opt == "-grids") - settings._gridRegex = argop; + else if (opt == "-vars") + settings._varRegex = argop; else if (opt == "-eq-bundles") settings._eqBundleTargets = argop; else if (opt == "-step-dim") @@ -412,7 +412,7 @@ void parseOpts(int argc, const char* argv[]) // Create equations from the overloaded 'define()' methods. stencilSoln->define(); - cout << "Num grids defined: " << soln->get_num_grids() << endl; + cout << "Num vars defined: " << soln->get_num_vars() << endl; cout << "Num equations defined: " << soln->get_num_equations() << endl; } diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index 7f5139cc..23085131 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -49,15 +49,15 @@ namespace yask { // Make call for a point. // This is a utility function used for both reads and writes. string CppPrintHelper::makePointCall(ostream& os, - const GridPoint& gp, + const VarPoint& gp, const string& fname, string optArg) { // Get/set local vars. - string gridPtr = getLocalVar(os, gp.getGridPtr(), _grid_ptr_type); - string stepArgVar = getLocalVar(os, gp.makeStepArgStr(gridPtr, _dims), _step_val_type); + string varPtr = getLocalVar(os, gp.getVarPtr(), _var_ptr_type); + string stepArgVar = getLocalVar(os, gp.makeStepArgStr(varPtr, _dims), _step_val_type); - string res = gridPtr + "->" + fname + "("; + string res = varPtr + "->" + fname + "("; if (optArg.length()) res += optArg + ", "; string args = gp.makeArgStr(); @@ -65,13 +65,13 @@ namespace yask { return res; } - // Return a grid-point reference. - string CppPrintHelper::readFromPoint(ostream& os, const GridPoint& gp) { + // Return a var-point reference. + string CppPrintHelper::readFromPoint(ostream& os, const VarPoint& gp) { return makePointCall(os, gp, "readElem"); } - // Return code to update a grid point. - string CppPrintHelper::writeToPoint(ostream& os, const GridPoint& gp, + // Return code to update a var point. + string CppPrintHelper::writeToPoint(ostream& os, const VarPoint& gp, const string& val) { return makePointCall(os, gp, "writeElem", val); } @@ -80,7 +80,7 @@ namespace yask { // Read from a single point. // Return code for read. - string CppVecPrintHelper::readFromScalarPoint(ostream& os, const GridPoint& gp, + string CppVecPrintHelper::readFromScalarPoint(ostream& os, const VarPoint& gp, const VarMap* vMap) { // Use default var-map if not provided. @@ -88,18 +88,18 @@ namespace yask { vMap = &_vec2elemMap; // Determine type to avoid virtual call. - bool folded = gp.isGridFoldable(); - string gtype = folded ? "YkVecGrid" : "YkElemGrid"; + bool folded = gp.isVarFoldable(); + string gtype = folded ? "YkVecVar" : "YkElemVar"; // Get/set local vars. - string gridPtr = getLocalVar(os, gp.getGridPtr(), CppPrintHelper::_grid_ptr_type); - string stepArgVar = getLocalVar(os, gp.makeStepArgStr(gridPtr, _dims), + string varPtr = getLocalVar(os, gp.getVarPtr(), CppPrintHelper::_var_ptr_type); + string stepArgVar = getLocalVar(os, gp.makeStepArgStr(varPtr, _dims), CppPrintHelper::_step_val_type); // Assume that broadcast will be handled automatically by // operator overloading in kernel code. // Specify that any indices should use element vars. - string str = gridPtr + "->" + gtype + "::readElem("; + string str = varPtr + "->" + gtype + "::readElem("; string args = gp.makeArgStr(vMap); str += "{" + args + "}, " + stepArgVar + ",__LINE__)"; return str; @@ -107,7 +107,7 @@ namespace yask { // Read from multiple points that are not vectorizable. // Return var name. - string CppVecPrintHelper::printNonVecRead(ostream& os, const GridPoint& gp) { + string CppVecPrintHelper::printNonVecRead(ostream& os, const VarPoint& gp) { printPointComment(os, gp, "Construct folded vector from non-folded"); // Make a vec var. @@ -120,7 +120,7 @@ namespace yask { // Example: vecPoint contains x=0, y=2, z=1, where each val // is the offset in the given fold dim. We want to map - // x=>x_elem, y=>(y_elem+2), z=>(z_elem+1) in grid-point + // x=>x_elem, y=>(y_elem+2), z=>(z_elem+1) in var-point // index args. VarMap vMap; for (auto& dim : vecPoint.getDims()) { @@ -162,18 +162,18 @@ namespace yask { // Print call for a point. // This is a utility function used for reads & writes. string CppVecPrintHelper::printVecPointCall(ostream& os, - const GridPoint& gp, + const VarPoint& gp, const string& funcName, const string& firstArg, const string& lastArg, bool isNorm) { // Get/set local vars. - string gridPtr = getLocalVar(os, gp.getGridPtr(), CppPrintHelper::_grid_ptr_type); - string stepArgVar = getLocalVar(os, gp.makeStepArgStr(gridPtr, _dims), + string varPtr = getLocalVar(os, gp.getVarPtr(), CppPrintHelper::_var_ptr_type); + string stepArgVar = getLocalVar(os, gp.makeStepArgStr(varPtr, _dims), CppPrintHelper::_step_val_type); - string res = gridPtr + "->" + funcName + "("; + string res = varPtr + "->" + funcName + "("; if (firstArg.length()) res += firstArg + ", "; string args = isNorm ? gp.makeNormArgStr(_dims) : gp.makeArgStr(); @@ -189,7 +189,7 @@ namespace yask { const string& idim = _dims._innerDim; // A set for the aligned reads & writes. - GridPointSet gps; + VarPointSet gps; // Aligned reads as determined by VecInfoVisitor. gps = _vv._alignedVecs; @@ -201,7 +201,7 @@ namespace yask { for (auto& gp : gps) { // Can we use a pointer? - if (gp.getLoopType() != GridPoint::LOOP_OFFSET) + if (gp.getLoopType() != VarPoint::LOOP_OFFSET) continue; // Make base point (misc & inner-dim indices = 0). @@ -326,7 +326,7 @@ namespace yask { // Finish loop header. os << "; ofs++) {\n"; - // Need to print prefetch for every unique grid-point read. + // Need to print prefetch for every unique var-point read. set done; for (auto& gp : _vv._alignedVecs) { @@ -364,8 +364,8 @@ namespace yask { } // Make base point (misc & inner-dim indices = 0). - gridPointPtr CppVecPrintHelper::makeBasePoint(const GridPoint& gp) { - gridPointPtr bgp = gp.cloneGridPoint(); + varPointPtr CppVecPrintHelper::makeBasePoint(const VarPoint& gp) { + varPointPtr bgp = gp.cloneVarPoint(); for (auto& dim : gp.getDims()) { auto& dname = dim->getName(); auto type = dim->getType(); @@ -379,8 +379,8 @@ namespace yask { // Set misc indices to their min value if they are inside // inner domain dim. else if (_settings._innerMisc && type == MISC_INDEX) { - auto* grid = gp.getGrid(); - auto min_val = grid->getMinIndices()[dname]; + auto* var = gp.getVar(); + auto min_val = var->getMinIndices()[dname]; IntScalar idi(dname, min_val); bgp->setArgConst(idi); } @@ -390,7 +390,7 @@ namespace yask { // Print code to set ptrName to gp. void CppVecPrintHelper::printPointPtr(ostream& os, const string& ptrName, - const GridPoint& gp) { + const VarPoint& gp) { printPointComment(os, gp, "Calculate pointer to "); // Get pointer to vector using normalized indices. @@ -399,14 +399,14 @@ namespace yask { auto vp = printVecPointCall(os, gp, "getVecPtrNorm", "", "false", true); // Ptr will be unique if: - // - GridVar doesn't have step dim, or - // - GridVar doesn't allow dynamic step allocs and the alloc size is one (TODO), or - // - GridVar doesn't allow dynamic step allocs and all accesses are via + // - Var doesn't have step dim, or + // - Var doesn't allow dynamic step allocs and the alloc size is one (TODO), or + // - Var doesn't allow dynamic step allocs and all accesses are via // offsets from the step dim w/compatible offsets (TODO). // TODO: must also share pointers during code gen in last 2 cases. - auto* grid = gp.getGrid(); - bool is_unique = (grid->getStepDim() == nullptr); - // || (!grid->is_dynamic_step_alloc() && grid->get_step_alloc_size() == 1); + auto* var = gp.getVar(); + bool is_unique = (var->getStepDim() == nullptr); + // || (!var->is_dynamic_step_alloc() && var->get_step_alloc_size() == 1); string type = is_unique ? "auto* restrict " : "auto* "; // Print type and value. @@ -416,15 +416,15 @@ namespace yask { // Get expression for offset of 'gp' from base pointer. Base pointer // points to vector with outer-dims == same values as in 'gp', inner-dim // == 0 and misc dims == their min value. - string CppVecPrintHelper::getPtrOffset(const GridPoint& gp, const string& innerExpr) { - auto* grid = gp.getGrid(); + string CppVecPrintHelper::getPtrOffset(const VarPoint& gp, const string& innerExpr) { + auto* var = gp.getVar(); // Need to create an expression for inner-dim // and misc indices offsets. // Start with offset in inner-dim direction. // This must the dim that appears before the misc dims - // in the grid-var layout. + // in the var layout. string idim = _dims._innerDim; string ofsStr = "("; if (innerExpr.length()) @@ -435,27 +435,27 @@ namespace yask { // Misc indices if they are inside inner-dim. if (_settings._innerMisc) { - for (int i = 0; i < grid->get_num_dims(); i++) { + for (int i = 0; i < var->get_num_dims(); i++) { auto& dimi = gp.getDims().at(i); auto& dni = dimi->getName(); auto typei = dimi->getType(); if (typei == MISC_INDEX) { // Mult by size of remaining misc dims. - for (int j = i; j < grid->get_num_dims(); j++) { + for (int j = i; j < var->get_num_dims(); j++) { auto& dimj = gp.getDims().at(j); auto& dnj = dimj->getName(); auto typej = dimj->getType(); if (typej == MISC_INDEX) { - auto min_idx = grid->getMinIndices()[dnj]; - auto max_idx = grid->getMaxIndices()[dnj]; + auto min_idx = var->getMinIndices()[dnj]; + auto max_idx = var->getMaxIndices()[dnj]; ofsStr += " * (" + to_string(max_idx) + " - " + to_string(min_idx) + " + 1)"; } } // Add offset of this misc value, which must be const. - auto min_val = grid->getMinIndices()[dni]; + auto min_val = var->getMinIndices()[dni]; auto val = gp.getArgConsts()[dni]; ofsStr += " + (" + to_string(val) + " - " + to_string(min_val) + ")"; @@ -466,8 +466,8 @@ namespace yask { } // Print any needed memory reads and/or constructions to 'os'. - // Return code containing a vector of grid points. - string CppVecPrintHelper::readFromPoint(ostream& os, const GridPoint& gp) { + // Return code containing a vector of var points. + string CppVecPrintHelper::readFromPoint(ostream& os, const VarPoint& gp) { string codeStr; // Already done and saved. @@ -477,8 +477,8 @@ namespace yask { // Can we use a vec pointer? // Read must be aligned, and we must have a pointer. else if (_vv._alignedVecs.count(gp) && - gp.getVecType() == GridPoint::VEC_FULL && - gp.getLoopType() == GridPoint::LOOP_OFFSET) { + gp.getVecType() == VarPoint::VEC_FULL && + gp.getLoopType() == VarPoint::LOOP_OFFSET) { // Got a pointer to the base addr? auto bgp = makeBasePoint(gp); @@ -510,13 +510,13 @@ namespace yask { } // Print any immediate memory writes to 'os'. - // Return code to update a vector of grid points or null string + // Return code to update a vector of var points or null string // if all writes were printed. - string CppVecPrintHelper::writeToPoint(ostream& os, const GridPoint& gp, + string CppVecPrintHelper::writeToPoint(ostream& os, const VarPoint& gp, const string& val) { // Can we use a pointer? - if (gp.getLoopType() == GridPoint::LOOP_OFFSET) { + if (gp.getLoopType() == VarPoint::LOOP_OFFSET) { // Got a pointer to the base addr? auto bgp = makeBasePoint(gp); @@ -542,7 +542,7 @@ namespace yask { } // Print aligned memory read. - string CppVecPrintHelper::printAlignedVecRead(ostream& os, const GridPoint& gp) { + string CppVecPrintHelper::printAlignedVecRead(ostream& os, const VarPoint& gp) { printPointComment(os, gp, "Read aligned"); auto rvn = printVecPointCall(os, gp, "readVecNorm", "", "__LINE__", true); @@ -555,7 +555,7 @@ namespace yask { // Print unaliged memory read. // Assumes this results in same values as printUnalignedVec(). - string CppVecPrintHelper::printUnalignedVecRead(ostream& os, const GridPoint& gp) { + string CppVecPrintHelper::printUnalignedVecRead(ostream& os, const VarPoint& gp) { printPointComment(os, gp, "Read unaligned"); os << " // NOTICE: Assumes constituent vectors are consecutive in memory!" << endl; @@ -571,7 +571,7 @@ namespace yask { } // Print aligned memory write. - string CppVecPrintHelper::printAlignedVecWrite(ostream& os, const GridPoint& gp, + string CppVecPrintHelper::printAlignedVecWrite(ostream& os, const VarPoint& gp, const string& val) { printPointComment(os, gp, "Write aligned"); auto vn = printVecPointCall(os, gp, "writeVecNorm_masked", val, "write_mask, __LINE__", true); @@ -585,7 +585,7 @@ namespace yask { // Print conversion from memory vars to point var gp if needed. // This calls printUnalignedVecCtor(), which can be overloaded // by derived classes. - string CppVecPrintHelper::printUnalignedVec(ostream& os, const GridPoint& gp) { + string CppVecPrintHelper::printUnalignedVec(ostream& os, const VarPoint& gp) { printPointComment(os, gp, "Construct unaligned"); // Declare var. @@ -598,7 +598,7 @@ namespace yask { } // Print per-element construction for one point var pvName from elems. - void CppVecPrintHelper::printUnalignedVecSimple(ostream& os, const GridPoint& gp, + void CppVecPrintHelper::printUnalignedVecSimple(ostream& os, const VarPoint& gp, const string& pvName, string linePrefix, const set* doneElems) { @@ -624,7 +624,7 @@ namespace yask { os << linePrefix << pvName << "[" << pelem << "] = " << mvName << "[" << alignedElem << "]; // for " << - gp.getGridName() << "(" << elemStr << ")" << _lineSuffix; + gp.getVarName() << "(" << elemStr << ")" << _lineSuffix; } } @@ -646,27 +646,27 @@ namespace yask { } } - // Print invariant grid-access vars for non-time loop(s). - string CppStepVarPrintVisitor::visit(GridPoint* gp) { + // Print invariant var-access vars for non-time loop(s). + string CppStepVarPrintVisitor::visit(VarPoint* gp) { - // Pointer to grid. - string gridPtr = _cvph.getLocalVar(_os, gp->getGridPtr(), CppPrintHelper::_grid_ptr_type); + // Pointer to var. + string varPtr = _cvph.getLocalVar(_os, gp->getVarPtr(), CppPrintHelper::_var_ptr_type); // Time var. auto& dims = _cvph.getDims(); - _cvph.getLocalVar(_os, gp->makeStepArgStr(gridPtr, dims), + _cvph.getLocalVar(_os, gp->makeStepArgStr(varPtr, dims), CppPrintHelper::_step_val_type); return ""; } - // Print invariant grid-access vars for an inner loop. - string CppLoopVarPrintVisitor::visit(GridPoint* gp) { + // Print invariant var-access vars for an inner loop. + string CppLoopVarPrintVisitor::visit(VarPoint* gp) { - // Retrieve prior analysis of this grid point. + // Retrieve prior analysis of this var point. auto loopType = gp->getLoopType(); // If invariant, we can load now. - if (loopType == GridPoint::LOOP_INVARIANT) { + if (loopType == VarPoint::LOOP_INVARIANT) { // Not already loaded? if (!_cvph.lookupPointVar(*gp)) { diff --git a/src/compiler/lib/Cpp.hpp b/src/compiler/lib/Cpp.hpp index cdeca07e..2df7a34f 100644 --- a/src/compiler/lib/Cpp.hpp +++ b/src/compiler/lib/Cpp.hpp @@ -31,7 +31,7 @@ IN THE SOFTWARE. #define CPP_HPP #include "Vec.hpp" -#include "Grid.hpp" +#include "Var.hpp" namespace yask { @@ -41,7 +41,7 @@ namespace yask { class CppPrintHelper : public PrintHelper { public: - static constexpr const char* _grid_ptr_type = "auto*"; + static constexpr const char* _var_ptr_type = "auto*"; static constexpr const char* _step_val_type = "const auto"; CppPrintHelper(const CompilerSettings& settings, @@ -67,15 +67,15 @@ namespace yask { // Make call for a point. // This is a utility function used for both reads and writes. virtual string makePointCall(ostream& os, - const GridPoint& gp, + const VarPoint& gp, const string& fname, string optArg = ""); - // Return a grid-point reference. - virtual string readFromPoint(ostream& os, const GridPoint& gp); + // Return a var-point reference. + virtual string readFromPoint(ostream& os, const VarPoint& gp); - // Return code to update a grid point. - virtual string writeToPoint(ostream& os, const GridPoint& gp, + // Return code to update a var point. + virtual string writeToPoint(ostream& os, const VarPoint& gp, const string& val); }; @@ -98,8 +98,8 @@ namespace yask { protected: - // Vars for tracking pointers to grid values. - map _vecPtrs; // pointers to grid vecs. value: ptr-var name. + // Vars for tracking pointers to var values. + map _vecPtrs; // pointers to var vecs. value: ptr-var name. map _ptrOfsLo; // lowest read offset from _vecPtrs in inner dim. map _ptrOfsHi; // highest read offset from _vecPtrs in inner dim. @@ -119,7 +119,7 @@ namespace yask { // Print a comment about a point. // This is a utility function used for both reads and writes. - virtual void printPointComment(ostream& os, const GridPoint& gp, + virtual void printPointComment(ostream& os, const VarPoint& gp, const string& verb) const { os << endl << " // " << verb << " vector starting at " << @@ -129,51 +129,51 @@ namespace yask { // Return code for a vectorized point. // This is a utility function used for both reads and writes. virtual string printVecPointCall(ostream& os, - const GridPoint& gp, + const VarPoint& gp, const string& funcName, const string& firstArg, const string& lastArg, bool isNorm); // Print aligned memory read. - virtual string printAlignedVecRead(ostream& os, const GridPoint& gp); + virtual string printAlignedVecRead(ostream& os, const VarPoint& gp); // Print unaliged memory read. // Assumes this results in same values as printUnalignedVec(). - virtual string printUnalignedVecRead(ostream& os, const GridPoint& gp); + virtual string printUnalignedVecRead(ostream& os, const VarPoint& gp); // Print aligned memory write. - virtual string printAlignedVecWrite(ostream& os, const GridPoint& gp, + virtual string printAlignedVecWrite(ostream& os, const VarPoint& gp, const string& val); // Print conversion from memory vars to point var gp if needed. // This calls printUnalignedVecCtor(), which can be overloaded // by derived classes. - virtual string printUnalignedVec(ostream& os, const GridPoint& gp); + virtual string printUnalignedVec(ostream& os, const VarPoint& gp); // Print per-element construction for one point var pvName from elems. - virtual void printUnalignedVecSimple(ostream& os, const GridPoint& gp, + virtual void printUnalignedVecSimple(ostream& os, const VarPoint& gp, const string& pvName, string linePrefix, const set* doneElems = 0); // Read from a single point to be broadcast to a vector. // Return code for read. - virtual string readFromScalarPoint(ostream& os, const GridPoint& gp, + virtual string readFromScalarPoint(ostream& os, const VarPoint& gp, const VarMap* vMap=0); // Read from multiple points that are not vectorizable. // Return var name. - virtual string printNonVecRead(ostream& os, const GridPoint& gp); + virtual string printNonVecRead(ostream& os, const VarPoint& gp); // Print construction for one point var pvName from elems. // This version prints inefficient element-by-element assignment. // Override this in derived classes for more efficient implementations. - virtual void printUnalignedVecCtor(ostream& os, const GridPoint& gp, const string& pvName) { + virtual void printUnalignedVecCtor(ostream& os, const VarPoint& gp, const string& pvName) { printUnalignedVecSimple(os, gp, pvName, _linePrefix); } // Get offset from base pointer. - virtual string getPtrOffset(const GridPoint& gp, + virtual string getPtrOffset(const VarPoint& gp, const string& innerExpr = ""); public: @@ -182,20 +182,20 @@ namespace yask { virtual void printBasePtrs(ostream& os); // Make base point (misc & inner-dim indices = 0). - virtual gridPointPtr makeBasePoint(const GridPoint& gp); + virtual varPointPtr makeBasePoint(const VarPoint& gp); // Print prefetches for each base pointer. // Print only 'ptrVar' if provided. virtual void printPrefetches(ostream& os, bool ahead, string ptrVar = ""); // Print any needed memory reads and/or constructions to 'os'. - // Return code containing a vector of grid points. - virtual string readFromPoint(ostream& os, const GridPoint& gp); + // Return code containing a vector of var points. + virtual string readFromPoint(ostream& os, const VarPoint& gp); // Print any immediate memory writes to 'os'. - // Return code to update a vector of grid points or null string + // Return code to update a vector of var points or null string // if all writes were printed. - virtual string writeToPoint(ostream& os, const GridPoint& gp, + virtual string writeToPoint(ostream& os, const VarPoint& gp, const string& val); // print init of un-normalized indices. @@ -207,13 +207,13 @@ namespace yask { } // Print code to set ptrName to gp. - virtual void printPointPtr(ostream& os, const string& ptrName, const GridPoint& gp); + virtual void printPointPtr(ostream& os, const string& ptrName, const VarPoint& gp); // Access cached values. - virtual void savePointPtr(const GridPoint& gp, string var) { + virtual void savePointPtr(const VarPoint& gp, string var) { _vecPtrs[gp] = var; } - virtual string* lookupPointPtr(const GridPoint& gp) { + virtual string* lookupPointPtr(const VarPoint& gp) { if (_vecPtrs.count(gp)) return &_vecPtrs.at(gp); return 0; @@ -232,8 +232,8 @@ namespace yask { PrintVisitorBase(os, ph, varMap), _cvph(ph) { } - // A grid access. - virtual string visit(GridPoint* gp); + // A var access. + virtual string visit(VarPoint* gp); }; // Outputs the loop-invariant variables for an inner loop. @@ -248,8 +248,8 @@ namespace yask { PrintVisitorBase(os, ph, varMap), _cvph(ph) { } - // A grid access. - virtual string visit(GridPoint* gp); + // A var access. + virtual string visit(VarPoint* gp); }; // Print out a stencil in C++ form for YASK. diff --git a/src/compiler/lib/CppIntrin.cpp b/src/compiler/lib/CppIntrin.cpp index 4fdecc43..d2f79c4a 100644 --- a/src/compiler/lib/CppIntrin.cpp +++ b/src/compiler/lib/CppIntrin.cpp @@ -34,7 +34,7 @@ void CppIntrinPrintHelper::tryAlign(ostream& os, size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs, + const VarPointSet& alignedVecs, bool maskAllowed) { size_t nelems = elems.size(); @@ -186,7 +186,7 @@ void CppIntrinPrintHelper::tryPerm1(ostream& os, size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs) { + const VarPointSet& alignedVecs) { size_t nelems = elems.size(); // Try a permute of each aligned vector. @@ -280,7 +280,7 @@ void CppIntrinPrintHelper::tryPerm2(ostream& os, size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs) { + const VarPointSet& alignedVecs) { size_t nelems = elems.size(); // There is no source-preserving mask version of permutex2var, so @@ -407,7 +407,7 @@ void CppIntrinPrintHelper::tryPerm2(ostream& os, // Print construction for one unaligned vector pvName at gp. void CppIntrinPrintHelper::printUnalignedVecCtor(ostream& os, - const GridPoint& gp, + const VarPoint& gp, const string& pvName) { // Create an explanatory comment by printing the straightforward diff --git a/src/compiler/lib/CppIntrin.hpp b/src/compiler/lib/CppIntrin.hpp index bae61986..f6827658 100644 --- a/src/compiler/lib/CppIntrin.hpp +++ b/src/compiler/lib/CppIntrin.hpp @@ -69,7 +69,7 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs) =0; + const VarPointSet& alignedVecs) =0; // Try to use align instruction(s) to construct nelemsTarget elements // per instruction. @@ -78,7 +78,7 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs, + const VarPointSet& alignedVecs, bool maskAllowed); // Try to use 1-var permute instruction(s) to construct nelemsTarget elements @@ -88,7 +88,7 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs); + const VarPointSet& alignedVecs); // Try to use 2-var permute instruction(s) to construct nelemsTarget elements // per instruction. @@ -97,12 +97,12 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs); + const VarPointSet& alignedVecs); public: // Print construction for one unaligned vector pvName at gp. virtual void printUnalignedVecCtor(ostream& os, - const GridPoint& gp, + const VarPoint& gp, const string& pvName); }; @@ -117,7 +117,7 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs) { + const VarPointSet& alignedVecs) { tryAlign(os, pvName, nelemsTarget, elems, doneElems, alignedVecs, true); tryPerm1(os, pvName, nelemsTarget, elems, doneElems, alignedVecs); } @@ -145,7 +145,7 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs) { + const VarPointSet& alignedVecs) { tryAlign(os, pvName, nelemsTarget, elems, doneElems, alignedVecs, true); tryPerm2(os, pvName, nelemsTarget, elems, doneElems, alignedVecs); tryPerm1(os, pvName, nelemsTarget, elems, doneElems, alignedVecs); @@ -174,7 +174,7 @@ namespace yask { size_t nelemsTarget, const VecElemList& elems, set& doneElems, - const GridPointSet& alignedVecs) { + const VarPointSet& alignedVecs) { tryAlign(os, pvName, nelemsTarget, elems, doneElems, alignedVecs, false); } diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index 7b3439c0..60be5b7f 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -34,22 +34,22 @@ IN THE SOFTWARE. namespace yask { - // A visitor to collect grids and points visited in a set of eqs. - // For each eq, there are accessors for its output grid and point - // and its input grids and points. + // A visitor to collect vars and points visited in a set of eqs. + // For each eq, there are accessors for its output var and point + // and its input vars and points. class PointVisitor : public ExprVisitor { - // A type to hold a mapping of equations to a set of grids in each. - typedef unordered_set GridSet; - typedef unordered_map GridMap; - typedef unordered_map GridSetMap; + // A type to hold a mapping of equations to a set of vars in each. + typedef unordered_set VarSet; + typedef unordered_map VarMap; + typedef unordered_map VarSetMap; - GridMap _lhs_grids; // outputs of eqs. - GridSetMap _rhs_grids; // inputs of eqs. + VarMap _lhs_vars; // outputs of eqs. + VarSetMap _rhs_vars; // inputs of eqs. // A type to hold a mapping of equations to a set of points in each. - typedef unordered_set PointSet; - typedef unordered_map PointMap; + typedef unordered_set PointSet; + typedef unordered_map PointMap; typedef unordered_map PointSetMap; PointMap _lhs_pts; // outputs of eqs. @@ -68,9 +68,9 @@ namespace yask { PointVisitor() {} virtual ~PointVisitor() {} - // Get access to grids per eq. - GridMap& getOutputGrids() { return _lhs_grids; } - GridSetMap& getInputGrids() { return _rhs_grids; } + // Get access to vars per eq. + VarMap& getOutputVars() { return _lhs_vars; } + VarSetMap& getInputVars() { return _rhs_vars; } // Get access to pts per eq. // Contains unique ptrs to pts, but pts may not @@ -84,15 +84,15 @@ namespace yask { int getNumEqs() const { return (int)_lhs_pts.size(); } // Callback at an equality. - // Visits all parts that might have grid points. + // Visits all parts that might have var points. virtual string visit(EqualsExpr* ee) { // Set this equation as current one. _eq = ee; // Make sure all map entries exist for this eq. - _lhs_grids[_eq]; - _rhs_grids[_eq]; + _lhs_vars[_eq]; + _rhs_vars[_eq]; _lhs_pts[_eq]; _rhs_pts[_eq]; _cond_pts[_eq]; @@ -123,23 +123,23 @@ namespace yask { return ""; } - // Callback at a grid point. - virtual string visit(GridPoint* gp) { + // Callback at a var point. + virtual string visit(VarPoint* gp) { assert(_eq); - auto* g = gp->getGrid(); + auto* g = gp->getVar(); _all_pts[_eq].insert(gp); - // Save pt and/or grid based on state. + // Save pt and/or var based on state. switch (_state) { case _in_lhs: _lhs_pts[_eq] = gp; - _lhs_grids[_eq] = g; + _lhs_vars[_eq] = g; break; case _in_rhs: _rhs_pts[_eq].insert(gp); - _rhs_grids[_eq].insert(g); + _rhs_vars[_eq].insert(g); break; case _in_cond: @@ -173,8 +173,8 @@ namespace yask { // Gather initial stats from all eqs. PointVisitor pt_vis; visitEqs(&pt_vis); - auto& outGrids = pt_vis.getOutputGrids(); - auto& inGrids = pt_vis.getInputGrids(); + auto& outVars = pt_vis.getOutputVars(); + auto& inVars = pt_vis.getInputVars(); auto& outPts = pt_vis.getOutputPts(); auto& inPts = pt_vis.getInputPts(); //auto& condPts = pt_vis.getCondPts(); @@ -184,12 +184,12 @@ namespace yask { os << "\nProcessing " << getNum() << " stencil equation(s)...\n"; for (auto eq1 : getAll()) { auto* eq1p = eq1.get(); - assert(outGrids.count(eq1p)); - assert(inGrids.count(eq1p)); - auto* og1 = outGrids.at(eq1p); - assert(og1 == eq1->getGrid()); + assert(outVars.count(eq1p)); + assert(inVars.count(eq1p)); + auto* og1 = outVars.at(eq1p); + assert(og1 == eq1->getVar()); auto* op1 = outPts.at(eq1p); - //auto& ig1 = inGrids.at(eq1p); + //auto& ig1 = inVars.at(eq1p); auto& ip1 = inPts.at(eq1p); auto cond1 = eq1p->getCond(); auto stcond1 = eq1p->getStepCond(); @@ -200,12 +200,12 @@ namespace yask { eq1->makeQuotedStr() << "...\n"; #endif - // Scratch grid must not have a condition. + // Scratch var must not have a condition. if (cond1 && og1->isScratch()) - THROW_YASK_EXCEPTION("Error: scratch-grid equation " + eq1->makeQuotedStr() + + THROW_YASK_EXCEPTION("Error: scratch-var equation " + eq1->makeQuotedStr() + " cannot have a domain condition"); if (stcond1 && og1->isScratch()) - THROW_YASK_EXCEPTION("Error: scratch-grid equation " + eq1->makeQuotedStr() + + THROW_YASK_EXCEPTION("Error: scratch-var equation " + eq1->makeQuotedStr() + " cannot have a step condition"); // LHS must have all domain dims. @@ -213,7 +213,7 @@ namespace yask { auto& dname = dd.getName(); numExprPtr dexpr = op1->getArg(dname); if (!dexpr) - THROW_YASK_EXCEPTION("Error: grid equation " + eq1->makeQuotedStr() + + THROW_YASK_EXCEPTION("Error: var equation " + eq1->makeQuotedStr() + " does not use domain-dimension '" + dname + "' on LHS"); } @@ -221,16 +221,16 @@ namespace yask { // LHS of non-scratch must have step dim and vice-versa. if (!og1->isScratch()) { if (!step_expr1) - THROW_YASK_EXCEPTION("Error: non-scratch grid equation " + eq1->makeQuotedStr() + + THROW_YASK_EXCEPTION("Error: non-scratch var equation " + eq1->makeQuotedStr() + " does not use step-dimension '" + stepDim + "' on LHS"); } else { if (step_expr1) - THROW_YASK_EXCEPTION("Error: scratch-grid equation " + eq1->makeQuotedStr() + + THROW_YASK_EXCEPTION("Error: scratch-var equation " + eq1->makeQuotedStr() + " cannot use step-dimension '" + stepDim + "'"); } - // Check LHS grid dimensions and associated args. + // Check LHS var dimensions and associated args. for (int di = 0; di < og1->get_num_dims(); di++) { auto& dn = og1->get_dim_name(di); // name of this dim. auto argn = op1->getArgs().at(di); // LHS arg for this dim. @@ -313,7 +313,7 @@ namespace yask { // LHS of equation must be vectorizable. // TODO: relax this restriction. - if (op1->getVecType() != GridPoint::VEC_FULL) { + if (op1->getVecType() != VarPoint::VEC_FULL) { THROW_YASK_EXCEPTION("Error: LHS of equation " + eq1->makeQuotedStr() + " is not fully vectorizable because not all folded" " dimensions are accessed via simple offsets from their respective indices"); @@ -322,7 +322,7 @@ namespace yask { // Check that domain indices are simple offsets and // misc indices are consts on RHS. for (auto i1 : ip1) { - auto* ig1 = i1->getGrid(); + auto* ig1 = i1->getVar(); for (int di = 0; di < ig1->get_num_dims(); di++) { auto& dn = ig1->get_dim_name(di); // name of this dim. @@ -363,12 +363,12 @@ namespace yask { os << "Analyzing for dependencies...\n"; for (auto eq1 : getAll()) { auto* eq1p = eq1.get(); - assert(outGrids.count(eq1p)); - assert(inGrids.count(eq1p)); - auto* og1 = outGrids.at(eq1p); - assert(og1 == eq1->getGrid()); + assert(outVars.count(eq1p)); + assert(inVars.count(eq1p)); + auto* og1 = outVars.at(eq1p); + assert(og1 == eq1->getVar()); auto* op1 = outPts.at(eq1p); - //auto& ig1 = inGrids.at(eq1p); + //auto& ig1 = inVars.at(eq1p); //auto& ip1 = inPts.at(eq1p); auto cond1 = eq1p->getCond(); auto stcond1 = eq1p->getStepCond(); @@ -377,10 +377,10 @@ namespace yask { // Check each 'eq2' to see if it depends on 'eq1'. for (auto eq2 : getAll()) { auto* eq2p = eq2.get(); - auto& og2 = outGrids.at(eq2p); - assert(og2 == eq2->getGrid()); + auto& og2 = outVars.at(eq2p); + assert(og2 == eq2->getVar()); auto& op2 = outPts.at(eq2p); - auto& ig2 = inGrids.at(eq2p); + auto& ig2 = inVars.at(eq2p); auto& ip2 = inPts.at(eq2p); auto cond2 = eq2p->getCond(); auto stcond2 = eq2p->getStepCond(); @@ -396,8 +396,8 @@ namespace yask { bool same_cond = areExprsSame(cond1, cond2); bool same_stcond = areExprsSame(stcond1, stcond2); - // A separate grid is defined by its name and any const indices. - //bool same_og = op1->isSameLogicalGrid(*op2); + // A separate var is defined by its name and any const indices. + //bool same_og = op1->isSameLogicalVar(*op2); // If two different eqs have the same conditions, they // cannot have the same LHS. @@ -450,7 +450,7 @@ namespace yask { continue; // Next dep check: inexact matches on LHS of eq1 to RHS of eq2. - // Does eq1 define *any* point in a grid that eq2 inputs + // Does eq1 define *any* point in a var that eq2 inputs // at the same step index? If so, they *might* have a // dependency. Some of these may not be real // dependencies due to conditions. Those that are real @@ -471,11 +471,11 @@ namespace yask { // detailed check of g1 input points on RHS of eq2. for (auto* i2 : ip2) { - // Same logical grid? - bool same_grid = i2->isSameLogicalGrid(*op1); + // Same logical var? + bool same_var = i2->isSameLogicalVar(*op1); - // If not same grid, no dependency. - if (!same_grid) + // If not same var, no dependency. + if (!same_var) continue; // Both points at same step? @@ -494,8 +494,8 @@ namespace yask { // Exit with error. string stepmsg = same_step ? " at '" + step_expr1->makeQuotedStr() + "'" : ""; - THROW_YASK_EXCEPTION("Error: disallowed dependency: grid '" + - op1->makeLogicalGridStr() + "' on LHS of equation " + + THROW_YASK_EXCEPTION("Error: disallowed dependency: var '" + + op1->makeLogicalVarStr() + "' on LHS of equation " + eq1->makeQuotedStr() + " also appears on its RHS" + stepmsg); } @@ -546,9 +546,9 @@ namespace yask { topo_sort(); } - // Visitor for determining vectorization potential of grid points. - // Vectorization depends not only on the dims of the grid itself - // but also on how the grid is indexed at each point. + // Visitor for determining vectorization potential of var points. + // Vectorization depends not only on the dims of the var itself + // but also on how the var is indexed at each point. class SetVecVisitor : public ExprVisitor { const Dimensions& _dims; @@ -556,28 +556,28 @@ namespace yask { SetVecVisitor(const Dimensions& dims) : _dims(dims) { _visitEqualsLhs = true; - _visitGridPointArgs = true; + _visitVarPointArgs = true; _visitConds = true; } - // Check each grid point in expr. - virtual string visit(GridPoint* gp) { - auto* grid = gp->getGrid(); + // Check each var point in expr. + virtual string visit(VarPoint* gp) { + auto* var = gp->getVar(); // Never vectorize scalars. - if (grid->get_num_dims() == 0) { - gp->setVecType(GridPoint::VEC_NONE); + if (var->get_num_dims() == 0) { + gp->setVecType(VarPoint::VEC_NONE); return ""; // Also, no args to visit. } // Amount of vectorization allowed primarily depends on number - // of folded dimensions in the grid accessed at this point. - int grid_nfd = grid->getNumFoldableDims(); + // of folded dimensions in the var accessed at this point. + int var_nfd = var->getNumFoldableDims(); int soln_nfd = _dims._foldGT1.size(); - assert(grid_nfd <= soln_nfd); + assert(var_nfd <= soln_nfd); // Vectorization is only possible if each access to a vectorized - // dim is a simple offset. For example, in grid dim 'x', the + // dim is a simple offset. For example, in var dim 'x', the // index in the corresponding posn must be 'x', 'x+n', or 'x-n'. int fdoffsets = 0; for (auto fdim : _dims._foldGT1.getDims()) { @@ -585,28 +585,28 @@ namespace yask { if (gp->getArgOffsets().lookup(fdname)) fdoffsets++; } - assert(fdoffsets <= grid_nfd); + assert(fdoffsets <= var_nfd); // All folded dims are vectorizable? // NB: this will always be the case when there is // no folding in the soln. if (fdoffsets == soln_nfd) - gp->setVecType(GridPoint::VEC_FULL); // all good. + gp->setVecType(VarPoint::VEC_FULL); // all good. // Some dims are vectorizable? else if (fdoffsets > 0) - gp->setVecType(GridPoint::VEC_PARTIAL); + gp->setVecType(VarPoint::VEC_PARTIAL); // Uses no folded dims, so scalar only. else - gp->setVecType(GridPoint::VEC_NONE); + gp->setVecType(VarPoint::VEC_NONE); - // Also check args of this grid point. + // Also check args of this var point. return ExprVisitor::visit(gp); } }; - // Determine which grid points can be vectorized. + // Determine which var points can be vectorized. void Eqs::analyzeVec(const Dimensions& dims) { // Send a 'SetVecVisitor' to each point in @@ -628,7 +628,7 @@ namespace yask { } }; - // Visitor for determining inner-loop accesses of grid points. + // Visitor for determining inner-loop accesses of var points. class SetLoopVisitor : public ExprVisitor { const Dimensions& _dims; @@ -638,19 +638,19 @@ namespace yask { _visitEqualsLhs = true; } - // Check each grid point in expr. - virtual string visit(GridPoint* gp) { + // Check each var point in expr. + virtual string visit(VarPoint* gp) { - // Info from grid. - auto* grid = gp->getGrid(); - auto gdims = grid->get_dim_names(); + // Info from var. + auto* var = gp->getVar(); + auto gdims = var->get_dim_names(); // Check loop in this dim. auto idim = _dims._innerDim; // Access type. // Assume invariant, then check below. - GridPoint::LoopType lt = GridPoint::LOOP_INVARIANT; + VarPoint::LoopType lt = VarPoint::LOOP_INVARIANT; // Check every point arg. auto& args = gp->getArgs(); @@ -669,13 +669,13 @@ namespace yask { int offset = 0; if (gdims.at(ai) == idim && arg->isOffsetFrom(idim, offset)) { - lt = GridPoint::LOOP_OFFSET; + lt = VarPoint::LOOP_OFFSET; } // Otherwise, this arg uses idim, but not // in a simple way. else { - lt = GridPoint::LOOP_OTHER; + lt = VarPoint::LOOP_OTHER; break; // no need to continue. } } @@ -685,7 +685,7 @@ namespace yask { } }; - // Determine loop access behavior of grid points. + // Determine loop access behavior of var points. void Eqs::analyzeLoop(const Dimensions& dims) { // Send a 'SetLoopVisitor' to each point in @@ -694,30 +694,30 @@ namespace yask { visitEqs(&slv); } - // Update access stats for the grids. + // Update access stats for the vars. // For now, this us just const indices. // Halos are updated later, after packs are established. - void Eqs::updateGridStats() { + void Eqs::updateVarStats() { - // Find all LHS and RHS points and grids for all eqs. + // Find all LHS and RHS points and vars for all eqs. PointVisitor pv; visitEqs(&pv); // Analyze each eq. for (auto& eq : getAll()) { - // Get all grid points touched by this eq. + // Get all var points touched by this eq. auto& allPts1 = pv.getAllPts().at(eq.get()); - // Update stats of each grid accessed in 'eq'. + // Update stats of each var accessed in 'eq'. for (auto ap : allPts1) { - auto* g = ap->getGrid(); // grid for point 'ap'. + auto* g = ap->getVar(); // var for point 'ap'. g->updateConstIndices(ap->getArgConsts()); } } } - // Find scratch-grid eqs needed for each non-scratch eq. These will + // Find scratch-var eqs needed for each non-scratch eq. These will // eventually be gathered into bundles and saved as the "scratch // children" for each non-scratch bundles. void Eqs::analyzeScratch() { @@ -735,15 +735,15 @@ namespace yask { // Direct deps: eq3 -> eq2(s) -> eq1(s). // eq1 and eq2 are scratch children of eq3. - // Find all LHS and RHS points and grids for all eqs. + // Find all LHS and RHS points and vars for all eqs. PointVisitor pv; visitEqs(&pv); // Analyze each eq. for (auto& eq1 : getAll()) { - // Output grid for this eq. - auto* og1 = pv.getOutputGrids().at(eq1.get()); + // Output var for this eq. + auto* og1 = pv.getOutputVars().at(eq1.get()); // Only need to look at dep paths starting from non-scratch eqs. if (og1->isScratch()) @@ -752,7 +752,7 @@ namespace yask { // We start with each non-scratch eq and walk the dep tree to // find all dependent scratch eqs. It's important to // then visit the eqs in dep order using 'path' to get only - // unbroken chains of scratch grids. + // unbroken chains of scratch vars. // Note that sub-paths may be visited more than once, e.g., // 'eq3 -> eq2(s)' and 'eq3 -> eq2(s) -> eq1(s)' are 2 paths from // the second example above, but this shouldn't cause any issues, @@ -763,12 +763,12 @@ namespace yask { // immediately or indirectly; 'path' leads from // 'eq1' to 'b'. (eq1, [&](equalsExprPtr b, EqList& path) { - //auto* ogb = pv.getOutputGrids().at(b.get()); + //auto* ogb = pv.getOutputVars().at(b.get()); - // Find scratch-grid eqs in this dep path that are + // Find scratch-var eqs in this dep path that are // needed for 'eq1'. Walk dep path from 'eq1' to 'b' - // until a non-scratch grid is found. - unordered_set scratches_seen; + // until a non-scratch var is found. + unordered_set scratches_seen; for (auto eq2 : path) { // Don't process 'eq1', the initial non-scratch eq. @@ -778,8 +778,8 @@ namespace yask { // If this isn't a scratch eq, we are done // w/this path because we only want the eqs // from 'eq1' through an *unbroken* chain of - // scratch grids. - auto* og2 = pv.getOutputGrids().at(eq2.get()); + // scratch vars. + auto* og2 = pv.getOutputVars().at(eq2.get()); if (!og2->isScratch()) break; @@ -789,12 +789,12 @@ namespace yask { // Check for illegal scratch path. // TODO: this is only illegal because the scratch - // write area is stored in the grid, so >1 write + // write area is stored in the var, so >1 write // areas can't be shared. Need to store the write // areas somewhere else, maybe in the equation or // bundle. Would require changes to kernel as well. if (scratches_seen.count(og2)) - THROW_YASK_EXCEPTION("Error: scratch-grid '" + + THROW_YASK_EXCEPTION("Error: scratch-var '" + og2->get_name() + "' depends upon itself"); scratches_seen.insert(og2); } @@ -844,12 +844,12 @@ namespace yask { PointVisitor pv; ee->accept(&pv); - // update list of input and output grids for this bundle. - auto* outGrid = pv.getOutputGrids().at(ee.get()); - _outGrids.insert(outGrid); - auto& inGrids = pv.getInputGrids().at(ee.get()); - for (auto* g : inGrids) - _inGrids.insert(g); + // update list of input and output vars for this bundle. + auto* outVar = pv.getOutputVars().at(ee.get()); + _outVars.insert(outVar); + auto& inVars = pv.getInputVars().at(ee.get()); + for (auto* g : inVars) + _inVars.insert(g); } // Print stats from eqs. @@ -873,7 +873,7 @@ namespace yask { cv.printStats(os, msg); } - // Visitor that will shift each grid point by an offset. + // Visitor that will shift each var point by an offset. class OffsetVisitor: public ExprVisitor { IntTuple _ofs; @@ -883,10 +883,10 @@ namespace yask { _visitEqualsLhs = true; } - // Visit a grid point. - virtual string visit(GridPoint* gp) { + // Visit a var point. + virtual string visit(VarPoint* gp) { - // Shift grid _ofs points. + // Shift var _ofs points. auto ofs0 = gp->getArgOffsets(); IntTuple new_loc = ofs0.addElements(_ofs, false); gp->setArgOffsets(new_loc); @@ -922,7 +922,7 @@ namespace yask { // Make a copy. auto eq2 = eq->clone(); - // Add offsets to each grid point. + // Add offsets to each var point. OffsetVisitor ov(clusterOffset); eq2->accept(&ov); @@ -965,7 +965,7 @@ namespace yask { // Loop through existing bundles, looking for one that // 'eq' can be added to. EqBundle* target = 0; - auto eqg = eq->getGrid(); + auto eqg = eq->getVar(); for (auto& eg : getAll()) { // Must be same scratch-ness. @@ -990,7 +990,7 @@ namespace yask { // adding 'eq' to 'eg'. bool is_ok = true; for (auto& eq2 : eg->getEqs()) { - auto eq2g = eq2->getGrid(); + auto eq2g = eq2->getVar(); assert (eqg); assert (eq2g); @@ -1007,7 +1007,7 @@ namespace yask { // Look for any dependency between 'eq' and 'eq2'. if (is_ok && eq_deps.is_dep(eq, eq2)) { #if DEBUG_ADD_EXPRS - cout << "addEqFromGrid: not adding equation " << + cout << "addEqFromVar: not adding equation " << eq->makeQuotedStr() << " to " << eg.getDescr() << " because of dependency w/equation " << eq2->makeQuotedStr() << endl; @@ -1052,17 +1052,17 @@ namespace yask { #endif target->addEq(eq); - // Remember eq and updated grid. + // Remember eq and updated var. _eqs_in_bundles.insert(eq); - _outGrids.insert(eq->getGrid()); + _outVars.insert(eq->getVar()); return newBundle; } - // Find halos needed for each grid. + // Find halos needed for each var. void EqBundlePacks::calcHalos(EqBundles& allBundles) { - // Find all LHS and RHS points and grids for all eqs. + // Find all LHS and RHS points and vars for all eqs. PointVisitor pv; visitEqs(&pv); @@ -1076,18 +1076,18 @@ namespace yask { for (auto& eq : bp->getEqs()) { - // Get all grid points touched by this eq. + // Get all var points touched by this eq. auto& allPts1 = pv.getAllPts().at(eq.get()); - // Update stats of each grid accessed in 'eq'. + // Update stats of each var accessed in 'eq'. for (auto ap : allPts1) { - auto* g = ap->getGrid(); // grid for point 'ap'. + auto* g = ap->getVar(); // var for point 'ap'. g->updateHalo(pname, ap->getArgOffsets()); } } } - // Next, propagate halos through scratch grids as needed. + // Next, propagate halos through scratch vars as needed. // Example: // eq1: scr(x) EQUALS u(t,x+1); <-- orig halo of u = 1. @@ -1113,16 +1113,16 @@ namespace yask { // eq1 and eq2 are bundled => scr1 and scr2 halos are max(3,4) = 4. // Direct deps: eq3 -> eq1(s), eq3 -> eq2(s). - // Keep a list of maps of shadow grids. - // Each map: key=real-grid ptr, val=shadow-grid ptr. - // These shadow grids will be used to track + // Keep a list of maps of shadow vars. + // Each map: key=real-var ptr, val=shadow-var ptr. + // These shadow vars will be used to track // updated halos for each path. // We don't want to update the real halos until // we've walked all the paths using the original // halos. - // At the end, the real grids will be updated + // At the end, the real vars will be updated // from the shadows. - vector< map> shadows; + vector< map> shadows; // Packs. for (auto& bp : getAll()) { @@ -1154,7 +1154,7 @@ namespace yask { // 'b1' to 'bn'. (b1, [&](EqBundlePtr bn, EqBundleList& path) { - // Create a new empty map of shadow grids for this path. + // Create a new empty map of shadow vars for this path. shadows.resize(shadows.size() + 1); auto& shadow_map = shadows.back(); @@ -1173,41 +1173,41 @@ namespace yask { if (!b2->isScratch()) break; - // Make shadow copies of all grids touched by 'eq2'. - // All changes will be applied to these shadow grids + // Make shadow copies of all vars touched by 'eq2'. + // All changes will be applied to these shadow vars // for the current 'path'. for (auto& eq : b2->getEqs()) { - // Output grid. - auto* og = pv.getOutputGrids().at(eq.get()); + // Output var. + auto* og = pv.getOutputVars().at(eq.get()); if (shadow_map.count(og) == 0) - shadow_map[og] = new GridVar(*og); + shadow_map[og] = new Var(*og); - // Input grids. + // Input vars. auto& inPts = pv.getInputPts().at(eq.get()); for (auto* ip : inPts) { - auto* ig = ip->getGrid(); + auto* ig = ip->getVar(); if (shadow_map.count(ig) == 0) - shadow_map[ig] = new GridVar(*ig); + shadow_map[ig] = new Var(*ig); } } // For each scratch bundle, set the size of all its - // output grids' halos to the max across its + // output vars' halos to the max across its // halos. We need to do this because halos are - // written in a scratch grid. Since they are + // written in a scratch var. Since they are // bundled, all the writes must be over the same // area. // First, set first eq halo the max of all. auto& eq1 = b2->getEqs().front(); - auto* og1 = shadow_map[eq1->getGrid()]; + auto* og1 = shadow_map[eq1->getVar()]; for (auto& eq2 : b2->getEqs()) { if (eq1 == eq2) continue; // Adjust g1 to max(g1, g2). - auto* og2 = shadow_map[eq2->getGrid()]; + auto* og2 = shadow_map[eq2->getVar()]; og1->updateHalo(*og2); } @@ -1217,13 +1217,13 @@ namespace yask { continue; // Adjust g2 to g1. - auto* og2 = shadow_map[eq2->getGrid()]; + auto* og2 = shadow_map[eq2->getVar()]; og2->updateHalo(*og1); } // Get updated halos from the scratch bundle. These // are the points that are read from the dependent - // eq(s). For scratch grids, the halo areas must + // eq(s). For scratch vars, the halo areas must // also be written to. auto left_ohalo = og1->getHaloSizes(pname, true); auto right_ohalo = og1->getHaloSizes(pname, false); @@ -1234,15 +1234,15 @@ namespace yask { " & " << right_ohalo.makeDimValStr() << endl; #endif - // Recalc min halos of all input grids of all + // Recalc min halos of all input vars of all // scratch eqs in this bundle by adding size of - // output-grid halos. + // output-var halos. for (auto& eq : b2->getEqs()) { auto& inPts = pv.getInputPts().at(eq.get()); // Input points. for (auto ip : inPts) { - auto* ig = shadow_map[ip->getGrid()]; + auto* ig = shadow_map[ip->getVar()]; auto& ao = ip->getArgOffsets(); // e.g., '2' for 'x+2'. // Increase range by subtracting left halos and @@ -1263,8 +1263,8 @@ namespace yask { } // bundles. } // packs. - // Apply the changes from the shadow grids. - // This will result in the grids containing the max + // Apply the changes from the shadow vars. + // This will result in the vars containing the max // of the shadow halos. for (auto& shadow_map : shadows) { #ifdef DEBUG_SCRATCH @@ -1282,7 +1282,7 @@ namespace yask { cout << "** cH: updated '" << orig_gp->get_name() << "'.\n"; #endif - // Release the shadow grid. + // Release the shadow var. delete shadow_gp; shadow_map.at(orig_gp) = NULL; } @@ -1290,7 +1290,7 @@ namespace yask { } // calcHalos(). // Divide all equations into eqBundles. - // Only process updates to grids in 'gridRegex'. + // Only process updates to vars in 'varRegex'. // 'targets': string provided by user to specify bundleing. void EqBundles::makeEqBundles(Eqs& allEqs, const CompilerSettings& settings, @@ -1308,8 +1308,8 @@ namespace yask { } } - // Make a regex for the allowed grids. - regex gridx(settings._gridRegex); + // Make a regex for the allowed vars. + regex varx(settings._varRegex); // Handle each key-value pair in 'targets' string. // Key is eq-bundle name (with possible format strings); value is regex pattern. @@ -1324,13 +1324,13 @@ namespace yask { // Search allEqs for matches to current value. for (auto eq : allEqs.getAll()) { - // Get name of updated grid. - auto gp = eq->getGrid(); + // Get name of updated var. + auto gp = eq->getVar(); assert(gp); string gname = gp->getName(); - // Match to gridx? - if (!regex_search(gname, gridx)) + // Match to varx? + if (!regex_search(gname, varx)) continue; // Match to patx? @@ -1349,13 +1349,13 @@ namespace yask { // Add all remaining equations. for (auto eq : allEqs.getAll()) { - // Get name of updated grid. - auto gp = eq->getGrid(); + // Get name of updated var. + auto gp = eq->getVar(); assert(gp); string gname = gp->getName(); - // Match to gridx? - if (!regex_search(gname, gridx)) + // Match to varx? + if (!regex_search(gname, varx)) continue; // Add equation. @@ -1373,9 +1373,9 @@ namespace yask { for (auto& eg1 : getAll()) { os << " " << eg1->getDescr() << ":\n" " Contains " << eg1->getNumEqs() << " equation(s).\n" - " Updates the following grid(s): "; + " Updates the following var(s): "; int i = 0; - for (auto* g : eg1->getOutputGrids()) { + for (auto* g : eg1->getOutputVars()) { if (i++) os << ", "; os << g->getName(); @@ -1471,11 +1471,11 @@ namespace yask { for (auto& eq : bp->getEqs()) _eqs.insert(eq); - // update list of input and output grids for this pack. - for (auto& g : bp->getOutputGrids()) - _outGrids.insert(g); - for (auto& g : bp->getInputGrids()) - _inGrids.insert(g); + // update list of input and output vars for this pack. + for (auto& g : bp->getOutputVars()) + _outVars.insert(g); + for (auto& g : bp->getInputVars()) + _inVars.insert(g); } // Add 'bp' from 'allBundles'. Create new pack if needed. Returns @@ -1541,10 +1541,10 @@ namespace yask { assert(target); target->addBundle(bp); - // Remember pack and updated grids. + // Remember pack and updated vars. _bundles_in_packs.insert(bp); - for (auto& g : bp->getOutputGrids()) - _outGrids.insert(g); + for (auto& g : bp->getOutputVars()) + _outVars.insert(g); return newPack; } @@ -1576,9 +1576,9 @@ namespace yask { os << b->getName(); } os << ".\n"; - os << " Updates the following grid(s): "; + os << " Updates the following var(s): "; i = 0; - for (auto* g : bp1->getOutputGrids()) { + for (auto* g : bp1->getOutputVars()) { if (i++) os << ", "; os << g->getName(); diff --git a/src/compiler/lib/Eqs.hpp b/src/compiler/lib/Eqs.hpp index ae97057e..513dfb5e 100644 --- a/src/compiler/lib/Eqs.hpp +++ b/src/compiler/lib/Eqs.hpp @@ -370,16 +370,16 @@ namespace yask { Dimensions& dims, std::ostream& os); - // Determine which grid points can be vectorized. + // Determine which var points can be vectorized. virtual void analyzeVec(const Dimensions& dims); - // Determine how grid points are accessed in a loop. + // Determine how var points are accessed in a loop. virtual void analyzeLoop(const Dimensions& dims); - // Update grid access stats. - virtual void updateGridStats(); + // Update var access stats. + virtual void updateVarStats(); - // Find scratch-grid eqs needed for each non-scratch eq. + // Find scratch-var eqs needed for each non-scratch eq. virtual void analyzeScratch(); }; @@ -387,9 +387,9 @@ namespace yask { class EqLot { protected: EqList _eqs; // all equations. - Grids _outGrids; // grids updated by _eqs. - Grids _inGrids; // grids read from by _eqs. - bool _isScratch = false; // true if _eqs update temp grid(s). + Vars _outVars; // vars updated by _eqs. + Vars _inVars; // vars read from by _eqs. + bool _isScratch = false; // true if _eqs update temp var(s). public: @@ -425,19 +425,19 @@ namespace yask { // Updating temp vars? virtual bool isScratch() const { return _isScratch; } - // Get grids output and input. - virtual const Grids& getOutputGrids() const { - return _outGrids; + // Get vars output and input. + virtual const Vars& getOutputVars() const { + return _outVars; } - virtual const Grids& getInputGrids() const { - return _inGrids; + virtual const Vars& getInputVars() const { + return _inVars; } // Print stats for the equation(s). virtual void printStats(ostream& os, const string& msg); }; - // A named equation bundle, which contains one or more grid-update + // A named equation bundle, which contains one or more var-update // equations. All equations in a bundle must have the same conditions. // Equations in a bundle must not have inter-dependencies because they // will be combined into a single expression. @@ -521,8 +521,8 @@ namespace yask { string _basename_default; Dimensions* _dims = 0; - // Track grids that are updated. - Grids _outGrids; + // Track vars that are updated. + Vars _outVars; // Map to track indices per eq-bundle name. map _indices; @@ -557,15 +557,15 @@ namespace yask { // on the target string. // Target string is a comma-separated list of key-value pairs, e.g., // "eqBundle1=foo,eqBundle2=bar". - // In this example, all eqs updating grid names containing 'foo' go in eqBundle1, - // all eqs updating grid names containing 'bar' go in eqBundle2, and + // In this example, all eqs updating var names containing 'foo' go in eqBundle1, + // all eqs updating var names containing 'bar' go in eqBundle2, and // each remaining eq goes into a separate eqBundle. void makeEqBundles(Eqs& eqs, const CompilerSettings& settings, std::ostream& os); - virtual const Grids& getOutputGrids() const { - return _outGrids; + virtual const Vars& getOutputVars() const { + return _outVars; } // Visit all the equations in all eqBundles. @@ -664,8 +664,8 @@ namespace yask { // Bundle index. int _idx = 0; - // Track grids that are updated. - Grids _outGrids; + // Track vars that are updated. + Vars _outVars; // Track bundles that have been added already. set _bundles_in_packs; @@ -681,9 +681,9 @@ namespace yask { void makePacks(EqBundles& bundles, std::ostream& os); - // Get all output grids. - virtual const Grids& getOutputGrids() const { - return _outGrids; + // Get all output vars. + virtual const Vars& getOutputVars() const { + return _outVars; } // Visit all the equations in all packs. @@ -692,7 +692,7 @@ namespace yask { bp->visitEqs(ev); } - // Find halos needed for each grid. + // Find halos needed for each var. virtual void calcHalos(EqBundles& allBundles); }; // EqBundlePacks. diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index 8d30e852..fcf988ba 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -33,9 +33,9 @@ IN THE SOFTWARE. namespace yask { - // grid_point APIs. - yc_grid* GridPoint::get_grid() { - return _grid; + // var_point APIs. + yc_var* VarPoint::get_var() { + return _var; } //node_factory API methods. @@ -53,12 +53,12 @@ namespace yask { } yc_equation_node_ptr - yc_node_factory::new_equation_node(yc_grid_point_node_ptr lhs, + yc_node_factory::new_equation_node(yc_var_point_node_ptr lhs, yc_number_node_ptr rexpr, yc_bool_node_ptr cond) const { if (!lhs) THROW_YASK_EXCEPTION("Error: empty LHS of equation"); - auto gpp = dynamic_pointer_cast(lhs); + auto gpp = dynamic_pointer_cast(lhs); assert(gpp); if (!rexpr) THROW_YASK_EXCEPTION("Error: empty RHS of " + @@ -66,8 +66,8 @@ namespace yask { auto rhs = dynamic_pointer_cast(rexpr); assert(rhs); - // Get to list of equations in soln indirectly thru grid. - GridVar* gp = gpp->getGrid(); + // Get to list of equations in soln indirectly thru var. + Var* gp = gpp->getVar(); assert(gp); auto* soln = gp->getSoln(); assert(soln); @@ -463,9 +463,9 @@ namespace yask { return ep; } - // Define the value of a grid point. + // Define the value of a var point. // Add this equation to the list of eqs for this stencil. - yc_equation_node_ptr operator EQUALS(yc_grid_point_node_ptr lhs, + yc_equation_node_ptr operator EQUALS(yc_var_point_node_ptr lhs, const yc_number_any_arg rhs) { yc_node_factory nfac; return nfac.new_equation_node(lhs, rhs); @@ -508,7 +508,7 @@ namespace yask { string FuncExpr::accept(ExprVisitor* ev) { return ev->visit(this); } - string GridPoint::accept(ExprVisitor* ev) { + string VarPoint::accept(ExprVisitor* ev) { return ev->visit(this); } string EqualsExpr::accept(ExprVisitor* ev) { @@ -520,7 +520,7 @@ namespace yask { // EqualsExpr methods. bool EqualsExpr::isScratch() { - GridVar* gp = getGrid(); + Var* gp = getVar(); return gp && gp->isScratch(); } bool EqualsExpr::isSame(const Expr* other) const { @@ -605,23 +605,23 @@ namespace yask { return false; } - // GridPoint methods. - GridPoint::GridPoint(GridVar* grid, const numExprPtrVec& args) : - _grid(grid), _args(args) { + // VarPoint methods. + VarPoint::VarPoint(Var* var, const numExprPtrVec& args) : + _var(var), _args(args) { // Check for correct number of args. - size_t nd = grid->getDims().size(); + size_t nd = var->getDims().size(); if (nd != args.size()) { - FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a grid point in " << - nd << "-D grid '" << getGridName() << "' with " << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a var point in " << + nd << "-D var '" << getVarName() << "' with " << args.size() << " indices"); } // Eval each arg. #ifdef DEBUG_GP - cout << "Creating grid point " << makeQuotedStr() << "...\n"; + cout << "Creating var point " << makeQuotedStr() << "...\n"; #endif - auto dims = grid->getDims(); + auto dims = var->getDims(); for (size_t i = 0; i < nd; i++) { auto dim = dims.at(i); auto dname = dim->getName(); @@ -651,31 +651,31 @@ namespace yask { } _updateStr(); } - const numExprPtr GridPoint::getArg(const string& dim) const { - for (int di = 0; di < _grid->get_num_dims(); di++) { - auto& dn = _grid->get_dim_name(di); // name of this dim. + const numExprPtr VarPoint::getArg(const string& dim) const { + for (int di = 0; di < _var->get_num_dims(); di++) { + auto& dn = _var->get_dim_name(di); // name of this dim. if (dim == dn) return _args.at(di); } return nullptr; } - const string& GridPoint::getGridName() const { - return _grid->getName(); + const string& VarPoint::getVarName() const { + return _var->getName(); } - string GridPoint::getGridPtr() const { - string gname = _grid->getName(); + string VarPoint::getVarPtr() const { + string gname = _var->getName(); string expr = "(static_cast<_context_type::" + gname + "_type*>(_context_data->"; - if (_grid->isScratch()) + if (_var->isScratch()) expr += gname + "_list[region_thread_idx]"; else expr += gname + "_ptr"; expr += ".get()->gbp()))"; return expr; } - bool GridPoint::isGridFoldable() const { - return _grid->isFoldable(); + bool VarPoint::isVarFoldable() const { + return _var->isFoldable(); } - string GridPoint::makeArgStr(const VarMap* varMap) const { + string VarPoint::makeArgStr(const VarMap* varMap) const { string str; int i = 0; for (auto arg : _args) { @@ -684,26 +684,26 @@ namespace yask { } return str; } - string GridPoint::makeStr(const VarMap* varMap) const { - string str = _grid->getName() + "(" + + string VarPoint::makeStr(const VarMap* varMap) const { + string str = _var->getName() + "(" + makeArgStr(varMap) + ")"; return str; } - string GridPoint::makeLogicalGridStr(const VarMap* varMap) const { - string str = _grid->getName(); + string VarPoint::makeLogicalVarStr(const VarMap* varMap) const { + string str = _var->getName(); if (_consts.size()) str += "(" + _consts.makeDimValStr() + ")"; return str; } - const indexExprPtrVec& GridPoint::getDims() const { - return _grid->getDims(); + const indexExprPtrVec& VarPoint::getDims() const { + return _var->getDims(); } // Make string like "x+(4/VLEN_X)" from // original arg "x+4" in 'dname' dim. // This object has numerators; 'fold' object has denominators. // Args w/o simple offset are not modified. - string GridPoint::makeNormArgStr(const string& dname, + string VarPoint::makeNormArgStr(const string& dname, const Dimensions& dims, const VarMap* varMap) const { string res; @@ -715,7 +715,7 @@ namespace yask { // Otherwise, just find and format arg as-is. else { - auto& gdims = _grid->getDims(); + auto& gdims = _var->getDims(); for (size_t i = 0; i < gdims.size(); i++) { auto gdname = gdims[i]->getName(); if (gdname == dname) @@ -730,11 +730,11 @@ namespace yask { // original args "x+4, y, z-2". // This object has numerators; norm object has denominators. // Args w/o simple offset are not modified. - string GridPoint::makeNormArgStr(const Dimensions& dims, + string VarPoint::makeNormArgStr(const Dimensions& dims, const VarMap* varMap) const { string res; - auto& gd = _grid->getDims(); + auto& gd = _var->getDims(); for (size_t i = 0; i < gd.size(); i++) { if (i) res += ", "; @@ -745,19 +745,19 @@ namespace yask { } // Make string like "g->_wrap_step(t+1)" from original arg "t+1" - // if grid uses step dim, "0" otherwise. - // If grid doesn't allow dynamic alloc, set to fixed value. - string GridPoint::makeStepArgStr(const string& gridPtr, const Dimensions& dims) const { + // if var uses step dim, "0" otherwise. + // If var doesn't allow dynamic alloc, set to fixed value. + string VarPoint::makeStepArgStr(const string& varPtr, const Dimensions& dims) const { - auto& gd = _grid->getDims(); + auto& gd = _var->getDims(); for (size_t i = 0; i < gd.size(); i++) { auto dname = gd[i]->getName(); auto& arg = _args.at(i); if (dname == dims._stepDim) { - if (_grid->is_dynamic_step_alloc()) - return gridPtr + "->_wrap_step(" + arg->makeStr() + ")"; + if (_var->is_dynamic_step_alloc()) + return varPtr + "->_wrap_step(" + arg->makeStr() + ")"; else { - auto step_alloc = _grid->get_step_alloc_size(); + auto step_alloc = _var->get_step_alloc_size(); if (step_alloc == 1) return "0"; // 1 alloc => always index 0. else @@ -769,11 +769,11 @@ namespace yask { return "0"; } - // Set given arg to given offset; ignore if not in step or domain grid dims. - void GridPoint::setArgOffset(const IntScalar& offset) { + // Set given arg to given offset; ignore if not in step or domain var dims. + void VarPoint::setArgOffset(const IntScalar& offset) { - // Find dim in grid. - auto gdims = _grid->getDims(); + // Find dim in var. + auto gdims = _var->getDims(); for (size_t i = 0; i < gdims.size(); i++) { auto gdim = gdims[i]; @@ -815,10 +815,10 @@ namespace yask { } // Set given arg to given const; - void GridPoint::setArgConst(const IntScalar& val) { + void VarPoint::setArgConst(const IntScalar& val) { - // Find dim in grid. - auto gdims = _grid->getDims(); + // Find dim in var. + auto gdims = _var->getDims(); for (size_t i = 0; i < gdims.size(); i++) { auto gdim = gdims[i]; diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 9cdc5431..a3b699ae 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -64,8 +64,8 @@ namespace yask { class NumExpr; typedef shared_ptr numExprPtr; typedef vector numExprPtrVec; - class GridPoint; - typedef shared_ptr gridPointPtr; + class VarPoint; + typedef shared_ptr varPointPtr; class IndexExpr; typedef shared_ptr indexExprPtr; typedef vector indexExprPtrVec; @@ -76,7 +76,7 @@ namespace yask { // More forward-decls. class ExprVisitor; - class GridVar; + class Var; class StencilSolution; struct Dimensions; @@ -218,7 +218,7 @@ namespace yask { } }; - // GridVar index types. + // Var index types. enum IndexType { STEP_INDEX, // the step dim. DOMAIN_INDEX, // a domain dim. @@ -333,7 +333,7 @@ namespace yask { virtual double get_value() const { return _f; } }; - // Any expression that returns a real (not from a grid). + // Any expression that returns a real (not from a var). // This is an expression leaf-node. class CodeExpr : public NumExpr { protected: @@ -771,10 +771,10 @@ namespace yask { } }; - // One specific point in a grid. + // One specific point in a var. // This is an expression leaf-node. - class GridPoint : public NumExpr, - public virtual yc_grid_point_node { + class VarPoint : public NumExpr, + public virtual yc_var_point_node { public: @@ -795,7 +795,7 @@ namespace yask { }; protected: - GridVar* _grid = 0; // the grid this point is from. + Var* _var = 0; // the var this point is from. // Index exprs for each dim, e.g., // "3, x-5, y*2, z+4" for dims "n, x, y, z". @@ -823,18 +823,18 @@ namespace yask { public: - // Construct a point given a grid and an arg for each dim. - GridPoint(GridVar* grid, const numExprPtrVec& args); + // Construct a point given a var and an arg for each dim. + VarPoint(Var* var, const numExprPtrVec& args); // Dtor. - virtual ~GridPoint() {} - - // Get parent grid info. - const GridVar* getGrid() const { return _grid; } - GridVar* getGrid() { return _grid; } - virtual const string& getGridName() const; - virtual string getGridPtr() const; - virtual bool isGridFoldable() const; + virtual ~VarPoint() {} + + // Get parent var info. + const Var* getVar() const { return _var; } + Var* getVar() { return _var; } + virtual const string& getVarName() const; + virtual string getVarPtr() const; + virtual bool isVarFoldable() const; virtual const indexExprPtrVec& getDims() const; // Accessors. @@ -859,7 +859,7 @@ namespace yask { // Get arg for 'dim' or return null if none. virtual const numExprPtr getArg(const string& dim) const; - // Set given arg to given offset; ignore if not in step or domain grid dims. + // Set given arg to given offset; ignore if not in step or domain var dims. virtual void setArgOffset(const IntScalar& offset); // Set given args to be given offsets. @@ -872,10 +872,10 @@ namespace yask { virtual void setArgConst(const IntScalar& val); // Some comparisons. - bool operator==(const GridPoint& rhs) const { + bool operator==(const VarPoint& rhs) const { return _defStr == rhs._defStr; } - bool operator<(const GridPoint& rhs) const { + bool operator<(const VarPoint& rhs) const { return _defStr < rhs._defStr; } @@ -884,15 +884,15 @@ namespace yask { // Check for equivalency. virtual bool isSame(const Expr* other) const { - auto p = dynamic_cast(other); + auto p = dynamic_cast(other); return p && *this == *p; } - // Check for same logical grid. - // A logical grid is defined by the grid itself + // Check for same logical var. + // A logical var is defined by the var itself // and any const indices. - virtual bool isSameLogicalGrid(const GridPoint& rhs) const { - return _grid == rhs._grid && _consts == rhs._consts; + virtual bool isSameLogicalVar(const VarPoint& rhs) const { + return _var == rhs._var && _consts == rhs._consts; } // String w/name and parens around args, e.g., 'u(x, y+2)'. @@ -901,7 +901,7 @@ namespace yask { // String w/name and parens around const args, e.g., 'u(n=4)'. // Apply substitutions to indices using 'varMap' if provided. - virtual string makeLogicalGridStr(const VarMap* varMap = 0) const; + virtual string makeLogicalVarStr(const VarMap* varMap = 0) const; // String w/just comma-sep args, e.g., 'x, y+2'. // Apply substitutions to indices using 'varMap' if provided. @@ -921,26 +921,26 @@ namespace yask { const VarMap* varMap = 0) const; // Make string like "g->_wrap_step(t+1)" from original arg "t+1" - // if grid uses step dim, "0" otherwise. - virtual string makeStepArgStr(const string& gridPtr, const Dimensions& dims) const; + // if var uses step dim, "0" otherwise. + virtual string makeStepArgStr(const string& varPtr, const Dimensions& dims) const; // Create a deep copy of this expression, - // except pointed-to grid is not copied. - virtual numExprPtr clone() const { return make_shared(*this); } - virtual gridPointPtr cloneGridPoint() const { return make_shared(*this); } + // except pointed-to var is not copied. + virtual numExprPtr clone() const { return make_shared(*this); } + virtual varPointPtr cloneVarPoint() const { return make_shared(*this); } // APIs. - virtual yc_grid* get_grid(); + virtual yc_var* get_var(); }; } // namespace yask. -// Define hash function for GridPoint for unordered_{set,map}. +// Define hash function for VarPoint for unordered_{set,map}. // TODO: make this more efficient. namespace std { using namespace yask; - template <> struct hash { - size_t operator()(const GridPoint& k) const { + template <> struct hash { + size_t operator()(const VarPoint& k) const { return hash{}(k.makeStr()); } }; @@ -948,25 +948,25 @@ namespace std { namespace yask { - // Equality operator for a grid point. + // Equality operator for a var point. // This defines the LHS as equal to the RHS; it is NOT // a comparison operator; it is NOT an assignment operator. // It also holds an optional condition. class EqualsExpr : public Expr, public virtual yc_equation_node { protected: - gridPointPtr _lhs; + varPointPtr _lhs; numExprPtr _rhs; boolExprPtr _cond; boolExprPtr _step_cond; public: - EqualsExpr(gridPointPtr lhs, numExprPtr rhs, + EqualsExpr(varPointPtr lhs, numExprPtr rhs, boolExprPtr cond = nullptr, boolExprPtr step_cond = nullptr) : _lhs(lhs), _rhs(rhs), _cond(cond), _step_cond(step_cond) { } EqualsExpr(const EqualsExpr& src) : - _lhs(src._lhs->cloneGridPoint()), + _lhs(src._lhs->cloneVarPoint()), _rhs(src._rhs->clone()) { if (src._cond) _cond = src._cond->clone(); @@ -978,8 +978,8 @@ namespace yask { _step_cond = nullptr; } - gridPointPtr& getLhs() { return _lhs; } - const gridPointPtr& getLhs() const { return _lhs; } + varPointPtr& getLhs() { return _lhs; } + const varPointPtr& getLhs() const { return _lhs; } numExprPtr& getRhs() { return _rhs; } const numExprPtr& getRhs() const { return _rhs; } boolExprPtr& getCond() { return _cond; } @@ -993,14 +993,14 @@ namespace yask { static string condOpStr() { return "IF"; } static string stepCondOpStr() { return "IF_STEP"; } - // Get pointer to grid on LHS or NULL if not set. - virtual GridVar* getGrid() { + // Get pointer to var on LHS or NULL if not set. + virtual Var* getVar() { if (_lhs.get()) - return _lhs->getGrid(); + return _lhs->getVar(); return NULL; } - // LHS is scratch grid. + // LHS is scratch var. virtual bool isScratch(); // Check for equivalency. @@ -1013,7 +1013,7 @@ namespace yask { } // APIs. - virtual yc_grid_point_node_ptr get_lhs() { return _lhs; } + virtual yc_var_point_node_ptr get_lhs() { return _lhs; } virtual yc_number_node_ptr get_rhs() { return _rhs; } virtual yc_bool_node_ptr get_cond() { return _cond; } virtual yc_bool_node_ptr get_step_cond() { return _step_cond; } @@ -1035,15 +1035,15 @@ namespace yask { } }; - typedef set GridPointSet; - typedef set gridPointPtrSet; - typedef vector GridPointVec; + typedef set VarPointSet; + typedef set varPointPtrSet; + typedef vector VarPointVec; // Use SET_VALUE_FROM_EXPR for creating a string to insert any C++ code // that evaluates to a real_t. // The 1st arg must be the LHS of an assignment statement. // The 2nd arg must evaluate to a real_t (float or double) expression, - // but it must NOT include access to a grid. + // but it must NOT include access to a var. // The code string is constructed as if writing to an ostream, // so '<<' operators may be used to evaluate local variables. // Floating-point variables will be printed w/o loss of precision. diff --git a/src/compiler/lib/ExprUtils.hpp b/src/compiler/lib/ExprUtils.hpp index d5a20455..2148efc7 100644 --- a/src/compiler/lib/ExprUtils.hpp +++ b/src/compiler/lib/ExprUtils.hpp @@ -224,8 +224,8 @@ namespace yask { os << ":" << endl << " " << getNumNodes() << " node(s)." << endl << " " << getNumPairs() << " node pair(s)." << endl << - " " << getNumReads() << " grid read(s)." << endl << - " " << getNumWrites() << " grid write(s)." << endl << + " " << getNumReads() << " var read(s)." << endl << + " " << getNumWrites() << " var write(s)." << endl << " " << getNumOps() << " FP math operation(s)." << endl; } @@ -246,7 +246,7 @@ namespace yask { _numNodes++; return ""; } - virtual string visit(GridPoint* gp) { + virtual string visit(VarPoint* gp) { if (alreadyVisited(gp)) return ""; _numNodes++; _numReads++; diff --git a/src/compiler/lib/Print.cpp b/src/compiler/lib/Print.cpp index acd21970..bea476cc 100644 --- a/src/compiler/lib/Print.cpp +++ b/src/compiler/lib/Print.cpp @@ -52,9 +52,9 @@ namespace yask { /////// Top-down - // A grid read. + // A var read. // Uses the PrintHelper to format. - string PrintVisitorTopDown::visit(GridPoint* gp) { + string PrintVisitorTopDown::visit(VarPoint* gp) { _numCommon += _ph.getNumCommon(gp); return _ph.readFromPoint(_os, *gp); } @@ -156,7 +156,7 @@ namespace yask { string rhs = ee->getRhs()->accept(this); // Write statement with embedded rhs. - gridPointPtr gpp = ee->getLhs(); + varPointPtr gpp = ee->getLhs(); _os << _ph.getLinePrefix() << _ph.writeToPoint(_os, *gpp, rhs); // Null ptr => no condition. @@ -238,12 +238,12 @@ namespace yask { return res; } - // A grid point: just set expr. - string PrintVisitorBottomUp::visit(GridPoint* gp) { + // A var point: just set expr. + string PrintVisitorBottomUp::visit(VarPoint* gp) { return trySimplePrint(gp, true); } - // A grid index. + // A var index. string PrintVisitorBottomUp::visit(IndexExpr* ie) { return trySimplePrint(ie, true); } @@ -430,7 +430,7 @@ namespace yask { string PrintVisitorBottomUp::visit(EqualsExpr* ee) { // Note that we don't try top-down here. - // We always assign the RHS to the grid. + // We always assign the RHS to the var. // Eval RHS. Expr* rp = ee->getRhs().get(); @@ -441,7 +441,7 @@ namespace yask { makeNextTempVar(tmp, rp) << rhs << _ph.getLineSuffix(); // sets _exprStr. // Comment about update. - gridPointPtr gpp = ee->getLhs(); + varPointPtr gpp = ee->getLhs(); _os << "\n // Update value at " << gpp->makeStr(); // Comment about condition. @@ -456,7 +456,7 @@ namespace yask { } _os << ".\n"; - // Write RHS expr to grid. + // Write RHS expr to var. _os << _ph.getLinePrefix() << _ph.writeToPoint(_os, *gpp, tmp) << _ph.getLineSuffix(); return ""; // EQUALS doesn't return a value. @@ -470,7 +470,7 @@ namespace yask { } // A point: output it. - string POVRayPrintVisitor::visit(GridPoint* gp) { + string POVRayPrintVisitor::visit(VarPoint* gp) { _numPts++; // Pick a color based on its distance. @@ -483,8 +483,8 @@ namespace yask { ////// DOT-language. - // A grid access. - string DOTPrintVisitor::visit(GridPoint* gp) { + // A var access. + string DOTPrintVisitor::visit(VarPoint* gp) { string label = getLabel(gp); if (label.size()) _os << label << " [ shape = box ];" << endl; @@ -577,12 +577,12 @@ namespace yask { return ""; } - // A grid access. - string SimpleDOTPrintVisitor::visit(GridPoint* gp) { + // A var access. + string SimpleDOTPrintVisitor::visit(VarPoint* gp) { string label = getLabel(gp); if (label.size()) { _os << label << " [ shape = box ];" << endl; - _gridsSeen.insert(label); + _varsSeen.insert(label); } return ""; } @@ -620,15 +620,15 @@ namespace yask { // LHS is source. ee->getLhs()->accept(this); string label = getLabel(ee, false); - for (auto g : _gridsSeen) + for (auto g : _varsSeen) label = g; // really should only be one. - _gridsSeen.clear(); + _varsSeen.clear(); // RHS nodes are target. ee->getRhs()->accept(this); - for (auto g : _gridsSeen) + for (auto g : _varsSeen) _os << label << " -> " << g << ";" << endl; - _gridsSeen.clear(); + _varsSeen.clear(); // Ignoring conditions. return ""; @@ -713,7 +713,7 @@ namespace yask { // Loop through all eqBundles. for (auto& eq : _eqBundles.getAll()) { - // TODO: separate mutiple grids. + // TODO: separate mutiple vars. POVRayPrintVisitor pv(os); eq->visitEqs(&pv); os << " // " << pv.getNumPoints() << " stencil points" << endl; diff --git a/src/compiler/lib/Print.hpp b/src/compiler/lib/Print.hpp index 9787f2eb..3c413f34 100644 --- a/src/compiler/lib/Print.hpp +++ b/src/compiler/lib/Print.hpp @@ -145,17 +145,17 @@ namespace yask { return to_string(v); } - // Return a grid reference. + // Return a var reference. // The 'os' parameter is provided for derived types that // need to write intermediate code to a stream. - virtual string readFromPoint(ostream& os, const GridPoint& gp) { + virtual string readFromPoint(ostream& os, const VarPoint& gp) { return gp.makeStr(); } - // Return code to update a grid point. + // Return code to update a var point. // The 'os' parameter is provided for derived types that // need to write intermediate code to a stream. - virtual string writeToPoint(ostream& os, const GridPoint& gp, const string& val) { + virtual string writeToPoint(ostream& os, const VarPoint& gp, const string& val) { return gp.makeStr() + " EQUALS " + val; } }; @@ -215,10 +215,10 @@ namespace yask { // has been accepted. int getNumCommon() const { return _numCommon; } - // A grid access. - virtual string visit(GridPoint* gp); + // A var access. + virtual string visit(VarPoint* gp); - // A grid index. + // A var index. virtual string visit(IndexExpr* ie); // A constant. @@ -269,8 +269,8 @@ namespace yask { // Return empty string if more complex method should be used. virtual string trySimplePrint(Expr* ex, bool force); - // A grid point. - virtual string visit(GridPoint* gp); + // A var point. + virtual string visit(VarPoint* gp); // An index. virtual string visit(IndexExpr* ie); @@ -330,7 +330,7 @@ namespace yask { virtual string visit(EqualsExpr* ee); // A point. - virtual string visit(GridPoint* gp); + virtual string visit(VarPoint* gp); }; // Outputs a full GraphViz input file. @@ -357,8 +357,8 @@ namespace yask { public: DOTPrintVisitor(ostream& os) : _os(os) { } - // A grid read. - virtual string visit(GridPoint* gp); + // A var read. + virtual string visit(VarPoint* gp); // A constant. virtual string visit(ConstExpr* ce); @@ -385,14 +385,14 @@ namespace yask { // Outputs a simple GraphViz input file. class SimpleDOTPrintVisitor : public DOTPrintVisitor { protected: - set _gridsSeen; + set _varsSeen; public: SimpleDOTPrintVisitor(ostream& os) : DOTPrintVisitor(os) { } - // A grid read. - virtual string visit(GridPoint* gp); + // A var read. + virtual string visit(VarPoint* gp); // A constant. virtual string visit(ConstExpr* ce) { return ""; } @@ -425,7 +425,7 @@ namespace yask { StencilSolution& _stencil; const CompilerSettings& _settings; const Dimensions& _dims; - Grids& _grids; + Vars& _vars; EqBundles& _eqBundles; public: @@ -434,7 +434,7 @@ namespace yask { _stencil(stencil), _settings(stencil.getSettings()), _dims(stencil.getDims()), - _grids(stencil.getGrids()), + _vars(stencil.getVars()), _eqBundles(eqBundles) { } virtual ~PrinterBase() { } diff --git a/src/compiler/lib/Settings.cpp b/src/compiler/lib/Settings.cpp index 0c0895ad..fdc01760 100644 --- a/src/compiler/lib/Settings.cpp +++ b/src/compiler/lib/Settings.cpp @@ -28,7 +28,7 @@ IN THE SOFTWARE. #include "Print.hpp" #include "ExprUtils.hpp" #include "Parse.hpp" -#include "Grid.hpp" +#include "Var.hpp" #include "Print.hpp" #include "CppIntrin.hpp" @@ -43,9 +43,9 @@ namespace yask { return make_shared(name); } - // Find the dimensions to be used based on the grids in + // Find the dimensions to be used based on the vars in // the solution and the settings from the cmd-line or API. - void Dimensions::setDims(Grids& grids, + void Dimensions::setDims(Vars& vars, CompilerSettings& settings, int vlen, // SIMD len based on CPU arch. bool is_folding_efficient, // heuristic based on CPU arch. @@ -70,12 +70,12 @@ namespace yask { if (_domainDims.size()) os << "Explicit domain dimension(s): " << _domainDims.makeDimStr() << endl; - // Get dims from grids. - for (auto& gp : grids) { + // Get dims from vars. + for (auto& gp : vars) { auto& gname = gp->getName(); - os << "GridVar: " << gp->getDescr() << endl; + os << "Var: " << gp->getDescr() << endl; - // Dimensions in this grid. + // Dimensions in this var. for (auto dim : gp->getDims()) { auto& dname = dim->getName(); auto type = dim->getType(); @@ -89,9 +89,9 @@ namespace yask { } addStepDim(dname); - // Scratch grids cannot use step dim. + // Scratch vars cannot use step dim. if (gp->isScratch()) - THROW_YASK_EXCEPTION("Error: scratch grid '" + gname + + THROW_YASK_EXCEPTION("Error: scratch var '" + gname + "' cannot use step dimension '" + dname + "'.\n"); break; diff --git a/src/compiler/lib/Settings.hpp b/src/compiler/lib/Settings.hpp index a084b43c..3855d445 100644 --- a/src/compiler/lib/Settings.hpp +++ b/src/compiler/lib/Settings.hpp @@ -27,7 +27,7 @@ IN THE SOFTWARE. #pragma once -#include "Grid.hpp" +#include "Var.hpp" using namespace std; @@ -56,7 +56,7 @@ namespace yask { bool _doPairs = true; // find equation pairs. bool _doOptCluster = true; // apply optimizations also to cluster. string _eqBundleTargets; // how to bundle equations. - string _gridRegex; // grids to update. + string _varRegex; // vars to update. bool _findDeps = true; bool _printEqs = false; }; @@ -100,7 +100,7 @@ namespace yask { } // Find the dimensions to be used. - void setDims(Grids& grids, + void setDims(Vars& vars, CompilerSettings& settings, int vlen, bool is_folding_efficient, diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index d32167f7..175e4a03 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -33,11 +33,11 @@ using namespace std; namespace yask { // Stencil-solution APIs. - yc_grid_ptr StencilSolution::newGrid(const std::string& name, + yc_var_ptr StencilSolution::newVar(const std::string& name, bool isScratch, const std::vector& dims) { - // Make new grid and add to solution. + // Make new var and add to solution. // TODO: fix this mem leak--make smart ptr. // Copy pointers to concrete type. @@ -48,7 +48,7 @@ namespace yask { dims2.push_back(d2); } - auto* gp = new GridVar(name, isScratch, this, dims2); + auto* gp = new Var(name, isScratch, this, dims2); assert(gp); return gp; } @@ -69,25 +69,25 @@ namespace yask { void StencilSolution::analyze_solution(int vlen, bool is_folding_efficient) { - // Find all the stencil dimensions from the grids. + // Find all the stencil dimensions from the vars. // Create the final folds and clusters from the cmd-line options. - _dims.setDims(_grids, _settings, vlen, is_folding_efficient, *_dos); + _dims.setDims(_vars, _settings, vlen, is_folding_efficient, *_dos); - // Determine which grids can be folded. - _grids.setFolding(_dims); + // Determine which vars can be folded. + _vars.setFolding(_dims); - // Determine which grid points can be vectorized and analyze inner-loop accesses. + // Determine which var points can be vectorized and analyze inner-loop accesses. _eqs.analyzeVec(_dims); _eqs.analyzeLoop(_dims); // Find dependencies between equations. _eqs.analyzeEqs(_settings, _dims, *_dos); - // Update access stats for the grids. - _eqs.updateGridStats(); + // Update access stats for the vars. + _eqs.updateVarStats(); // Create equation bundles based on dependencies and/or target strings. - // This process may alter the halos in scratch grids. + // This process may alter the halos in scratch vars. _eqBundles.set_basename_default(_settings._eq_bundle_basename_default); _eqBundles.set_dims(_dims); _eqBundles.makeEqBundles(_eqs, _settings, *_dos); diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index dd8b37ad..d0e38dc7 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -63,7 +63,7 @@ namespace yask { ostream* _dos = &std::cout; // just a handy pointer to an ostream. // All vars accessible by the kernel. - Grids _grids; + Vars _vars; // All equations defined in this solution. Eqs _eqs; @@ -103,7 +103,7 @@ namespace yask { } // Simple accessors. - virtual Grids& getGrids() { return _grids; } + virtual Vars& getVars() { return _vars; } virtual Eqs& getEqs() { return _eqs; } virtual const CompilerSettings& getSettings() { return _settings; } virtual void setSettings(const CompilerSettings& settings) { @@ -127,8 +127,8 @@ namespace yask { return *_dos; } - // Make a new grid. - virtual yc_grid_ptr newGrid(const std::string& name, + // Make a new var. + virtual yc_var_ptr newVar(const std::string& name, bool isScratch, const std::vector& dims); @@ -154,37 +154,37 @@ namespace yask { return getLongName(); } - virtual yc_grid_ptr new_grid(const std::string& name, + virtual yc_var_ptr new_var(const std::string& name, const std::vector& dims) { - return newGrid(name, false, dims); + return newVar(name, false, dims); } - virtual yc_grid_ptr new_grid(const std::string& name, + virtual yc_var_ptr new_var(const std::string& name, const std::initializer_list& dims) { std::vector dim_vec(dims); - return newGrid(name, false, dim_vec); + return newVar(name, false, dim_vec); } - virtual yc_grid_ptr new_scratch_grid(const std::string& name, + virtual yc_var_ptr new_scratch_var(const std::string& name, const std::vector& dims) { - return newGrid(name, true, dims); + return newVar(name, true, dims); } - virtual yc_grid_ptr new_scratch_grid(const std::string& name, + virtual yc_var_ptr new_scratch_var(const std::string& name, const std::initializer_list& dims) { std::vector dim_vec(dims); - return newGrid(name, true, dim_vec); + return newVar(name, true, dim_vec); } - virtual int get_num_grids() const { - return int(_grids.size()); + virtual int get_num_vars() const { + return int(_vars.size()); } - virtual yc_grid_ptr get_grid(const std::string& name) { - for (int i = 0; i < get_num_grids(); i++) - if (_grids.at(i)->getName() == name) - return _grids.at(i); + virtual yc_var_ptr get_var(const std::string& name) { + for (int i = 0; i < get_num_vars(); i++) + if (_vars.at(i)->getName() == name) + return _vars.at(i); return nullptr; } - virtual std::vector get_grids() { - std::vector gv; - for (int i = 0; i < get_num_grids(); i++) - gv.push_back(_grids.at(i)); + virtual std::vector get_vars() { + std::vector gv; + for (int i = 0; i < get_num_vars(); i++) + gv.push_back(_vars.at(i)); return gv; } diff --git a/src/compiler/lib/Grid.cpp b/src/compiler/lib/Var.cpp similarity index 84% rename from src/compiler/lib/Grid.cpp rename to src/compiler/lib/Var.cpp index 9ef7884f..381c818c 100644 --- a/src/compiler/lib/Grid.cpp +++ b/src/compiler/lib/Var.cpp @@ -23,26 +23,26 @@ IN THE SOFTWARE. *****************************************************************************/ -///////// Methods for Grids, etc. //////////// +///////// Methods for Vars, etc. //////////// #include "Print.hpp" #include "ExprUtils.hpp" #include "Parse.hpp" -#include "Grid.hpp" +#include "Var.hpp" #include "Print.hpp" #include "CppIntrin.hpp" namespace yask { - // grid APIs. - yc_grid_point_node_ptr - GridVar::new_grid_point(const std::vector& index_exprs) { + // var APIs. + yc_var_point_node_ptr + Var::new_var_point(const std::vector& index_exprs) { // Check for correct number of indices. if (_dims.size() != index_exprs.size()) { - FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a grid point in " << - _dims.size() << "D grid '" << _name << "' with " << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a var point in " << + _dims.size() << "D var '" << _name << "' with " << index_exprs.size() << " index expressions"); } @@ -55,17 +55,17 @@ namespace yask { } // Create a point from the args. - gridPointPtr gpp = make_shared(this, args); + varPointPtr gpp = make_shared(this, args); return gpp; } - yc_grid_point_node_ptr - GridVar::new_relative_grid_point(const std::vector& dim_offsets) { + yc_var_point_node_ptr + Var::new_relative_var_point(const std::vector& dim_offsets) { // Check for correct number of indices. if (_dims.size() != dim_offsets.size()) { - FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a relative grid point in " << - _dims.size() << "D grid '" << _name << "' with " << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a relative var point in " << + _dims.size() << "D var '" << _name << "' with " << dim_offsets.size() << " indices"); } @@ -75,8 +75,8 @@ namespace yask { for (size_t i = 0; i < _dims.size(); i++) { auto dim = _dims.at(i); if (dim->getType() == MISC_INDEX) { - FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a relative grid point in " << - _dims.size() << "D grid '" << _name << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create a relative var point in " << + _dims.size() << "D var '" << _name << "' containing non-step or non-domain dim '" << dim->getName() << "'"); } @@ -85,7 +85,7 @@ namespace yask { } // Create a point from the args. - gridPointPtr gpp = make_shared(this, args); + varPointPtr gpp = make_shared(this, args); // Set the offsets, which creates a new // expression for each index. @@ -97,15 +97,15 @@ namespace yask { return gpp; } - vector GridVar::get_dim_names() const { + vector Var::get_dim_names() const { vector ret; for (auto dn : getDims()) ret.push_back(dn->getName()); return ret; } - // Ctor for GridVar. - GridVar::GridVar(string name, + // Ctor for Var. + Var::Var(string name, bool isScratch, StencilSolution* soln, const indexExprPtrVec& dims) : @@ -116,21 +116,21 @@ namespace yask { assert(soln); // Name already used? - auto& grids = soln->getGrids(); - for (auto gp : grids) { + auto& vars = soln->getVars(); + for (auto gp : vars) { if (gp->getName() == name) - THROW_YASK_EXCEPTION("Error: grid name '" + name + "' already used"); + THROW_YASK_EXCEPTION("Error: var name '" + name + "' already used"); } // Register in soln. - grids.insert(this); + vars.insert(this); // Define dims. _dims = dims; } - // Determine whether grid can be folded. - void GridVar::setFolding(const Dimensions& dims) { + // Determine whether var can be folded. + void Var::setFolding(const Dimensions& dims) { _numFoldableDims = 0; @@ -140,11 +140,11 @@ namespace yask { return; } - // Find the number of folded dims used in this grid. + // Find the number of folded dims used in this var. for (auto fdim : dims._foldGT1.getDims()) { auto& fdname = fdim.getName(); - // Search for dim in grid. + // Search for dim in var. bool found = false; for (auto gdim : _dims) { auto& gdname = gdim->getName(); @@ -157,7 +157,7 @@ namespace yask { _numFoldableDims++; } - // Can fold if ALL fold dims >1 are used in this grid. + // Can fold if ALL fold dims >1 are used in this var. // NB: this will always be true if there is no vectorization, i.e., // both are zero. We do this because the compiler expects stencils @@ -166,7 +166,7 @@ namespace yask { } // Determine whether halo sizes are equal. - bool GridVar::isHaloSame(const GridVar& other) const { + bool Var::isHaloSame(const Var& other) const { // Same dims? if (!areDimsSame(other)) @@ -188,12 +188,12 @@ namespace yask { return true; } - // Update halos based on halo in 'other' grid. - // This grid's halos can only be increased. - void GridVar::updateHalo(const GridVar& other) { + // Update halos based on halo in 'other' var. + // This var's halos can only be increased. + void Var::updateHalo(const Var& other) { assert(areDimsSame(other)); - // Loop thru other grid's halo values. + // Loop thru other var's halo values. for (auto& hi : other._halos) { auto& pname = hi.first; auto& h2 = hi.second; @@ -227,9 +227,9 @@ namespace yask { } // Update halos based on each value in 'offsets' in some - // read or write to this grid. - // This grid's halos can only be increased. - void GridVar::updateHalo(const string& packName, const IntTuple& offsets) { + // read or write to this var. + // This var's halos can only be increased. + void Var::updateHalo(const string& packName, const IntTuple& offsets) { // Find step value or use 0 if none. int stepVal = 0; @@ -270,7 +270,7 @@ namespace yask { } // Update const indices based on 'indices'. - void GridVar::updateConstIndices(const IntTuple& indices) { + void Var::updateConstIndices(const IntTuple& indices) { for (auto& dim : indices.getDims()) { auto& dname = dim.getName(); @@ -293,7 +293,7 @@ namespace yask { } // Determine how many values in step-dim are needed. - int GridVar::getStepDimSize() const + int Var::getStepDimSize() const { // Specified by API. if (_stepAlloc > 0) @@ -339,7 +339,7 @@ namespace yask { // Any existing value? if (halo.size()) { #ifdef DEBUG_HALOS - cout << "** grid " << _name << " has halo " << halo.makeDimValStr() << + cout << "** var " << _name << " has halo " << halo.makeDimValStr() << " at ofs " << ofs << " in pack " << pname << endl; #endif @@ -354,7 +354,7 @@ namespace yask { } } #ifdef DEBUG_HALOS - cout << "** grid " << _name << " has halos from " << first_ofs << + cout << "** var " << _name << " has halos from " << first_ofs << " to " << last_ofs << " in pack " << pname << endl; #endif @@ -392,8 +392,8 @@ namespace yask { return max_sz; } - // Description of this grid. - string GridVar::getDescr() const { + // Description of this var. + string Var::getDescr() const { string d = _name + "("; int i = 0; for (auto dn : getDims()) { diff --git a/src/compiler/lib/Grid.hpp b/src/compiler/lib/Var.hpp similarity index 78% rename from src/compiler/lib/Grid.hpp rename to src/compiler/lib/Var.hpp index f52ec447..322c74e1 100644 --- a/src/compiler/lib/Grid.hpp +++ b/src/compiler/lib/Var.hpp @@ -23,7 +23,7 @@ IN THE SOFTWARE. *****************************************************************************/ -///////// Classes for Grids //////////// +///////// Classes for Vars //////////// #pragma once @@ -36,31 +36,31 @@ namespace yask { // Fwd decl. struct Dimensions; - // A class for a GridVar. + // A class for a Var. // This is a generic container for all variables to be accessed - // from the kernel. A 0-D grid is a scalar, a 1-D grid is an array, etc. + // from the kernel. A 0-D var is a scalar, a 1-D var is an array, etc. // Dims can be the step dim, a domain dim, or anything else. - class GridVar : public virtual yc_grid { + class Var : public virtual yc_var { protected: - string _name; // name of this grid. - indexExprPtrVec _dims; // dimensions of this grid. - bool _isScratch = false; // true if a temp grid. + string _name; // name of this var. + indexExprPtrVec _dims; // dimensions of this var. + bool _isScratch = false; // true if a temp var. // Step-dim info. bool _isStepAllocFixed = true; // step alloc cannot be changed at run-time. idx_t _stepAlloc = 0; // step-alloc override (0 => calculate). - // Ptr to solution that this grid belongs to (its parent). + // Ptr to solution that this var belongs to (its parent). StencilSolution* _soln = 0; // How many dims are foldable. int _numFoldableDims = -1; // -1 => unknown. - // Whether this grid can be vector-folded. + // Whether this var can be vector-folded. bool _isFoldable = false; - ///// Values below are computed based on GridPoint accesses in equations. + ///// Values below are computed based on VarPoint accesses in equations. // Min and max const indices that are used to access each dim. IntTuple _minIndices, _maxIndices; @@ -74,13 +74,13 @@ namespace yask { public: // Ctors. - GridVar(string name, + Var(string name, bool isScratch, StencilSolution* soln, const indexExprPtrVec& dims); // Dtor. - virtual ~GridVar() { } + virtual ~Var() { } // Name accessors. const string& getName() const { return _name; } @@ -98,7 +98,7 @@ namespace yask { return nullptr; } - // Temp grid? + // Temp var? virtual bool isScratch() const { return _isScratch; } // Access to solution. @@ -151,7 +151,7 @@ namespace yask { } // Determine whether dims are same. - virtual bool areDimsSame(const GridVar& other) const { + virtual bool areDimsSame(const Var& other) const { if (_dims.size() != other._dims.size()) return false; size_t i = 0; @@ -167,14 +167,14 @@ namespace yask { // Determine how many values in step-dim are needed. virtual int getStepDimSize() const; - // Determine whether grid can be folded. + // Determine whether var can be folded. virtual void setFolding(const Dimensions& dims); // Determine whether halo sizes are equal. - virtual bool isHaloSame(const GridVar& other) const; + virtual bool isHaloSame(const Var& other) const; - // Update halos based on halo in 'other' grid. - virtual void updateHalo(const GridVar& other); + // Update halos based on halo in 'other' var. + virtual void updateHalo(const Var& other); // Update halos based on each value in 'offsets'. virtual void updateHalo(const string& packName, const IntTuple& offsets); @@ -213,35 +213,35 @@ namespace yask { set_step_alloc_size(idx_t size) { _stepAlloc = size; } - virtual yc_grid_point_node_ptr - new_grid_point(const std::vector& index_exprs); - virtual yc_grid_point_node_ptr - new_grid_point(const std::initializer_list& index_exprs) { + virtual yc_var_point_node_ptr + new_var_point(const std::vector& index_exprs); + virtual yc_var_point_node_ptr + new_var_point(const std::initializer_list& index_exprs) { std::vector idx_expr_vec(index_exprs); - return new_grid_point(idx_expr_vec); + return new_var_point(idx_expr_vec); } - virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::vector& dim_offsets); - virtual yc_grid_point_node_ptr - new_relative_grid_point(const std::initializer_list& dim_offsets) { + virtual yc_var_point_node_ptr + new_relative_var_point(const std::vector& dim_offsets); + virtual yc_var_point_node_ptr + new_relative_var_point(const std::initializer_list& dim_offsets) { std::vector dim_ofs_vec(dim_offsets); - return new_relative_grid_point(dim_ofs_vec); + return new_relative_var_point(dim_ofs_vec); } }; - // A list of grids. This holds pointers to grids defined by the stencil - // class in the order in which they are added via the INIT_GRID_* macros. - class Grids : public vector_set { + // A list of vars. This holds pointers to vars defined by the stencil + // class in the order in which they are added via the INIT_VAR_* macros. + class Vars : public vector_set { public: - Grids() {} - virtual ~Grids() {} + Vars() {} + virtual ~Vars() {} // Copy ctor. - // Copies list of grid pointers, but not grids (shallow copy). - Grids(const Grids& src) : vector_set(src) {} + // Copies list of var pointers, but not vars (shallow copy). + Vars(const Vars& src) : vector_set(src) {} - // Determine whether each grid can be folded. + // Determine whether each var can be folded. virtual void setFolding(const Dimensions& dims) { for (auto gp : *this) gp->setFolding(dims); diff --git a/src/compiler/lib/Vec.cpp b/src/compiler/lib/Vec.cpp index b1a836ba..e63308f2 100644 --- a/src/compiler/lib/Vec.cpp +++ b/src/compiler/lib/Vec.cpp @@ -29,26 +29,26 @@ IN THE SOFTWARE. namespace yask { - // Determine vectorizability information about this grid point. - // Called when a grid point is read in a stencil function. - string VecInfoVisitor::visit(GridPoint* gp) { + // Determine vectorizability information about this var point. + // Called when a var point is read in a stencil function. + string VecInfoVisitor::visit(VarPoint* gp) { - // Nothing to do if this grid-point is not vectorizable. - if (gp->getVecType() == GridPoint::VEC_NONE) { + // Nothing to do if this var-point is not vectorizable. + if (gp->getVecType() == VarPoint::VEC_NONE) { #ifdef DEBUG_VV cout << " //** cannot vectorize scalar-access " << gp->makeQuotedStr() << endl; #endif _scalarPoints.insert(*gp); return ""; } - else if (gp->getVecType() == GridPoint::VEC_PARTIAL) { + else if (gp->getVecType() == VarPoint::VEC_PARTIAL) { #ifdef DEBUG_VV cout << " //** cannot vectorize non-standard-access " << gp->makeQuotedStr() << endl; #endif _nonVecPoints.insert(*gp); return ""; } - assert(gp->getVecType() == GridPoint::VEC_FULL); + assert(gp->getVecType() == VarPoint::VEC_FULL); // Already seen this point? if (_vecPoints.count(*gp) > 0) { @@ -68,11 +68,11 @@ namespace yask { _dims._fold.visitAllPoints([&](const IntTuple& vecPoint, size_t pelem){ - // Final offset in each dim is offset of grid point plus + // Final offset in each dim is offset of var point plus // fold offset. - // This works because we know this grid point is accessed + // This works because we know this var point is accessed // only by simple offsets in each foldable dim. - // Note: there may be more or fewer dims in vecPoint than in grid point. + // Note: there may be more or fewer dims in vecPoint than in var point. auto offsets = gp->getArgOffsets().addElements(vecPoint, false); // Find aligned vector indices and offsets @@ -99,7 +99,7 @@ namespace yask { #endif // Create aligned vector block that contains this point. - GridPoint alignedVec = *gp; // copy original. + VarPoint alignedVec = *gp; // copy original. alignedVec.setArgOffsets(vecLocation); // Find linear offset within this aligned vector block. @@ -130,10 +130,10 @@ namespace yask { return ""; } // end of visit() method. - // Return code containing a vector of grid points, e.g., code fragment + // Return code containing a vector of var points, e.g., code fragment // or var name. Optionally print memory reads and/or constructions to // 'os' as needed. - string VecPrintHelper::readFromPoint(ostream& os, const GridPoint& gp) { + string VecPrintHelper::readFromPoint(ostream& os, const VarPoint& gp) { string codeStr; @@ -142,7 +142,7 @@ namespace yask { codeStr = _vecVars[gp]; // do nothing. // Scalar GP? - else if (gp.getVecType() == GridPoint::VEC_NONE) { + else if (gp.getVecType() == VarPoint::VEC_NONE) { #ifdef DEBUG_GP cout << " //** reading from point " << gp.makeStr() << " as scalar.\n"; #endif @@ -150,7 +150,7 @@ namespace yask { } // Non-scalar but non-vectorizable GP? - else if (gp.getVecType() == GridPoint::VEC_PARTIAL) { + else if (gp.getVecType() == VarPoint::VEC_PARTIAL) { #ifdef DEBUG_GP cout << " //** reading from point " << gp.makeStr() << " as partially vectorized.\n"; #endif @@ -203,9 +203,9 @@ namespace yask { } // Print any immediate memory writes to 'os'. - // Return code to update a vector of grid points or null string + // Return code to update a vector of var points or null string // if all writes were printed. - string VecPrintHelper::writeToPoint(ostream& os, const GridPoint& gp, const string& val) { + string VecPrintHelper::writeToPoint(ostream& os, const VarPoint& gp, const string& val) { // NB: currently, all eqs must be vectorizable on LHS, // so we only need to handle vectorized writes. @@ -226,9 +226,9 @@ namespace yask { // Repeat until done. // TODO: make more efficient--this is O(n^2), so it blows up // when there are long exprs with many reads. - // TODO: sort based on all reused exprs, not just grid reads. + // TODO: sort based on all reused exprs, not just var reads. - GridPointSet alignedVecs; // aligned vecs needed so far. + VarPointSet alignedVecs; // aligned vecs needed so far. set usedExprs; // expressions used. for (size_t i = 0; i < oev.size(); i++) { @@ -239,7 +239,7 @@ namespace yask { // Scan unused exprs. size_t jBest = 0; size_t jBestCost = size_t(-1); - GridPointSet jBestAlignedVecs; + VarPointSet jBestAlignedVecs; for (size_t j = 0; j < oev.size(); j++) { if (usedExprs.count(j) == 0) { @@ -305,8 +305,8 @@ namespace yask { string separator(","); VecInfoVisitor::printStatsHeader(cout, separator); - // Loop through all grids. - for (auto gp : grids) { + // Loop through all vars. + for (auto gp : vars) { // Loop through possible folds of given length. for (int xlen = vlenForStats; xlen > 0; xlen--) { diff --git a/src/compiler/lib/Vec.hpp b/src/compiler/lib/Vec.hpp index 171cd04b..855b3d6c 100644 --- a/src/compiler/lib/Vec.hpp +++ b/src/compiler/lib/Vec.hpp @@ -37,11 +37,11 @@ namespace yask { // One element in a vector. class VecElem { public: - GridPoint _vec; // starting index of vector containing this element. + VarPoint _vec; // starting index of vector containing this element. size_t _offset; // 1-D offset in _vec. IntTuple _offsets; // n-D offsets. - VecElem(const GridPoint& vec, int offset, const IntTuple& offsets) : + VecElem(const VarPoint& vec, int offset, const IntTuple& offsets) : _vec(vec), _offset(offset), _offsets(offsets) { } virtual bool operator==(const VecElem& rhs) const { @@ -59,10 +59,10 @@ namespace yask { typedef vector VecElemList; // Map of each vector block to aligned block(s) that contain its points. - typedef map Point2Vecs; + typedef map Point2Vecs; // Map of each vector block to its elements. - typedef map Point2VecElemLists; + typedef map Point2VecElemLists; // This visitor determines the vector blocks needed to calculate the stencil. // It doesn't actually generate code; it just collects info from the AST. @@ -77,21 +77,21 @@ namespace yask { public: // Data on vectorizable points. - GridPointSet _alignedVecs; // set of aligned vectors, i.e., ones that need to be read from memory. + VarPointSet _alignedVecs; // set of aligned vectors, i.e., ones that need to be read from memory. Point2Vecs _vblk2avblks; // each vec block -> its constituent aligned vec blocks. Point2VecElemLists _vblk2elemLists; // each vec block -> in-order list of its aligned vec blocks' elements. - GridPointSet _vecPoints; // set of all vectorizable points read from, aligned and unaligned. - GridPointSet _vecWrites; // set of vectors written to. + VarPointSet _vecPoints; // set of all vectorizable points read from, aligned and unaligned. + VarPointSet _vecWrites; // set of vectors written to. // NB: the above hold much of the same info, but arranged differently: // _alignedVecs contains only a set of aligned blocks. // _vblk2avblks is used to quickly determine which aligned blocks contribute to a given block. // _vblk2elemLists is used to find exactly where each element comes from. - // The keys are the same for both maps: the vectorizable grid points. + // The keys are the same for both maps: the vectorizable var points. // Data on non-vectorizable points. - GridPointSet _scalarPoints; // set of points that should be read as scalars and broadcast to vectors. - GridPointSet _nonVecPoints; // set of points that are not scalars or vectorizable. + VarPointSet _scalarPoints; // set of points that should be read as scalars and broadcast to vectors. + VarPointSet _nonVecPoints; // set of points that are not scalars or vectorizable. VecInfoVisitor(const Dimensions& dims) : _dims(dims) { @@ -130,7 +130,7 @@ namespace yask { #if 0 // Print stats header. virtual void printStatsHeader(ostream& os, string separator) const { - os << "destination grid" << + os << "destination var" << separator << "num vector elems" << separator << "fold" << separator << "num points in stencil" << @@ -142,14 +142,14 @@ namespace yask { // Print some stats for the current values. // Pre-requisite: visitor has been accepted. - virtual void printStats(ostream& os, const string& destGrid, const string& separator) const { + virtual void printStats(ostream& os, const string& destVar, const string& separator) const { // calc num blends needed. int numBlends = 0; for (auto i = _vblk2elemLists.begin(); i != _vblk2elemLists.end(); i++) { //auto pt = i->first; auto vev = i->second; - GridPointSet mems; // inputs for this point. + VarPointSet mems; // inputs for this point. for (size_t j = 0; j < vev.size(); j++) mems.insert(vev[j]._vec); if (mems.size() > 1) // only need to blend if >1 inputs. @@ -170,7 +170,7 @@ namespace yask { footprints[dname] = footprint.size(); } - os << destGrid << + os << destVar << separator << _vlen << separator << _dims._fold.makeValStr("*") << separator << getNumPoints() << @@ -194,8 +194,8 @@ namespace yask { return ""; } - // Called when a grid point is read in a stencil function. - virtual string visit(GridPoint* gp); + // Called when a var point is read in a stencil function. + virtual string visit(VarPoint* gp); }; // Define methods for printing a vectorized version of the stencil. @@ -204,39 +204,39 @@ namespace yask { VecInfoVisitor& _vv; bool _reuseVars; // if true, load to a local var; else, reload on every access. bool _definedNA; // NA var defined. - map _vecVars; // vecs that are already constructed. + map _vecVars; // vecs that are already constructed. map _elemVars; // elems that are already read (key is read stmt). // Print access to an aligned vector block. // Return var name. - virtual string printAlignedVecRead(ostream& os, const GridPoint& gp) =0; + virtual string printAlignedVecRead(ostream& os, const VarPoint& gp) =0; // Print unaligned vector memory read. // Assumes this results in same values as printUnalignedVec(). // Return var name. - virtual string printUnalignedVecRead(ostream& os, const GridPoint& gp) =0; + virtual string printUnalignedVecRead(ostream& os, const VarPoint& gp) =0; // Print write to an aligned vector block. // Return expression written. - virtual string printAlignedVecWrite(ostream& os, const GridPoint& gp, + virtual string printAlignedVecWrite(ostream& os, const VarPoint& gp, const string& val) =0; // Print conversion from existing vars to make an unaligned vector block. // Return var name. - virtual string printUnalignedVec(ostream& os, const GridPoint& gp) =0; + virtual string printUnalignedVec(ostream& os, const VarPoint& gp) =0; // Print construction for one point var pvName from elems. - virtual void printUnalignedVecCtor(ostream& os, const GridPoint& gp, + virtual void printUnalignedVecCtor(ostream& os, const VarPoint& gp, const string& pvName) =0; // Read from a single point. // Return code for read. - virtual string readFromScalarPoint(ostream& os, const GridPoint& gp, + virtual string readFromScalarPoint(ostream& os, const VarPoint& gp, const VarMap* vMap=0) =0; // Read from multiple points that are not vectorizable. // Return var name. - virtual string printNonVecRead(ostream& os, const GridPoint& gp) =0; + virtual string printNonVecRead(ostream& os, const VarPoint& gp) =0; public: VecPrintHelper(VecInfoVisitor& vv, @@ -266,28 +266,28 @@ namespace yask { } // Return point info. - virtual bool isAligned(const GridPoint& gp) { + virtual bool isAligned(const VarPoint& gp) { return _vv._alignedVecs.count(gp) > 0; } // Access cached values. - virtual void savePointVar(const GridPoint& gp, string var) { + virtual void savePointVar(const VarPoint& gp, string var) { _vecVars[gp] = var; } - virtual string* lookupPointVar(const GridPoint& gp) { + virtual string* lookupPointVar(const VarPoint& gp) { if (_vecVars.count(gp)) return &_vecVars.at(gp); return 0; } // Print any needed memory reads and/or constructions to 'os'. - // Return code containing a vector of grid points. - virtual string readFromPoint(ostream& os, const GridPoint& gp); + // Return code containing a vector of var points. + virtual string readFromPoint(ostream& os, const VarPoint& gp); // Print any immediate memory writes to 'os'. - // Return code to update a vector of grid points or null string + // Return code to update a vector of var points or null string // if all writes were printed. - virtual string writeToPoint(ostream& os, const GridPoint& gp, const string& val); + virtual string writeToPoint(ostream& os, const VarPoint& gp, const string& val); }; // A visitor that reorders exprs based on vector info. diff --git a/src/compiler/lib/Visitor.hpp b/src/compiler/lib/Visitor.hpp index fb3cd706..690c1bfe 100644 --- a/src/compiler/lib/Visitor.hpp +++ b/src/compiler/lib/Visitor.hpp @@ -38,7 +38,7 @@ namespace yask { class ExprVisitor { protected: bool _visitEqualsLhs = false; // whether to visit LHS of EQUALS. - bool _visitGridPointArgs = false; // whether to visit exprs in grid point args. + bool _visitVarPointArgs = false; // whether to visit exprs in var point args. bool _visitConds = false; // whether to visit conditional exprs. public: @@ -49,10 +49,10 @@ namespace yask { virtual string visit(CodeExpr* ce) { return ""; } virtual string visit(IndexExpr* ie) { return ""; } - // Visit grid-point args only if flag is set. - virtual string visit(GridPoint* gp) { + // Visit var-point args only if flag is set. + virtual string visit(VarPoint* gp) { string res; - if (_visitGridPointArgs) { + if (_visitVarPointArgs) { for (auto& arg : gp->getArgs()) res = arg->accept(this); } diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index bd41fc14..82d2edce 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -65,7 +65,7 @@ namespace yask { os << "\n#ifdef DEFINE_CONTEXT\n" "namespace yask {" << endl; - // First, create a class to hold the data (grids). + // First, create a class to hold the data (vars). printData(os); // A struct for each equation bundle. @@ -103,17 +103,17 @@ namespace yask { os << "#define STENCIL_DIM_IDX_" << dname << " (" << (i++) << ")\n"; } int gdims = 0; - for (auto gp : _grids) { + for (auto gp : _vars) { int ndims = gp->get_num_dims(); gdims = max(gdims, ndims); } auto nsdims = _dims._stencilDims.size(); os << "\n// Number of stencil dimensions (step and domain):\n" "#define NUM_STENCIL_DIMS " << nsdims << endl; - os << "\n// Max number of grid dimensions:\n" - "#define NUM_GRID_DIMS " << gdims << endl; - os << "\n// Max of stencil and grid dims:\n" - "#define NUM_STENCIL_AND_GRID_DIMS " << max(gdims, nsdims) << endl; + os << "\n// Max number of var dimensions:\n" + "#define NUM_VAR_DIMS " << gdims << endl; + os << "\n// Max of stencil and var dims:\n" + "#define NUM_STENCIL_AND_VAR_DIMS " << max(gdims, nsdims) << endl; os << "\n// Number of stencil equations:\n" "#define NUM_STENCIL_EQS " << _stencil.get_num_equations() << endl; @@ -187,14 +187,14 @@ namespace yask { "class " << _context_base << " : public StencilContext {\n" "public:\n"; - // Save data for ctor and new-grid method. - string ctorCode, ctorList, newGridCode, scratchCode; - set newGridDims; + // Save data for ctor and new-var method. + string ctorCode, ctorList, newVarCode, scratchCode; + set newVarDims; - // Grids. - os << "\n ///// GridVar(s)." << endl; - for (auto gp : _grids) { - string grid = gp->getName(); + // Vars. + os << "\n ///// Var(s)." << endl; + for (auto gp : _vars) { + string var = gp->getName(); int ndims = gp->get_num_dims(); // Tuple version of dims. @@ -207,13 +207,13 @@ namespace yask { os << "\n // The "; if (ndims) - os << ndims << "-D grid var"; + os << ndims << "-D var"; else os << "scalar value"; - os << " '" << grid << "', which is "; + os << " '" << var << "', which is "; if (gp->isScratch()) os << " a scratch variable.\n"; - else if (_eqBundles.getOutputGrids().count(gp)) + else if (_eqBundles.getOutputVars().count(gp)) os << "updated by one or more equations.\n"; else os << "not updated by any equation (read-only).\n"; @@ -230,9 +230,9 @@ namespace yask { // Use vector-folded layout if possible. bool folded = gp->isFoldable(); - string gtype = folded ? "YkVecGrid" : "YkElemGrid"; + string gtype = folded ? "YkVecVar" : "YkElemVar"; - // Type-name in kernel is 'GRID_TYPE'. + // Type-name in kernel is 'VAR_TYPE'. string typeName = gtype + " 0) { - THROW_YASK_EXCEPTION("Error: cannot create grid '" + grid + + THROW_YASK_EXCEPTION("Error: cannot create var '" + var + "' with dimensions '" + gdims.makeDimStr() + "' because '" + dname + "' must be first dimension"); } @@ -323,34 +323,34 @@ namespace yask { typeName += ">"; // Typedef. - string typeDef = grid + "_type"; - string ptrTypeDef = grid + "_ptr_type"; + string typeDef = var + "_type"; + string ptrTypeDef = var + "_ptr_type"; os << " typedef " << typeName << " " << typeDef << ";\n" << " typedef std::shared_ptr<" << typeDef << "> " << ptrTypeDef << ";\n" - " GridDimNames " + grid + "_dim_names;\n"; + " VarDimNames " + var + "_dim_names;\n"; - ctorCode += "\n // GridVar '" + grid + "'.\n"; - ctorCode += " " + grid + "_dim_names = {" + + ctorCode += "\n // Var '" + var + "'.\n"; + ctorCode += " " + var + "_dim_names = {" + gdims.makeDimStr(", ", "\"", "\"") + "};\n"; - string gbp = grid + "_base_ptr"; - string initCode = " " + grid + "_ptr_type " + gbp + " = std::make_shared<" + typeDef + - ">(*this, \"" + grid + "\", " + grid + "_dim_names);\n" + string gbp = var + "_base_ptr"; + string initCode = " " + var + "_ptr_type " + gbp + " = std::make_shared<" + typeDef + + ">(*this, \"" + var + "\", " + var + "_dim_names);\n" " assert(" + gbp + ");\n" - " " + grid + "_ptr = std::make_shared(" + gbp + ");\n" - " assert(" + grid + "_ptr->gbp());\n"; + " " + var + "_ptr = std::make_shared(" + gbp + ");\n" + " assert(" + var + "_ptr->gbp());\n"; - // GridVar vars. + // Vars. if (gp->isScratch()) { - // Collection of scratch grids. - os << " GridPtrs " << grid << "_list;\n"; - ctorCode += " addScratch(" + grid + "_list);\n"; + // Collection of scratch vars. + os << " VarPtrs " << var << "_list;\n"; + ctorCode += " addScratch(" + var + "_list);\n"; } else { - // GridVar ptr declaration. + // Var ptr declaration. // Default ctor gives null ptr. - os << " YkGridPtr " << grid << "_ptr;\n"; + os << " YkVarPtr " << var << "_ptr;\n"; } // Alloc-setting code. @@ -364,25 +364,25 @@ namespace yask { // Halos for this dimension. for (bool left : { true, false }) { string bstr = left ? "_left_halo_" : "_right_halo_"; - string hvar = grid + bstr + dname; + string hvar = var + bstr + dname; int hval = _settings._haloSize > 0 ? _settings._haloSize : gp->getHaloSize(dname, left); os << " const idx_t " << hvar << " = " << hval << "; // default halo size in '" << dname << "' dimension.\n"; - initCode += " " + grid + "_ptr->set" + bstr + "size(\"" + dname + + initCode += " " + var + "_ptr->set" + bstr + "size(\"" + dname + "\", " + hvar + ");\n"; } } // non-domain dimension. else { - string avar = grid + "_alloc_" + dname; - string ovar = grid + "_ofs_" + dname; + string avar = var + "_alloc_" + dname; + string ovar = var + "_ofs_" + dname; int aval = 1; int oval = 0; if (dtype == STEP_INDEX) { aval = gp->getStepDimSize(); - initCode += " " + grid + "_base_ptr->_set_dynamic_step_alloc(" + + initCode += " " + var + "_base_ptr->_set_dynamic_step_alloc(" + (gp->is_dynamic_step_alloc() ? "true" : "false") + ");\n"; } else { @@ -395,62 +395,62 @@ namespace yask { } os << " const idx_t " << avar << " = " << aval << "; // default allocation in '" << dname << "' dimension.\n"; - initCode += " " + grid + "_ptr->_set_alloc_size(\"" + dname + + initCode += " " + var + "_ptr->_set_alloc_size(\"" + dname + "\", " + avar + ");\n"; if (oval) { os << " const idx_t " << ovar << " = " << oval << "; // first index in '" << dname << "' dimension.\n"; - initCode += " " + grid + "_ptr->_set_local_offset(\"" + dname + + initCode += " " + var + "_ptr->_set_local_offset(\"" + dname + "\", " + ovar + ");\n"; } } } // dims. // Allow dynamic misc alloc setting if not interleaved. - initCode += " " + grid + "_base_ptr->_set_dynamic_misc_alloc(" + + initCode += " " + var + "_base_ptr->_set_dynamic_misc_alloc(" + (_settings._innerMisc ? "false" : "true") + ");\n"; - // If not scratch, init grids in ctor. + // If not scratch, init vars in ctor. if (!gp->isScratch()) { - // GridVar init. + // Var init. ctorCode += initCode; - ctorCode += " addGrid(" + grid + "_ptr, true, "; - if (_eqBundles.getOutputGrids().count(gp)) - ctorCode += "true /* is an output grid */"; + ctorCode += " addVar(" + var + "_ptr, true, "; + if (_eqBundles.getOutputVars().count(gp)) + ctorCode += "true /* is an output var */"; else - ctorCode += "false /* is not an output grid */"; + ctorCode += "false /* is not an output var */"; ctorCode += ");\n"; } // For scratch, make code for one vec element. else { - scratchCode += " " + grid + "_list.clear();\n" + scratchCode += " " + var + "_list.clear();\n" " for (int i = 0; i < num_threads; i++) {\n" - " YkGridPtr " + grid + "_ptr;\n" + + " YkVarPtr " + var + "_ptr;\n" + initCode + - " " + grid + "_base_ptr->set_scratch(true);\n" + - " " + grid + "_list.push_back(" + grid + "_ptr);\n" + " " + var + "_base_ptr->set_scratch(true);\n" + + " " + var + "_list.push_back(" + var + "_ptr);\n" " }\n"; } - // Make new grids via API. - string newGridKey = gdims.makeDimStr(); - if (!newGridDims.count(newGridKey)) { - newGridDims.insert(newGridKey); - bool firstGrid = newGridCode.length() == 0; + // Make new vars via API. + string newVarKey = gdims.makeDimStr(); + if (!newVarDims.count(newVarKey)) { + newVarDims.insert(newVarKey); + bool firstVar = newVarCode.length() == 0; if (gdims.getNumDims()) - newGridCode += "\n // Grids with '" + newGridKey + "' dim(s).\n"; + newVarCode += "\n // Vars with '" + newVarKey + "' dim(s).\n"; else - newGridCode += "\n // Scalar grids.\n"; - if (!firstGrid) - newGridCode += " else"; - newGridCode += " if (dims == " + grid + "_dim_names)\n" + newVarCode += "\n // Scalar vars.\n"; + if (!firstVar) + newVarCode += " else"; + newVarCode += " if (dims == " + var + "_dim_names)\n" " gp = std::make_shared<" + typeDef + ">(*this, name, dims);\n"; } - } // grids. + } // vars. // Ctor. { @@ -460,30 +460,30 @@ namespace yask { " {\n name = \"" << _stencil.getName() << "\";\n" " long_name = \"" << _stencil.getLongName() << "\";\n"; - os << "\n // Create grids (but do not allocate data in them).\n" << + os << "\n // Create vars (but do not allocate data in them).\n" << ctorCode << - "\n // Update grids with context info.\n" - " update_grid_info(false);\n"; + "\n // Update vars with context info.\n" + " update_var_info(false);\n"; // end of ctor. os << " } // ctor" << endl; } - // New-grid method. - os << "\n // Make a new grid iff its dims match any in the stencil.\n" - " // Returns pointer to the new grid or nullptr if no match.\n" - " virtual GridBasePtr newStencilGrid(const std::string& name," - " const GridDimNames& dims) {\n" - " GridBasePtr gp;\n" << - newGridCode << + // New-var method. + os << "\n // Make a new var iff its dims match any in the stencil.\n" + " // Returns pointer to the new var or nullptr if no match.\n" + " virtual VarBasePtr newStencilVar(const std::string& name," + " const VarDimNames& dims) {\n" + " VarBasePtr gp;\n" << + newVarCode << " return gp;\n" - " } // newStencilGrid\n"; + " } // newStencilVar\n"; - // Scratch-grids method. - os << "\n // Make new scratch grids.\n" - " virtual void makeScratchGrids(int num_threads) {\n" << + // Scratch-vars method. + os << "\n // Make new scratch vars.\n" + " virtual void makeScratchVars(int num_threads) {\n" << scratchCode << - " } // newScratchGrids\n"; + " } // newScratchVars\n"; os << "}; // " << _context_base << endl; } @@ -525,23 +525,23 @@ namespace yask { " _scalar_points_written = " << stats.getNumWrites() << ";\n" " _is_scratch = " << (eq->isScratch() ? "true" : "false") << ";\n"; - // I/O grids. - os << "\n // The following grid(s) are read by " << egsName << endl; - for (auto gp : eq->getInputGrids()) { + // I/O vars. + os << "\n // The following var(s) are read by " << egsName << endl; + for (auto gp : eq->getInputVars()) { if (gp->isScratch()) os << " inputScratchVecs.push_back(&_context_data->" << gp->getName() << "_list);\n"; else - os << " inputGridPtrs.push_back(_context_data->" << gp->getName() << "_ptr);\n"; + os << " inputVarPtrs.push_back(_context_data->" << gp->getName() << "_ptr);\n"; } - os << "\n // The following grid(s) are written by " << egsName; + os << "\n // The following var(s) are written by " << egsName; if (eq->step_expr) os << " at " << eq->step_expr->makeQuotedStr(); os << ".\n"; - for (auto gp : eq->getOutputGrids()) { + for (auto gp : eq->getOutputVars()) { if (gp->isScratch()) os << " outputScratchVecs.push_back(&_context_data->" << gp->getName() << "_list);\n"; else - os << " outputGridPtrs.push_back(_context_data->" << gp->getName() << "_ptr);\n"; + os << " outputVarPtrs.push_back(_context_data->" << gp->getName() << "_ptr);\n"; } os << " } // Ctor." << endl; } @@ -620,7 +620,7 @@ namespace yask { " 'input_step_index' and return 'true'.\n"; else os << "// Return 'false' because this bundle does not update" - " grids with the step dimension.\n"; + " vars with the step dimension.\n"; os << " virtual bool get_output_step_index(idx_t input_step_index," " idx_t& output_step_index) const final {\n"; if (eq->step_expr) { @@ -671,7 +671,7 @@ namespace yask { // Create vector info for this eqBundle. // The visitor is accepted at all nodes in the cluster AST; - // for each grid access node in the AST, the vectors + // for each var access node in the AST, the vectors // needed are determined and saved in the visitor. VecInfoVisitor vv(_dims); vceq->visitEqs(&vv); diff --git a/src/compiler/swig/yask_compiler_api.i b/src/compiler/swig/yask_compiler_api.i index 4dcdaed7..a0f5c786 100644 --- a/src/compiler/swig/yask_compiler_api.i +++ b/src/compiler/swig/yask_compiler_api.i @@ -39,12 +39,12 @@ IN THE SOFTWARE. // Must declare shared_ptrs for the entire expr_node hierarchy! %shared_ptr(yask::yc_solution) - //%shared_ptr(yask::yc_grid) + //%shared_ptr(yask::yc_var) %shared_ptr(yask::yc_expr_node) %shared_ptr(yask::yc_index_node) %shared_ptr(yask::yc_equation_node) %shared_ptr(yask::yc_number_node) -%shared_ptr(yask::yc_grid_point_node) +%shared_ptr(yask::yc_var_point_node) %shared_ptr(yask::yc_const_number_node) %shared_ptr(yask::yc_negate_node) %shared_ptr(yask::yc_commutative_number_node) @@ -81,7 +81,7 @@ IN THE SOFTWARE. %template(yc_vector_index) std::vector>; %template(yc_vector_num) std::vector>; %template(yc_vector_eq) std::vector>; -%template(yc_vector_grid) std::vector; +%template(yc_vector_var) std::vector; // Tell SWIG how to catch a YASK exception and rethrow it in Python. %exception { diff --git a/src/compiler/tests/yask_compiler_api_exception_test.cpp b/src/compiler/tests/yask_compiler_api_exception_test.cpp index 0a293eb1..c0bcf528 100644 --- a/src/compiler/tests/yask_compiler_api_exception_test.cpp +++ b/src/compiler/tests/yask_compiler_api_exception_test.cpp @@ -56,10 +56,10 @@ int main() { soln->set_step_dim(t); soln->set_domain_dims({x, z, y}); - // Create a grid var. - auto g1 = soln->new_grid("test_grid", {t, x, y, z}); + // Create a var. + auto g1 = soln->new_var("test_var", {t, x, y, z}); - // Create an equation for the grid. + // Create an equation for the var. auto n1 = fac.new_const_number_node(3.14); cout << n1->format_simple() << endl; @@ -68,9 +68,9 @@ int main() { cout << n2->format_simple() << endl; // Exception test - cout << "Exception Test: Call 'new_relative_grid_point' with wrong argument.\n"; + cout << "Exception Test: Call 'new_relative_var_point' with wrong argument.\n"; try { - auto n3 = g1->new_relative_grid_point({0, +1, 0, -2, 1}); + auto n3 = g1->new_relative_var_point({0, +1, 0, -2, 1}); } catch (yask_exception& e) { cout << "YASK threw an expected exception.\n"; cout << e.get_message() << endl; @@ -78,27 +78,27 @@ int main() { num_exception++; } - auto n3 = g1->new_relative_grid_point({0, +1, 0, -2}); + auto n3 = g1->new_relative_var_point({0, +1, 0, -2}); cout << n3->format_simple() << endl; auto n4a = fac.new_add_node(n2, n3); auto n4b = fac.new_add_node(n4a, n1); cout << n4b->format_simple() << endl; - auto n5 = g1->new_relative_grid_point({0, +1, -1, 0}); + auto n5 = g1->new_relative_var_point({0, +1, -1, 0}); cout << n5->format_simple() << endl; auto n6 = fac.new_multiply_node(n4b, n5); cout << n6->format_simple() << endl; - auto n_lhs = g1->new_relative_grid_point({+1, 0, 0, 0}); + auto n_lhs = g1->new_relative_var_point({+1, 0, 0, 0}); cout << n_lhs->format_simple() << endl; auto n_eq = fac.new_equation_node(n_lhs, n6); cout << n_eq->format_simple() << endl; cout << "Solution '" << soln->get_name() << "' contains " << - soln->get_num_grids() << " grid(s), and " << + soln->get_num_vars() << " var(s), and " << soln->get_num_equations() << " equation(s)." << endl; // Number of bytes in each FP value. @@ -139,7 +139,7 @@ int main() { // TODO: better to have exception test for the methods below // Eqs::findDeps (<-EqGroups::makeEqGroups<-StencilSolution::analyze_solution<-StencilSolution::format()) // EqGroups::sort (<-EqGroups::makeEqGroups<-StencilSolution::analyze_solution<-StencilSolution::format()) - // GridPoint::GridPoint + // VarPoint::VarPoint // castExpr // NumExpr::getNumVal, NumExpr::getIntVal, NumExpr::getBoolVal // Dimensions::setDims (<-StencilSolution::analyze_solution<-StencilSolution::format) diff --git a/src/compiler/tests/yask_compiler_api_exception_test.py b/src/compiler/tests/yask_compiler_api_exception_test.py index ad470229..94b9751f 100755 --- a/src/compiler/tests/yask_compiler_api_exception_test.py +++ b/src/compiler/tests/yask_compiler_api_exception_test.py @@ -48,18 +48,18 @@ y = nfac.new_domain_index("y"); z = nfac.new_domain_index("z"); - # Create a grid var. - g1 = soln.new_grid("test_grid", [t, x, y, z]) + # Create a var. + g1 = soln.new_var("test_var", [t, x, y, z]) # Create an expression for the new value. # This will average some of the neighboring points around the # current stencil application point in the current timestep. - n0 = g1.new_relative_grid_point([0, 0, 0, 0]) # center-point at this timestep. + n0 = g1.new_relative_var_point([0, 0, 0, 0]) # center-point at this timestep. # Exception test - print("Exception Test: Call 'new_relative_grid_point' with wrong argument.") + print("Exception Test: Call 'new_relative_var_point' with wrong argument.") try: - n1 = nfac.new_add_node(n0, g1.new_relative_grid_point([0, -1, 0, 0, 1])) # left. + n1 = nfac.new_add_node(n0, g1.new_relative_var_point([0, -1, 0, 0, 1])) # left. except RuntimeError as e: print ("YASK threw an expected exception.") print (format(e)) @@ -69,26 +69,26 @@ # Create an expression using points in g1. # This will average some of the neighboring points around the # current stencil application point in the current timestep. - n1 = (g1.new_grid_point([t, x, y, z ]) + # center. - g1.new_grid_point([t, x-1, y, z ]) + # left. - g1.new_grid_point([t, x+1, y, z ]) + # right. - g1.new_grid_point([t, x, y-1, z ]) + # above. - g1.new_grid_point([t, x, y+1, z ]) + # below. - g1.new_grid_point([t, x, y, z-1]) + # in front. - g1.new_grid_point([t, x, y, z ])) # behind. + n1 = (g1.new_var_point([t, x, y, z ]) + # center. + g1.new_var_point([t, x-1, y, z ]) + # left. + g1.new_var_point([t, x+1, y, z ]) + # right. + g1.new_var_point([t, x, y-1, z ]) + # above. + g1.new_var_point([t, x, y+1, z ]) + # below. + g1.new_var_point([t, x, y, z-1]) + # in front. + g1.new_var_point([t, x, y, z ])) # behind. n2 = n1 / 7 # ave of the 7 points. # Create an equation to define the value at the next timestep. - n3 = g1.new_relative_grid_point([1, 0, 0, 0]) # center-point at next timestep. + n3 = g1.new_relative_var_point([1, 0, 0, 0]) # center-point at next timestep. n4 = nfac.new_equation_node(n3, n2) # equate to expr n2. print("Equation before formatting: " + n4.format_simple()) print("Solution '" + soln.get_name() + "' contains " + - str(soln.get_num_grids()) + " grid(s), and " + + str(soln.get_num_vars()) + " var(s), and " + str(soln.get_num_equations()) + " equation(s).") - for grid in soln.get_grids() : - print("Grid " + grid.get_name() + + for var in soln.get_vars() : + print("Var " + var.get_name() + " has the following dim(s): " + - repr(grid.get_dim_names())); + repr(var.get_dim_names())); # Number of bytes in each FP value. soln.set_element_bytes(4) diff --git a/src/compiler/tests/yask_compiler_api_test.cpp b/src/compiler/tests/yask_compiler_api_test.cpp index bb6376eb..785de22c 100644 --- a/src/compiler/tests/yask_compiler_api_test.cpp +++ b/src/compiler/tests/yask_compiler_api_test.cpp @@ -54,14 +54,14 @@ int main() { auto y = fac.new_domain_index("y"); auto z = fac.new_domain_index("z"); - // Create a grid var. - auto g1 = soln->new_grid("test_grid", {t, x, y, z}); + // Create a var. + auto g1 = soln->new_var("test_var", {t, x, y, z}); // Create an equation based on some values from 'g1'. - auto n1 = g1->new_grid_point({t, x, y, z}); + auto n1 = g1->new_var_point({t, x, y, z}); cout << n1->format_simple() << endl; - auto n2 = g1->new_grid_point({t, x+1, y, z-2}); + auto n2 = g1->new_var_point({t, x+1, y, z-2}); cout << n2->format_simple() << endl; auto n3 = n1 + n2; @@ -70,34 +70,34 @@ int main() { auto n4 = n2 * -n3 * 0.9; cout << n4->format_simple() << endl; - auto n5 = g1->new_grid_point({t, x+2, y-1, z}); + auto n5 = g1->new_var_point({t, x+2, y-1, z}); cout << n5->format_simple() << endl; auto n6 = n4 / n5; cout << n6->format_simple() << endl; - // Create a scratch-grid var. - auto sg1 = soln->new_scratch_grid("scratch_grid", {x, y, z}); + // Create a scratch var. + auto sg1 = soln->new_scratch_var("scratch_var", {x, y, z}); - // Define scratch-grid value based on expression 'n6' above. - auto ns_lhs = sg1->new_grid_point({x, y, z}); + // Define scratch-var value based on expression 'n6' above. + auto ns_lhs = sg1->new_var_point({x, y, z}); auto ns_eq = fac.new_equation_node(ns_lhs, n6); cout << ns_eq->format_simple() << endl; // Define another equation based on some values from 'sg1'. - auto n7a = sg1->new_grid_point({x-1, y, z+2}); - auto n7b = sg1->new_grid_point({x+1, y-1, z-2}); + auto n7a = sg1->new_var_point({x-1, y, z+2}); + auto n7b = sg1->new_var_point({x+1, y-1, z-2}); auto n8 = n7a + n7b; cout << n8->format_simple() << endl; - // Define main grid value at t+1. - auto n_lhs = g1->new_grid_point({t+1, x, y, z}); + // Define main var value at t+1. + auto n_lhs = g1->new_var_point({t+1, x, y, z}); cout << n_lhs->format_simple() << endl; // Define a sub-domain in which to apply this value. auto sd0 = (x >= fac.new_first_domain_index(x) + 5); - // Set equations to update the main grid using + // Set equations to update the main var using // expression 'n8' in sub-domain 'sd0' and -'n8' otherwise. auto n_eq0 = fac.new_equation_node(n_lhs, n8, sd0); cout << n_eq0->format_simple() << endl; @@ -105,7 +105,7 @@ int main() { cout << n_eq1->format_simple() << endl; cout << "Solution '" << soln->get_name() << "' contains " << - soln->get_num_grids() << " grid(s), and " << + soln->get_num_vars() << " var(s), and " << soln->get_num_equations() << " equation(s)." << endl; // Generate DOT output. diff --git a/src/compiler/tests/yask_compiler_api_test.py b/src/compiler/tests/yask_compiler_api_test.py index 0b4b1c7e..f83c2582 100755 --- a/src/compiler/tests/yask_compiler_api_test.py +++ b/src/compiler/tests/yask_compiler_api_test.py @@ -50,46 +50,46 @@ e0 = x + 3; print("Simple index expression: " + e0.format_simple()); - # Create a grid var. - g1 = soln.new_grid("test_grid", [t, x, y, z]) + # Create a var. + g1 = soln.new_var("test_var", [t, x, y, z]) # Create simple expressions to reference a point in g1. - n0r = g1.new_relative_grid_point([0, 0, 0, 0]) # center-point at this timestep. - print("Simple grid-access expression: " + n0r.format_simple()); - n0 = g1.new_grid_point([t, x, y, z]) # center-point at this timestep. - print("Simple grid-access expression: " + n0.format_simple()); + n0r = g1.new_relative_var_point([0, 0, 0, 0]) # center-point at this timestep. + print("Simple var-access expression: " + n0r.format_simple()); + n0 = g1.new_var_point([t, x, y, z]) # center-point at this timestep. + print("Simple var-access expression: " + n0.format_simple()); # Create a more complex expression using points in g1. # This will average some of the neighboring points around the # current stencil application point in the current timestep. n1 = (n0 + - g1.new_grid_point([t, x-1, y, z ]) + # left. - g1.new_grid_point([t, x+1, y, z ]) + # right. - g1.new_grid_point([t, x, y-1, z ]) + # above. - g1.new_grid_point([t, x, y+1, z ]) + # below. - g1.new_grid_point([t, x, y, z-1]) + # in front. - g1.new_grid_point([t, x, y, z ])) # behind. + g1.new_var_point([t, x-1, y, z ]) + # left. + g1.new_var_point([t, x+1, y, z ]) + # right. + g1.new_var_point([t, x, y-1, z ]) + # above. + g1.new_var_point([t, x, y+1, z ]) + # below. + g1.new_var_point([t, x, y, z-1]) + # in front. + g1.new_var_point([t, x, y, z ])) # behind. n2 = n1 / 7 # ave of the 7 points. - # Create a scratch-grid var. - sg1 = soln.new_scratch_grid("scratch_grid", [x, y, z]); + # Create a scratch var. + sg1 = soln.new_scratch_var("scratch_var", [x, y, z]); - # Define value in scratch grid to be the above equation, i.e., + # Define value in scratch var to be the above equation, i.e., # this is a temporary 3-D variable that holds the average # values of each point. - sn0 = sg1.new_grid_point([x, y, z]) # LHS of eq is a point on scratch-grid + sn0 = sg1.new_var_point([x, y, z]) # LHS of eq is a point on scratch-var sn1 = nfac.new_equation_node(sn0, n2) # equate to expr n2. - print("Scratch-grid equation before formatting: " + sn1.format_simple()) + print("Scratch-var equation before formatting: " + sn1.format_simple()) - # Use values in scratch grid to make a new eq. - sn2 = (sg1.new_grid_point([x+1, y, z ]) + - sg1.new_grid_point([x, y+1, z ]) + - sg1.new_grid_point([x, y, z+1])) + # Use values in scratch var to make a new eq. + sn2 = (sg1.new_var_point([x+1, y, z ]) + + sg1.new_var_point([x, y+1, z ]) + + sg1.new_var_point([x, y, z+1])) sn5 = sn2 * 2.5 - 9 sn5n = -sn5 - # Expression for main grid value at t+1. - n3 = g1.new_grid_point([t+1, x, y, z]) # center-point at next timestep. + # Expression for main var value at t+1. + n3 = g1.new_var_point([t+1, x, y, z]) # center-point at next timestep. # Define a sub-domain in which to apply this value. sd0 = (x >= nfac.new_first_domain_index(x) + 5) @@ -98,18 +98,18 @@ # Create an equation to define the value at the next timestep # using sn5 in sub-domain sd0 and -sn5 otherwise. n4a = nfac.new_equation_node(n3, sn5, sd0) - print("Main-grid interior equation before formatting: " + n4a.format_simple()) + print("Main-var interior equation before formatting: " + n4a.format_simple()) n4b = nfac.new_equation_node(n3, sn5n, sd0n) - print("Main-grid edge equation before formatting: " + n4b.format_simple()) + print("Main-var edge equation before formatting: " + n4b.format_simple()) # Print some info about the solution. print("Solution '" + soln.get_name() + "' contains " + - str(soln.get_num_grids()) + " grid(s), and " + + str(soln.get_num_vars()) + " var(s), and " + str(soln.get_num_equations()) + " equation(s).") - for grid in soln.get_grids() : - print("Grid " + grid.get_name() + + for var in soln.get_vars() : + print("Var " + var.get_name() + " has the following dim(s): " + - repr(grid.get_dim_names())); + repr(var.get_dim_names())); # Number of bytes in each FP value. soln.set_element_bytes(4) diff --git a/src/contrib/coefficients/fd_coeff_test.cpp b/src/contrib/coefficients/fd_coeff_test.cpp index 66ecee4c..797ee79e 100644 --- a/src/contrib/coefficients/fd_coeff_test.cpp +++ b/src/contrib/coefficients/fd_coeff_test.cpp @@ -47,17 +47,17 @@ int main() double coeff[num_points]; //Construct a set of points (-h*radius, -h*(radius-1), .. 0, h,..., h*radius) - //Could pass any arbitrary array grid_points = {x_0, x_1, ... x_n} + //Could pass any arbitrary array var_points = {x_0, x_1, ... x_n} - double grid_points[num_points]; - cout << "Approximating derivative from grid points: " ; + double var_points[num_points]; + cout << "Approximating derivative from var points: " ; for(int i=0; i $@ + $(PERL) $< -m $(NVDIMS) > $@ @- gindent -fca $@ || \ indent -fca $@ || \ echo "note:" $@ "is not properly indented because indent program failed or was not found." $(YK_GEN_DIR)/yask_layouts.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(MKDIR) $(YK_GEN_DIR) - $(PERL) $< -d $(NGDIMS) > $@ + $(PERL) $< -d $(NVDIMS) > $@ @- gindent -fca $@ || \ indent -fca $@ || \ echo "note:" $@ "is not properly indented because indent program failed or was not found." -$(YK_GEN_DIR)/yask_grid_code.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) +$(YK_GEN_DIR)/yask_var_code.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(MKDIR) $(YK_GEN_DIR) - $(PERL) $< -g $(NGDIMS) > $@ + $(PERL) $< -v $(NVDIMS) > $@ $(YK_CODE_FILE): $(YC_EXEC) $(MKDIR) $(dir $@) @@ -686,7 +686,7 @@ $(YK_PY_LIB): $(YK_OBJS) $(YK_EXT_OBJS) $(YK_SWIG_OUT_DIR)/yask_kernel_api_wrap # Simple tests. -$(YK_GRID_TEST_EXEC): $(YK_TEST_SRC_DIR)/grid_test.cpp $(YK_LIB) +$(YK_VAR_TEST_EXEC): $(YK_TEST_SRC_DIR)/var_test.cpp $(YK_LIB) $(MKDIR) $(dir $@) $(CXX_PREFIX) $(YK_CXX) $(YK_CXXFLAGS) $< $(YK_LFLAGS) -o $@ @ls -l $@ @@ -700,8 +700,8 @@ $(YK_API_TEST_EXEC): $(YK_TEST_SRC_DIR)/yask_kernel_api_test.cpp $(YK_LIB) @ls -l $@ # Run C++ tests. -cxx-yk-grid-test: $(YK_GRID_TEST_EXEC) - @echo '*** Running the C++ YASK grid test...' +cxx-yk-var-test: $(YK_VAR_TEST_EXEC) + @echo '*** Running the C++ YASK var test...' $(RUN_PREFIX) $< cxx-yk-api-test: $(YK_API_TEST_EXEC) @@ -814,7 +814,7 @@ api-tests: # These tests are focused on the kernel and not the compiler. # For testing both the kernel and compiler in various combinations, # run the tests from the top-level Makefile. -STENCIL_TEST_ARGS := yc-and-yk-test real_bytes=8 allow_new_grid_types=0 +STENCIL_TEST_ARGS := yc-and-yk-test real_bytes=8 allow_new_var_types=0 stencil-tests: $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_empty step_dim=t domain_dims=d1,d2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_empty_2d @@ -855,7 +855,7 @@ stencil-tests: $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_4d fold=w=2,x=2 all-tests: - $(MAKE) clean; $(MAKE) cxx-yk-grid-test stencil=test_3d fold=x=4,y=2 + $(MAKE) clean; $(MAKE) cxx-yk-var-test stencil=test_3d fold=x=4,y=2 $(MAKE) stencil-tests $(MAKE) api-tests diff --git a/src/kernel/lib/alloc.cpp b/src/kernel/lib/alloc.cpp index 9d7ef7e1..8d1978df 100644 --- a/src/kernel/lib/alloc.cpp +++ b/src/kernel/lib/alloc.cpp @@ -50,9 +50,9 @@ namespace yask { // Alloc 'nbytes' for each requested mem type. // Pointers are returned in 'data_buf'. - // 'ngrids' and 'type' are only used for debug msg. + // 'nvars' and 'type' are only used for debug msg. void StencilContext::_alloc_data(const map & nbytes, - const map & ngrids, + const map & nvars, map >& data_buf, const std::string& type) { STATE_VARS(this); @@ -61,7 +61,7 @@ namespace yask { for (const auto& i : nbytes) { int mem_key = i.first; size_t nb = i.second; - size_t ng = ngrids.at(mem_key); + size_t ng = nvars.at(mem_key); // Alloc data depending on magic key. shared_ptr p; @@ -117,26 +117,26 @@ namespace yask { } } - // Allocate memory for grids that do not already have storage. - void StencilContext::allocGridData() { + // Allocate memory for vars that do not already have storage. + void StencilContext::allocVarData() { STATE_VARS(this); - // Allocate I/O grids before read-only grids. - GridPtrs sortedGridPtrs; - GridPtrSet done; - for (auto op : outputGridPtrs) { - sortedGridPtrs.push_back(op); + // Allocate I/O vars before read-only vars. + VarPtrs sortedVarPtrs; + VarPtrSet done; + for (auto op : outputVarPtrs) { + sortedVarPtrs.push_back(op); done.insert(op); } - for (auto gp : gridPtrs) { + for (auto gp : varPtrs) { if (!done.count(gp)) - sortedGridPtrs.push_back(gp); + sortedVarPtrs.push_back(gp); } done.clear(); #ifdef USE_PMEM - os << "PMEM grid-allocation priority:" << endl; - for (auto sp : sortedGridPtrs) { + os << "PMEM var-allocation priority:" << endl; + for (auto sp : sortedVarPtrs) { os << " '" << sp->get_name() << "'"; if (done.find(sp)!=done.end()) os << " (output)"; @@ -145,11 +145,11 @@ namespace yask { #endif // Base ptrs for all default-alloc'd data. - // These pointers will be shared by the ones in the grid + // These pointers will be shared by the ones in the var // objects, which will take over ownership when these go // out of scope. // Key is preferred numa node or -1 for local. - map > _grid_data_buf; + map > _var_data_buf; #ifdef USE_PMEM auto preferredNUMASize = opts->_numa_pref_max * 1024*1024*(size_t)1024; @@ -159,27 +159,27 @@ namespace yask { // Pass 1: count required size for each NUMA node, allocate chunk of memory at end. // Pass 2: distribute parts of already-allocated memory chunk. for (int pass = 0; pass < 3; pass++) { - TRACE_MSG("allocGridData pass " << pass << " for " << - gridPtrs.size() << " grid(s)"); + TRACE_MSG("allocVarData pass " << pass << " for " << + varPtrs.size() << " var(s)"); - // Count bytes needed and number of grids for each NUMA node. - map npbytes, ngrids; + // Count bytes needed and number of vars for each NUMA node. + map npbytes, nvars; - // Grids. - for (auto gp : sortedGridPtrs) { + // Vars. + for (auto gp : sortedVarPtrs) { if (!gp) continue; auto& gname = gp->get_name(); auto& gb = gp->gb(); - // Grid data. + // Var data. // Don't alloc if already done. if (!gp->is_storage_allocated()) { int numa_pref = gp->get_numa_preferred(); // Set storage if buffer has been allocated in pass 1. if (pass == 2) { - auto p = _grid_data_buf[numa_pref]; + auto p = _var_data_buf[numa_pref]; assert(p); gp->set_storage(p, npbytes[numa_pref]); os << gb.make_info_string() << endl; @@ -189,7 +189,7 @@ namespace yask { size_t nbytes = gp->get_num_storage_bytes(); npbytes[numa_pref] += ROUND_UP(nbytes + _data_buf_pad, CACHELINE_BYTES); - ngrids[numa_pref]++; + nvars[numa_pref]++; if (pass == 0) { #ifdef USE_PMEM @@ -201,17 +201,17 @@ namespace yask { else // TODO: change this behavior so that it doesn't actually - // modify the NUMA pref of the grid. + // modify the NUMA pref of the var. gp->set_numa_preferred(_pmem_key + getnode()); #endif } if (pass == 1) - TRACE_MSG(" grid '" << gname << "' needs " << makeByteStr(nbytes) << + TRACE_MSG(" var '" << gname << "' needs " << makeByteStr(nbytes) << " on NUMA node " << numa_pref); } - // Otherwise, just print existing grid info. + // Otherwise, just print existing var info. else if (pass == 1) os << gb.make_info_string() << endl; } @@ -219,14 +219,14 @@ namespace yask { // Reset the counters if (pass == 0) { npbytes.clear(); - ngrids.clear(); + nvars.clear(); } // Alloc for each node. if (pass == 1) - _alloc_data(npbytes, ngrids, _grid_data_buf, "grid"); + _alloc_data(npbytes, nvars, _var_data_buf, "var"); - } // grid passes. + } // var passes. }; // Determine the size and shape of all MPI buffers. @@ -257,7 +257,7 @@ namespace yask { // Determine max dist needed. TODO: determine max dist // automatically from stencils; may not be same for all - // grids. + // vars. #ifndef MAX_EXCH_DIST #define MAX_EXCH_DIST (NUM_STENCIL_DIMS - 1) #endif @@ -287,7 +287,7 @@ namespace yask { mpiInfo->has_all_vlen_mults[neigh_idx]; // Determine size of MPI buffers between neigh_rank and my - // rank for each grid and create those that are needed. It + // rank for each var and create those that are needed. It // is critical that the number, size, and shape of my // send/receive buffers match those of the receive/send // buffers of my neighbors. Important: Current algorithm @@ -295,13 +295,13 @@ namespace yask { // by considering my rank's right side data and vice-versa. // Thus, all ranks must have consistent data that contribute // to these calculations. - for (auto& gp : origGridPtrs) { + for (auto& gp : origVarPtrs) { auto& gb = gp->gb(); auto& gname = gp->get_name(); - bool grid_vec_ok = vec_ok; + bool var_vec_ok = vec_ok; // Lookup first & last domain indices and calc exchange sizes - // for this grid. + // for this var. bool found_delta = false; IdxTuple my_halo_sizes, neigh_halo_sizes; IdxTuple first_inner_idx, last_inner_idx; @@ -309,13 +309,13 @@ namespace yask { for (auto& dim : domain_dims.getDims()) { auto& dname = dim.getName(); - // Only consider domain dims that are used in this grid. + // Only consider domain dims that are used in this var. if (gp->is_dim_used(dname)) { auto vlen = gp->_get_vec_len(dname); auto lhalo = gp->get_left_halo_size(dname); auto rhalo = gp->get_right_halo_size(dname); - // Get domain indices for this grid. If there + // Get domain indices for this var. If there // are no more ranks in the given direction, // extend the "outer" index to include the halo // in that direction to make sure all data are @@ -334,23 +334,23 @@ namespace yask { // Determine if it is possible to round the // outer indices to vec-multiples. This will // be required to allow full vec exchanges for - // this grid. We won't do the actual rounding + // this var. We won't do the actual rounding // yet, because we need to see if it's safe // in all dims. // Need +1 and then -1 trick for last. fidx = round_down_flr(fidx, vlen); lidx = round_up_flr(lidx + 1, vlen) - 1; if (fidx < gp->get_first_rank_alloc_index(dname)) - grid_vec_ok = false; + var_vec_ok = false; if (lidx > gp->get_last_rank_alloc_index(dname)) - grid_vec_ok = false; + var_vec_ok = false; // Determine size of exchange in this dim. This // will be the actual halo size plus any // wave-front shifts. In the current // implementation, we need the wave-front shifts // regardless of whether there is a halo on a - // given grid. This is because each + // given var. This is because each // stencil-bundle gets shifted by the WF angles // at each step in the WF. @@ -367,7 +367,7 @@ namespace yask { // Assume my right is same as their right. neigh_halo_sizes.addDimBack(dname, rhalo + ext); - // Flag that this grid has a neighbor to left or right. + // Flag that this var has a neighbor to left or right. found_delta = true; } @@ -384,7 +384,7 @@ namespace yask { // Assume my left is same as their left. neigh_halo_sizes.addDimBack(dname, lhalo + ext); - // Flag that this grid has a neighbor to left or right. + // Flag that this var has a neighbor to left or right. found_delta = true; } @@ -394,18 +394,18 @@ namespace yask { neigh_halo_sizes.addDimBack(dname, 0); } - } // domain dims in this grid. + } // domain dims in this var. } // domain dims. // Is buffer needed? - // Example: if this grid is 2D in y-z, but only neighbors are in + // Example: if this var is 2D in y-z, but only neighbors are in // x-dim, we don't need any exchange. if (!found_delta) { - TRACE_MSG("no halo exchange needed for grid '" << gname << + TRACE_MSG("no halo exchange needed for var '" << gname << "' with rank " << neigh_rank << " because the neighbor is not in a direction" - " corresponding to a grid dim"); - continue; // to next grid. + " corresponding to a var dim"); + continue; // to next var. } // Round halo sizes if vectorized exchanges allowed. @@ -413,7 +413,7 @@ namespace yask { // and outer indices must be vec-mults or extendable // to be so. // TODO: add a heuristic to avoid increasing by a large factor. - if (grid_vec_ok) { + if (var_vec_ok) { for (auto& dim : domain_dims.getDims()) { auto& dname = dim.getName(); if (gp->is_dim_used(dname)) { @@ -434,7 +434,7 @@ namespace yask { my_halo_sizes.setVal(dname, ROUND_UP(my_halo_sizes[dname], vlen)); neigh_halo_sizes.setVal(dname, ROUND_UP(neigh_halo_sizes[dname], vlen)); - } // domain dims in this grid. + } // domain dims in this var. } // domain dims. } @@ -442,12 +442,12 @@ namespace yask { for (int bd = 0; bd < MPIBufs::nBufDirs; bd++) { // Begin/end vars to indicate what part - // of main grid to read from or write to based on + // of main var to read from or write to based on // the current neighbor being processed. IdxTuple copy_begin = gb.get_allocs(); IdxTuple copy_end = gb.get_allocs(); // one past last! - // Adjust along domain dims in this grid. + // Adjust along domain dims in this var. for (auto& dim : domain_dims.getDims()) { auto& dname = dim.getName(); if (gp->is_dim_used(dname)) { @@ -527,13 +527,13 @@ namespace yask { // Else, this neighbor is in same posn as I am in this dim, // so we leave the default begin/end settings. } - } // domain dims in this grid. + } // domain dims in this var. } // domain dims. - // Sizes of buffer in all dims of this grid. + // Sizes of buffer in all dims of this var. // Also, set begin/end value for non-domain dims. IdxTuple buf_sizes = gb.get_allocs(); - bool buf_vec_ok = grid_vec_ok; + bool buf_vec_ok = var_vec_ok; for (auto& dname : gp->get_dim_names()) { idx_t dsize = 1; @@ -564,7 +564,7 @@ namespace yask { // misc? // Copy over entire range. - // TODO: make dirty flags for misc dims in grids. + // TODO: make dirty flags for misc dims in vars. else { dsize = gp->get_alloc_size(dname); copy_begin[dname] = gp->get_first_misc_index(dname); @@ -575,9 +575,9 @@ namespace yask { // Save computed size. buf_sizes[dname] = dsize; - } // all dims in this grid. + } // all dims in this var. - // Unique name for buffer based on grid name, direction, and ranks. + // Unique name for buffer based on var name, direction, and ranks. ostringstream oss; oss << gname; if (bd == MPIBufs::bufSend) @@ -594,18 +594,18 @@ namespace yask { } // At this point, buf_sizes, copy_begin, and copy_end - // should be set for each dim in this grid. + // should be set for each dim in this var. // Compute last from end. IdxTuple copy_last = copy_end.subElements(1); - // Make MPI data entry for this grid. + // Make MPI data entry for this var. auto gbp = mpiData.emplace(gname, state->_mpiInfo); auto& gbi = gbp.first; // iterator from pair returned by emplace(). auto& gbv = gbi->second; // value from iterator. auto& buf = gbv.getBuf(MPIBufs::BufDir(bd), neigh_offsets); - // Config buffer for this grid. + // Config buffer for this var. // (But don't allocate storage yet.) buf.begin_pt = copy_begin; buf.last_pt = copy_last; @@ -625,7 +625,7 @@ namespace yask { num_elems[bd] += buf.get_size(); } // send, recv. - } // grids. + } // vars. }); // neighbors. TRACE_MSG("number of MPI send buffers on this rank: " << num_exchanges[int(MPIBufs::bufSend)]); TRACE_MSG("number of elements in send buffers: " << makeNumStr(num_elems[int(MPIBufs::bufSend)])); @@ -643,13 +643,13 @@ namespace yask { // Now we need to allocate space for them. // Base ptrs for all alloc'd data. - // These pointers will be shared by the ones in the grid + // These pointers will be shared by the ones in the var // objects, which will take over ownership when these go // out of scope. Key is memory type. map > _mpi_data_buf; - // A table for send-buffer offsets for all rank pairs for every grid: - // [grid-name][sending-rank][receiving-rank] + // A table for send-buffer offsets for all rank pairs for every var: + // [var-name][sending-rank][receiving-rank] map>> sb_ofs; bool do_shm = false; auto my_shm_rank = env->my_shm_rank; @@ -669,15 +669,15 @@ namespace yask { // Count bytes needed and number of buffers for each NUMA node. map npbytes, nbufs; - // Grids. Use the map to ensure same order in all ranks. - for (auto gi : gridMap) { + // Vars. Use the map to ensure same order in all ranks. + for (auto gi : varMap) { auto& gname = gi.first; auto& gp = gi.second; - // Are there MPI bufs for this grid? + // Are there MPI bufs for this var? if (mpiData.count(gname) == 0) continue; - auto& grid_mpi_data = mpiData.at(gname); + auto& var_mpi_data = mpiData.at(gname); // Resize table. if (pass == 0) { @@ -687,15 +687,15 @@ namespace yask { gtab.resize(env->num_shm_ranks, 0); } - // Visit buffers for each neighbor for this grid. - grid_mpi_data.visitNeighbors + // Visit buffers for each neighbor for this var. + var_mpi_data.visitNeighbors ([&](const IdxTuple& roffsets, int nrank, int nidx, MPIBufs& bufs) { // Default is global numa pref setting for MPI - // buffer, not possible override for this grid. + // buffer, not possible override for this var. int numa_pref = opts->_numa_pref; // If neighbor can use MPI shm, set key, etc. @@ -708,7 +708,7 @@ namespace yask { // Send and recv. for (int bd = 0; bd < MPIBufs::nBufDirs; bd++) { - auto& buf = grid_mpi_data.getBuf(MPIBufs::BufDir(bd), roffsets); + auto& buf = var_mpi_data.getBuf(MPIBufs::BufDir(bd), roffsets); if (buf.get_size() == 0) continue; @@ -770,7 +770,7 @@ namespace yask { for (int rn = 0; rn < env->num_shm_ranks; rn++) { TRACE_MSG("Sharing MPI shm offsets from shm-rank " << rn << - " for grid '" << gname << "'"); + " for var '" << gname << "'"); MPI_Bcast(sb_ofs[gname][rn].data(), env->num_shm_ranks, MPI_INTEGER8, rn, env->shm_comm); for (int rn2 = 0; rn2 < env->num_shm_ranks; rn2++) @@ -779,7 +779,7 @@ namespace yask { } } - } // grids. + } // vars. // Alloc for each mem type. if (pass == 0) @@ -791,7 +791,7 @@ namespace yask { #endif } - // Allocate memory for scratch grids based on number of threads and + // Allocate memory for scratch vars based on number of threads and // block sizes. void StencilContext::allocScratchData() { STATE_VARS(this); @@ -800,19 +800,19 @@ namespace yask { freeScratchData(); // Base ptrs for all alloc'd data. - // This pointer will be shared by the ones in the grid + // This pointer will be shared by the ones in the var // objects, which will take over ownership when it goes // out of scope. map > _scratch_data_buf; // Make sure the right number of threads are set so we - // have the right number of scratch grids. + // have the right number of scratch vars. int rthreads = set_region_threads(); - // Delete any existing scratch grids. - // Create new scratch grids, but without any + // Delete any existing scratch vars. + // Create new scratch vars, but without any // data allocated. - makeScratchGrids(rthreads); + makeScratchVars(rthreads); // Find the max mini-block size across all packs. // They can be different across packs when pack-specific @@ -834,16 +834,16 @@ namespace yask { // Pass 1: distribute parts of already-allocated memory chunk. for (int pass = 0; pass < 2; pass++) { TRACE_MSG("allocScratchData pass " << pass << " for " << - scratchVecs.size() << " set(s) of scratch grids"); + scratchVecs.size() << " set(s) of scratch vars"); - // Count bytes needed and number of grids for each NUMA node. - map npbytes, ngrids; + // Count bytes needed and number of vars for each NUMA node. + map npbytes, nvars; - // Loop through each scratch grid vector. + // Loop through each scratch var vector. for (auto* sgv : scratchVecs) { assert(sgv); - // Loop through each scratch grid in this vector. + // Loop through each scratch var in this vector. // There will be one for each region thread. assert(int(sgv->size()) == rthreads); int thr_num = 0; @@ -859,7 +859,7 @@ namespace yask { if (gp->is_dim_used(dname)) { - // Set domain size of scratch grid to mini-block size. + // Set domain size of scratch var to mini-block size. gp->_set_domain_size(dname, mblksize[dname]); // Conservative allowance for WF exts and/or temporal shifts. @@ -886,20 +886,20 @@ namespace yask { size_t nbytes = gp->get_num_storage_bytes(); npbytes[numa_pref] += ROUND_UP(nbytes + _data_buf_pad, CACHELINE_BYTES); - ngrids[numa_pref]++; + nvars[numa_pref]++; if (pass == 0) - TRACE_MSG(" scratch grid '" << gname << "' for thread " << + TRACE_MSG(" scratch var '" << gname << "' for thread " << thr_num << " needs " << makeByteStr(nbytes) << " on NUMA node " << numa_pref); thr_num++; - } // scratch grids. - } // scratch-grid vecs. + } // scratch vars. + } // scratch-var vecs. // Alloc for each node. if (pass == 0) - _alloc_data(npbytes, ngrids, _scratch_data_buf, "scratch grid"); + _alloc_data(npbytes, nvars, _scratch_data_buf, "scratch var"); - } // scratch-grid passes. + } // scratch-var passes. } } // namespace yask. diff --git a/src/kernel/lib/auto_tuner.cpp b/src/kernel/lib/auto_tuner.cpp index fe2b04b3..af1000ff 100644 --- a/src/kernel/lib/auto_tuner.cpp +++ b/src/kernel/lib/auto_tuner.cpp @@ -79,7 +79,7 @@ namespace yask { } // Apply auto-tuning immediately, i.e., not as part of normal processing. - // Will alter data in grids. + // Will alter data in vars. void StencilContext::run_auto_tuner_now(bool verbose) { STATE_VARS(this); if (!rank_bb.bb_valid) diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 907f5dae..b8dcaa8b 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -33,7 +33,7 @@ namespace yask { ///// Top-level methods for evaluating reference and optimized stencils. - // Eval stencil bundle(s) over grid(s) using reference scalar code. + // Eval stencil bundle(s) over var(s) using reference scalar code. void StencilContext::run_ref(idx_t first_step_index, idx_t last_step_index) { STATE_VARS(this); @@ -62,21 +62,21 @@ namespace yask { end.makeDimValStr() << ")"); // Force sub-sizes to whole rank size so that scratch - // grids will be large enough. Turn off any temporal blocking. + // vars will be large enough. Turn off any temporal blocking. opts->_region_sizes.setValsSame(0); opts->_block_sizes.setValsSame(0); opts->_mini_block_sizes.setValsSame(0); opts->_sub_block_sizes.setValsSame(0); opts->adjustSettings(); - update_grid_info(true); + update_var_info(true); - // Copy these settings to packs and realloc scratch grids. + // Copy these settings to packs and realloc scratch vars. for (auto& sp : stPacks) sp->getLocalSettings() = *opts; allocScratchData(); - // Use only one set of scratch grids. - int scratch_grid_idx = 0; + // Use only one set of scratch vars. + int scratch_var_idx = 0; // Indices to loop through. // Init from begin & end tuples. @@ -84,10 +84,10 @@ namespace yask { rank_idxs.begin = begin; rank_idxs.end = end; - // Set offsets in scratch grids. - // Requires scratch grids to be allocated for whole - // rank instead of smaller grid size. - update_scratch_grid_info(scratch_grid_idx, rank_idxs.begin); + // Set offsets in scratch vars. + // Requires scratch vars to be allocated for whole + // rank instead of smaller var size. + update_scratch_var_info(scratch_var_idx, rank_idxs.begin); // Initial halo exchange. // TODO: get rid of all halo exchanges in this function, @@ -130,7 +130,7 @@ namespace yask { exchange_halos(); // Find the bundles that need to be processed. - // This will be the prerequisite scratch-grid + // This will be the prerequisite scratch-var // bundles plus this non-scratch group. auto sg_list = asg->get_reqd_bundles(); @@ -138,18 +138,18 @@ namespace yask { for (auto* sg : sg_list) { // Indices needed for the generated misc loops. Will normally be a - // copy of rank_idxs except when updating scratch-grids. - ScanIndices misc_idxs = sg->adjust_span(scratch_grid_idx, rank_idxs); + // copy of rank_idxs except when updating scratch-vars. + ScanIndices misc_idxs = sg->adjust_span(scratch_var_idx, rank_idxs); misc_idxs.stride.setFromConst(1); // ensure unit stride. // Define misc-loop function. Since stride is always 1, we // ignore misc_stop. If point is in sub-domain for this // bundle, then evaluate the reference scalar code. - // TODO: fix domain of scratch grids. + // TODO: fix domain of scratch vars. #define MISC_FN(misc_idxs) \ do { \ if (sg->is_in_valid_domain(misc_idxs.start)) \ - sg->calc_scalar(scratch_grid_idx, misc_idxs.start); \ + sg->calc_scalar(scratch_var_idx, misc_idxs.start); \ } while(0) // Scan through n-D space. @@ -161,12 +161,12 @@ namespace yask { #undef misc_fn } // needed bundles. - // Mark grids that [may] have been written to. - // Mark grids as dirty even if not actually written by this + // Mark vars that [may] have been written to. + // Mark vars as dirty even if not actually written by this // rank. This is needed because neighbors will not know what - // grids are actually dirty, and all ranks must have the same - // information about which grids are possibly dirty. - update_grids(nullptr, start_t, stop_t, true); + // vars are actually dirty, and all ranks must have the same + // information about which vars are possibly dirty. + update_vars(nullptr, start_t, stop_t, true); } // all bundles. @@ -179,7 +179,7 @@ namespace yask { run_time.stop(); } // run_ref. - // Eval stencil bundle pack(s) over grid(s) using optimized code. + // Eval stencil bundle pack(s) over var(s) using optimized code. void StencilContext::run_solution(idx_t first_step_index, idx_t last_step_index) { @@ -390,16 +390,16 @@ namespace yask { } // domain dims. #endif - // Mark grids that [may] have been written to by - // this pack. Mark grids as dirty even if not + // Mark vars that [may] have been written to by + // this pack. Mark vars as dirty even if not // actually written by this rank, perhaps due to // sub-domains or asymmetrical stencils. This is - // needed because neighbors will not know what grids + // needed because neighbors will not know what vars // are actually dirty, and all ranks must have the - // same information about which grids are possibly + // same information about which vars are possibly // dirty. TODO: make this smarter to save unneeded // MPI exchanges. - update_grids(bp, start_t, stop_t, true); + update_vars(bp, start_t, stop_t, true); // Do the appropriate steps for halo exchange of exterior. // TODO: exchange halo for each dim as soon as it's done. @@ -421,7 +421,7 @@ namespace yask { // Mark as dirty only if we did exterior. bool mark_dirty = do_mpi_left || do_mpi_right; - update_grids(bp, start_t, stop_t, mark_dirty); + update_vars(bp, start_t, stop_t, mark_dirty); // Do the appropriate steps for halo exchange depending // on 'do_mpi_*' flags. @@ -476,8 +476,8 @@ namespace yask { } // left/right. } // domain dims. - // Mark grids dirty for all packs. - update_grids(bp, start_t, stop_t, true); + // Mark vars dirty for all packs. + update_vars(bp, start_t, stop_t, true); // Do the appropriate steps for halo exchange of exterior. // TODO: exchange halo for each dim as soon as it's done. @@ -499,7 +499,7 @@ namespace yask { // Mark as dirty only if we did exterior. bool mark_dirty = do_mpi_left || do_mpi_right; - update_grids(bp, start_t, stop_t, mark_dirty); + update_vars(bp, start_t, stop_t, mark_dirty); // Do the appropriate steps for halo exchange depending // on 'do_mpi_*' flags. @@ -1089,10 +1089,10 @@ namespace yask { if (ok) { - // Update offsets of scratch grids based on the current + // Update offsets of scratch vars based on the current // mini-block location. if (scratchVecs.size()) - update_scratch_grid_info(region_thread_idx, mini_block_idxs.begin); + update_scratch_var_info(region_thread_idx, mini_block_idxs.begin); // Call calc_mini_block() for each non-scratch bundle. for (auto* sb : *bp) @@ -1464,20 +1464,20 @@ namespace yask { return ok; } - // Adjust offsets of scratch grids based on thread number 'thread_idx' - // and beginning point of mini-block 'idxs'. Each scratch-grid is + // Adjust offsets of scratch vars based on thread number 'thread_idx' + // and beginning point of mini-block 'idxs'. Each scratch-var is // assigned to a thread, so it must "move around" as the thread is // assigned to each mini-block. This move is accomplished by changing - // the grids' local offsets. - void StencilContext::update_scratch_grid_info(int thread_idx, + // the vars' local offsets. + void StencilContext::update_scratch_var_info(int thread_idx, const Indices& idxs) { STATE_VARS(this); - // Loop thru vecs of scratch grids. + // Loop thru vecs of scratch vars. for (auto* sv : scratchVecs) { assert(sv); - // Get ptr to the scratch grid for this thread. + // Get ptr to the scratch var for this thread. auto& gp = sv->at(thread_idx); assert(gp); auto& gb = gp->gb(); @@ -1489,22 +1489,22 @@ namespace yask { auto& dim = stencil_dims.getDim(i); auto& dname = dim.getName(); - // Is this dim used in this grid? + // Is this dim used in this var? int posn = gb.get_dim_posn(dname); if (posn >= 0) { - // Set rank offset of grid based on starting point of rank. + // Set rank offset of var based on starting point of rank. // Thus, it it not necessarily a vec mult. auto rofs = rank_domain_offsets[j]; gp->_set_rank_offset(posn, rofs); - // Must use the vector len in this grid, which may - // not be the same as vec_lens[posn] because grid + // Must use the vector len in this var, which may + // not be the same as vec_lens[posn] because var // may not be vectorized. auto vlen = gp->_get_vec_len(posn); - // See diagram in yk_grid defn. Local offset is the - // offset of this grid relative to the beginning of the + // See diagram in yk_var defn. Local offset is the + // offset of this var relative to the beginning of the // current rank. Set local offset to diff between // global offset and rank offset. Round down to make // sure it's vec-aligned. @@ -1515,21 +1515,21 @@ namespace yask { } } - // Compare grids in contexts. + // Compare vars in contexts. // Return number of mis-compares. idx_t StencilContext::compareData(const StencilContext& ref) const { STATE_VARS_CONST(this); - os << "Comparing grid(s) in '" << name << "' to '" << ref.name << "'..." << endl; - if (gridPtrs.size() != ref.gridPtrs.size()) { - cerr << "** number of grids not equal." << endl; + os << "Comparing var(s) in '" << name << "' to '" << ref.name << "'..." << endl; + if (varPtrs.size() != ref.varPtrs.size()) { + cerr << "** number of vars not equal." << endl; return 1; } idx_t errs = 0; - for (size_t gi = 0; gi < gridPtrs.size(); gi++) { - TRACE_MSG("Grid '" << ref.gridPtrs[gi]->get_name() << "'..."); - auto& gb = gridPtrs[gi]->gb(); - auto* rgbp = ref.gridPtrs[gi]->gbp(); + for (size_t gi = 0; gi < varPtrs.size(); gi++) { + TRACE_MSG("Var '" << ref.varPtrs[gi]->get_name() << "'..."); + auto& gb = varPtrs[gi]->gb(); + auto* rgbp = ref.varPtrs[gi]->gbp(); errs += gb.compare(rgbp); } @@ -1552,22 +1552,22 @@ namespace yask { int num_tests = 0; for (auto& mdi : mpiData) { auto& gname = mdi.first; - auto& grid_mpi_data = mdi.second; - MPI_Request* grid_recv_reqs = grid_mpi_data.recv_reqs.data(); - MPI_Request* grid_send_reqs = grid_mpi_data.send_reqs.data(); + auto& var_mpi_data = mdi.second; + MPI_Request* var_recv_reqs = var_mpi_data.recv_reqs.data(); + MPI_Request* var_send_reqs = var_mpi_data.send_reqs.data(); int flag; #if 1 - int indices[max(grid_mpi_data.recv_reqs.size(), grid_mpi_data.send_reqs.size())]; - MPI_Testsome(int(grid_mpi_data.recv_reqs.size()), grid_recv_reqs, &flag, indices, MPI_STATUS_IGNORE); - MPI_Testsome(int(grid_mpi_data.send_reqs.size()), grid_send_reqs, &flag, indices, MPI_STATUS_IGNORE); + int indices[max(var_mpi_data.recv_reqs.size(), var_mpi_data.send_reqs.size())]; + MPI_Testsome(int(var_mpi_data.recv_reqs.size()), var_recv_reqs, &flag, indices, MPI_STATUS_IGNORE); + MPI_Testsome(int(var_mpi_data.send_reqs.size()), var_send_reqs, &flag, indices, MPI_STATUS_IGNORE); #elif 0 int index; - MPI_Testany(int(grid_mpi_data.recv_reqs.size()), grid_recv_reqs, &index, &flag, MPI_STATUS_IGNORE); - MPI_Testany(int(grid_mpi_data.send_reqs.size()), grid_send_reqs, &index, &flag, MPI_STATUS_IGNORE); + MPI_Testany(int(var_mpi_data.recv_reqs.size()), var_recv_reqs, &index, &flag, MPI_STATUS_IGNORE); + MPI_Testany(int(var_mpi_data.send_reqs.size()), var_send_reqs, &index, &flag, MPI_STATUS_IGNORE); #else - for (size_t i = 0; i < grid_mpi_data.recv_reqs.size(); i++) { - auto& r = grid_recv_reqs[i]; + for (size_t i = 0; i < var_mpi_data.recv_reqs.size(); i++) { + auto& r = var_recv_reqs[i]; if (r != MPI_REQUEST_NULL) { //TRACE_MSG(gname << " recv test &MPI_Request = " << &r); MPI_Test(&r, &flag, MPI_STATUS_IGNORE); @@ -1576,8 +1576,8 @@ namespace yask { r = MPI_REQUEST_NULL; } } - for (size_t i = 0; i < grid_mpi_data.send_reqs.size(); i++) { - auto& r = grid_send_reqs[i]; + for (size_t i = 0; i < var_mpi_data.send_reqs.size(); i++) { + auto& r = var_send_reqs[i]; if (r != MPI_REQUEST_NULL) { //TRACE_MSG(gname << " send test &MPI_Request = " << &r); MPI_Test(&r, &flag, MPI_STATUS_IGNORE); @@ -1594,7 +1594,7 @@ namespace yask { #endif } - // Exchange dirty halo data for all grids and all steps. + // Exchange dirty halo data for all vars and all steps. void StencilContext::exchange_halos() { #ifdef USE_MPI @@ -1614,30 +1614,30 @@ namespace yask { TRACE_MSG(" following calc of MPI interior"); } - // Vars for list of grids that need to be swapped and their step - // indices. Use an ordered map by *name* to make sure grids are - // swapped in same order on all ranks. (If we order grids by + // Vars for list of vars that need to be swapped and their step + // indices. Use an ordered map by *name* to make sure vars are + // swapped in same order on all ranks. (If we order vars by // pointer, pointer values will not generally be the same on each // rank.) - GridPtrMap gridsToSwap; - map firstStepsToSwap; - map lastStepsToSwap; + VarPtrMap varsToSwap; + map firstStepsToSwap; + map lastStepsToSwap; - // Loop thru all grids. - for (auto& gp : gridPtrs) { + // Loop thru all vars. + for (auto& gp : varPtrs) { auto& gb = gp->gb(); - // Don't swap scratch grids. + // Don't swap scratch vars. if (gb.is_scratch()) continue; - // Only need to swap grids that have any MPI buffers. + // Only need to swap vars that have any MPI buffers. auto& gname = gp->get_name(); if (mpiData.count(gname) == 0) continue; // Check all allocated step indices. - // Use '0' for grids that don't use the step dim. + // Use '0' for vars that don't use the step dim. idx_t start_t = 0, stop_t = 1; if (gp->is_dim_used(step_dim)) { start_t = gp->get_first_valid_step_index(); @@ -1645,13 +1645,13 @@ namespace yask { } for (idx_t t = start_t; t < stop_t; t++) { - // Only need to swap grids whose halos are not up-to-date + // Only need to swap vars whose halos are not up-to-date // for this step. if (!gb.is_dirty(t)) continue; - // Swap this grid. - gridsToSwap[gname] = gp; + // Swap this var. + varsToSwap[gname] = gp; // Update first step. if (firstStepsToSwap.count(gp) == 0 || t < firstStepsToSwap[gp]) @@ -1662,19 +1662,19 @@ namespace yask { lastStepsToSwap[gp] = t; } // steps. - } // grids. + } // vars. TRACE_MSG("exchange_halos: need to exchange halos for " << - gridsToSwap.size() << " grid(s)"); - assert(gridsToSwap.size() == firstStepsToSwap.size()); - assert(gridsToSwap.size() == lastStepsToSwap.size()); + varsToSwap.size() << " var(s)"); + assert(varsToSwap.size() == firstStepsToSwap.size()); + assert(varsToSwap.size() == lastStepsToSwap.size()); // Sequence of things to do for each neighbor. enum halo_steps { halo_irecv, halo_pack_isend, halo_unpack, halo_final }; vector steps_to_do; - // Flags indicate what part of grids were most recently calc'd. + // Flags indicate what part of vars were most recently calc'd. // These determine what exchange steps need to be done now. - if (gridsToSwap.size()) { + if (varsToSwap.size()) { if (do_mpi_left || do_mpi_right) { steps_to_do.push_back(halo_irecv); steps_to_do.push_back(halo_pack_isend); @@ -1700,20 +1700,20 @@ namespace yask { else THROW_YASK_EXCEPTION("internal error: unknown halo-exchange step"); - // Loop thru all grids to swap. + // Loop thru all vars to swap. // Use 'gi' as an MPI tag. int gi = 0; - for (auto gtsi : gridsToSwap) { + for (auto gtsi : varsToSwap) { gi++; auto& gname = gtsi.first; auto& gp = gtsi.second; auto& gb = gp->gb(); - auto& grid_mpi_data = mpiData.at(gname); - MPI_Request* grid_recv_reqs = grid_mpi_data.recv_reqs.data(); - MPI_Request* grid_send_reqs = grid_mpi_data.send_reqs.data(); + auto& var_mpi_data = mpiData.at(gname); + MPI_Request* var_recv_reqs = var_mpi_data.recv_reqs.data(); + MPI_Request* var_send_reqs = var_mpi_data.send_reqs.data(); // Loop thru all this rank's neighbors. - grid_mpi_data.visitNeighbors + var_mpi_data.visitNeighbors ([&](const IdxTuple& offsets, // NeighborOffset. int neighbor_rank, int ni, // unique neighbor index. @@ -1735,7 +1735,7 @@ namespace yask { else { void* buf = (void*)recvBuf._elems; TRACE_MSG("exchange_halos: requesting up to " << makeByteStr(nbytes)); - auto& r = grid_recv_reqs[ni]; + auto& r = var_recv_reqs[ni]; MPI_Irecv(buf, nbytes, MPI_BYTE, neighbor_rank, int(gi), env->comm, &r); @@ -1776,7 +1776,7 @@ namespace yask { wait_delta += wait_time.stop(); } - // Copy (pack) data from grid to buffer. + // Copy (pack) data from var to buffer. void* buf = (void*)sendBuf._elems; idx_t nelems = 0; TRACE_MSG("exchange_halos: packing [" << first.makeDimValStr() << @@ -1798,7 +1798,7 @@ namespace yask { // Send packed buffer to neighbor. assert(nbytes <= sendBuf.get_bytes()); TRACE_MSG("exchange_halos: sending " << makeByteStr(nbytes)); - auto& r = grid_send_reqs[ni]; + auto& r = var_send_reqs[ni]; MPI_Isend(buf, nbytes, MPI_BYTE, neighbor_rank, int(gi), env->comm, &r); num_send_reqs++; @@ -1823,7 +1823,7 @@ namespace yask { else { // Wait for data from neighbor before unpacking it. - auto& r = grid_recv_reqs[ni]; + auto& r = var_recv_reqs[ni]; if (r != MPI_REQUEST_NULL) { TRACE_MSG(" waiting for receipt of " << makeByteStr(nbytes)); wait_time.start(); @@ -1846,7 +1846,7 @@ namespace yask { last.setVal(step_dim, lastStepsToSwap[gp]); } - // Copy data from buffer to grid. + // Copy data from buffer to var. void* buf = (void*)recvBuf._elems; idx_t nelems = 0; TRACE_MSG("exchange_halos: got data; unpacking into [" << first.makeDimValStr() << @@ -1881,22 +1881,22 @@ namespace yask { // send to finish until we want to reuse this buffer, // so we could wait on the *previous* send right before // doing another one. - auto& r = grid_send_reqs[ni]; + auto& r = var_send_reqs[ni]; if (r != MPI_REQUEST_NULL) { TRACE_MSG(" waiting to finish send of " << makeByteStr(nbytes)); wait_time.start(); - MPI_Wait(&grid_send_reqs[ni], MPI_STATUS_IGNORE); + MPI_Wait(&var_send_reqs[ni], MPI_STATUS_IGNORE); wait_delta += wait_time.stop(); } r = MPI_REQUEST_NULL; } } - // Mark grids as up-to-date when done. + // Mark vars as up-to-date when done. for (idx_t si = firstStepsToSwap[gp]; si <= lastStepsToSwap[gp]; si++) { if (gb.is_dirty(si)) { gb.set_dirty(false, si); - TRACE_MSG("exchange_halos: grid '" << gname << + TRACE_MSG("exchange_halos: var '" << gname << "' marked as clean at step-index " << si); } } @@ -1904,7 +1904,7 @@ namespace yask { }); // visit neighbors. - } // grids. + } // vars. } // exchange sequence. @@ -1917,13 +1917,13 @@ namespace yask { #endif } - // Update data in grids that have been written to by bundle pack 'sel_bp'. - void StencilContext::update_grids(const BundlePackPtr& sel_bp, + // Update data in vars that have been written to by bundle pack 'sel_bp'. + void StencilContext::update_vars(const BundlePackPtr& sel_bp, idx_t start, idx_t stop, bool mark_dirty) { STATE_VARS(this); idx_t stride = (start > stop) ? -1 : 1; - map> grids_done; + map> vars_done; // Stencil bundle packs. for (auto& bp : stPacks) { @@ -1945,25 +1945,25 @@ namespace yask { if (!sb->get_output_step_index(t, t_out)) continue; - // Output grids for this bundle. NB: don't need to mark - // scratch grids as dirty because they are never exchanged. - for (auto gp : sb->outputGridPtrs) { + // Output vars for this bundle. NB: don't need to mark + // scratch vars as dirty because they are never exchanged. + for (auto gp : sb->outputVarPtrs) { auto& gb = gp->gb(); // Update if not already done. - if (grids_done[gp].count(t_out) == 0) { + if (vars_done[gp].count(t_out) == 0) { gb.update_valid_step(t_out); if (mark_dirty) gb.set_dirty(true, t_out); - TRACE_MSG("grid '" << gp->get_name() << + TRACE_MSG("var '" << gp->get_name() << "' updated at step " << t_out); - grids_done[gp].insert(t_out); + vars_done[gp].insert(t_out); } } } // bundles. } // steps. } // packs. - } // update_grids(). + } // update_vars(). // Reset any locks, etc. void StencilContext::reset_locks() { diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index d9cc10a0..8eb34b0a 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -163,7 +163,7 @@ namespace yask { // Alloc given bytes on each NUMA node. virtual void _alloc_data(const std::map & nbytes, - const std::map & ngrids, + const std::map & nvars, std::map >& _data_buf, const std::string& type); @@ -217,20 +217,20 @@ namespace yask { // which they should be evaluated within a step. BundlePackList stPacks; - // All non-scratch grids, including those created by APIs. - GridPtrs gridPtrs; - GridPtrMap gridMap; + // All non-scratch vars, including those created by APIs. + VarPtrs varPtrs; + VarPtrMap varMap; - // Only grids defined by the YASK compiler. - GridPtrs origGridPtrs; - GridPtrMap origGridMap; + // Only vars defined by the YASK compiler. + VarPtrs origVarPtrs; + VarPtrMap origVarMap; - // Only grids defined by the YASK compiler that are updated by the stencils. - GridPtrs outputGridPtrs; - GridPtrMap outputGridMap; + // Only vars defined by the YASK compiler that are updated by the stencils. + VarPtrs outputVarPtrs; + VarPtrMap outputVarMap; - // Scratch-grid vectors. - // Each vector contains a grid for each thread. + // Scratch-var vectors. + // Each vector contains a var for each thread. ScratchVecs scratchVecs; // Some calculated sizes for this rank and overall. @@ -247,7 +247,7 @@ namespace yask { YaskTimer test_time; // time spent just doing MPI tests. idx_t steps_done = 0; // number of steps that have been run. - // Maximum halos, skewing angles, and work extensions over all grids + // Maximum halos, skewing angles, and work extensions over all vars // used for wave-front rank tiling (wf). IdxTuple max_halos; // spatial halos. idx_t wf_steps = 0; // max number of steps in a WF. 0 => no WF. @@ -281,8 +281,8 @@ namespace yask { // Clear this to ignore step conditions. bool check_step_conds = true; - // MPI buffers for each grid. - // Map key: grid name. + // MPI buffers for each var. + // Map key: var name. std::map mpiData; // Constructor. @@ -309,9 +309,9 @@ namespace yask { // Misc accessors. AutoTuner& getAT() { return _at; } - // Add a new grid to the containers. - virtual void addGrid(YkGridPtr gp, bool is_orig, bool is_output); - virtual void addScratch(GridPtrs& scratch_vec) { + // Add a new var to the containers. + virtual void addVar(YkVarPtr gp, bool is_orig, bool is_output); + virtual void addScratch(VarPtrs& scratch_vec) { scratchVecs.push_back(&scratch_vec); } @@ -319,9 +319,9 @@ namespace yask { // Allocate MPI buffers as needed. virtual void setupRank(); - // Allocate grid memory for any grids that do not + // Allocate var memory for any vars that do not // already have storage. - virtual void allocGridData(); + virtual void allocVarData(); // Determine sizes of MPI buffers and allocate MPI buffer memory. // Dealloc any existing MPI buffers first. @@ -330,14 +330,14 @@ namespace yask { mpiData.clear(); } - // Alloc scratch-grid memory. - // Dealloc any existing scratch-grids first. + // Alloc scratch-var memory. + // Dealloc any existing scratch-vars first. virtual void allocScratchData(); virtual void freeScratchData() { - makeScratchGrids(0); + makeScratchVars(0); } - // Allocate grids, params, MPI bufs, etc. + // Allocate vars, params, MPI bufs, etc. // Calculate rank position in problem. // Initialize some other data structures. // Print lots of stats. @@ -356,28 +356,28 @@ namespace yask { /// Get statistics associated with preceding calls to run_solution(). virtual yk_stats_ptr get_stats(); - // Dealloc grids, etc. + // Dealloc vars, etc. virtual void end_solution(); - // Set grid sizes and offsets. + // Set var sizes and offsets. // This should be called anytime a setting or offset is changed. - virtual void update_grid_info(bool force); + virtual void update_var_info(bool force); // Set temporal blocking data. // This should be called anytime a block size is changed. virtual void update_tb_info(); - // Adjust offsets of scratch grids based + // Adjust offsets of scratch vars based // on thread and scan indices. - virtual void update_scratch_grid_info(int region_thread_idx, + virtual void update_scratch_var_info(int region_thread_idx, const Indices& idxs); - // Get total memory allocation required by grids. + // Get total memory allocation required by vars. // Does not include MPI buffers. // TODO: add MPI buffers. virtual size_t get_num_bytes() { size_t sz = 0; - for (auto gp : gridPtrs) { + for (auto gp : varPtrs) { if (gp) sz += gp->get_num_storage_bytes() + _data_buf_pad; } @@ -389,29 +389,29 @@ namespace yask { return sz; } - // Init all grids & params by calling realInitFn. - virtual void initValues(std::function realInitFn); - // Init all grids & params to same value within grids, - // but different for each grid. + // Init all vars & params to same value within vars, + // but different for each var. virtual void initSame() { - initValues([&](YkGridPtr gp, real_t seed){ gp->set_all_elements_same(seed); }); + initValues([&](YkVarPtr gp, real_t seed){ gp->set_all_elements_same(seed); }); } - // Init all grids & params to different values within grids, - // and different for each grid. + // Init all vars & params to different values within vars, + // and different for each var. virtual void initDiff() { - initValues([&](YkGridPtr gp, real_t seed){ gp->set_all_elements_in_seq(seed); }); + initValues([&](YkVarPtr gp, real_t seed){ gp->set_all_elements_in_seq(seed); }); } - // Init all grids & params. + // Init all vars & params. // By default it uses the initSame initialization routine. virtual void initData() { initDiff(); // Safer than initSame() to avoid NaNs due to div-by-zero. } - // Compare grids in contexts for validation. + // Compare vars in contexts for validation. // Params should not be written to, so they are not compared. // Return number of mis-compares. virtual idx_t compareData(const StencilContext& ref) const; @@ -449,10 +449,10 @@ namespace yask { // Call MPI_Test() on all unfinished requests to promote MPI progress. void poke_halo_exchange(); - // Update valid steps in grids that have been written to by bundle pack 'sel_bp'. + // Update valid steps in vars that have been written to by bundle pack 'sel_bp'. // If sel_bp==null, use all bundles. // If 'mark_dirty', also mark as needing halo exchange. - void update_grids(const BundlePackPtr& sel_bp, + void update_vars(const BundlePackPtr& sel_bp, idx_t start, idx_t stop, bool mark_dirty); @@ -480,19 +480,19 @@ namespace yask { // Set the bounding-box around all stencil bundles. void find_bounding_boxes(); - // Make new scratch grids. - virtual void makeScratchGrids (int num_threads) =0; + // Make new scratch vars. + virtual void makeScratchVars (int num_threads) =0; - // Make a new grid iff its dims match any in the stencil. - // Returns pointer to the new grid or nullptr if no match. - virtual GridBasePtr newStencilGrid (const std::string & name, - const GridDimNames & dims) =0; + // Make a new var iff its dims match any in the stencil. + // Returns pointer to the new var or nullptr if no match. + virtual VarBasePtr newStencilVar (const std::string & name, + const VarDimNames & dims) =0; - // Make a new grid with 'name' and 'dims'. + // Make a new var with 'name' and 'dims'. // Set sizes if 'sizes' is non-null. - virtual YkGridPtr newGrid(const std::string& name, - const GridDimNames& dims, - const GridDimSizes* sizes); + virtual YkVarPtr newVar(const std::string& name, + const VarDimNames& dims, + const VarDimSizes* sizes); // APIs. // See yask_kernel_api.hpp. @@ -509,46 +509,46 @@ namespace yask { return REAL_BYTES; } - virtual int get_num_grids() const { - return int(gridPtrs.size()); + virtual int get_num_vars() const { + return int(varPtrs.size()); } - virtual yk_grid_ptr get_grid(const std::string& name) { - auto i = gridMap.find(name); - if (i != gridMap.end()) + virtual yk_var_ptr get_var(const std::string& name) { + auto i = varMap.find(name); + if (i != varMap.end()) return i->second; return nullptr; } - virtual std::vector get_grids() { - std::vector grids; - for (int i = 0; i < get_num_grids(); i++) - grids.push_back(gridPtrs.at(i)); - return grids; + virtual std::vector get_vars() { + std::vector vars; + for (int i = 0; i < get_num_vars(); i++) + vars.push_back(varPtrs.at(i)); + return vars; } - virtual yk_grid_ptr - new_grid(const std::string& name, - const GridDimNames& dims) { - return newGrid(name, dims, NULL); + virtual yk_var_ptr + new_var(const std::string& name, + const VarDimNames& dims) { + return newVar(name, dims, NULL); } - virtual yk_grid_ptr - new_grid(const std::string& name, + virtual yk_var_ptr + new_var(const std::string& name, const std::initializer_list& dims) { - GridDimNames dims2(dims); - return new_grid(name, dims2); + VarDimNames dims2(dims); + return new_var(name, dims2); } - virtual yk_grid_ptr - new_fixed_size_grid(const std::string& name, - const GridDimNames& dims, - const GridDimSizes& dim_sizes) { - return newGrid(name, dims, &dim_sizes); + virtual yk_var_ptr + new_fixed_size_var(const std::string& name, + const VarDimNames& dims, + const VarDimSizes& dim_sizes) { + return newVar(name, dims, &dim_sizes); } - virtual yk_grid_ptr - new_fixed_size_grid(const std::string& name, + virtual yk_var_ptr + new_fixed_size_var(const std::string& name, const std::initializer_list& dims, const std::initializer_list& dim_sizes) { - GridDimNames dims2(dims); - GridDimSizes sizes2(dim_sizes); - return new_fixed_size_grid(name, dims2, sizes2); + VarDimNames dims2(dims); + VarDimSizes sizes2(dim_sizes); + return new_fixed_size_var(name, dims2, sizes2); } virtual std::string get_step_dim_name() const { @@ -582,7 +582,7 @@ namespace yask { virtual void run_solution(idx_t step_index) { run_solution(step_index, step_index); } - virtual void fuse_grids(yk_solution_ptr other); + virtual void fuse_vars(yk_solution_ptr other); // APIs that access settings. virtual void set_overall_domain_size(const std::string& dim, idx_t size); diff --git a/src/kernel/lib/generic_grids.cpp b/src/kernel/lib/generic_var.cpp similarity index 82% rename from src/kernel/lib/generic_grids.cpp rename to src/kernel/lib/generic_var.cpp index dad88685..c0c83aa7 100644 --- a/src/kernel/lib/generic_grids.cpp +++ b/src/kernel/lib/generic_var.cpp @@ -29,15 +29,15 @@ using namespace std; namespace yask { // Ctor. No allocation is done. See notes on default_alloc(). - GenericGridBase::GenericGridBase(KernelStateBase& state, + GenericVarBase::GenericVarBase(KernelStateBase& state, const string& name, Layout& layout_base, - const GridDimNames& dimNames) : + const VarDimNames& dimNames) : KernelStateBase(state), _name(name), _layout_base(&layout_base) { for (auto& dn : dimNames) - _grid_dims.addDimBack(dn, 1); + _var_dims.addDimBack(dn, 1); _sync_layout_with_dims(); } @@ -45,7 +45,7 @@ namespace yask { // For other options, // programmer should call get_num_elems() or get_num_bytes() and // then provide allocated memory via set_storage(). - void GenericGridBase::default_alloc() { + void GenericVarBase::default_alloc() { STATE_VARS(this); // Release any old data if last owner. @@ -57,7 +57,7 @@ namespace yask { // Alloc required number of bytes. size_t sz = get_num_bytes(); os << "Allocating " << makeByteStr(sz) << - " for grid '" << _name << "'"; + " for var '" << _name << "'"; #ifdef USE_NUMA if (numa_pref >= 0) os << " preferring NUMA node " << numa_pref; @@ -72,14 +72,14 @@ namespace yask { } // Make some descriptive info. - string GenericGridBase::make_info_string(const string& elem_name) const { + string GenericVarBase::make_info_string(const string& elem_name) const { stringstream oss; oss << "'" << _name << "' "; - if (_grid_dims.getNumDims() == 0) + if (_var_dims.getNumDims() == 0) oss << "scalar"; else - oss << _grid_dims.getNumDims() << "-D var (" << - _grid_dims.makeDimValStr(" * ") << ")"; + oss << _var_dims.getNumDims() << "-D var (" << + _var_dims.makeDimValStr(" * ") << ")"; if (_elems) oss << " with storage at " << _elems << " containing "; else @@ -94,13 +94,13 @@ namespace yask { // Set pointer to storage. // Free old storage. // 'base' should provide get_num_bytes() bytes at offset bytes. - void GenericGridBase::set_storage(shared_ptr& base, size_t offset) { + void GenericVarBase::set_storage(shared_ptr& base, size_t offset) { // Release any old data if last owner. release_storage(); // Share ownership of base. - // This ensures that last grid to use a shared allocation + // This ensures that last var to use a shared allocation // will trigger dealloc. _base = base; @@ -116,7 +116,7 @@ namespace yask { // Template implementations. template - void GenericGridTemplate::set_elems_same(T val) { + void GenericVarTemplate::set_elems_same(T val) { if (_elems) { yask_for(0, get_num_elems(), 1, [&](idx_t start, idx_t stop, idx_t thread_num) { @@ -126,7 +126,7 @@ namespace yask { } template - void GenericGridTemplate::set_elems_in_seq(T seed) { + void GenericVarTemplate::set_elems_in_seq(T seed) { if (_elems) { const idx_t wrap = 71; // TODO: avoid multiple of any dim size. yask_for(0, get_num_elems(), 1, @@ -137,17 +137,17 @@ namespace yask { } template - idx_t GenericGridTemplate::count_diffs(const GenericGridBase* ref, + idx_t GenericVarTemplate::count_diffs(const GenericVarBase* ref, double epsilon) const { if (!ref) return get_num_elems(); - auto* p = dynamic_cast*>(ref); + auto* p = dynamic_cast*>(ref); if (!p) return get_num_elems(); // Dims & sizes same? - if (_grid_dims != p->_grid_dims) + if (_var_dims != p->_var_dims) return get_num_elems(); // Count abs diffs > epsilon. @@ -162,7 +162,7 @@ namespace yask { } // Explicitly allowed instantiations. - template class GenericGridTemplate; - template class GenericGridTemplate; + template class GenericVarTemplate; + template class GenericVarTemplate; } // yask namespace. diff --git a/src/kernel/lib/generic_grids.hpp b/src/kernel/lib/generic_var.hpp similarity index 78% rename from src/kernel/lib/generic_grids.hpp rename to src/kernel/lib/generic_var.hpp index 5a773003..0c956301 100644 --- a/src/kernel/lib/generic_grids.hpp +++ b/src/kernel/lib/generic_var.hpp @@ -23,25 +23,25 @@ IN THE SOFTWARE. *****************************************************************************/ -// Generic grids: -// T: type stored in grid. +// Generic vars: +// T: type stored in var. // LayoutFn: class that transforms N dimensions to 1. #pragma once namespace yask { - // A base class for a generic n-D grid. + // A base class for a generic n-D var. // This class does not define a type or memory layout. - class GenericGridBase : + class GenericVarBase : public KernelStateBase { protected: - std::string _name; // name for grid. + std::string _name; // name for var. // Base address of malloc'd memory. // Not necessarily the address at which the data is stored. - // Several grids may have the same base addr; then the last one + // Several vars may have the same base addr; then the last one // to release it will free the mem. std::shared_ptr _base; @@ -53,27 +53,27 @@ namespace yask { // Note that both _dims and *_layout_base hold sizes unless this // is a scalar. For a scalar, _dims is empty and _layout_base = 0. - IdxTuple _grid_dims; // names and lengths of grid dimensions. + IdxTuple _var_dims; // names and lengths of var dimensions. Layout* _layout_base = 0; // memory layout. void _sync_dims_with_layout() { Indices idxs(_layout_base->get_sizes()); - idxs.setTupleVals(_grid_dims); + idxs.setTupleVals(_var_dims); } void _sync_layout_with_dims() { - Indices idxs(_grid_dims); + Indices idxs(_var_dims); _layout_base->set_sizes(idxs); } public: // Ctor. No allocation is done. See notes on default_alloc(). - GenericGridBase(KernelStateBase& state, + GenericVarBase(KernelStateBase& state, const std::string& name, Layout& layout_base, - const GridDimNames& dimNames); + const VarDimNames& dimNames); - virtual ~GenericGridBase() { } + virtual ~GenericVarBase() { } // Perform default allocation. // For other options, @@ -101,14 +101,14 @@ namespace yask { #endif } - // Access dims of this grid (not necessarily same as solution dims). + // Access dims of this var (not necessarily same as solution dims). const IdxTuple& get_dims() const { - return _grid_dims; + return _var_dims; } // Get number of elements. virtual idx_t get_num_elems() const { - return _grid_dims.product(); + return _var_dims.product(); } // Get size of one element. @@ -119,25 +119,25 @@ namespace yask { // Get number of dimensions. virtual int get_num_dims() const { - return _grid_dims.getNumDims(); + return _var_dims.getNumDims(); } // Get the nth dim name. virtual const std::string& get_dim_name(int n) const { - return _grid_dims.getDimName(n); + return _var_dims.getDimName(n); } // Is dim used? virtual bool is_dim_used(const std::string& dim) const { - return _grid_dims.lookup(dim) != 0; + return _var_dims.lookup(dim) != 0; } // Access nth dim size. idx_t get_dim_size(int n) const { - return _grid_dims.getVal(n); + return _var_dims.getVal(n); } void set_dim_size(int n, idx_t size) { - _grid_dims.setVal(n, size); + _var_dims.setVal(n, size); _sync_layout_with_dims(); } @@ -146,15 +146,15 @@ namespace yask { return _layout_base->get_sizes(); } void set_dim_sizes(const Indices& sizes) { - for (int i = 0; size_t(i) < _grid_dims.size(); i++) - _grid_dims.setVal(i, sizes[i]); + for (int i = 0; size_t(i) < _var_dims.size(); i++) + _var_dims.setVal(i, sizes[i]); _sync_layout_with_dims(); } // Return 'true' if dimensions are same names // and sizes, 'false' otherwise. - inline bool are_dims_and_sizes_same(const GenericGridBase& src) { - return _grid_dims == src._grid_dims; + inline bool are_dims_and_sizes_same(const GenericVarBase& src) { + return _var_dims == src._var_dims; } // Print some descriptive info. @@ -163,7 +163,7 @@ namespace yask { // Get linear index. virtual idx_t get_index(const Indices& idxs, bool check=true) const =0; virtual idx_t get_index(const IdxTuple& pt, bool check=true) const { - assert(_grid_dims.areDimsSame(pt)); + assert(_var_dims.areDimsSame(pt)); Indices idxs(pt); return get_index(idxs, check); } @@ -187,35 +187,35 @@ namespace yask { // 'base' should provide get_num_bytes() bytes at offset bytes. virtual void set_storage(std::shared_ptr& base, size_t offset); - // Share storage from another grid. - virtual void share_storage(const GenericGridBase* src) { + // Share storage from another var. + virtual void share_storage(const GenericVarBase* src) { _base = src->_base; _elems = src->_elems; } // Check for equality, assuming same layout. // Return number of mismatches greater than epsilon. - virtual idx_t count_diffs(const GenericGridBase* ref, + virtual idx_t count_diffs(const GenericVarBase* ref, double epsilon) const =0; }; - // A base class for a generic n-D grid of elements of arithmetic type T. + // A base class for a generic n-D var of elements of arithmetic type T. // This class defines the type but does not define the memory layout. template - class GenericGridTemplate : public GenericGridBase { + class GenericVarTemplate : public GenericVarBase { public: // Ctor. No allocation is done. See notes on default_alloc(). - GenericGridTemplate(KernelStateBase& state, + GenericVarTemplate(KernelStateBase& state, const std::string& name, Layout& layout_base, - const GridDimNames& dimNames) : - GenericGridBase(state, name, layout_base, dimNames) { } + const VarDimNames& dimNames) : + GenericVarBase(state, name, layout_base, dimNames) { } // Dealloc _base when last pointer to it is destructed. - virtual ~GenericGridTemplate() { + virtual ~GenericVarTemplate() { // Release data. release_storage(); @@ -259,27 +259,27 @@ namespace yask { // Check for equality, assuming same layout. // Return number of mismatches greater than epsilon. - virtual idx_t count_diffs(const GenericGridBase* ref, + virtual idx_t count_diffs(const GenericVarBase* ref, double epsilon) const; }; - // A generic n-D grid of elements of type T. + // A generic n-D var of elements of type T. // This class defines the type and memory layout. // The LayoutFn class must provide a 1:1 transform between // n-D and 1-D indices. template - class GenericGrid : - public GenericGridTemplate { + class GenericVar : + public GenericVarTemplate { protected: LayoutFn _layout; public: - // Construct an unallocated grid. - GenericGrid(KernelStateBase& state, + // Construct an unallocated var. + GenericVar(KernelStateBase& state, std::string name, - const GridDimNames& dimNames) : - GenericGridTemplate(state, name, _layout, dimNames) { + const VarDimNames& dimNames) : + GenericVarTemplate(state, name, _layout, dimNames) { assert(int(dimNames.size()) == _layout.get_num_sizes()); } @@ -299,10 +299,10 @@ namespace yask { virtual idx_t get_index(const Indices& idxs, bool check=true) const final { #ifdef CHECK if (check) { - for (int i = 0; size_t(i) < this->_grid_dims.size(); i++) { + for (int i = 0; size_t(i) < this->_var_dims.size(); i++) { idx_t j = idxs[i]; assert(j >= 0); - assert(j < this->_grid_dims.getVal(i)); + assert(j < this->_var_dims.getVal(i)); } } #endif @@ -317,32 +317,32 @@ namespace yask { // Pointer to given element. // Calling this helps the compiler avoid virtual function calls. const T* getPtr(const Indices& pt, bool check=true) const { - idx_t ai = GenericGrid::get_index(pt, check); + idx_t ai = GenericVar::get_index(pt, check); return &((T*)this->_elems)[ai]; } T* getPtr(const Indices& pt, bool check=true) { - idx_t ai = GenericGrid::get_index(pt, check); + idx_t ai = GenericVar::get_index(pt, check); return &((T*)this->_elems)[ai]; } }; - // A generic 0-D grid (scalar) of elements of type T. + // A generic 0-D var (scalar) of elements of type T. // Special case: No layout or dim names needed. template class GenericScalar : - public GenericGrid { + public GenericVar { protected: // List of dims is for consistency; should be empty for 0-D. - const GridDimNames _dimNames; + const VarDimNames _dimNames; public: // Construct an unallocated scalar. GenericScalar(KernelStateBase& state, std::string name) : - GenericGrid(state, name, _dimNames) { } + GenericVar(state, name, _dimNames) { } }; } // namespace yask. diff --git a/src/kernel/lib/indices.hpp b/src/kernel/lib/indices.hpp index 4f348680..8c12a1e5 100644 --- a/src/kernel/lib/indices.hpp +++ b/src/kernel/lib/indices.hpp @@ -27,9 +27,9 @@ IN THE SOFTWARE. namespace yask { - typedef std::vector GridIndices; - typedef std::vector GridDimSizes; - typedef std::vector GridDimNames; + typedef std::vector VarIndices; + typedef std::vector VarDimSizes; + typedef std::vector VarDimNames; // A class to hold up to a given number of sizes or indices efficiently. // Similar to a Tuple, but less overhead and doesn't keep names. @@ -60,7 +60,7 @@ namespace yask { Indices(const IdxTuple& src) { setFromTuple(src); } - Indices(const GridIndices& src) { + Indices(const VarIndices& src) { setFromVec(src); } Indices(const std::initializer_list& src) { @@ -114,7 +114,7 @@ namespace yask { } // Other inits. - void setFromVec(const GridIndices& src) { + void setFromVec(const VarIndices& src) { assert(src.size() <= +max_idxs); int n = int(src.size()); for (int i = 0; i < n; i++) @@ -293,7 +293,7 @@ namespace yask { } // Make string like "x=4, y=8". - std::string makeDimValStr(const GridDimNames& names, + std::string makeDimValStr(const VarDimNames& names, std::string separator=", ", std::string infix="=", std::string prefix="", diff --git a/src/kernel/lib/new_grid.cpp b/src/kernel/lib/new_var.cpp similarity index 82% rename from src/kernel/lib/new_grid.cpp rename to src/kernel/lib/new_var.cpp index baee3fea..9264e41a 100644 --- a/src/kernel/lib/new_grid.cpp +++ b/src/kernel/lib/new_var.cpp @@ -28,25 +28,25 @@ using namespace std; namespace yask { - // Make a new grid. - YkGridPtr StencilContext::newGrid(const std::string& name, - const GridDimNames& gdims, - const GridDimSizes* sizes) { + // Make a new var. + YkVarPtr StencilContext::newVar(const std::string& name, + const VarDimNames& gdims, + const VarDimSizes* sizes) { STATE_VARS(this); // Check parameters. bool got_sizes = sizes != NULL; if (got_sizes) { if (gdims.size() != sizes->size()) { - FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create grid '" << name << "' with " << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: attempt to create var '" << name << "' with " << gdims.size() << " dimension names but " << sizes->size() << " dimension sizes"); } } - // First, try to make a grid that matches the layout in + // First, try to make a var that matches the layout in // the stencil. - GridBasePtr gp = newStencilGrid(name, gdims); + VarBasePtr gp = newStencilVar(name, gdims); // No match. if (!gp) { @@ -56,8 +56,8 @@ namespace yask { for (auto& d : gdims) dtup.addDimBack(d, 0); -#if ALLOW_NEW_GRIDS - // Allow new grid types. +#if ALLOW_NEW_VARS + // Allow new var types. // Check dims. int ndims = gdims.size(); @@ -68,7 +68,7 @@ namespace yask { // Already used? if (seenDims.count(gdim)) { - THROW_YASK_EXCEPTION("Error: cannot create grid '" + name + + THROW_YASK_EXCEPTION("Error: cannot create var '" + name + "' because dimension '" + gdim + "' is used more than once"); } @@ -77,7 +77,7 @@ namespace yask { if (gdim == step_dim) { step_used = true; if (i != step_posn) { - THROW_YASK_EXCEPTION("Error: cannot create grid '" + name + + THROW_YASK_EXCEPTION("Error: cannot create var '" + name + "' because step dimension '" + gdim + "' is not first dimension"); } @@ -99,22 +99,22 @@ namespace yask { // Scalar? if (ndims == 0) - gp = make_shared>(*this, name, gdims); + gp = make_shared>(*this, name, gdims); // Include auto-gen code for all other cases. -#include "yask_grid_code.hpp" +#include "yask_var_code.hpp" // Failed. if (!gp) - FORMAT_AND_THROW_YASK_EXCEPTION("Error: cannot create new grid '" << name << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: cannot create new var '" << name << "' with dimensions '" << dtup.makeDimStr() << "'; only up to " << MAX_DIMS << " dimensions supported"); #else - // Don't allow new grid types. - FORMAT_AND_THROW_YASK_EXCEPTION("Error: cannot create new grid '" << name << + // Don't allow new var types. + FORMAT_AND_THROW_YASK_EXCEPTION("Error: cannot create new var '" << name << "' with dimensions '" << dtup.makeDimStr() << - "'; this list of dimensions is not in any existing grid"); + "'; this list of dimensions is not in any existing var"); #endif } @@ -122,13 +122,13 @@ namespace yask { gp->set_fixed_size(got_sizes); // Mark as created via API. - gp->set_user_grid(true); + gp->set_user_var(true); - // Wrap with a Yk grid. - YkGridPtr ygp = make_shared(gp); + // Wrap with a Yk var. + YkVarPtr ygp = make_shared(gp); // Add to context. - addGrid(ygp, false, false); // mark as non-orig, non-output grid. + addVar(ygp, false, false); // mark as non-orig, non-output var. // Set sizes as provided. if (got_sizes) { @@ -154,7 +154,7 @@ namespace yask { // Set sizes based on solution settings. else - update_grid_info(false); + update_var_info(false); return ygp; } diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index d3e937e1..5a3367e0 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -344,8 +344,8 @@ namespace yask { _add_domain_option(parser, "mbg", "Mini-block-group size", _mini_block_group_sizes); _add_domain_option(parser, "sbg", "Sub-block-group size", _sub_block_group_sizes); #endif - _add_domain_option(parser, "mp", "Minimum grid-padding size (including halo)", _min_pad_sizes); - _add_domain_option(parser, "ep", "Extra grid-padding size (beyond halo)", _extra_pad_sizes); + _add_domain_option(parser, "mp", "Minimum var-padding size (including halo)", _min_pad_sizes); + _add_domain_option(parser, "ep", "Extra var-padding size (beyond halo)", _extra_pad_sizes); #ifdef USE_MPI _add_domain_option(parser, "nr", "Num ranks", _num_ranks); _add_domain_option(parser, "ri", "This rank's logical index (0-based)", _rank_indices); @@ -374,7 +374,7 @@ namespace yask { #endif parser.add_option(new CommandLineParser::BoolOption ("force_scalar", - "Evaluate every grid point with scalar stencil operations (for debug).", + "Evaluate every var point with scalar stencil operations (for debug).", force_scalar)); parser.add_option(new CommandLineParser::IntOption ("max_threads", @@ -405,14 +405,14 @@ namespace yask { "(usually the outer-domain dimension), ignoring other sub-block sizes. " "Assign each slab to a block thread based on its global index in that dimension. " "This setting may increase cache locality when using multiple " - "block-threads when scrach-grid vars are used and/or " + "block-threads when scratch vars are used and/or " "when temporal blocking is active. " "This option is ignored if there are fewer than two block threads.", bind_block_threads)); #ifdef USE_NUMA stringstream msg; msg << "Preferred NUMA node on which to allocate data for " - "grids and MPI buffers. Alternatively, use special values " << + "vars and MPI buffers. Alternatively, use special values " << yask_numa_local << " for explicit local-node allocation, " << yask_numa_interleave << " for interleaving pages across all nodes, or " << yask_numa_none << " for no NUMA policy."; @@ -439,7 +439,7 @@ namespace yask { parser.add_option(new CommandLineParser::BoolOption ("auto_tune_each_pass", "Apply the auto-tuner separately to each stencil pack when " - "those packs are applied in separate passes across the entire grid, " + "those packs are applied in separate passes across the entire var, " "i.e., when no temporal tiling is used.", _allow_pack_tuners)); } @@ -531,7 +531,7 @@ namespace yask { " Set local-domain sizes to specify the work done on this MPI rank.\n" " A local-domain size of 0 in a given domain dimension =>\n" " local-domain size is determined by the global-domain size in that dimension.\n" - " This and the number of grids affect the amount of memory used.\n" + " This and the number of vars affect the amount of memory used.\n" " Set global-domain sizes to specify the work done across all MPI ranks.\n" " A global-domain size of 0 in a given domain dimension =>\n" " global-domain size is the sum of local-domain sizes in that dimension.\n" diff --git a/src/kernel/lib/settings.hpp b/src/kernel/lib/settings.hpp index 479700b8..1c1b733d 100644 --- a/src/kernel/lib/settings.hpp +++ b/src/kernel/lib/settings.hpp @@ -29,15 +29,15 @@ namespace yask { // Forward defns. class StencilContext; - class YkGridBase; - class YkGridImpl; + class YkVarBase; + class YkVarImpl; - // Some derivations from grid types. - typedef std::shared_ptr YkGridPtr; - typedef std::set GridPtrSet; - typedef std::vector GridPtrs; - typedef std::map GridPtrMap; - typedef std::vector ScratchVecs; + // Some derivations from var types. + typedef std::shared_ptr YkVarPtr; + typedef std::set VarPtrSet; + typedef std::vector VarPtrs; + typedef std::map VarPtrMap; + typedef std::vector ScratchVecs; // Environmental settings. class KernelEnv : @@ -233,7 +233,7 @@ namespace yask { int num_block_threads = 1; // Number of threads to use for a block. bool bind_block_threads = false; // Bind block threads to indices. - // Grid behavior. + // Var behavior. bool _step_wrap = false; // Allow invalid step indices to alias to valid ones. // Stencil-dim posn in which to apply block-thread binding. @@ -404,7 +404,7 @@ namespace yask { }; typedef std::shared_ptr MPIInfoPtr; - // MPI data for one buffer for one neighbor of one grid. + // MPI data for one buffer for one neighbor of one var. class MPIBuf { // Ptr to read/write lock when buffer is in shared mem. @@ -419,11 +419,11 @@ namespace yask { std::shared_ptr _base; real_t* _elems = 0; - // Range to copy to/from grid. - // NB: step index not set properly for grids with step dim. + // Range to copy to/from var. + // NB: step index not set properly for vars with step dim. IdxTuple begin_pt, last_pt; - // Number of points to copy to/from grid in each dim. + // Number of points to copy to/from var in each dim. IdxTuple num_pts; // Whether the number of points is a multiple of the @@ -501,7 +501,7 @@ namespace yask { } }; - // MPI data for both buffers for one neighbor of one grid. + // MPI data for both buffers for one neighbor of one var. struct MPIBufs { // Need one buf for send and one for receive for each neighbor. @@ -516,7 +516,7 @@ namespace yask { } }; - // MPI data for one grid. + // MPI data for one var. // Contains a send and receive buffer for each neighbor // and some meta-data. struct MPIData { diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index 614dea19..2b0219f1 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -445,12 +445,12 @@ namespace yask { } // setupRank(). - // Set non-scratch grid sizes and offsets based on settings. + // Set non-scratch var sizes and offsets based on settings. // Set wave-front settings. // This should be called anytime a setting or rank offset is changed. - void StencilContext::update_grid_info(bool force) { + void StencilContext::update_var_info(bool force) { STATE_VARS(this); - TRACE_MSG("update_grid_info(" << force << ")..."); + TRACE_MSG("update_var_info(" << force << ")..."); // If we haven't finished constructing the context, it's too early // to do this. @@ -464,17 +464,17 @@ namespace yask { for (auto& dim : domain_dims.getDims()) { auto& dname = dim.getName(); - // Each non-scratch grid. - for (auto gp : gridPtrs) { + // Each non-scratch var. + for (auto gp : varPtrs) { assert(gp); if (!gp->is_dim_used(dname)) continue; auto& gb = gp->gb(); - // Don't resize manually-sized grid - // unless it is a solution grid and 'force' is 'true'. + // Don't resize manually-sized var + // unless it is a solution var and 'force' is 'true'. if (!gp->is_fixed_size() || - (!gb.is_user_grid() && force)) { + (!gb.is_user_var() && force)) { // Rank domains. gp->_set_domain_size(dname, opts->_rank_sizes[dname]); @@ -489,8 +489,8 @@ namespace yask { gp->_set_local_offset(dname, 0); } - // Update max halo across grids, used for temporal angles. - if (!gb.is_user_grid()) { + // Update max halo across vars, used for temporal angles. + if (!gb.is_user_var()) { max_halos[dname] = max(max_halos[dname], gp->get_left_halo_size(dname)); max_halos[dname] = max(max_halos[dname], gp->get_right_halo_size(dname)); } @@ -567,10 +567,10 @@ namespace yask { } // Now that wave-front settings are known, we can push this info - // back to the grids. It's useful to store this redundant info - // in the grids, because there it's indexed by grid dims instead - // of domain dims. This makes it faster to do grid indexing. - for (auto gp : origGridPtrs) { + // back to the vars. It's useful to store this redundant info + // in the vars, because there it's indexed by var dims instead + // of domain dims. This makes it faster to do var indexing. + for (auto gp : origVarPtrs) { assert(gp); // Loop through each domain dim. @@ -582,16 +582,16 @@ namespace yask { gp->_set_right_wf_ext(dname, right_wf_exts[dname]); } } - } // grids. + } // vars. // Calculate temporal-block shifts. // NB: this will change if/when block sizes change. update_tb_info(); - } // update_grid_info(). + } // update_var_info(). // Set temporal blocking data. This should be called anytime a block - // size is changed. Must be called after update_grid_info() to ensure + // size is changed. Must be called after update_var_info() to ensure // angles are properly set. TODO: calculate 'tb_steps' dynamically // considering temporal conditions; this assumes worst-case, which is // all packs always done. @@ -634,7 +634,7 @@ namespace yask { auto mblksize = opts->_mini_block_sizes[i]; // Req'd shift in this dim based on max halos. - // Can't use separate L & R shift because of possible data reuse in grids. + // Can't use separate L & R shift because of possible data reuse in vars. // Can't use separate shifts for each pack for same reason. // TODO: make round-up optional. auto fpts = dims->_fold_pts[j]; @@ -754,21 +754,21 @@ namespace yask { ", tops = " << tb_tops.makeDimValStr()); } // update_tb_info(). - // Init all grids & params by calling initFn. - void StencilContext::initValues(function realInitFn) { STATE_VARS(this); real_t seed = 0.1; - os << "Initializing grids...\n" << flush; + os << "Initializing vars...\n" << flush; YaskTimer itimer; itimer.start(); - for (auto gp : gridPtrs) { + for (auto gp : varPtrs) { realInitFn(gp, seed); seed += 0.01; } itimer.stop(); - os << "Grid initialization done in " << + os << "Var initialization done in " << makeNumStr(itimer.get_elapsed_secs()) << " secs.\n" << flush; } diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 28a4b815..088ad905 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -54,7 +54,7 @@ namespace yask { GET_SOLN_API(get_rank_index, opts->_rank_indices[dim], false, true, false, true) #undef GET_SOLN_API - // The grid sizes are updated any time these settings are changed. + // The var sizes are updated any time these settings are changed. #define SET_SOLN_API(api_name, expr, step_ok, domain_ok, misc_ok, reset_prep) \ void StencilContext::api_name(const string& dim, idx_t n) { \ STATE_VARS(this); \ @@ -62,7 +62,7 @@ namespace yask { #api_name "('" << dim << "', " << n << ")"); \ dims->checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ expr; \ - update_grid_info(false); \ + update_var_info(false); \ if (reset_prep) rank_bb.bb_valid = ext_bb.bb_valid = false; \ } SET_SOLN_API(set_rank_index, opts->_rank_indices[dim] = n; @@ -77,7 +77,7 @@ namespace yask { SET_SOLN_API(set_min_pad_size, opts->_min_pad_sizes[dim] = n, false, true, false, false) #undef SET_SOLN_API - // Allocate grids and MPI bufs. + // Allocate vars and MPI bufs. // Initialize some data structures. void StencilContext::prepare_solution() { STATE_VARS(this); @@ -117,24 +117,24 @@ namespace yask { yask_for(0, rthreads * 100, 1, [&](idx_t start, idx_t stop, idx_t thread_num) { }); - // Some grid stats. + // Some var stats. os << endl; - os << "Num grids: " << gridPtrs.size() << endl; - os << "Num grids to be updated: " << outputGridPtrs.size() << endl; + os << "Num vars: " << varPtrs.size() << endl; + os << "Num vars to be updated: " << outputVarPtrs.size() << endl; // Set up data based on MPI rank, including local or global sizes, - // grid positions. + // var positions. setupRank(); - // Adjust all settings before setting MPI buffers or sizing grids. + // Adjust all settings before setting MPI buffers or sizing vars. // Prints adjusted settings. // TODO: print settings again after auto-tuning. opts->adjustSettings(os); - // Set offsets in grids and find WF extensions - // based on the grids' halos. Force setting - // the size of all solution grids. - update_grid_info(true); + // Set offsets in vars and find WF extensions + // based on the vars' halos. Force setting + // the size of all solution vars. + update_var_info(true); // Determine bounding-boxes for all bundles. // This must be done after finding WF extensions. @@ -147,15 +147,15 @@ namespace yask { for (auto& sp : stPacks) sp->getLocalSettings() = *opts; - // Alloc grids, scratch grids, MPI bufs. + // Alloc vars, scratch vars, MPI bufs. // This is the order in which preferred NUMA nodes (e.g., HBW mem) // will be used. - // We free the scratch and MPI data first to give grids preference. + // We free the scratch and MPI data first to give vars preference. YaskTimer allocTimer; allocTimer.start(); freeScratchData(); freeMpiData(); - allocGridData(); + allocVarData(); allocScratchData(); allocMpiData(); allocTimer.stop(); @@ -279,7 +279,7 @@ namespace yask { sp->init_work_stats(); } - // Dealloc grids, etc. + // Dealloc vars, etc. void StencilContext::end_solution() { STATE_VARS(this); TRACE_MSG("end_solution()..."); @@ -291,8 +291,8 @@ namespace yask { env->global_barrier(); mpiData.clear(); - // Release grid data. - for (auto gp : gridPtrs) { + // Release var data. + for (auto gp : varPtrs) { if (!gp) continue; gp->release_storage(); @@ -302,16 +302,16 @@ namespace yask { set_max_threads(); } - void StencilContext::fuse_grids(yk_solution_ptr source) { + void StencilContext::fuse_vars(yk_solution_ptr source) { auto sp = dynamic_pointer_cast(source); assert(sp); - for (auto gp : gridPtrs) { + for (auto gp : varPtrs) { auto gname = gp->get_name(); - auto si = sp->gridMap.find(gname); - if (si != sp->gridMap.end()) { + auto si = sp->varMap.find(gname); + if (si != sp->varMap.end()) { auto sgp = si->second; - gp->fuse_grids(sgp); + gp->fuse_vars(sgp); } } } @@ -340,28 +340,28 @@ namespace yask { return rem; } - // Add a new grid to the containers. - void StencilContext::addGrid(YkGridPtr gp, bool is_orig, bool is_output) { + // Add a new var to the containers. + void StencilContext::addVar(YkVarPtr gp, bool is_orig, bool is_output) { STATE_VARS(this); assert(gp); auto& gname = gp->get_name(); - if (gridMap.count(gname)) - THROW_YASK_EXCEPTION("Error: grid '" + gname + "' already exists"); + if (varMap.count(gname)) + THROW_YASK_EXCEPTION("Error: var '" + gname + "' already exists"); // Add to list and map. - gridPtrs.push_back(gp); - gridMap[gname] = gp; + varPtrs.push_back(gp); + varMap[gname] = gp; // Add to orig list and map if 'is_orig'. if (is_orig) { - origGridPtrs.push_back(gp); - origGridMap[gname] = gp; + origVarPtrs.push_back(gp); + origVarMap[gname] = gp; } // Add to output list and map if 'is_output'. if (is_output) { - outputGridPtrs.push_back(gp); - outputGridMap[gname] = gp; + outputVarPtrs.push_back(gp); + outputVarMap[gname] = gp; } } diff --git a/src/kernel/lib/stencil_calc.cpp b/src/kernel/lib/stencil_calc.cpp index 3c08afc5..b05d7a92 100644 --- a/src/kernel/lib/stencil_calc.cpp +++ b/src/kernel/lib/stencil_calc.cpp @@ -33,7 +33,7 @@ namespace yask { // Calculate results within a mini-block defined by 'mini_block_idxs'. // This is called by StencilContext::calc_mini_block() for each bundle. - // It is here that any required scratch-grid stencils are evaluated + // It is here that any required scratch-var stencils are evaluated // first and then the non-scratch stencils in the stencil bundle. // It is also here that the boundaries of the bounding-box(es) of the bundle // are respected. There must not be any temporal blocking at this point. @@ -117,7 +117,7 @@ namespace yask { " ... " << mb_idxs.end.makeValStr(nsdims) << ")"); // Get the bundles that need to be processed in - // this block. This will be any prerequisite scratch-grid + // this block. This will be any prerequisite scratch-var // bundles plus this non-scratch bundle. auto sg_list = get_reqd_bundles(); @@ -139,7 +139,7 @@ namespace yask { } // Indices needed for the generated loops. Will normally be a - // copy of 'mb_idxs' except when updating scratch-grids. + // copy of 'mb_idxs' except when updating scratch-vars. ScanIndices adj_mb_idxs = sg->adjust_span(region_thread_idx, mb_idxs); // Tweak settings for adjusted indices. @@ -680,14 +680,14 @@ namespace yask { calc_loop_of_vectors(region_thread_idx, block_thread_idx, start_idxs, stop_inner, write_mask); } - // If this bundle is updating scratch grid(s), + // If this bundle is updating scratch var(s), // expand begin & end of 'idxs' by sizes of halos. // Stride indices may also change. - // NB: it is not necessary that the domain of each grid + // NB: it is not necessary that the domain of each var // is the same as the span of 'idxs'. However, it should be - // at least that large to ensure that grid is able to hold + // at least that large to ensure that var is able to hold // calculated results. This is checked when 'CHECK' is defined. - // In other words, grid can be larger than span of 'idxs', but + // In other words, var can be larger than span of 'idxs', but // its halo sizes are still used to specify how much to // add to 'idxs'. // Returns adjusted indices. @@ -696,7 +696,7 @@ namespace yask { STATE_VARS(this); ScanIndices adj_idxs(idxs); - // Loop thru vecs of scratch grids for this bundle. + // Loop thru vecs of scratch vars for this bundle. for (auto* sv : outputScratchVecs) { assert(sv); @@ -711,7 +711,7 @@ namespace yask { auto& dim = dims->_stencil_dims.getDim(i); auto& dname = dim.getName(); - // Is this dim used in this grid? + // Is this dim used in this var? int posn = gb.get_dim_posn(dname); if (posn >= 0) { @@ -728,12 +728,12 @@ namespace yask { adj_idxs.begin[i] = idxs.begin[i] - lh; adj_idxs.end[i] = idxs.end[i] + rh; - // Make sure grid covers index bounds. + // Make sure var covers index bounds. TRACE_MSG("adjust_span: mini-blk [" << idxs.begin[i] << "..." << idxs.end[i] << ") adjusted to [" << adj_idxs.begin[i] << "..." << - adj_idxs.end[i] << ") within scratch-grid '" << + adj_idxs.end[i] << ") within scratch-var '" << gp->get_name() << "' allocated [" << gp->get_first_rank_alloc_index(posn) << "..." << gp->get_last_rank_alloc_index(posn) << "] in dim '" << dname << "'"); @@ -749,8 +749,8 @@ namespace yask { } } - // Only need to get info from one grid. - // TODO: check that grids are consistent. + // Only need to get info from one var. + // TODO: check that vars are consistent. break; } return adj_idxs; @@ -773,7 +773,7 @@ namespace yask { getAT().steps_done += num_steps; } - static void print_grid_list(ostream& os, const GridPtrs& gps, const string& type) { + static void print_var_list(ostream& os, const VarPtrs& gps, const string& type) { os << " num " << type << " vars:"; for (size_t i = 0; i < max(21ULL - type.length(), 1ULL); i++) os << ' '; @@ -869,19 +869,19 @@ namespace yask { } } os << - " grid-reads per point: " << reads1 << endl << - " grid-reads in rank: " << makeNumStr(reads_bb) << endl << - " grid-writes per point: " << writes1 << endl << - " grid-writes in rank: " << makeNumStr(writes_bb) << endl << + " var-reads per point: " << reads1 << endl << + " var-reads in rank: " << makeNumStr(reads_bb) << endl << + " var-writes per point: " << writes1 << endl << + " var-writes in rank: " << makeNumStr(writes_bb) << endl << " est FP-ops per point: " << fpops1 << endl << " est FP-ops in rank: " << makeNumStr(fpops_bb) << endl; // Classify vars. - GridPtrs idvars, imvars, odvars, omvars, iodvars, iomvars; // i[nput], o[utput], d[omain], m[isc]. - for (auto gp : sg->inputGridPtrs) { + VarPtrs idvars, imvars, odvars, omvars, iodvars, iomvars; // i[nput], o[utput], d[omain], m[isc]. + for (auto gp : sg->inputVarPtrs) { auto& gb = gp->gb(); bool isdom = gb.is_domain_var(); - auto& ogps = sg->outputGridPtrs; + auto& ogps = sg->outputVarPtrs; bool isout = find(ogps.begin(), ogps.end(), gp) != ogps.end(); if (isout) { if (isdom) @@ -895,10 +895,10 @@ namespace yask { imvars.push_back(gp); } } - for (auto gp : sg->outputGridPtrs) { + for (auto gp : sg->outputVarPtrs) { auto& gb = gp->gb(); bool isdom = gb.is_domain_var(); - auto& igps = sg->inputGridPtrs; + auto& igps = sg->inputVarPtrs; bool isin = find(igps.begin(), igps.end(), gp) != igps.end(); if (!isin) { if (isdom) @@ -907,12 +907,12 @@ namespace yask { omvars.push_back(gp); } } - print_grid_list(os, idvars, "input-only domain"); - print_grid_list(os, odvars, "output-only domain"); - print_grid_list(os, iodvars, "input-output domain"); - print_grid_list(os, imvars, "input-only other"); - print_grid_list(os, omvars, "output-only other"); - print_grid_list(os, iomvars, "input-output other"); + print_var_list(os, idvars, "input-only domain"); + print_var_list(os, odvars, "output-only domain"); + print_var_list(os, iodvars, "input-output domain"); + print_var_list(os, imvars, "input-only other"); + print_var_list(os, omvars, "output-only other"); + print_var_list(os, iomvars, "input-output other"); } // bundles. diff --git a/src/kernel/lib/stencil_calc.hpp b/src/kernel/lib/stencil_calc.hpp index a6465b76..6745b9aa 100644 --- a/src/kernel/lib/stencil_calc.hpp +++ b/src/kernel/lib/stencil_calc.hpp @@ -44,11 +44,11 @@ namespace yask { // Other bundles that this one depends on. StencilBundleSet _depends_on; - // List of scratch-grid bundles that need to be evaluated + // List of scratch-var bundles that need to be evaluated // before this bundle. Listed in eval order first-to-last. StencilBundleList _scratch_children; - // Whether this updates scratch grid(s); + // Whether this updates scratch var(s); bool _is_scratch = false; // Overall bounding box for the bundle. @@ -85,14 +85,14 @@ namespace yask { public: - // Grids that are written to by these stencils. - GridPtrs outputGridPtrs; + // Vars that are written to by these stencils. + VarPtrs outputVarPtrs; - // Grids that are read by these stencils (not necessarify - // read-only, i.e., a grid can be input and output). - GridPtrs inputGridPtrs; + // Vars that are read by these stencils (not necessarify + // read-only, i.e., a var can be input and output). + VarPtrs inputVarPtrs; - // Vectors of scratch grids that are written to/read from. + // Vectors of scratch vars that are written to/read from. ScratchVecs outputScratchVecs; ScratchVecs inputScratchVecs; @@ -146,9 +146,9 @@ namespace yask { return sg_list; } - // If this bundle is updating scratch grid(s), + // If this bundle is updating scratch var(s), // expand indices to calculate values in halo. - // Adjust offsets in grids based on original idxs. + // Adjust offsets in vars based on original idxs. // Return adjusted indices. ScanIndices adjust_span(int thread_idx, const ScanIndices& idxs) const; @@ -178,7 +178,7 @@ namespace yask { virtual bool is_in_valid_step(idx_t input_step_index) const =0; - // If bundle updates grid(s) with the step index, + // If bundle updates var(s) with the step index, // set 'output_step_index' to the step that an update // occurs when calling one of the calc_*() methods with // 'input_step_index' and return 'true'. diff --git a/src/kernel/lib/yask_stencil.hpp b/src/kernel/lib/yask_stencil.hpp index 26c432ce..2c1edc98 100644 --- a/src/kernel/lib/yask_stencil.hpp +++ b/src/kernel/lib/yask_stencil.hpp @@ -53,8 +53,8 @@ IN THE SOFTWARE. // TODO: make Indices a templated class based on // number of dims. #ifndef MAX_DIMS -#if NUM_GRID_DIMS >= NUM_STENCIL_DIMS -#define MAX_DIMS NUM_GRID_DIMS +#if NUM_VAR_DIMS >= NUM_STENCIL_DIMS +#define MAX_DIMS NUM_VAR_DIMS #else #define MAX_DIMS NUM_STENCIL_DIMS #endif @@ -74,8 +74,8 @@ IN THE SOFTWARE. // Base types for stencil context, etc. #include "indices.hpp" #include "settings.hpp" -#include "generic_grids.hpp" -#include "realv_grids.hpp" +#include "generic_var.hpp" +#include "yk_var.hpp" #include "auto_tuner.hpp" #include "context.hpp" #include "stencil_calc.hpp" diff --git a/src/kernel/lib/realv_grids.cpp b/src/kernel/lib/yk_var.cpp similarity index 90% rename from src/kernel/lib/realv_grids.cpp rename to src/kernel/lib/yk_var.cpp index 27aeb323..fbd86520 100644 --- a/src/kernel/lib/realv_grids.cpp +++ b/src/kernel/lib/yk_var.cpp @@ -23,7 +23,7 @@ IN THE SOFTWARE. *****************************************************************************/ -// Implement methods for RealVecGridBase. +// Implement methods for RealVecVarBase. #include "yask_stencil.hpp" using namespace std; @@ -32,9 +32,9 @@ namespace yask { // Ctor. // Important: '*ggb' exists but is NOT yet constructed. - YkGridBase::YkGridBase(KernelStateBase& stateb, - GenericGridBase* ggb, - const GridDimNames& dimNames) : + YkVarBase::YkVarBase(KernelStateBase& stateb, + GenericVarBase* ggb, + const VarDimNames& dimNames) : KernelStateBase(stateb), _ggb(ggb) { STATE_VARS(this); @@ -74,7 +74,7 @@ namespace yask { // Convenience function to format indices like // "x=5, y=3". - std::string YkGridBase::makeIndexString(const Indices& idxs, + std::string YkVarBase::makeIndexString(const Indices& idxs, std::string separator, std::string infix, std::string prefix, @@ -85,7 +85,7 @@ namespace yask { } // Does this var cover the N-D domain? - bool YkGridBase::is_domain_var() const { + bool YkVarBase::is_domain_var() const { // Problem dims. auto* dims = get_dims().get(); @@ -100,16 +100,16 @@ namespace yask { } // Halo-exchange flag accessors. - bool YkGridBase::is_dirty(idx_t step_idx) const { + bool YkVarBase::is_dirty(idx_t step_idx) const { if (_dirty_steps.size() == 0) - const_cast(this)->resize(); + const_cast(this)->resize(); if (_has_step_dim) step_idx = _wrap_step(step_idx); else step_idx = 0; return _dirty_steps[step_idx]; } - void YkGridBase::set_dirty(bool dirty, idx_t step_idx) { + void YkVarBase::set_dirty(bool dirty, idx_t step_idx) { if (_dirty_steps.size() == 0) resize(); if (_has_step_dim) { @@ -125,7 +125,7 @@ namespace yask { step_idx = 0; set_dirty_using_alloc_index(dirty, step_idx); } - void YkGridBase::set_dirty_all(bool dirty) { + void YkVarBase::set_dirty_all(bool dirty) { if (_dirty_steps.size() == 0) resize(); for (auto i : _dirty_steps) @@ -134,7 +134,7 @@ namespace yask { // Lookup position by dim name. // Return -1 or die if not found, depending on flag. - int YkGridBase::get_dim_posn(const std::string& dim, + int YkVarBase::get_dim_posn(const std::string& dim, bool die_on_failure, const std::string& die_msg) const { auto& dims = _ggb->get_dims(); @@ -149,22 +149,22 @@ namespace yask { // Determine required padding from halos. // Does not include user-specified min padding or // final rounding for left pad. - Indices YkGridBase::getReqdPad(const Indices& halos, const Indices& wf_exts) const { + Indices YkVarBase::getReqdPad(const Indices& halos, const Indices& wf_exts) const { STATE_VARS(this); // Start with halos plus WF exts. Indices mp = halos.addElements(wf_exts); - // For any grid, reads will be expanded to full vec-len during - // computation. For scratch grids, halo area must be written to. + // For any var, reads will be expanded to full vec-len during + // computation. For scratch vars, halo area must be written to. // Halo is sum of dependent's write halo and depender's read halo, // but these two components are not stored individually. Write halo // will be expanded to full vec len during computation, requiring // load from read halo beyond full vec len. Worst case is when // write halo is one and rest is read halo. So, min padding should // be halos + wave-front exts + vec-len - 1. This vec-len should be - // the solution one, not the one for this grid to handle the case - // where this grid is not vectorized. + // the solution one, not the one for this var to handle the case + // where this var is not vectorized. for (int i = 0; i < _ggb->get_num_dims(); i++) { auto& dname = _ggb->get_dim_name(i); auto* p = dims->_fold_pts.lookup(dname); // solution vec-len. @@ -176,10 +176,10 @@ namespace yask { return mp; } - // Resizes the underlying generic grid. + // Resizes the underlying generic var. // Modifies _pads and _allocs. // Fails if mem different and already alloc'd. - void YkGridBase::resize() { + void YkVarBase::resize() { STATE_VARS(this); // Original size. @@ -189,17 +189,17 @@ namespace yask { // Check settings. for (int i = 0; i < _ggb->get_num_dims(); i++) { if (_left_halos[i] < 0) - THROW_YASK_EXCEPTION("Error: negative left halo in grid '" + _ggb->get_name() + "'"); + THROW_YASK_EXCEPTION("Error: negative left halo in var '" + _ggb->get_name() + "'"); if (_right_halos[i] < 0) - THROW_YASK_EXCEPTION("Error: negative right halo in grid '" + _ggb->get_name() + "'"); + THROW_YASK_EXCEPTION("Error: negative right halo in var '" + _ggb->get_name() + "'"); if (_left_wf_exts[i] < 0) - THROW_YASK_EXCEPTION("Error: negative left wave-front ext in grid '" + _ggb->get_name() + "'"); + THROW_YASK_EXCEPTION("Error: negative left wave-front ext in var '" + _ggb->get_name() + "'"); if (_right_wf_exts[i] < 0) - THROW_YASK_EXCEPTION("Error: negative right wave-front ext in grid '" + _ggb->get_name() + "'"); + THROW_YASK_EXCEPTION("Error: negative right wave-front ext in var '" + _ggb->get_name() + "'"); if (_req_left_pads[i] < 0) - THROW_YASK_EXCEPTION("Error: negative left padding in grid '" + _ggb->get_name() + "'"); + THROW_YASK_EXCEPTION("Error: negative left padding in var '" + _ggb->get_name() + "'"); if (_req_right_pads[i] < 0) - THROW_YASK_EXCEPTION("Error: negative right padding in grid '" + _ggb->get_name() + "'"); + THROW_YASK_EXCEPTION("Error: negative right padding in var '" + _ggb->get_name() + "'"); } // Increase padding as needed and calculate new allocs. @@ -256,7 +256,7 @@ namespace yask { // TODO: restore the values before the API that called // resize() on failure. if (p && old_allocs != new_allocs) { - THROW_YASK_EXCEPTION("Error: attempt to change allocation size of grid '" + + THROW_YASK_EXCEPTION("Error: attempt to change allocation size of var '" + _ggb->get_name() + "' from " + makeIndexString(old_allocs, " * ") + " to " + makeIndexString(new_allocs, " * ") + @@ -275,7 +275,7 @@ namespace yask { _vec_left_pads[i] = new_left_pads[i] / _vec_lens[i]; _vec_allocs[i] = _allocs[i] / _vec_lens[i]; - // Actual resize of underlying grid. + // Actual resize of underlying var. _ggb->set_dim_size(i, _vec_allocs[i]); // Number of dirty bits is number of steps. @@ -298,7 +298,7 @@ namespace yask { if (old_allocs != new_allocs || old_dirty != new_dirty) { Indices first_allocs = _rank_offsets.subElements(_actl_left_pads); Indices end_allocs = first_allocs.addElements(_allocs); - TRACE_MSG("grid '" << _ggb->get_name() << "' resized from " << + TRACE_MSG("var '" << _ggb->get_name() << "' resized from " << makeIndexString(old_allocs, " * ") << " to " << makeIndexString(new_allocs, " * ") << " at [" << makeIndexString(first_allocs) << " ... " << @@ -312,7 +312,7 @@ namespace yask { } // Check whether dim is used and of allowed type. - void YkGridBase::checkDimType(const std::string& dim, + void YkVarBase::checkDimType(const std::string& dim, const std::string& fn_name, bool step_ok, bool domain_ok, @@ -326,18 +326,18 @@ namespace yask { // Check for equality. // Return number of mismatches greater than epsilon. - idx_t YkGridBase::compare(const YkGridBase* ref, + idx_t YkVarBase::compare(const YkVarBase* ref, real_t epsilon, int maxPrint) const { STATE_VARS(this); if (!ref) { - os << "** mismatch: no reference grid.\n"; + os << "** mismatch: no reference var.\n"; return _allocs.product(); // total number of elements. } // Dims & sizes same? if (!_ggb->are_dims_and_sizes_same(*ref->_ggb)) { - os << "** mismatch due to incompatible grids: " << + os << "** mismatch due to incompatible vars: " << make_info_string() << " and " << ref->make_info_string() << ".\n"; return _allocs.product(); // total number of elements. } @@ -398,7 +398,7 @@ namespace yask { "(" << opt.makeDimValStr() << "): " << te << " != " << re << endl; else - os << "** Additional errors not printed for grid '" << + os << "** Additional errors not printed for var '" << _ggb->get_name() << "'.\n"; } } @@ -413,7 +413,7 @@ namespace yask { // Side-effect: If clipped_indices is not NULL, // 1) set them to in-range if out-of-range, and // 2) normalize them if 'normalize' is 'true'. - bool YkGridBase::checkIndices(const Indices& indices, + bool YkVarBase::checkIndices(const Indices& indices, const string& fn, // name for error msg. bool strict_indices, // die if out-of-range. bool check_step, // check step index. @@ -456,7 +456,7 @@ namespace yask { THROW_YASK_EXCEPTION("Error: " + fn + ": index in dim '" + dname + "' is " + to_string(idx) + ", which is not in allowed range [" + to_string(first_ok) + "..." + to_string(last_ok) + - "] of grid '" + _ggb->get_name() + "'"); + "] of var '" + _ggb->get_name() + "'"); } // Update the output indices. @@ -477,12 +477,12 @@ namespace yask { (*clipped_indices)[i] = idiv_flr((*clipped_indices)[i], _vec_lens[i]); } } - } // grid dims. + } // var dims. return all_ok; } // Update what steps are valid. - void YkGridBase::update_valid_step(idx_t t) { + void YkVarBase::update_valid_step(idx_t t) { STATE_VARS(this); if (_has_step_dim) { @@ -502,7 +502,7 @@ namespace yask { // Set dirty flags between indices. - void YkGridBase::set_dirty_in_slice(const Indices& first_indices, + void YkVarBase::set_dirty_in_slice(const Indices& first_indices, const Indices& last_indices) { if (_has_step_dim) { for (idx_t i = first_indices[+Indices::step_posn]; @@ -513,7 +513,7 @@ namespace yask { } // Make tuple needed for slicing. - IdxTuple YkGridBase::get_slice_range(const Indices& first_indices, + IdxTuple YkVarBase::get_slice_range(const Indices& first_indices, const Indices& last_indices) const { // Find ranges. Indices numElems = last_indices.addConst(1).subElements(first_indices); @@ -525,8 +525,8 @@ namespace yask { } // Print one element like - // "message: mygrid[x=4, y=7] = 3.14 at line 35". - void YkGridBase::printElem(const std::string& msg, + // "message: myvar[x=4, y=7] = 3.14 at line 35". + void YkVarBase::printElem(const std::string& msg, const Indices& idxs, real_t eval, int line) const { @@ -543,7 +543,7 @@ namespace yask { // Print one vector. // Indices must be normalized and rank-relative. - void YkGridBase::printVecNorm(const std::string& msg, + void YkVarBase::printVecNorm(const std::string& msg, const Indices& idxs, const real_vec_t& val, int line) const { diff --git a/src/kernel/lib/realv_grids.hpp b/src/kernel/lib/yk_var.hpp similarity index 84% rename from src/kernel/lib/realv_grids.hpp rename to src/kernel/lib/yk_var.hpp index 4bf93fdd..7ce67eaa 100644 --- a/src/kernel/lib/realv_grids.hpp +++ b/src/kernel/lib/yk_var.hpp @@ -27,21 +27,21 @@ IN THE SOFTWARE. namespace yask { - // Underlying storage using GenericGrids. - typedef GenericGridTemplate RealElemGrid; - typedef GenericGridTemplate RealVecGrid; + // Underlying storage using GenericVars. + typedef GenericVarTemplate RealElemVar; + typedef GenericVarTemplate RealVecVar; - // Base class implementing all yk_grid functionality. Used for - // grids that contain either individual elements or vectors. - class YkGridBase : + // Base class implementing all yk_var functionality. Used for + // vars that contain either individual elements or vectors. + class YkVarBase : public KernelStateBase { - friend class YkGridImpl; + friend class YkVarImpl; // Rank and local offsets in domain dim: // | ... | +------+ | // | global ofs | | | - // |<------------>|grid | | + // |<------------>|var | | // | | loc |domain| | // |rank | ofs | | | // | ofs |<------>| | | @@ -56,32 +56,32 @@ namespace yask { // Local offset must be a vector multiple. protected: - // Underlying storage. A GenericGrid doesn't have stencil features - // like padding, halos, offsets, etc. Holds name of grid, names of + // Underlying storage. A GenericVar doesn't have stencil features + // like padding, halos, offsets, etc. Holds name of var, names of // dims, sizes of dims, memory layout, actual data. - GenericGridBase* _ggb = 0; + GenericVarBase* _ggb = 0; - // The following masks have one bit for each dim in the grid. + // The following masks have one bit for each dim in the var. idx_t _step_dim_mask = 0; idx_t _domain_dim_mask = 0; idx_t _misc_dim_mask = 0; - // The following indices have one value for each dim in the grid. + // The following indices have one value for each dim in the var. // All values are in units of reals, not underlying elements, if different. // See diagram above for '_rank_offsets' and '_local_offsets'. // Comments show settings for domain dims | non-domain dims. - Indices _domains; // size of "interior" of grid | alloc size. + Indices _domains; // size of "interior" of var | alloc size. Indices _req_left_pads, _req_right_pads; // requested extra space around domains | zero. Indices _actl_left_pads, _actl_right_pads; // actual extra space around domains | zero. Indices _left_halos, _right_halos; // space within pads for halo exchange | zero. Indices _left_wf_exts, _right_wf_exts; // additional halos for wave-fronts | zero. - Indices _rank_offsets; // offsets of this grid domain in overall problem | zero. - Indices _local_offsets; // offsets of this grid domain in this rank | first index for step or misc. - Indices _allocs; // actual grid alloc in reals | same. + Indices _rank_offsets; // offsets of this var domain in overall problem | zero. + Indices _local_offsets; // offsets of this var domain in this rank | first index for step or misc. + Indices _allocs; // actual var alloc in reals | same. // Sizes in vectors for sizes that are always vec lens (to avoid division). // Each entry _vec_lens may be same as dims->_fold_pts or one, depending - // on whether grid is fully vectorized. + // on whether var is fully vectorized. Indices _vec_lens; // num reals in each elem | one. Indices _vec_left_pads; // same as _actl_left_pads. Indices _vec_allocs; // same as _allocs. @@ -96,21 +96,21 @@ namespace yask { bool _is_dynamic_misc_alloc = false; // Data that needs to be copied to neighbor's halos if using MPI. - // If this grid has the step dim, there is one bit per alloc'd step. + // If this var has the step dim, there is one bit per alloc'd step. // Otherwise, only bit 0 is used. std::vector _dirty_steps; // Data layout for slice APIs. bool _is_col_major = false; - // Whether to resize this grid based on solution parameters. + // Whether to resize this var based on solution parameters. bool _fixed_size = false; - // Whether this is a scratch grid. + // Whether this is a scratch var. bool _is_scratch = false; // Whether this was created via an API. - bool _is_user_grid = false; + bool _is_user_var = false; // Convenience function to format indices like // "x=5, y=3". @@ -162,10 +162,10 @@ namespace yask { const Indices& last_indices) const; public: - YkGridBase(KernelStateBase& state, - GenericGridBase* ggb, - const GridDimNames& dimNames); - virtual ~YkGridBase() { } + YkVarBase(KernelStateBase& state, + GenericVarBase* ggb, + const VarDimNames& dimNames); + virtual ~YkVarBase() { } // Step-indices. void update_valid_step(idx_t t); @@ -215,13 +215,13 @@ namespace yask { _rank_offsets.setFromConst(0); } - // New-grid accessors. - virtual bool is_user_grid() const { - return _is_user_grid; + // New-var accessors. + virtual bool is_user_var() const { + return _is_user_var; } - virtual void set_user_grid(bool is_user_grid) { - _is_user_grid = is_user_grid; - if (_is_user_grid) { + virtual void set_user_var(bool is_user_var) { + _is_user_var = is_user_var; + if (_is_user_var) { _is_dynamic_step_alloc = true; _is_dynamic_misc_alloc = true; } @@ -254,24 +254,24 @@ namespace yask { } // Convert logical step index to index in allocated range. - // If this grid doesn't use the step dim, returns 0. + // If this var doesn't use the step dim, returns 0. inline idx_t get_alloc_step_index(const Indices& indices) const { return _has_step_dim ? _wrap_step(indices[+Indices::step_posn]) : 0; } - // Get grid dims with allocations in number of reals. + // Get var dims with allocations in number of reals. virtual IdxTuple get_allocs() const { IdxTuple allocs = _ggb->get_dims(); // make a copy. _allocs.setTupleVals(allocs); return allocs; } - // Make a human-readable description of the grid var. + // Make a human-readable description of the var. virtual std::string _make_info_string() const =0; virtual std::string make_info_string() const { std::stringstream oss; if (is_scratch()) oss << "scratch "; - if (is_user_grid()) oss << "user-defined "; + if (is_user_var()) oss << "user-defined "; if (_fixed_size) oss << "fixed-size "; oss << _make_info_string() << " and meta-data at " << (void*)this; @@ -280,7 +280,7 @@ namespace yask { // Check for equality. // Return number of mismatches greater than epsilon. - virtual idx_t compare(const YkGridBase* ref, + virtual idx_t compare(const YkVarBase* ref, real_t epsilon = EPSILON, int maxPrint = 20) const; @@ -368,42 +368,42 @@ namespace yask { int line) const; }; - typedef std::shared_ptr GridBasePtr; + typedef std::shared_ptr VarBasePtr; - // Implementation of yk_grid interface. Class contains no real data, - // just a pointer to the underlying data and meta-data. This allows grid + // Implementation of yk_var interface. Class contains no real data, + // just a pointer to the underlying data and meta-data. This allows var // data to be shared and moved without changing pointers. - class YkGridImpl : public virtual yk_grid { + class YkVarImpl : public virtual yk_var { protected: - GridBasePtr _gbp; + VarBasePtr _gbp; public: - YkGridImpl() { } - YkGridImpl(const GridBasePtr& gp) : _gbp(gp) { } - virtual ~YkGridImpl() { } + YkVarImpl() { } + YkVarImpl(const VarBasePtr& gp) : _gbp(gp) { } + virtual ~YkVarImpl() { } - inline void set_gbp(const GridBasePtr& gp) { + inline void set_gbp(const VarBasePtr& gp) { _gbp = gp; } - inline YkGridBase& gb() { + inline YkVarBase& gb() { assert(_gbp.get()); return *(_gbp.get()); } - inline YkGridBase& gb() const { + inline YkVarBase& gb() const { assert(_gbp.get()); return *(_gbp.get()); } - inline YkGridBase* gbp() { + inline YkVarBase* gbp() { return _gbp.get(); } - inline YkGridBase* gbp() const { + inline YkVarBase* gbp() const { return _gbp.get(); } - inline GenericGridBase& gg() { + inline GenericVarBase& gg() { assert(gb()._ggb); return *(gb()._ggb); } - inline GenericGridBase& gg() const { + inline GenericVarBase& gg() const { assert(gb()._ggb); return *(gb()._ggb); } @@ -442,7 +442,7 @@ namespace yask { assert(n < get_num_dims()); return gg().get_dim_name(n); } - virtual GridDimNames get_dim_names() const { + virtual VarDimNames get_dim_names() const { std::vector dims(get_num_dims()); for (int i = 0; i < get_num_dims(); i++) dims.at(i) = get_dim_name(i); @@ -466,22 +466,22 @@ namespace yask { virtual idx_t get_first_valid_step_index() const { if (!gb()._has_step_dim) - THROW_YASK_EXCEPTION("Error: 'get_first_valid_step_index()' called on grid '" + + THROW_YASK_EXCEPTION("Error: 'get_first_valid_step_index()' called on var '" + get_name() + "' that does not use the step dimension"); return gb()._local_offsets[+Indices::step_posn]; } virtual idx_t get_last_valid_step_index() const { if (!gb()._has_step_dim) - THROW_YASK_EXCEPTION("Error: 'get_last_valid_step_index()' called on grid '" + + THROW_YASK_EXCEPTION("Error: 'get_last_valid_step_index()' called on var '" + get_name() + "' that does not use the step dimension"); return gb()._local_offsets[+Indices::step_posn] + gb()._domains[+Indices::step_posn] - 1; } -#define GET_GRID_API(api_name) \ +#define GET_VAR_API(api_name) \ virtual idx_t api_name(const std::string& dim) const; \ virtual idx_t api_name(int posn) const; -#define SET_GRID_API(api_name) \ +#define SET_VAR_API(api_name) \ virtual void api_name(const std::string& dim, idx_t n); \ virtual void api_name(int posn, idx_t n); @@ -489,64 +489,64 @@ namespace yask { // they can break the usage model. // They are not protected because they are used from outside // this class hierarchy. - GET_GRID_API(_get_left_wf_ext) - GET_GRID_API(_get_local_offset) - GET_GRID_API(_get_rank_offset) - GET_GRID_API(_get_right_wf_ext) - GET_GRID_API(_get_vec_len) - - SET_GRID_API(_set_alloc_size) - SET_GRID_API(_set_domain_size) - SET_GRID_API(_set_left_pad_size) - SET_GRID_API(_set_left_wf_ext) - SET_GRID_API(_set_local_offset) - SET_GRID_API(_set_rank_offset) - SET_GRID_API(_set_right_pad_size) - SET_GRID_API(_set_right_wf_ext) + GET_VAR_API(_get_left_wf_ext) + GET_VAR_API(_get_local_offset) + GET_VAR_API(_get_rank_offset) + GET_VAR_API(_get_right_wf_ext) + GET_VAR_API(_get_vec_len) + + SET_VAR_API(_set_alloc_size) + SET_VAR_API(_set_domain_size) + SET_VAR_API(_set_left_pad_size) + SET_VAR_API(_set_left_wf_ext) + SET_VAR_API(_set_local_offset) + SET_VAR_API(_set_rank_offset) + SET_VAR_API(_set_right_pad_size) + SET_VAR_API(_set_right_wf_ext) // Exposed APIs. - GET_GRID_API(get_first_local_index) - GET_GRID_API(get_last_local_index) - GET_GRID_API(get_rank_domain_size) - GET_GRID_API(get_first_rank_domain_index) - GET_GRID_API(get_last_rank_domain_index) - GET_GRID_API(get_left_halo_size) - GET_GRID_API(get_right_halo_size) - GET_GRID_API(get_halo_size) - GET_GRID_API(get_first_rank_halo_index) - GET_GRID_API(get_last_rank_halo_index) - GET_GRID_API(get_left_extra_pad_size) - GET_GRID_API(get_right_extra_pad_size) - GET_GRID_API(get_extra_pad_size) - GET_GRID_API(get_left_pad_size) - GET_GRID_API(get_right_pad_size) - GET_GRID_API(get_pad_size) - GET_GRID_API(get_alloc_size) - GET_GRID_API(get_first_rank_alloc_index) - GET_GRID_API(get_last_rank_alloc_index) - GET_GRID_API(get_first_misc_index) - GET_GRID_API(get_last_misc_index) - - SET_GRID_API(set_left_halo_size) - SET_GRID_API(set_right_halo_size) - SET_GRID_API(set_halo_size) - SET_GRID_API(set_left_min_pad_size) - SET_GRID_API(set_right_min_pad_size) - SET_GRID_API(set_min_pad_size) - SET_GRID_API(set_left_extra_pad_size) - SET_GRID_API(set_right_extra_pad_size) - SET_GRID_API(set_extra_pad_size) - SET_GRID_API(set_alloc_size) - SET_GRID_API(set_first_misc_index) - -#undef GET_GRID_API -#undef SET_GRID_API + GET_VAR_API(get_first_local_index) + GET_VAR_API(get_last_local_index) + GET_VAR_API(get_rank_domain_size) + GET_VAR_API(get_first_rank_domain_index) + GET_VAR_API(get_last_rank_domain_index) + GET_VAR_API(get_left_halo_size) + GET_VAR_API(get_right_halo_size) + GET_VAR_API(get_halo_size) + GET_VAR_API(get_first_rank_halo_index) + GET_VAR_API(get_last_rank_halo_index) + GET_VAR_API(get_left_extra_pad_size) + GET_VAR_API(get_right_extra_pad_size) + GET_VAR_API(get_extra_pad_size) + GET_VAR_API(get_left_pad_size) + GET_VAR_API(get_right_pad_size) + GET_VAR_API(get_pad_size) + GET_VAR_API(get_alloc_size) + GET_VAR_API(get_first_rank_alloc_index) + GET_VAR_API(get_last_rank_alloc_index) + GET_VAR_API(get_first_misc_index) + GET_VAR_API(get_last_misc_index) + + SET_VAR_API(set_left_halo_size) + SET_VAR_API(set_right_halo_size) + SET_VAR_API(set_halo_size) + SET_VAR_API(set_left_min_pad_size) + SET_VAR_API(set_right_min_pad_size) + SET_VAR_API(set_min_pad_size) + SET_VAR_API(set_left_extra_pad_size) + SET_VAR_API(set_right_extra_pad_size) + SET_VAR_API(set_extra_pad_size) + SET_VAR_API(set_alloc_size) + SET_VAR_API(set_first_misc_index) + +#undef GET_VAR_API +#undef SET_VAR_API virtual std::string format_indices(const Indices& indices) const { std::string str = get_name() + "(" + gb().makeIndexString(indices) + ")"; return str; } - virtual std::string format_indices(const GridIndices& indices) const { + virtual std::string format_indices(const VarIndices& indices) const { const Indices indices2(indices); return format_indices(indices2); } @@ -556,7 +556,7 @@ namespace yask { } virtual bool are_indices_local(const Indices& indices) const; - virtual bool are_indices_local(const GridIndices& indices) const { + virtual bool are_indices_local(const VarIndices& indices) const { const Indices indices2(indices); return are_indices_local(indices2); } @@ -566,7 +566,7 @@ namespace yask { } virtual double get_element(const Indices& indices) const; - virtual double get_element(const GridIndices& indices) const { + virtual double get_element(const VarIndices& indices) const { const Indices indices2(indices); return get_element(indices2); } @@ -580,8 +580,8 @@ namespace yask { return gb().get_elements_in_slice(buffer_ptr, first_indices, last_indices); } virtual idx_t get_elements_in_slice(void* buffer_ptr, - const GridIndices& first_indices, - const GridIndices& last_indices) const { + const VarIndices& first_indices, + const VarIndices& last_indices) const { const Indices first(first_indices); const Indices last(last_indices); return get_elements_in_slice(buffer_ptr, first, last); @@ -590,7 +590,7 @@ namespace yask { const Indices& indices, bool strict_indices = false); virtual idx_t set_element(double val, - const GridIndices& indices, + const VarIndices& indices, bool strict_indices = false) { const Indices indices2(indices); return set_element(val, indices2, strict_indices); @@ -605,7 +605,7 @@ namespace yask { const Indices& indices, bool strict_indices = false); virtual idx_t add_to_element(double val, - const GridIndices& indices, + const VarIndices& indices, bool strict_indices = false) { const Indices indices2(indices); return add_to_element(val, indices2, strict_indices); @@ -627,8 +627,8 @@ namespace yask { return gb().set_elements_in_slice_same(val, first_indices, last_indices, strict_indices); } virtual idx_t set_elements_in_slice_same(double val, - const GridIndices& first_indices, - const GridIndices& last_indices, + const VarIndices& first_indices, + const VarIndices& last_indices, bool strict_indices) { const Indices first(first_indices); const Indices last(last_indices); @@ -641,8 +641,8 @@ namespace yask { return gb().set_elements_in_slice(buffer_ptr, first_indices, last_indices); } virtual idx_t set_elements_in_slice(const void* buffer_ptr, - const GridIndices& first_indices, - const GridIndices& last_indices) { + const VarIndices& first_indices, + const VarIndices& last_indices) { const Indices first(first_indices); const Indices last(last_indices); return set_elements_in_slice(buffer_ptr, first, last); @@ -668,14 +668,14 @@ namespace yask { virtual idx_t get_num_storage_elements() const { return gb()._allocs.product(); } - virtual bool is_storage_layout_identical(const YkGridImpl* other, + virtual bool is_storage_layout_identical(const YkVarImpl* other, bool check_sizes) const; - virtual bool is_storage_layout_identical(const yk_grid_ptr other) const { - auto op = std::dynamic_pointer_cast(other); + virtual bool is_storage_layout_identical(const yk_var_ptr other) const { + auto op = std::dynamic_pointer_cast(other); assert(op); return is_storage_layout_identical(op.get(), true); } - virtual void fuse_grids(yk_grid_ptr other); + virtual void fuse_vars(yk_var_ptr other); virtual void* get_raw_storage_buffer() { return gg().get_storage(); } @@ -684,21 +684,21 @@ namespace yask { } }; - // YASK grid of real elements. - // Used for grids that do not contain folded vectors. + // YASK var of real elements. + // Used for vars that do not contain folded vectors. // If '_use_step_idx', then index to step dim will wrap around. template - class YkElemGrid : public YkGridBase { + class YkElemVar : public YkVarBase { protected: - typedef GenericGrid _grid_type; - _grid_type _data; + typedef GenericVar _var_type; + _var_type _data; public: - YkElemGrid(KernelStateBase& state, + YkElemVar(KernelStateBase& state, std::string name, - const GridDimNames& dimNames) : - YkGridBase(state, &_data, dimNames), + const VarDimNames& dimNames) : + YkVarBase(state, &_data, dimNames), _data(state, name, dimNames) { _has_step_dim = _use_step_idx; resize(); @@ -729,7 +729,7 @@ namespace yask { idx_t alloc_step_idx, bool checkBounds=true) const final { STATE_VARS_CONST(this); - TRACE_MEM_MSG(_data.get_name() << "." << "YkElemGrid::getElemPtr(" << + TRACE_MEM_MSG(_data.get_name() << "." << "YkElemVar::getElemPtr(" << idxs.makeValStr(get_num_dims()) << ")"); const auto n = _data.get_num_dims(); Indices adj_idxs(n); @@ -770,7 +770,7 @@ namespace yask { bool checkBounds=true) final { const real_t* p = - const_cast(this)->getElemPtr(idxs, alloc_step_idx, checkBounds); + const_cast(this)->getElemPtr(idxs, alloc_step_idx, checkBounds); return const_cast(p); } @@ -779,7 +779,7 @@ namespace yask { virtual real_t readElem(const Indices& idxs, idx_t alloc_step_idx, int line) const final { - const real_t* ep = YkElemGrid::getElemPtr(idxs, alloc_step_idx); + const real_t* ep = YkElemVar::getElemPtr(idxs, alloc_step_idx); real_t e = *ep; #ifdef TRACE_MEM printElem("readElem", idxs, e, line); @@ -798,28 +798,28 @@ namespace yask { const Indices& last_indices) const { return get_elements_in_slice(buffer_ptr, first_indices, last_indices); } - }; // YkElemGrid. + }; // YkElemVar. - // YASK grid of real vectors. - // Used for grids that contain all the folded dims. + // YASK var of real vectors. + // Used for vars that contain all the folded dims. // If '_use_step_idx', then index to step dim will wrap around. // The '_templ_vec_lens' arguments must contain a list of vector lengths - // corresponding to each dim in the grid. + // corresponding to each dim in the var. template - class YkVecGrid : public YkGridBase { + class YkVecVar : public YkVarBase { protected: - typedef GenericGrid _grid_type; - _grid_type _data; + typedef GenericVar _var_type; + _var_type _data; - // Positions of grid dims in vector fold dims. + // Positions of var dims in vector fold dims. Indices _vec_fold_posns; public: - YkVecGrid(KernelStateBase& stateb, + YkVecVar(KernelStateBase& stateb, const std::string& name, - const GridDimNames& dimNames) : - YkGridBase(stateb, &_data, dimNames), + const VarDimNames& dimNames) : + YkVarBase(stateb, &_data, dimNames), _data(stateb, name, dimNames), _vec_fold_posns(idx_t(0), int(dimNames.size())) { STATE_VARS(this); @@ -831,7 +831,7 @@ namespace yask { assert((size_t)nvls == dimNames.size()); // Init vec sizes. - // For each dim in the grid, use the number of vector + // For each dim in the var, use the number of vector // fold points or 1 if not set. for (size_t i = 0; i < dimNames.size(); i++) { auto& dname = dimNames.at(i); @@ -844,12 +844,12 @@ namespace yask { assert(dval == vls[i]); } - // Init grid-dim positions of fold dims. + // Init var-dim positions of fold dims. assert(dims->_vec_fold_pts.getNumDims() == NUM_VEC_FOLD_DIMS); for (int i = 0; i < NUM_VEC_FOLD_DIMS; i++) { auto& fdim = dims->_vec_fold_pts.getDimName(i); int j = get_dim_posn(fdim, true, - "internal error: folded grid missing folded dim"); + "internal error: folded var missing folded dim"); assert(j >= 0); _vec_fold_posns[i] = j; } @@ -891,7 +891,7 @@ namespace yask { idx_t alloc_step_idx, bool checkBounds=true) const final { STATE_VARS_CONST(this); - TRACE_MEM_MSG(_data.get_name() << "." << "YkVecGrid::getElemPtr(" << + TRACE_MEM_MSG(_data.get_name() << "." << "YkVecVar::getElemPtr(" << idxs.makeValStr(get_num_dims()) << ")"); // Use template vec lengths instead of run-time values for @@ -940,7 +940,7 @@ namespace yask { // Get only the vectorized fold offsets, i.e., those // with vec-lengths > 1. // And, they need to be in the original folding order, - // which might be different than the grid-dim order. + // which might be different than the var-dim order. Indices fold_ofs(NUM_VEC_FOLD_DIMS); #pragma unroll for (int i = 0; i < NUM_VEC_FOLD_DIMS; i++) { @@ -953,7 +953,7 @@ namespace yask { #ifdef DEBUG_LAYOUT // Compare to more explicit offset extraction. - IdxTuple eofs = get_allocs(); // get dims for this grid. + IdxTuple eofs = get_allocs(); // get dims for this var. elem_ofs.setTupleVals(eofs); // set vals from elem_ofs. auto i2 = dims->getElemIndexInVec(eofs); assert(i == i2); @@ -977,7 +977,7 @@ namespace yask { bool checkBounds=true) final { const real_t* p = - const_cast(this)->getElemPtr(idxs, alloc_step_idx, + const_cast(this)->getElemPtr(idxs, alloc_step_idx, checkBounds); return const_cast(p); } @@ -987,7 +987,7 @@ namespace yask { virtual real_t readElem(const Indices& idxs, idx_t alloc_step_idx, int line) const final { - const real_t* ep = YkVecGrid::getElemPtr(idxs, alloc_step_idx); + const real_t* ep = YkVecVar::getElemPtr(idxs, alloc_step_idx); real_t e = *ep; #ifdef TRACE_MEM printElem("readElem", idxs, e, line); @@ -1003,7 +1003,7 @@ namespace yask { idx_t alloc_step_idx, bool checkBounds=true) const { STATE_VARS_CONST(this); - TRACE_MEM_MSG(_data.get_name() << "." << "YkVecGrid::getVecPtrNorm(" << + TRACE_MEM_MSG(_data.get_name() << "." << "YkVecVar::getVecPtrNorm(" << vec_idxs.makeValStr(get_num_dims()) << ")"); static constexpr int nvls = sizeof...(_templ_vec_lens); @@ -1044,7 +1044,7 @@ namespace yask { bool checkBounds=true) { const real_vec_t* p = - const_cast(this)->getVecPtrNorm(vec_idxs, + const_cast(this)->getVecPtrNorm(vec_idxs, alloc_step_idx, checkBounds); return const_cast(p); } @@ -1158,7 +1158,7 @@ namespace yask { const Indices& last_indices) const { STATE_VARS(this); if (_data.get_storage() == 0) - FORMAT_AND_THROW_YASK_EXCEPTION("Error: call to 'get_vecs_in_slice' with no storage allocated for grid '" << + FORMAT_AND_THROW_YASK_EXCEPTION("Error: call to 'get_vecs_in_slice' with no storage allocated for var '" << _data.get_name()); Indices firstv, lastv; checkIndices(first_indices, "get_vecs_in_slice", true, true, true, &firstv); @@ -1208,6 +1208,6 @@ namespace yask { // Return number of writes. return n; } - }; // YkVecGrid. + }; // YkVecVar. } // namespace. diff --git a/src/kernel/lib/grid_apis.cpp b/src/kernel/lib/yk_var_apis.cpp similarity index 70% rename from src/kernel/lib/grid_apis.cpp rename to src/kernel/lib/yk_var_apis.cpp index b93be574..19760902 100644 --- a/src/kernel/lib/grid_apis.cpp +++ b/src/kernel/lib/yk_var_apis.cpp @@ -23,7 +23,7 @@ IN THE SOFTWARE. *****************************************************************************/ -// Implement methods for yk_grid APIs. +// Implement methods for yk_var APIs. #include "yask_stencil.hpp" using namespace std; @@ -36,19 +36,19 @@ namespace yask { // APIs to get info from vars: one with name of dim with a lot // of checking, and one with index of dim with no checking. -#define GET_GRID_API(api_name, expr, step_ok, domain_ok, misc_ok, prep_req) \ - idx_t YkGridImpl::api_name(const string& dim) const { \ +#define GET_VAR_API(api_name, expr, step_ok, domain_ok, misc_ok, prep_req) \ + idx_t YkVarImpl::api_name(const string& dim) const { \ STATE_VARS(gbp()); \ dims->checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ int posn = gb().get_dim_posn(dim, true, #api_name); \ idx_t mbit = 1LL << posn; \ if (prep_req && gb()._rank_offsets[posn] < 0) \ - THROW_YASK_EXCEPTION("Error: '" #api_name "()' called on grid '" + \ + THROW_YASK_EXCEPTION("Error: '" #api_name "()' called on var '" + \ get_name() + "' before calling 'prepare_solution()'"); \ auto rtn = expr; \ return rtn; \ } \ - idx_t YkGridImpl::api_name(int posn) const { \ + idx_t YkVarImpl::api_name(int posn) const { \ STATE_VARS(gbp()); \ idx_t mbit = 1LL << posn; \ auto rtn = expr; \ @@ -56,53 +56,53 @@ namespace yask { } // Internal APIs. - GET_GRID_API(_get_left_wf_ext, gb()._left_wf_exts[posn], true, true, true, false) - GET_GRID_API(_get_right_wf_ext, gb()._right_wf_exts[posn], true, true, true, false) - GET_GRID_API(_get_vec_len, gb()._vec_lens[posn], true, true, true, true) - GET_GRID_API(_get_rank_offset, gb()._rank_offsets[posn], true, true, true, true) - GET_GRID_API(_get_local_offset, gb()._local_offsets[posn], true, true, true, false) + GET_VAR_API(_get_left_wf_ext, gb()._left_wf_exts[posn], true, true, true, false) + GET_VAR_API(_get_right_wf_ext, gb()._right_wf_exts[posn], true, true, true, false) + GET_VAR_API(_get_vec_len, gb()._vec_lens[posn], true, true, true, true) + GET_VAR_API(_get_rank_offset, gb()._rank_offsets[posn], true, true, true, true) + GET_VAR_API(_get_local_offset, gb()._local_offsets[posn], true, true, true, false) // Exposed APIs. - GET_GRID_API(get_first_local_index, gb().get_first_local_index(posn), true, true, true, true) - GET_GRID_API(get_last_local_index, gb().get_last_local_index(posn), true, true, true, true) - GET_GRID_API(get_first_misc_index, gb()._local_offsets[posn], false, false, true, false) - GET_GRID_API(get_last_misc_index, gb()._local_offsets[posn] + gb()._domains[posn] - 1, false, false, true, false) - GET_GRID_API(get_rank_domain_size, gb()._domains[posn], false, true, false, false) - GET_GRID_API(get_left_pad_size, gb()._actl_left_pads[posn], false, true, false, false) - GET_GRID_API(get_right_pad_size, gb()._actl_right_pads[posn], false, true, false, false) - GET_GRID_API(get_left_halo_size, gb()._left_halos[posn], false, true, false, false) - GET_GRID_API(get_right_halo_size, gb()._right_halos[posn], false, true, false, false) - GET_GRID_API(get_left_extra_pad_size, gb()._actl_left_pads[posn] - gb()._left_halos[posn], false, true, false, false) - GET_GRID_API(get_right_extra_pad_size, gb()._actl_right_pads[posn] - gb()._right_halos[posn], false, true, false, false) - GET_GRID_API(get_alloc_size, gb()._allocs[posn], true, true, true, false) - GET_GRID_API(get_first_rank_domain_index, gb()._rank_offsets[posn], false, true, false, true) - GET_GRID_API(get_last_rank_domain_index, gb()._rank_offsets[posn] + gb()._domains[posn] - 1, false, true, false, true) - GET_GRID_API(get_first_rank_halo_index, gb()._rank_offsets[posn] - gb()._left_halos[posn], false, true, false, true) - GET_GRID_API(get_last_rank_halo_index, gb()._rank_offsets[posn] + gb()._domains[posn] + + GET_VAR_API(get_first_local_index, gb().get_first_local_index(posn), true, true, true, true) + GET_VAR_API(get_last_local_index, gb().get_last_local_index(posn), true, true, true, true) + GET_VAR_API(get_first_misc_index, gb()._local_offsets[posn], false, false, true, false) + GET_VAR_API(get_last_misc_index, gb()._local_offsets[posn] + gb()._domains[posn] - 1, false, false, true, false) + GET_VAR_API(get_rank_domain_size, gb()._domains[posn], false, true, false, false) + GET_VAR_API(get_left_pad_size, gb()._actl_left_pads[posn], false, true, false, false) + GET_VAR_API(get_right_pad_size, gb()._actl_right_pads[posn], false, true, false, false) + GET_VAR_API(get_left_halo_size, gb()._left_halos[posn], false, true, false, false) + GET_VAR_API(get_right_halo_size, gb()._right_halos[posn], false, true, false, false) + GET_VAR_API(get_left_extra_pad_size, gb()._actl_left_pads[posn] - gb()._left_halos[posn], false, true, false, false) + GET_VAR_API(get_right_extra_pad_size, gb()._actl_right_pads[posn] - gb()._right_halos[posn], false, true, false, false) + GET_VAR_API(get_alloc_size, gb()._allocs[posn], true, true, true, false) + GET_VAR_API(get_first_rank_domain_index, gb()._rank_offsets[posn], false, true, false, true) + GET_VAR_API(get_last_rank_domain_index, gb()._rank_offsets[posn] + gb()._domains[posn] - 1, false, true, false, true) + GET_VAR_API(get_first_rank_halo_index, gb()._rank_offsets[posn] - gb()._left_halos[posn], false, true, false, true) + GET_VAR_API(get_last_rank_halo_index, gb()._rank_offsets[posn] + gb()._domains[posn] + gb()._right_halos[posn] - 1, false, true, false, true) - GET_GRID_API(get_first_rank_alloc_index, gb().get_first_local_index(posn), false, true, false, true) - GET_GRID_API(get_last_rank_alloc_index, gb().get_last_local_index(posn), false, true, false, true) + GET_VAR_API(get_first_rank_alloc_index, gb().get_first_local_index(posn), false, true, false, true) + GET_VAR_API(get_last_rank_alloc_index, gb().get_last_local_index(posn), false, true, false, true) // Deprecated APIs. - GET_GRID_API(get_pad_size, gb()._actl_left_pads[posn]; DEPRECATED(get_pad_size), false, true, false, false) - GET_GRID_API(get_halo_size, gb()._left_halos[posn]; DEPRECATED(get_halo_size), false, true, false, false) - GET_GRID_API(get_extra_pad_size, gb()._actl_left_pads[posn] - gb()._left_halos[posn]; + GET_VAR_API(get_pad_size, gb()._actl_left_pads[posn]; DEPRECATED(get_pad_size), false, true, false, false) + GET_VAR_API(get_halo_size, gb()._left_halos[posn]; DEPRECATED(get_halo_size), false, true, false, false) + GET_VAR_API(get_extra_pad_size, gb()._actl_left_pads[posn] - gb()._left_halos[posn]; DEPRECATED(get_extra_pad_size), false, true, false, false) -#undef GET_GRID_API +#undef GET_VAR_API // APIs to set vars. #define COMMA , -#define SET_GRID_API(api_name, expr, step_ok, domain_ok, misc_ok) \ - void YkGridImpl::api_name(const string& dim, idx_t n) { \ +#define SET_VAR_API(api_name, expr, step_ok, domain_ok, misc_ok) \ + void YkVarImpl::api_name(const string& dim, idx_t n) { \ STATE_VARS(gbp()); \ - TRACE_MSG("grid '" << get_name() << "'." \ + TRACE_MSG("var '" << get_name() << "'." \ #api_name "('" << dim << "', " << n << ")"); \ dims->checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ int posn = gb().get_dim_posn(dim, true, #api_name); \ idx_t mbit = 1LL << posn; \ expr; \ } \ - void YkGridImpl::api_name(int posn, idx_t n) { \ + void YkVarImpl::api_name(int posn, idx_t n) { \ STATE_VARS(gbp()); \ idx_t mbit = 1LL << posn; \ int dim = posn; \ @@ -111,38 +111,38 @@ namespace yask { // These are the internal, unchecked access functions that allow // changes prohibited thru the APIs. - SET_GRID_API(_set_rank_offset, gb()._rank_offsets[posn] = n, true, true, true) - SET_GRID_API(_set_local_offset, gb()._local_offsets[posn] = n; + SET_VAR_API(_set_rank_offset, gb()._rank_offsets[posn] = n, true, true, true) + SET_VAR_API(_set_local_offset, gb()._local_offsets[posn] = n; assert(imod_flr(n, gb()._vec_lens[posn]) == 0); gb()._vec_local_offsets[posn] = n / gb()._vec_lens[posn], true, true, true) - SET_GRID_API(_set_domain_size, gb()._domains[posn] = n; resize(), true, true, true) - SET_GRID_API(_set_left_pad_size, gb()._actl_left_pads[posn] = n; resize(), true, true, true) - SET_GRID_API(_set_right_pad_size, gb()._actl_right_pads[posn] = n; resize(), true, true, true) - SET_GRID_API(_set_left_wf_ext, gb()._left_wf_exts[posn] = n; resize(), true, true, true) - SET_GRID_API(_set_right_wf_ext, gb()._right_wf_exts[posn] = n; resize(), true, true, true) - SET_GRID_API(_set_alloc_size, gb()._domains[posn] = n; resize(), true, true, true) + SET_VAR_API(_set_domain_size, gb()._domains[posn] = n; resize(), true, true, true) + SET_VAR_API(_set_left_pad_size, gb()._actl_left_pads[posn] = n; resize(), true, true, true) + SET_VAR_API(_set_right_pad_size, gb()._actl_right_pads[posn] = n; resize(), true, true, true) + SET_VAR_API(_set_left_wf_ext, gb()._left_wf_exts[posn] = n; resize(), true, true, true) + SET_VAR_API(_set_right_wf_ext, gb()._right_wf_exts[posn] = n; resize(), true, true, true) + SET_VAR_API(_set_alloc_size, gb()._domains[posn] = n; resize(), true, true, true) // These are the safer ones used in the APIs. - SET_GRID_API(set_left_halo_size, gb()._left_halos[posn] = n; resize(), false, true, false) - SET_GRID_API(set_right_halo_size, gb()._right_halos[posn] = n; resize(), false, true, false) - SET_GRID_API(set_halo_size, gb()._left_halos[posn] = gb()._right_halos[posn] = n; resize(), false, true, false) - SET_GRID_API(set_alloc_size, gb()._domains[posn] = n; resize(), + SET_VAR_API(set_left_halo_size, gb()._left_halos[posn] = n; resize(), false, true, false) + SET_VAR_API(set_right_halo_size, gb()._right_halos[posn] = n; resize(), false, true, false) + SET_VAR_API(set_halo_size, gb()._left_halos[posn] = gb()._right_halos[posn] = n; resize(), false, true, false) + SET_VAR_API(set_alloc_size, gb()._domains[posn] = n; resize(), gb()._is_dynamic_step_alloc, gb()._fixed_size, gb()._is_dynamic_misc_alloc) - SET_GRID_API(set_left_min_pad_size, gb()._req_left_pads[posn] = n; resize(), false, true, false) - SET_GRID_API(set_right_min_pad_size, gb()._req_right_pads[posn] = n; resize(), false, true, false) - SET_GRID_API(set_min_pad_size, gb()._req_left_pads[posn] = gb()._req_right_pads[posn] = n; resize(), + SET_VAR_API(set_left_min_pad_size, gb()._req_left_pads[posn] = n; resize(), false, true, false) + SET_VAR_API(set_right_min_pad_size, gb()._req_right_pads[posn] = n; resize(), false, true, false) + SET_VAR_API(set_min_pad_size, gb()._req_left_pads[posn] = gb()._req_right_pads[posn] = n; resize(), false, true, false) - SET_GRID_API(set_left_extra_pad_size, + SET_VAR_API(set_left_extra_pad_size, set_left_min_pad_size(posn, gb()._left_halos[posn] + n), false, true, false) - SET_GRID_API(set_right_extra_pad_size, + SET_VAR_API(set_right_extra_pad_size, set_right_min_pad_size(posn, gb()._right_halos[posn] + n), false, true, false) - SET_GRID_API(set_extra_pad_size, set_left_extra_pad_size(posn, n); + SET_VAR_API(set_extra_pad_size, set_left_extra_pad_size(posn, n); set_right_extra_pad_size(posn, n), false, true, false) - SET_GRID_API(set_first_misc_index, gb()._local_offsets[posn] = n, false, false, gb()._is_user_grid) + SET_VAR_API(set_first_misc_index, gb()._local_offsets[posn] = n, false, false, gb()._is_user_var) #undef COMMA -#undef SET_GRID_API +#undef SET_VAR_API - bool YkGridImpl::is_storage_layout_identical(const YkGridImpl* op, + bool YkVarImpl::is_storage_layout_identical(const YkVarImpl* op, bool check_sizes) const { // Same size? @@ -176,56 +176,56 @@ namespace yask { return true; } - void YkGridImpl::fuse_grids(yk_grid_ptr src) { + void YkVarImpl::fuse_vars(yk_var_ptr src) { STATE_VARS(gbp()); - auto op = dynamic_pointer_cast(src); - TRACE_MSG("fuse_grids(" << src.get() << "): this=" << gb().make_info_string() << + auto op = dynamic_pointer_cast(src); + TRACE_MSG("fuse_vars(" << src.get() << "): this=" << gb().make_info_string() << "; source=" << op->gb().make_info_string()); assert(op); auto* sp = op.get(); assert(!_gbp->is_scratch()); - // Check conditions for fusing into a non-user grid. + // Check conditions for fusing into a non-user var. bool force_native = false; - if (gb().is_user_grid()) { + if (gb().is_user_var()) { force_native = true; if (!is_storage_layout_identical(sp, false)) - THROW_YASK_EXCEPTION("Error: fuse_grids(): attempt to replace meta-data" + THROW_YASK_EXCEPTION("Error: fuse_vars(): attempt to replace meta-data" " of " + gb().make_info_string() + " used in solution with incompatible " + sp->gb().make_info_string()); } - // Save ptr to source-storage grid before fusing meta-data. - GridBasePtr st_gbp = sp->_gbp; // Shared-ptr to keep source active to end of method. - GenericGridBase* st_ggb = st_gbp->_ggb; + // Save ptr to source-storage var before fusing meta-data. + VarBasePtr st_gbp = sp->_gbp; // Shared-ptr to keep source active to end of method. + GenericVarBase* st_ggb = st_gbp->_ggb; // Fuse meta-data. _gbp = sp->_gbp; - // Tag grid as a non-user grid if the original one was. + // Tag var as a non-user var if the original one was. if (force_native) - _gbp->set_user_grid(false); + _gbp->set_user_var(false); // Fuse storage. gg().share_storage(st_ggb); - TRACE_MSG("after fuse_grids: this=" << gb().make_info_string() << + TRACE_MSG("after fuse_vars: this=" << gb().make_info_string() << "; source=" << op->gb().make_info_string()); } // API get, set, etc. - bool YkGridImpl::are_indices_local(const Indices& indices) const { + bool YkVarImpl::are_indices_local(const Indices& indices) const { if (!is_storage_allocated()) return false; return gb().checkIndices(indices, "are_indices_local", false, true, false); } - double YkGridImpl::get_element(const Indices& indices) const { + double YkVarImpl::get_element(const Indices& indices) const { STATE_VARS(gbp()); TRACE_MSG("get_element({" << gb().makeIndexString(indices) << "}) on " << gb().make_info_string()); if (!is_storage_allocated()) - THROW_YASK_EXCEPTION("Error: call to 'get_element' with no storage allocated for grid '" + + THROW_YASK_EXCEPTION("Error: call to 'get_element' with no storage allocated for var '" + get_name() + "'"); gb().checkIndices(indices, "get_element", true, true, false); idx_t asi = gb().get_alloc_step_index(indices); @@ -234,7 +234,7 @@ namespace yask { get_name() + "' returns " << val); return double(val); } - idx_t YkGridImpl::set_element(double val, + idx_t YkVarImpl::set_element(double val, const Indices& indices, bool strict_indices) { STATE_VARS(gbp()); @@ -244,7 +244,7 @@ namespace yask { gb().make_info_string()); idx_t nup = 0; if (!get_raw_storage_buffer() && strict_indices) - THROW_YASK_EXCEPTION("Error: call to 'set_element' with no storage allocated for grid '" + + THROW_YASK_EXCEPTION("Error: call to 'set_element' with no storage allocated for var '" + get_name() + "'"); if (get_raw_storage_buffer() && @@ -264,7 +264,7 @@ namespace yask { get_name() + "' returns " << nup); return nup; } - idx_t YkGridImpl::add_to_element(double val, + idx_t YkVarImpl::add_to_element(double val, const Indices& indices, bool strict_indices) { STATE_VARS(gbp()); @@ -274,7 +274,7 @@ namespace yask { gb().make_info_string()); idx_t nup = 0; if (!get_raw_storage_buffer() && strict_indices) - THROW_YASK_EXCEPTION("Error: call to 'add_to_element' with no storage allocated for grid '" + + THROW_YASK_EXCEPTION("Error: call to 'add_to_element' with no storage allocated for var '" + get_name() + "'"); if (get_raw_storage_buffer() && @@ -294,7 +294,7 @@ namespace yask { return nup; } - idx_t YkGridBase::get_elements_in_slice(void* buffer_ptr, + idx_t YkVarBase::get_elements_in_slice(void* buffer_ptr, const Indices& first_indices, const Indices& last_indices) const { STATE_VARS(this); @@ -303,7 +303,7 @@ namespace yask { makeIndexString(last_indices) << "}) on " << make_info_string()); if (_ggb->get_storage() == 0) - THROW_YASK_EXCEPTION("Error: call to 'get_elements_in_slice' with no storage allocated for grid '" + + THROW_YASK_EXCEPTION("Error: call to 'get_elements_in_slice' with no storage allocated for var '" + _ggb->get_name() + "'"); checkIndices(first_indices, "get_elements_in_slice", true, true, false); checkIndices(last_indices, "get_elements_in_slice", true, true, false); @@ -330,7 +330,7 @@ namespace yask { _ggb->get_name() + "' returns " << nup); return nup; } - idx_t YkGridBase::set_elements_in_slice_same(double val, + idx_t YkVarBase::set_elements_in_slice_same(double val, const Indices& first_indices, const Indices& last_indices, bool strict_indices) { @@ -342,7 +342,7 @@ namespace yask { make_info_string()); if (_ggb->get_storage() == 0) { if (strict_indices) - THROW_YASK_EXCEPTION("Error: call to 'set_elements_in_slice_same' with no storage allocated for grid '" + + THROW_YASK_EXCEPTION("Error: call to 'set_elements_in_slice_same' with no storage allocated for var '" + _ggb->get_name() + "'"); return 0; } @@ -381,7 +381,7 @@ namespace yask { _ggb->get_name() + "' returns " << nup); return nup; } - idx_t YkGridBase::set_elements_in_slice(const void* buffer_ptr, + idx_t YkVarBase::set_elements_in_slice(const void* buffer_ptr, const Indices& first_indices, const Indices& last_indices) { STATE_VARS(this); @@ -390,7 +390,7 @@ namespace yask { makeIndexString(last_indices) << "}) on " << make_info_string()); if (_ggb->get_storage() == 0) - THROW_YASK_EXCEPTION("Error: call to 'set_elements_in_slice' with no storage allocated for grid '" + + THROW_YASK_EXCEPTION("Error: call to 'set_elements_in_slice' with no storage allocated for var '" + _ggb->get_name() + "'"); checkIndices(first_indices, "set_elements_in_slice", true, false, false); checkIndices(last_indices, "set_elements_in_slice", true, false, false); diff --git a/src/kernel/swig/yask_kernel_api.i b/src/kernel/swig/yask_kernel_api.i index 8bc04ef7..7e6bf8fd 100644 --- a/src/kernel/swig/yask_kernel_api.i +++ b/src/kernel/swig/yask_kernel_api.i @@ -42,7 +42,7 @@ IN THE SOFTWARE. %shared_ptr(yask::yk_env) %shared_ptr(yask::yk_settings) %shared_ptr(yask::yk_solution) -%shared_ptr(yask::yk_grid) +%shared_ptr(yask::yk_var) %shared_ptr(yask::yk_stats) // Mutable buffer to access raw data. @@ -56,7 +56,7 @@ IN THE SOFTWARE. // All vector types used in API. %template(vector_idx) std::vector; %template(vector_str) std::vector; -%template(vector_grid_ptr) std::vector>; +%template(vector_var_ptr) std::vector>; %exception { try { @@ -70,4 +70,4 @@ IN THE SOFTWARE. %include "yask_common_api.hpp" %include "yask_kernel_api.hpp" %include "aux/yk_solution_api.hpp" -%include "aux/yk_grid_api.hpp" +%include "aux/yk_var_api.hpp" diff --git a/src/kernel/tests/grid_test.cpp b/src/kernel/tests/var_test.cpp similarity index 86% rename from src/kernel/tests/grid_test.cpp rename to src/kernel/tests/var_test.cpp index 5bdf55ef..acd46291 100644 --- a/src/kernel/tests/grid_test.cpp +++ b/src/kernel/tests/var_test.cpp @@ -23,7 +23,7 @@ IN THE SOFTWARE. *****************************************************************************/ -// Test the YASK grids. +// Test the YASK vars. // This must be compiled with a kernel lib containing 'x', 'y', and 'z' dims. // enable assert(). @@ -68,14 +68,14 @@ int main(int argc, char** argv) { // 0D test. { os << "0-D test...\n"; - GridDimNames gdims; - string name = "test grid"; - auto gb0 = make_shared>(*context, name, gdims); - YkGridPtr g0 = make_shared(gb0); + VarDimNames gdims; + string name = "test var"; + auto gb0 = make_shared>(*context, name, gdims); + YkVarPtr g0 = make_shared(gb0); g0->alloc_storage(); os << gb0->make_info_string() << endl; - auto gb1 = make_shared>(*context, name, gdims); - YkGridPtr g1 = make_shared(gb1); + auto gb1 = make_shared>(*context, name, gdims); + YkVarPtr g1 = make_shared(gb1); g1->alloc_storage(); os << gb1->make_info_string() << endl; @@ -91,12 +91,12 @@ int main(int argc, char** argv) { // 3D test. { os << "3-D test...\n"; - GridDimNames gdims = {"x", "y", "z"}; - string name = "test grid"; - auto gb3 = make_shared>(*context, name, gdims); - YkGridPtr g3 = make_shared(gb3); - auto gb3f = make_shared>(*context, name, gdims); - YkGridPtr g3f = make_shared(gb3f); + VarDimNames gdims = {"x", "y", "z"}; + string name = "test var"; + auto gb3 = make_shared>(*context, name, gdims); + YkVarPtr g3 = make_shared(gb3); + auto gb3f = make_shared>(*context, name, gdims); + YkVarPtr g3f = make_shared(gb3f); int i = 0; int min_pad = 3; for (auto dname : gdims) { @@ -139,6 +139,6 @@ int main(int argc, char** argv) { }); } - os << "End of YASK grid test.\n"; + os << "End of YASK var test.\n"; return 0; } diff --git a/src/kernel/tests/yask_kernel_api_exception_test.cpp b/src/kernel/tests/yask_kernel_api_exception_test.cpp index bf1d8df9..05c8f1da 100644 --- a/src/kernel/tests/yask_kernel_api_exception_test.cpp +++ b/src/kernel/tests/yask_kernel_api_exception_test.cpp @@ -58,11 +58,11 @@ int main() { soln->set_block_size(dim_name, 32); } - // Make a test fixed-size grid. - vector fgrid_sizes; + // Make a test fixed-size var. + vector fvar_sizes; for (auto dim_name : soln_dims) - fgrid_sizes.push_back(5); - auto fgrid = soln->new_fixed_size_grid("fgrid", soln_dims, fgrid_sizes); + fvar_sizes.push_back(5); + auto fvar = soln->new_fixed_size_var("fvar", soln_dims, fvar_sizes); // Exception test cout << "Exception Test: Call 'run_solution' without calling prepare_solution().\n"; @@ -87,7 +87,7 @@ int main() { } - // Allocate memory for any grids that do not have storage set. + // Allocate memory for any vars that do not have storage set. // Set other data structures needed for stencil application. soln->prepare_solution(); @@ -103,33 +103,33 @@ int main() { } cout << endl; - // Print out some info about the grids and init their data. - for (auto grid : soln->get_grids()) { - cout << " " << grid->get_name() << "("; - for (auto dname : grid->get_dim_names()) + // Print out some info about the vars and init their data. + for (auto var : soln->get_vars()) { + cout << " " << var->get_name() << "("; + for (auto dname : var->get_dim_names()) cout << " '" << dname << "'"; cout << " )\n"; - for (auto dname : grid->get_dim_names()) { + for (auto dname : var->get_dim_names()) { if (domain_dim_set.count(dname)) { cout << " '" << dname << "' domain index range on this rank: " << - grid->get_first_rank_domain_index(dname) << " ... " << - grid->get_last_rank_domain_index(dname) << endl; + var->get_first_rank_domain_index(dname) << " ... " << + var->get_last_rank_domain_index(dname) << endl; cout << " '" << dname << "' allowed index range on this rank: " << - grid->get_first_rank_alloc_index(dname) << " ... " << - grid->get_last_rank_alloc_index(dname) << endl; + var->get_first_rank_alloc_index(dname) << " ... " << + var->get_last_rank_alloc_index(dname) << endl; } } // First, just init all the elements to the same value. - grid->set_all_elements_same(0.1); + var->set_all_elements_same(0.1); - // Done with fixed-size grids. - if (grid->is_fixed_size()) + // Done with fixed-size vars. + if (var->is_fixed_size()) continue; // Create indices describing a subset of the overall domain. vector first_indices, last_indices; - for (auto dname : grid->get_dim_names()) { + for (auto dname : var->get_dim_names()) { // Is this a domain dim? if (domain_dim_set.count(dname)) { @@ -157,19 +157,19 @@ int main() { // Add indices to set all allowed values. // (This isn't really meaningful; it's just illustrative.) - first_indices.push_back(grid->get_first_misc_index(dname)); - last_indices.push_back(grid->get_last_misc_index(dname)); + first_indices.push_back(var->get_first_misc_index(dname)); + last_indices.push_back(var->get_last_misc_index(dname)); } } // Init the values using the indices created above. - idx_t nset = grid->set_elements_in_slice_same(0.9, first_indices, last_indices); + idx_t nset = var->set_elements_in_slice_same(0.9, first_indices, last_indices); cout << " " << nset << " element(s) set.\n"; - // Raw access to this grid. - auto raw_p = grid->get_raw_storage_buffer(); - auto num_elems = grid->get_num_storage_elements(); - cout << " " << grid->get_num_storage_bytes() << + // Raw access to this var. + auto raw_p = var->get_raw_storage_buffer(); + auto num_elems = var->get_num_storage_elements(); + cout << " " << var->get_num_storage_bytes() << " bytes of raw data at " << raw_p << ": "; if (soln->get_element_bytes() == 4) cout << ((float*)raw_p)[0] << ", ..., " << ((float*)raw_p)[num_elems-1] << "\n"; @@ -186,19 +186,19 @@ int main() { // TODO: better to have exception test for the methods below // StencilContext::calc_region - // StencilContext::addGrid + // StencilContext::addVar // StencilContext::setupRank // StencilContext::prepare_solution - // StencilContext::newGrid - // YkGridBase::get_dim_posn - // YkGridBase::resize - // YkGridBase::checkDimType - // YkGridBase::share_storage - // YkGridBase::checkIndices - // YkGridBase::get_element - // YkGridBase::get_elements_in_slice - // YkGridBase::_share_data - // YkGridBase::get_vecs_in_slice + // StencilContext::newVar + // YkVarBase::get_dim_posn + // YkVarBase::resize + // YkVarBase::checkDimType + // YkVarBase::share_storage + // YkVarBase::checkIndices + // YkVarBase::get_element + // YkVarBase::get_elements_in_slice + // YkVarBase::_share_data + // YkVarBase::get_vecs_in_slice // real_vec_permute2 // Dims::checkDimType // KernelEnv::initEnv diff --git a/src/kernel/tests/yask_kernel_api_exception_test.py b/src/kernel/tests/yask_kernel_api_exception_test.py index 6f100fca..79a8b444 100755 --- a/src/kernel/tests/yask_kernel_api_exception_test.py +++ b/src/kernel/tests/yask_kernel_api_exception_test.py @@ -30,21 +30,21 @@ import argparse import yask_kernel -# Read data from grid using NumPy ndarray. -def read_grid(grid, timestep) : +# Read data from var using NumPy ndarray. +def read_var(var, timestep) : - # Ignore with fixed-sized grids. - if grid.is_fixed_size(): + # Ignore with fixed-sized vars. + if var.is_fixed_size(): return - print("Reading grid '" + grid.get_name() + "' at time " + repr(timestep) + "...") + print("Reading var '" + var.get_name() + "' at time " + repr(timestep) + "...") # Create indices for YASK and shape for NumPy. first_indices = [] last_indices = [] shape = [] nelems = 1 - for dname in grid.get_dim_names() : + for dname in var.get_dim_names() : if dname == soln.get_step_dim_name() : @@ -73,30 +73,30 @@ def read_grid(grid, timestep) : else : # Read first index only. - first_indices += [grid.get_first_misc_index(dname)] - last_indices += [grid.get_first_misc_index(dname)] + first_indices += [var.get_first_misc_index(dname)] + last_indices += [var.get_first_misc_index(dname)] # Create a NumPy ndarray to hold the extracted data. ndarray1 = np.empty(shape, dtype, 'C'); print("Reading " + repr(nelems) + " element(s)...") - nread = grid.get_elements_in_slice(ndarray1.data, first_indices, last_indices) + nread = var.get_elements_in_slice(ndarray1.data, first_indices, last_indices) print(ndarray1) - # Raw access to this grid. + # Raw access to this var. if soln.get_element_bytes() == 4 : ptype = ct.POINTER(ct.c_float) else : ptype = ct.POINTER(ct.c_double) - raw_ptr = grid.get_raw_storage_buffer() + raw_ptr = var.get_raw_storage_buffer() fp_ptr = ct.cast(int(raw_ptr), ptype) - num_elems = grid.get_num_storage_elements() + num_elems = var.get_num_storage_elements() print("Raw data: " + repr(fp_ptr[0]) + ", ..., " + repr(fp_ptr[num_elems-1])) #ndarray2 = np.fromiter(fp_ptr, dtype, num_elems); print(ndarray2) -# Init grid using NumPy ndarray. -def init_grid(grid, timestep) : - print("Initializing grid '" + grid.get_name() + "' at time " + repr(timestep) + "...") +# Init var using NumPy ndarray. +def init_var(var, timestep) : + print("Initializing var '" + var.get_name() + "' at time " + repr(timestep) + "...") # Create indices for YASK, shape & point for NumPy. first_indices = [] @@ -104,7 +104,7 @@ def init_grid(grid, timestep) : shape = [] point = () nelems = 1 - for dname in grid.get_dim_names() : + for dname in var.get_dim_names() : if dname == soln.get_step_dim_name() : @@ -138,8 +138,8 @@ def init_grid(grid, timestep) : else : # Write first index only. - first_indices += [grid.get_first_misc_index(dname)] - last_indices += [grid.get_first_misc_index(dname)] + first_indices += [var.get_first_misc_index(dname)] + last_indices += [var.get_first_misc_index(dname)] # Create a NumPy ndarray to hold the data. ndarray = np.zeros(shape, dtype, 'C'); @@ -149,7 +149,7 @@ def init_grid(grid, timestep) : print(ndarray) print("Writing " + repr(nelems) + " element(s)...") - nset = grid.set_elements_in_slice(ndarray.data, first_indices, last_indices) + nset = var.set_elements_in_slice(ndarray.data, first_indices, last_indices) print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) # Main script. @@ -171,7 +171,7 @@ def init_grid(grid, timestep) : soln.set_debug_output(debug_output) name = soln.get_name() - # NB: At this point, the grids' meta-data exists, but the grids have no + # NB: At this point, the vars' meta-data exists, but the vars have no # data allocated. We need to set the size of the domain before # allocating data. @@ -192,11 +192,11 @@ def init_grid(grid, timestep) : # Set block size. soln.set_block_size(dim_name, 32) - # Make a test fixed-size grid. - fgrid_sizes = () + # Make a test fixed-size var. + fvar_sizes = () for dim_name in soln_dims : - fgrid_sizes += (5,) - fgrid = soln.new_fixed_size_grid("fgrid", soln_dims, fgrid_sizes) + fvar_sizes += (5,) + fvar = soln.new_fixed_size_var("fvar", soln_dims, fvar_sizes) # Exception test print("Exception Test: Call 'run_solution' without calling prepare_solution().") @@ -218,7 +218,7 @@ def init_grid(grid, timestep) : print ("Exception Test: Catch exception correctly.") num_exception = num_exception + 1 - # Allocate memory for any grids that do not have storage set. + # Allocate memory for any vars that do not have storage set. # Set other data structures needed for stencil application. soln.prepare_solution() @@ -226,33 +226,33 @@ def init_grid(grid, timestep) : print("Stencil-solution '" + name + "':") print(" Step dimension: " + repr(soln.get_step_dim_name())) print(" Domain dimensions: " + repr(soln.get_domain_dim_names())) - print(" Grids:") - for grid in soln.get_grids() : - print(" " + grid.get_name() + repr(grid.get_dim_names())) - for dname in grid.get_dim_names() : + print(" Vars:") + for var in soln.get_vars() : + print(" " + var.get_name() + repr(var.get_dim_names())) + for dname in var.get_dim_names() : if dname in soln.get_domain_dim_names() : print(" '" + dname + "' allowed index range in this rank: " + - repr(grid.get_first_rank_alloc_index(dname)) + " ... " + - repr(grid.get_last_rank_alloc_index(dname))) + repr(var.get_first_rank_alloc_index(dname)) + " ... " + + repr(var.get_last_rank_alloc_index(dname))) elif dname in soln.get_misc_dim_names() : print(" '" + dname + "' allowed index range: " + - repr(grid.get_first_misc_index(dname)) + " ... " + - repr(grid.get_last_misc_index(dname))) + repr(var.get_first_misc_index(dname)) + " ... " + + repr(var.get_last_misc_index(dname))) - # Init the grids. - for grid in soln.get_grids() : + # Init the vars. + for var in soln.get_vars() : # Init all values including padding. - grid.set_all_elements_same(-9.0) + var.set_all_elements_same(-9.0) - # Done with fixed-sized grids. - if grid.is_fixed_size(): + # Done with fixed-sized vars. + if var.is_fixed_size(): continue # Init timestep 0 using NumPy. # This will set one point in each rank. - init_grid(grid, 0) - read_grid(grid, 0) + init_var(var, 0) + read_var(var, 0) # Simple one-index example. # Note that index relative to overall problem domain, @@ -270,7 +270,7 @@ def init_grid(grid, timestep) : first_indices = [] last_indices = [] - for dname in grid.get_dim_names() : + for dname in var.get_dim_names() : # Step dim? if dname == soln.get_step_dim_name() : @@ -298,21 +298,21 @@ def init_grid(grid, timestep) : # Add indices to set all allowed values. # (This isn't really meaningful; it's just illustrative.) - one_indices += [grid.get_first_misc_index(dname)] - first_indices += [grid.get_first_misc_index(dname)] - last_indices += [grid.get_last_misc_index(dname)] + one_indices += [var.get_first_misc_index(dname)] + first_indices += [var.get_first_misc_index(dname)] + last_indices += [var.get_last_misc_index(dname)] # Init value at one point. - nset = grid.set_element(15.0, one_indices) + nset = var.set_element(15.0, one_indices) print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) # Init the values within the small cube. - nset = grid.set_elements_in_slice_same(0.5, first_indices, last_indices) + nset = var.set_elements_in_slice_same(0.5, first_indices, last_indices) print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) - # Print the initial contents of the grid at timesteps 0 and 1. - read_grid(grid, 0) - read_grid(grid, 1) + # Print the initial contents of the var at timesteps 0 and 1. + read_var(var, 0) + read_var(var, 1) # Apply the stencil solution to the data. env.global_barrier() @@ -320,15 +320,15 @@ def init_grid(grid, timestep) : soln.run_solution(0) # Print result at timestep 1. - for grid in soln.get_grids() : - read_grid(grid, 1) + for var in soln.get_vars() : + read_var(var, 1) print("Running the solution for 10 more steps...") soln.run_solution(1, 10) # Print final result at timestep 11, assuming update was to t+1. - for grid in soln.get_grids() : - read_grid(grid, 11) + for var in soln.get_vars() : + read_var(var, 11) print("Debug output captured:\n" + debug_output.get_string()) diff --git a/src/kernel/tests/yask_kernel_api_test.cpp b/src/kernel/tests/yask_kernel_api_test.cpp index 087a51b8..22c0ab72 100644 --- a/src/kernel/tests/yask_kernel_api_test.cpp +++ b/src/kernel/tests/yask_kernel_api_test.cpp @@ -73,7 +73,7 @@ int main() { // Set domain size in each dim. soln->set_overall_domain_size(dim_name, 128); - // Ensure some minimal padding on all grids. + // Ensure some minimal padding on all vars. soln->set_min_pad_size(dim_name, 1); // Set block size to 64 in z dim and 32 in other dims. @@ -84,15 +84,15 @@ int main() { soln->set_block_size(dim_name, 32); } - // Make a test fixed-size grid. - auto fgrid_dims = soln_dims; - fgrid_dims.push_back("misc1"); - vector fgrid_sizes; - for (auto dim_name : fgrid_dims) - fgrid_sizes.push_back(5); - auto fgrid = soln->new_fixed_size_grid("fgrid", fgrid_dims, fgrid_sizes); + // Make a test fixed-size var. + auto fvar_dims = soln_dims; + fvar_dims.push_back("misc1"); + vector fvar_sizes; + for (auto dim_name : fvar_dims) + fvar_sizes.push_back(5); + auto fvar = soln->new_fixed_size_var("fvar", fvar_dims, fvar_sizes); - // Allocate memory for any grids that do not have storage set. + // Allocate memory for any vars that do not have storage set. // Set other data structures needed for stencil application. soln->prepare_solution(); @@ -108,52 +108,52 @@ int main() { } os << endl; - // Print out some info about the grids and init their data. - for (auto grid : soln->get_grids()) { - os << " grid-var '" << grid->get_name() << ":\n"; - for (auto dname : grid->get_dim_names()) { + // Print out some info about the vars and init their data. + for (auto var : soln->get_vars()) { + os << " var '" << var->get_name() << ":\n"; + for (auto dname : var->get_dim_names()) { os << " '" << dname << "' dim:\n"; os << " alloc-size on this rank: " << - grid->get_alloc_size(dname) << endl; + var->get_alloc_size(dname) << endl; // Is this a domain dim? if (domain_dim_set.count(dname)) { os << " domain index range on this rank: " << - grid->get_first_rank_domain_index(dname) << " ... " << - grid->get_last_rank_domain_index(dname) << endl; + var->get_first_rank_domain_index(dname) << " ... " << + var->get_last_rank_domain_index(dname) << endl; os << " domain+halo index range on this rank: " << - grid->get_first_rank_halo_index(dname) << " ... " << - grid->get_last_rank_halo_index(dname) << endl; + var->get_first_rank_halo_index(dname) << " ... " << + var->get_last_rank_halo_index(dname) << endl; os << " allowed index range on this rank: " << - grid->get_first_rank_alloc_index(dname) << " ... " << - grid->get_last_rank_alloc_index(dname) << endl; + var->get_first_rank_alloc_index(dname) << " ... " << + var->get_last_rank_alloc_index(dname) << endl; } // Step dim? else if (dname == soln->get_step_dim_name()) { os << " currently-valid step index range: " << - grid->get_first_valid_step_index() << " ... " << - grid->get_last_valid_step_index() << endl; + var->get_first_valid_step_index() << " ... " << + var->get_last_valid_step_index() << endl; } // Misc dim? else { os << " misc index range: " << - grid->get_first_misc_index(dname) << " ... " << - grid->get_last_misc_index(dname) << endl; + var->get_first_misc_index(dname) << " ... " << + var->get_last_misc_index(dname) << endl; } } // First, just init all the elements to the same value. - grid->set_all_elements_same(0.5); + var->set_all_elements_same(0.5); - // Done with fixed-size grids. - if (grid->is_fixed_size()) + // Done with fixed-size vars. + if (var->is_fixed_size()) continue; // Create indices describing a subset of the overall domain. vector first_indices, last_indices; - for (auto dname : grid->get_dim_names()) { + for (auto dname : var->get_dim_names()) { idx_t first_idx = 0, last_idx = 0; // Is this a domain dim? @@ -171,18 +171,18 @@ int main() { else if (dname == soln->get_step_dim_name()) { // Set indices for valid time-steps. - first_idx = grid->get_first_valid_step_index(); - last_idx = grid->get_last_valid_step_index(); - assert(last_idx - first_idx + 1 == grid->get_alloc_size(dname)); + first_idx = var->get_first_valid_step_index(); + last_idx = var->get_last_valid_step_index(); + assert(last_idx - first_idx + 1 == var->get_alloc_size(dname)); } // Misc dim? else { // Set indices to set all allowed values. - first_idx = grid->get_first_misc_index(dname); - last_idx = grid->get_last_misc_index(dname); - assert(last_idx - first_idx + 1 == grid->get_alloc_size(dname)); + first_idx = var->get_first_misc_index(dname); + last_idx = var->get_last_misc_index(dname); + assert(last_idx - first_idx + 1 == var->get_alloc_size(dname)); } // Add indices to index vectors. @@ -193,19 +193,19 @@ int main() { // Init the values using the indices created above. double val = 2.0; bool strict_indices = false; // because first/last_indices are global. - idx_t nset = grid->set_elements_in_slice_same(val, first_indices, last_indices, strict_indices); + idx_t nset = var->set_elements_in_slice_same(val, first_indices, last_indices, strict_indices); os << " " << nset << " element(s) set in sub-range from " << - grid->format_indices(first_indices) << " to " << - grid->format_indices(last_indices) << ".\n"; - if (grid->are_indices_local(first_indices)) { - auto val2 = grid->get_element(first_indices); + var->format_indices(first_indices) << " to " << + var->format_indices(last_indices) << ".\n"; + if (var->are_indices_local(first_indices)) { + auto val2 = var->get_element(first_indices); os << " first element == " << val2 << ".\n"; assert(val2 == val); } else os << " first element NOT in rank.\n"; - if (grid->are_indices_local(last_indices)) { - auto val2 = grid->get_element(last_indices); + if (var->are_indices_local(last_indices)) { + auto val2 = var->get_element(last_indices); os << " last element == " << val2 << ".\n"; assert(val2 == val); } @@ -213,24 +213,24 @@ int main() { os << " last element NOT in rank.\n"; // Add to a couple of values if they're in this rank. - nset = grid->add_to_element(1.0, first_indices); - nset += grid->add_to_element(3.0, last_indices); + nset = var->add_to_element(1.0, first_indices); + nset += var->add_to_element(3.0, last_indices); os << " " << nset << " element(s) updated.\n"; - if (grid->are_indices_local(first_indices)) { - auto val2 = grid->get_element(first_indices); + if (var->are_indices_local(first_indices)) { + auto val2 = var->get_element(first_indices); os << " first element == " << val2 << ".\n"; assert(val2 == val + 1.0); } - if (grid->are_indices_local(last_indices)) { - auto val2 = grid->get_element(last_indices); + if (var->are_indices_local(last_indices)) { + auto val2 = var->get_element(last_indices); os << " last element == " << val2 << ".\n"; assert(val2 == val + 3.0); } - // Raw access to this grid. - auto raw_p = grid->get_raw_storage_buffer(); - auto num_elems = grid->get_num_storage_elements(); - os << " " << grid->get_num_storage_bytes() << + // Raw access to this var. + auto raw_p = var->get_raw_storage_buffer(); + auto num_elems = var->get_num_storage_elements(); + os << " " << var->get_num_storage_bytes() << " bytes of raw data at " << raw_p << ": "; if (soln->get_element_bytes() == 4) os << ((float*)raw_p)[0] << ", ..., " << ((float*)raw_p)[num_elems-1] << "\n"; diff --git a/src/kernel/tests/yask_kernel_api_test.py b/src/kernel/tests/yask_kernel_api_test.py index dcb57d85..efc7a7ff 100755 --- a/src/kernel/tests/yask_kernel_api_test.py +++ b/src/kernel/tests/yask_kernel_api_test.py @@ -30,8 +30,8 @@ import argparse import yask_kernel as yk -# Prepare an NymPy ndarray to hold a slice of 'grid'. -def make_ndarray(grid, timestep) : +# Prepare an NymPy ndarray to hold a slice of 'var'. +def make_ndarray(var, timestep) : # Create indices for YASK and shape for NumPy. first_indices = [] @@ -39,7 +39,7 @@ def make_ndarray(grid, timestep) : shape = [] point = () nelems = 1 - for dname in grid.get_dim_names() : + for dname in var.get_dim_names() : if dname == soln.get_step_dim_name() : @@ -51,15 +51,15 @@ def make_ndarray(grid, timestep) : elif dname in soln.get_domain_dim_names() : # Cover full alloc in this rank. - first_idx = grid.get_first_rank_alloc_index(dname) - last_idx = grid.get_last_rank_alloc_index(dname) + first_idx = var.get_first_rank_alloc_index(dname) + last_idx = var.get_last_rank_alloc_index(dname) # Misc dim? else : # Cover all misc values. - first_idx = grid.get_first_misc_index(dname) - last_idx = grid.get_last_misc_index(dname) + first_idx = var.get_first_misc_index(dname) + last_idx = var.get_last_misc_index(dname) # Add indices to API vars. first_indices += [first_idx] @@ -77,59 +77,59 @@ def make_ndarray(grid, timestep) : ndarray = np.zeros(shape, dtype, 'C'); return ndarray, first_indices, last_indices, point -# Read data from grid using NumPy ndarray. -def read_grid(grid, timestep) : +# Read data from var using NumPy ndarray. +def read_var(var, timestep) : - # Ignore with fixed-sized grids. - if grid.is_fixed_size(): + # Ignore with fixed-sized vars. + if var.is_fixed_size(): return - print("Testing reading grid '" + grid.get_name() + "' at time " + repr(timestep) + "...") - ndarray, first_indices, last_indices, point = make_ndarray(grid, timestep) + print("Testing reading var '" + var.get_name() + "' at time " + repr(timestep) + "...") + ndarray, first_indices, last_indices, point = make_ndarray(var, timestep) print("Reading 1 element...") - val1 = grid.get_element(first_indices) + val1 = var.get_element(first_indices) print("Read value " + repr(val1)) print("Reading all element(s) in ndarray...") - nread = grid.get_elements_in_slice(ndarray.data, first_indices, last_indices) + nread = var.get_elements_in_slice(ndarray.data, first_indices, last_indices) print(ndarray) - # Raw access to this grid. + # Raw access to this var. if soln.get_element_bytes() == 4 : ptype = ct.POINTER(ct.c_float) else : ptype = ct.POINTER(ct.c_double) - raw_ptr = grid.get_raw_storage_buffer() + raw_ptr = var.get_raw_storage_buffer() fp_ptr = ct.cast(int(raw_ptr), ptype) - num_elems = grid.get_num_storage_elements() + num_elems = var.get_num_storage_elements() print("Raw data: " + repr(fp_ptr[0]) + ", ..., " + repr(fp_ptr[num_elems-1])) -# Init grid using NumPy ndarray. -def init_grid(grid, timestep) : - print("Initializing grid '" + grid.get_name() + "' at time " + repr(timestep) + "...") - ndarray, first_indices, last_indices, point = make_ndarray(grid, timestep) +# Init var using NumPy ndarray. +def init_var(var, timestep) : + print("Initializing var '" + var.get_name() + "' at time " + repr(timestep) + "...") + ndarray, first_indices, last_indices, point = make_ndarray(var, timestep) # Set one point to a non-zero value. val1 = 21.0 ndarray[point] = val1 print(ndarray) - print("Setting grid from all element(s) in ndarray...") - nset = grid.set_elements_in_slice(ndarray.data, first_indices, last_indices) + print("Setting var from all element(s) in ndarray...") + nset = var.set_elements_in_slice(ndarray.data, first_indices, last_indices) print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) # Check that set worked. print("Reading those element(s)...") - val2 = grid.get_element(first_indices) + val2 = var.get_element(first_indices) assert val2 == val1 - val2 = grid.get_element(last_indices) + val2 = var.get_element(last_indices) if nset > 1 : assert val2 == 0.0 else : assert val2 == val1 # Only 1 val => first == last. ndarray2 = ndarray ndarray2.fill(5.0) - nread = grid.get_elements_in_slice(ndarray2.data, first_indices, last_indices) + nread = var.get_elements_in_slice(ndarray2.data, first_indices, last_indices) assert nread == ndarray2.size assert ndarray2[point] == val1 assert ndarray2.sum() == val1 # One point is val1; others are zero. @@ -137,17 +137,17 @@ def init_grid(grid, timestep) : # Test element set. print("Testing setting 1 point at " + repr(last_indices) + "...") val1 += 1.0 - nset = grid.set_element(val1, last_indices); + nset = var.set_element(val1, last_indices); assert nset == 1 - val2 = grid.get_element(last_indices) + val2 = var.get_element(last_indices) assert val2 == val1 # Test add. val3 = 2.0 print("Testing adding to 1 point at " + repr(last_indices) + "...") - nset = grid.add_to_element(val3, last_indices); + nset = var.add_to_element(val3, last_indices); assert nset == 1 - val2 = grid.get_element(last_indices) + val2 = var.get_element(last_indices) assert val2 == val1 + val3 # Main script. @@ -166,7 +166,7 @@ def init_grid(grid, timestep) : soln.set_debug_output(debug_output) name = soln.get_name() - # NB: At this point, the grids' meta-data exists, but the grids have no + # NB: At this point, the vars' meta-data exists, but the vars have no # data allocated. We need to set the size of the domain before # allocating data. @@ -184,7 +184,7 @@ def init_grid(grid, timestep) : # Set domain size in each dim. soln.set_overall_domain_size(dim_name, 128) - # Ensure some minimal padding on all grids. + # Ensure some minimal padding on all vars. soln.set_min_pad_size(dim_name, 1) # Set block size to 64 in z dim and 32 in other dims. @@ -194,15 +194,15 @@ def init_grid(grid, timestep) : else : soln.set_block_size(dim_name, 32) - # Make a test fixed-size grid and set its NUMA preference. - fgrid_sizes = () + # Make a test fixed-size var and set its NUMA preference. + fvar_sizes = () for dim_name in soln_dims : - fgrid_sizes += (5,) - fgrid = soln.new_fixed_size_grid("fgrid", soln_dims, fgrid_sizes) - fgrid.set_numa_preferred(yk.cvar.yask_numa_local) - fgrid.alloc_storage() + fvar_sizes += (5,) + fvar = soln.new_fixed_size_var("fvar", soln_dims, fvar_sizes) + fvar.set_numa_preferred(yk.cvar.yask_numa_local) + fvar.alloc_storage() - # Allocate memory for any grids that do not have storage set. + # Allocate memory for any vars that do not have storage set. # Set other data structures needed for stencil application. soln.prepare_solution() @@ -210,38 +210,38 @@ def init_grid(grid, timestep) : print("Stencil-solution '" + name + "':") print(" Step dimension: " + repr(soln.get_step_dim_name())) print(" Domain dimensions: " + repr(soln.get_domain_dim_names())) - print(" Grids:") - for grid in soln.get_grids() : - print(" " + grid.get_name() + repr(grid.get_dim_names())) - for dname in grid.get_dim_names() : + print(" Vars:") + for var in soln.get_vars() : + print(" " + var.get_name() + repr(var.get_dim_names())) + for dname in var.get_dim_names() : if dname in soln.get_domain_dim_names() : print(" '" + dname + "' allowed domain index range in this rank: " + - repr(grid.get_first_rank_alloc_index(dname)) + " ... " + - repr(grid.get_last_rank_alloc_index(dname))) + repr(var.get_first_rank_alloc_index(dname)) + " ... " + + repr(var.get_last_rank_alloc_index(dname))) elif dname == soln.get_step_dim_name() : print(" '" + dname + "' allowed step index range: " + - repr(grid.get_first_valid_step_index()) + " ... " + - repr(grid.get_last_valid_step_index())) + repr(var.get_first_valid_step_index()) + " ... " + + repr(var.get_last_valid_step_index())) else : print(" '" + dname + "' allowed misc index range: " + - repr(grid.get_first_misc_index(dname)) + " ... " + - repr(grid.get_last_misc_index(dname))) + repr(var.get_first_misc_index(dname)) + " ... " + + repr(var.get_last_misc_index(dname))) - # Init the grids. - for grid in soln.get_grids() : + # Init the vars. + for var in soln.get_vars() : # Init all values including padding. - grid.set_all_elements_same(-9.0) + var.set_all_elements_same(-9.0) - # Done with fixed-sized grids. - if grid.is_fixed_size(): + # Done with fixed-sized vars. + if var.is_fixed_size(): continue # Init timestep 0 using NumPy. - init_grid(grid, 0) + init_var(var, 0) # Print out the values. - read_grid(grid, 0) + read_var(var, 0) # Simple one-index example. # Note that index relative to overall problem domain, @@ -259,7 +259,7 @@ def init_grid(grid, timestep) : first_indices = [] last_indices = [] - for dname in grid.get_dim_names() : + for dname in var.get_dim_names() : # Step dim? if dname == soln.get_step_dim_name() : @@ -287,20 +287,20 @@ def init_grid(grid, timestep) : # Add indices to set all allowed values. # (This isn't really meaningful; it's just illustrative.) - one_indices += [grid.get_first_misc_index(dname)] - first_indices += [grid.get_first_misc_index(dname)] - last_indices += [grid.get_last_misc_index(dname)] + one_indices += [var.get_first_misc_index(dname)] + first_indices += [var.get_first_misc_index(dname)] + last_indices += [var.get_last_misc_index(dname)] # Init value at one point. - nset = grid.set_element(15.0, one_indices) + nset = var.set_element(15.0, one_indices) print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) # Init the values within the small cube. - nset = grid.set_elements_in_slice_same(0.5, first_indices, last_indices, False) + nset = var.set_elements_in_slice_same(0.5, first_indices, last_indices, False) print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) - # Print the initial contents of the grid. - read_grid(grid, 0) + # Print the initial contents of the var. + read_var(var, 0) # Apply the stencil solution to the data. env.global_barrier() @@ -308,15 +308,15 @@ def init_grid(grid, timestep) : soln.run_solution(0) # Print result at timestep 1. - for grid in soln.get_grids() : - read_grid(grid, 1) + for var in soln.get_vars() : + read_var(var, 1) print("Running the solution for 10 more steps...") soln.run_solution(1, 10) # Print final result at timestep 11, assuming update was to t+1. - for grid in soln.get_grids() : - read_grid(grid, 11) + for var in soln.get_vars() : + read_var(var, 11) print("Debug output captured:\n" + debug_output.get_string()) print("End of YASK kernel API test.") diff --git a/src/kernel/yask_main.cpp b/src/kernel/yask_main.cpp index 535e2f5b..8850c915 100644 --- a/src/kernel/yask_main.cpp +++ b/src/kernel/yask_main.cpp @@ -114,7 +114,7 @@ struct AppSettings : public KernelSettings { doWarmup)); parser.add_option(new CommandLineParser::IntOption ("step_alloc", - "Number of steps to allocate in relevant grids, " + "Number of steps to allocate in relevant vars, " "overriding default value from YASK compiler.", step_alloc)); parser.add_option(new CommandLineParser::IntOption @@ -224,14 +224,14 @@ void alloc_steps(yk_solution_ptr soln, const AppSettings& opts) { if (opts.step_alloc <= 0) return; - // Find grids with steps. + // Find vars with steps. auto step_dim = soln->get_step_dim_name(); - auto grids = soln->get_grids(); - for (auto grid : grids) { - if (grid->is_dim_used(step_dim)) + auto vars = soln->get_vars(); + for (auto var : vars) { + if (var->is_dim_used(step_dim)) // override num steps. - grid->set_alloc_size(step_dim, opts.step_alloc); + var->set_alloc_size(step_dim, opts.step_alloc); } } @@ -292,7 +292,7 @@ int main(int argc, char** argv) if (context->rank_bb.bb_num_points < 1) THROW_YASK_EXCEPTION("Exiting because there are no points in the domain"); - // init data in grids and params. + // init data in vars and params. if (opts->doWarmup || !opts->validate) context->initData(); @@ -477,7 +477,7 @@ int main(int argc, char** argv) os << endl << divLine << "Setup for validation...\n"; - // Make a reference context for comparisons w/new grids. + // Make a reference context for comparisons w/new vars. auto ref_soln = kfac.new_solution(kenv, ksoln); auto ref_context = dynamic_pointer_cast(ref_soln); assert(ref_context.get()); @@ -491,7 +491,7 @@ int main(int argc, char** argv) ref_opts->_numa_pref = yask_numa_none; // TODO: re-enable the region and block settings below; - // requires allowing consistent init of different-sized grids + // requires allowing consistent init of different-sized vars // in kernel code. #if 0 auto sdim = ref_soln->get_step_dim_name(); diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp index db294a51..b633e618 100644 --- a/src/stencils/AwpElasticStencil.cpp +++ b/src/stencils/AwpElasticStencil.cpp @@ -24,15 +24,15 @@ IN THE SOFTWARE. *****************************************************************************/ // Stencil equations for AWP elastic* numerics. -// *This version does not contain the time-varying attenuation memory grids -// or the related attenuation constant grids. +// *This version does not contain the time-varying attenuation memory vars +// or the related attenuation constant vars. // This version also contains some experimental code for calculating the // free-surface boundary values. // http://hpgeoc.sdsc.edu/AWPODC // http://www.sdsc.edu/News%20Items/PR20160209_earthquake_center.html -// Set the following macro to use a sponge grid instead of 3 sponge arrays. -//#define FULL_SPONGE_GRID +// Set the following macro to use a sponge var instead of 3 sponge arrays. +//#define FULL_SPONGE_VAR // Set the following macro to define all points, even those above the // surface that are never used. @@ -41,8 +41,8 @@ IN THE SOFTWARE. // Set the following macro to calculate free-surface boundary values. #define DO_ABOVE_SURFACE -// Set the following macro to use intermediate scratch grids. -//#define USE_SCRATCH_GRIDS +// Set the following macro to use intermediate scratch vars. +//#define USE_SCRATCH_VARS // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. #include "yask_compiler_utility_api.hpp" @@ -59,32 +59,32 @@ class AwpElasticStencil : public yc_solution_base { yc_index_node_ptr y = new_domain_index("y"); // spatial dim. yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // Time-varying 3D-spatial velocity grids. - yc_grid_var vel_x = yc_grid_var("vel_x", get_soln(), { t, x, y, z }); - yc_grid_var vel_y = yc_grid_var("vel_y", get_soln(), { t, x, y, z }); - yc_grid_var vel_z = yc_grid_var("vel_z", get_soln(), { t, x, y, z }); + // Time-varying 3D-spatial velocity vars. + yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); + yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); + yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); - // Time-varying 3D-spatial Stress grids. - yc_grid_var stress_xx = yc_grid_var("stress_xx", get_soln(), { t, x, y, z }); - yc_grid_var stress_yy = yc_grid_var("stress_yy", get_soln(), { t, x, y, z }); - yc_grid_var stress_zz = yc_grid_var("stress_zz", get_soln(), { t, x, y, z }); - yc_grid_var stress_xy = yc_grid_var("stress_xy", get_soln(), { t, x, y, z }); - yc_grid_var stress_xz = yc_grid_var("stress_xz", get_soln(), { t, x, y, z }); - yc_grid_var stress_yz = yc_grid_var("stress_yz", get_soln(), { t, x, y, z }); + // Time-varying 3D-spatial Stress vars. + yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); // 3D-spatial Lame' coefficients. - yc_grid_var lambda = yc_grid_var("lambda", get_soln(), { x, y, z }); - yc_grid_var rho = yc_grid_var("rho", get_soln(), { x, y, z }); - yc_grid_var mu = yc_grid_var("mu", get_soln(), { x, y, z }); + yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); + yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); + yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); // Sponge coefficients. // (Most of these will be 1.0.) -#ifdef FULL_SPONGE_GRID - yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z }); +#ifdef FULL_SPONGE_VAR + yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); #else - yc_grid_var cr_x = yc_grid_var("cr_x", get_soln(), { x }); - yc_grid_var cr_y = yc_grid_var("cr_y", get_soln(), { y }); - yc_grid_var cr_z = yc_grid_var("cr_z", get_soln(), { z }); + yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); + yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); + yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); #endif // Spatial FD coefficients. @@ -92,8 +92,8 @@ class AwpElasticStencil : public yc_solution_base { const double c2 = -1.0/24.0; // Physical dimensions in time and space. - yc_grid_var delta_t = yc_grid_var("delta_t", get_soln(), { }); - yc_grid_var h = yc_grid_var("h", get_soln(), { }); + yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); + yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); // For the surface stress conditions, we need to write into 2 points // above the surface. Since we can only write into the "domain", we @@ -108,10 +108,10 @@ class AwpElasticStencil : public yc_solution_base { #define IF_ONE_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 1) #define IF_TWO_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 2) -#ifdef USE_SCRATCH_GRIDS - yc_grid_var tmp_vel_x = yc_grid_var("tmp_vel_x", get_soln(), { x, y, z }, true); - yc_grid_var tmp_vel_y = yc_grid_var("tmp_vel_y", get_soln(), { x, y, z }, true); - yc_grid_var tmp_vel_z = yc_grid_var("tmp_vel_z", get_soln(), { x, y, z }, true); +#ifdef USE_SCRATCH_VARS + yc_var_proxy tmp_vel_x = yc_var_proxy("tmp_vel_x", get_soln(), { x, y, z }, true); + yc_var_proxy tmp_vel_y = yc_var_proxy("tmp_vel_y", get_soln(), { x, y, z }, true); + yc_var_proxy tmp_vel_z = yc_var_proxy("tmp_vel_z", get_soln(), { x, y, z }, true); #endif public: @@ -122,17 +122,17 @@ class AwpElasticStencil : public yc_solution_base { // Adjustment for sponge layer. void adjust_for_sponge(yc_number_node_ptr& val) { -#ifdef FULL_SPONGE_GRID +#ifdef FULL_SPONGE_VAR val *= sponge(x, y, z); #else val *= cr_x(x) * cr_y(y) * cr_z(z); #endif } - // Velocity-grid define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress grids at t. Note that the t, - // x, y, z parameters are integer grid indices, not actual offsets in - // time or space, so half-steps due to staggered grids are adjusted + // Velocity-var define functions. For each D in x, y, z, define vel_D + // at t+1 based on vel_x at t and stress vars at t. Note that the t, + // x, y, z parameters are integer var indices, not actual offsets in + // time or space, so half-steps due to staggered vars are adjusted // appropriately. yc_number_node_ptr get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { @@ -197,13 +197,13 @@ class AwpElasticStencil : public yc_solution_base { // the surface itself will be at z - 1; auto surf = z - 1; -#ifdef USE_SCRATCH_GRIDS +#ifdef USE_SCRATCH_VARS // The values for velocity at t+1 will be needed // in multiple free-surface calculations. // Thus, it will reduce the number of FP ops // required if we pre-compute them and store them - // in scratch grids. + // in scratch vars. #define VEL_X tmp_vel_x #define VEL_Y tmp_vel_y #define VEL_Z tmp_vel_z @@ -213,7 +213,7 @@ class AwpElasticStencil : public yc_solution_base { #else - // If not using scratch grids, just call the + // If not using scratch vars, just call the // functions to calculate each value of velocity // at t+1 every time it's needed. #define VEL_X get_next_vel_x @@ -258,7 +258,7 @@ class AwpElasticStencil : public yc_solution_base { } // Compute average of 8 neighbors. - yc_number_node_ptr ave8(yc_grid_var& g, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + yc_number_node_ptr ave8(yc_var_proxy& g, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { return 8.0 / (g(x, y, z ) + g(x+1, y, z ) + @@ -284,12 +284,12 @@ class AwpElasticStencil : public yc_solution_base { c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); } - // Stress-grid define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel grids at t+1. - // This implies that the velocity-grid define functions must be called + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z - // parameters are integer grid indices, not actual offsets in time or - // space, so half-steps due to staggered grids are adjusted + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted // appropriately. yc_number_node_ptr get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { @@ -423,7 +423,7 @@ class AwpElasticStencil : public yc_solution_base { #endif } - // Define the t+1 values for all velocity and stress grids. + // Define the t+1 values for all velocity and stress vars. virtual void define() { // Define velocity components. @@ -463,5 +463,5 @@ class AwpElasticStencil : public yc_solution_base { static AwpElasticStencil AwpElasticStencil_instance; #undef DO_SURFACE -#undef FULL_SPONGE_GRID -#undef USE_SCRATCH_GRIDS +#undef FULL_SPONGE_VAR +#undef USE_SCRATCH_VARS diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index a7192296..728a1760 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -27,8 +27,8 @@ IN THE SOFTWARE. // http://hpgeoc.sdsc.edu/AWPODC // http://www.sdsc.edu/News%20Items/PR20160209_earthquake_center.html -// Set the following macro to use a sponge grid instead of 3 sponge arrays. -//#define FULL_SPONGE_GRID +// Set the following macro to use a sponge var instead of 3 sponge arrays. +//#define FULL_SPONGE_VAR // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. #include "yask_compiler_utility_api.hpp" @@ -45,49 +45,49 @@ class AwpStencil : public yc_solution_base { yc_index_node_ptr y = new_domain_index("y"); // spatial dim. yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // Time-varying 3D-spatial velocity grids. - yc_grid_var vel_x = yc_grid_var("vel_x", get_soln(), { t, x, y, z }); - yc_grid_var vel_y = yc_grid_var("vel_y", get_soln(), { t, x, y, z }); - yc_grid_var vel_z = yc_grid_var("vel_z", get_soln(), { t, x, y, z }); - - // Time-varying 3D-spatial Stress grids. - yc_grid_var stress_xx = yc_grid_var("stress_xx", get_soln(), { t, x, y, z }); - yc_grid_var stress_yy = yc_grid_var("stress_yy", get_soln(), { t, x, y, z }); - yc_grid_var stress_zz = yc_grid_var("stress_zz", get_soln(), { t, x, y, z }); - yc_grid_var stress_xy = yc_grid_var("stress_xy", get_soln(), { t, x, y, z }); - yc_grid_var stress_xz = yc_grid_var("stress_xz", get_soln(), { t, x, y, z }); - yc_grid_var stress_yz = yc_grid_var("stress_yz", get_soln(), { t, x, y, z }); - - // Time-varying attenuation memory grids. - yc_grid_var stress_mem_xx = yc_grid_var("stress_mem_xx", get_soln(), { t, x, y, z }); - yc_grid_var stress_mem_yy = yc_grid_var("stress_mem_yy", get_soln(), { t, x, y, z }); - yc_grid_var stress_mem_zz = yc_grid_var("stress_mem_zz", get_soln(), { t, x, y, z }); - yc_grid_var stress_mem_xy = yc_grid_var("stress_mem_xy", get_soln(), { t, x, y, z }); - yc_grid_var stress_mem_xz = yc_grid_var("stress_mem_xz", get_soln(), { t, x, y, z }); - yc_grid_var stress_mem_yz = yc_grid_var("stress_mem_yz", get_soln(), { t, x, y, z }); - - // 3D grids used for anelastic attenuation - yc_grid_var weight = yc_grid_var("weight", get_soln(), { x, y, z }); - yc_grid_var tau2 = yc_grid_var("tau2", get_soln(), { x, y, z }); - yc_grid_var anelastic_ap = yc_grid_var("anelastic_ap", get_soln(), { x, y, z }); - yc_grid_var anelastic_as_diag = yc_grid_var("anelastic_as_diag", get_soln(), { x, y, z }); - yc_grid_var anelastic_xy = yc_grid_var("anelastic_xy", get_soln(), { x, y, z }); - yc_grid_var anelastic_xz = yc_grid_var("anelastic_xz", get_soln(), { x, y, z }); - yc_grid_var anelastic_yz = yc_grid_var("anelastic_yz", get_soln(), { x, y, z }); + // Time-varying 3D-spatial velocity vars. + yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); + yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); + yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); + + // Time-varying 3D-spatial Stress vars. + yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); + + // Time-varying attenuation memory vars. + yc_var_proxy stress_mem_xx = yc_var_proxy("stress_mem_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_yy = yc_var_proxy("stress_mem_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_zz = yc_var_proxy("stress_mem_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_xy = yc_var_proxy("stress_mem_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_xz = yc_var_proxy("stress_mem_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_yz = yc_var_proxy("stress_mem_yz", get_soln(), { t, x, y, z }); + + // 3D vars used for anelastic attenuation + yc_var_proxy weight = yc_var_proxy("weight", get_soln(), { x, y, z }); + yc_var_proxy tau2 = yc_var_proxy("tau2", get_soln(), { x, y, z }); + yc_var_proxy anelastic_ap = yc_var_proxy("anelastic_ap", get_soln(), { x, y, z }); + yc_var_proxy anelastic_as_diag = yc_var_proxy("anelastic_as_diag", get_soln(), { x, y, z }); + yc_var_proxy anelastic_xy = yc_var_proxy("anelastic_xy", get_soln(), { x, y, z }); + yc_var_proxy anelastic_xz = yc_var_proxy("anelastic_xz", get_soln(), { x, y, z }); + yc_var_proxy anelastic_yz = yc_var_proxy("anelastic_yz", get_soln(), { x, y, z }); // 3D-spatial Lame' coefficients. - yc_grid_var lambda = yc_grid_var("lambda", get_soln(), { x, y, z }); - yc_grid_var rho = yc_grid_var("rho", get_soln(), { x, y, z }); - yc_grid_var mu = yc_grid_var("mu", get_soln(), { x, y, z }); + yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); + yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); + yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); // Sponge coefficients. // (Most of these will be 1.0.) -#ifdef FULL_SPONGE_GRID - yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z }); +#ifdef FULL_SPONGE_VAR + yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); #else - yc_grid_var cr_x = yc_grid_var("cr_x", get_soln(), { x }); - yc_grid_var cr_y = yc_grid_var("cr_y", get_soln(), { y }); - yc_grid_var cr_z = yc_grid_var("cr_z", get_soln(), { z }); + yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); + yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); + yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); #endif // Spatial FD coefficients. @@ -95,8 +95,8 @@ class AwpStencil : public yc_solution_base { const double c2 = -1.0/24.0; // Physical dimensions in time and space. - yc_grid_var delta_t = yc_grid_var("delta_t", get_soln(), { }); - yc_grid_var h = yc_grid_var("h", get_soln(), { }); + yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); + yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); public: @@ -106,17 +106,17 @@ class AwpStencil : public yc_solution_base { // Adjustment for sponge layer. void adjust_for_sponge(yc_number_node_ptr& val) { -#ifdef FULL_SPONGE_GRID +#ifdef FULL_SPONGE_VAR val *= sponge(x, y, z); #else val *= cr_x(x) * cr_y(y) * cr_z(z); #endif } - // Velocity-grid define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress grids at t. Note that the t, - // x, y, z parameters are integer grid indices, not actual offsets in - // time or space, so half-steps due to staggered grids are adjusted + // Velocity-var define functions. For each D in x, y, z, define vel_D + // at t+1 based on vel_x at t and stress vars at t. Note that the t, + // x, y, z parameters are integer var indices, not actual offsets in + // time or space, so half-steps due to staggered vars are adjusted // appropriately. void define_vel_x() { @@ -174,12 +174,12 @@ class AwpStencil : public yc_solution_base { vel_z(t+1, x, y, z) EQUALS next_vel_z; } - // Stress-grid define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel grids at t+1. - // This implies that the velocity-grid define functions must be called + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z - // parameters are integer grid indices, not actual offsets in time or - // space, so half-steps due to staggered grids are adjusted + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted // appropriately. void define_stress_xx(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index 4605ec5f..ddb57353 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -30,12 +30,12 @@ IN THE SOFTWARE. #include "ElasticStencil.hpp" // This class extends ElasticStencilBase to provide methods to make -// stencils with merged grids. +// stencils with merged vars. class Elastic2StencilBase : public ElasticStencilBase { protected: - // yc_grid_var selectors. + // yc_var_proxy selectors. yc_index_node_ptr vidx = new_misc_index("vidx"); yc_index_node_ptr sidx = new_misc_index("sidx"); yc_index_node_ptr cidx = new_misc_index("cidx"); @@ -46,7 +46,7 @@ class Elastic2StencilBase : public ElasticStencilBase { ElasticStencilBase(name, _bc) { } yc_number_node_ptr stencil_O8_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const int offset) + yc_var_proxy &g, yc_number_any_arg gidx, const int offset) { return (c0_8 * (g(t,x,y,z +offset, gidx) - @@ -60,19 +60,19 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const Z, const B) + yc_var_proxy &g, yc_number_any_arg gidx, const Z, const B) { return stencil_O8_Z(t, x, y, z, g, gidx, 0); } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const Z, const F) + yc_var_proxy &g, yc_number_any_arg gidx, const Z, const F) { return stencil_O8_Z(t, x, y, z, g, gidx, 1); } yc_number_node_ptr stencil_O8_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const int offset) + yc_var_proxy &g, yc_number_any_arg gidx, const int offset) { return (c0_8 * (g(t,x,y +offset,z, gidx) - @@ -86,18 +86,18 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const Y, const B) + yc_var_proxy &g, yc_number_any_arg gidx, const Y, const B) { return stencil_O8_Y(t, x, y, z, g, gidx, 0); } - yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_grid_var &g, yc_number_any_arg gidx, const Y, const F) + yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, yc_var_proxy &g, yc_number_any_arg gidx, const Y, const F) { return stencil_O8_Y(t, x, y, z, g, gidx, 1); } yc_number_node_ptr stencil_O8_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const int offset) + yc_var_proxy &g, yc_number_any_arg gidx, const int offset) { return (c0_8 * (g(t,x +offset,y,z, gidx) - @@ -111,13 +111,13 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const X, const B) + yc_var_proxy &g, yc_number_any_arg gidx, const X, const B) { return stencil_O8_X(t, x, y, z, g, gidx, 0); } yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, + yc_var_proxy &g, yc_number_any_arg gidx, const X, const F) { return stencil_O8_X(t, x, y, z, g, gidx, 1); @@ -125,21 +125,21 @@ class Elastic2StencilBase : public ElasticStencilBase { template yc_number_node_ptr stencil_O8(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx) + yc_var_proxy &g, yc_number_any_arg gidx) { return stencil_O8(t, x, y, z, g, gidx, Dim(), Dir()); } - // Velocity-grid define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress grids at t. Note that the t, - // x, y, z parameters are integer grid indices, not actual offsets in - // time or space, so half-steps due to staggered grids are adjusted + // Velocity-var define functions. For each D in x, y, z, define vel_D + // at t+1 based on vel_x at t and stress vars at t. Note that the t, + // x, y, z parameters are integer var indices, not actual offsets in + // time or space, so half-steps due to staggered vars are adjusted // appropriately. template void define_vel(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var& v, yc_number_any_arg vidx, - yc_grid_var& s, yc_number_any_arg sx_idx, yc_number_any_arg sy_idx, yc_number_any_arg sz_idx) { + yc_var_proxy& v, yc_number_any_arg vidx, + yc_var_proxy& s, yc_number_any_arg sx_idx, yc_number_any_arg sy_idx, yc_number_any_arg sz_idx) { yc_number_node_ptr lrho = interp_rho(x, y, z); @@ -158,7 +158,7 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const int offset) + yc_var_proxy &g, yc_number_any_arg gidx, const int offset) { return (g(t,x,y,z, gidx) - @@ -166,26 +166,26 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const B) + yc_var_proxy &g, yc_number_any_arg gidx, const B) { return stencil_O2_Z(t, x, y, z, g, gidx, -1); } yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const F) + yc_var_proxy &g, yc_number_any_arg gidx, const F) { return stencil_O2_Z(t, x, y, z, g, gidx, 1); } template yc_number_node_ptr stencil_O2_Z(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx) + yc_var_proxy &g, yc_number_any_arg gidx) { return stencil_O2_Z(t, x, y, z, g, gidx, D()); } yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const int offset) + yc_var_proxy &g, yc_number_any_arg gidx, const int offset) { return (g(t,x,y ,z, gidx) - @@ -193,26 +193,26 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const B) + yc_var_proxy &g, yc_number_any_arg gidx, const B) { return stencil_O2_Y(t, x, y, z, g, gidx,-1); } yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const F) + yc_var_proxy &g, yc_number_any_arg gidx, const F) { return stencil_O2_Y(t, x, y, z, g, gidx, 1); } template yc_number_node_ptr stencil_O2_Y(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx) + yc_var_proxy &g, yc_number_any_arg gidx) { return stencil_O2_Y(t, x, y, z, g, gidx, D()); } yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const int offset) + yc_var_proxy &g, yc_number_any_arg gidx, const int offset) { return (g(t,x ,y,z, gidx) - @@ -220,20 +220,20 @@ class Elastic2StencilBase : public ElasticStencilBase { } yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const B) + yc_var_proxy &g, yc_number_any_arg gidx, const B) { return stencil_O2_X(t, x, y, z, g, gidx,-1); } yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx, const F) + yc_var_proxy &g, yc_number_any_arg gidx, const F) { return stencil_O2_X(t, x, y, z, g, gidx, 1); } template yc_number_node_ptr stencil_O2_X(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, yc_number_any_arg gidx) + yc_var_proxy &g, yc_number_any_arg gidx) { return stencil_O2_X(t, x, y, z, g, gidx, D()); } diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index 0bc2a22d..9e85a359 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -82,7 +82,7 @@ class ElasticStencilBase : public yc_solution_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // 3D-spatial coefficients. - yc_grid_var rho = yc_grid_var("rho", get_soln(), { x, y, z }); + yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); // Spatial FD coefficients. const double c0_8 = 1.2; @@ -166,7 +166,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const int offset ) { return @@ -184,7 +184,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const Z, const B ) { return stencil_O8_Z( t, x, y, z, g, 0 ); @@ -194,7 +194,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const Z, const F ) { return stencil_O8_Z( t, x, y, z, g, 1 ); @@ -204,7 +204,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const int offset ) { return @@ -222,7 +222,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const Y, const B ) { return stencil_O8_Y( t, x, y, z, g, 0 ); @@ -232,7 +232,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const Y, const F ) { return stencil_O8_Y( t, x, y, z, g, 1 ); @@ -242,7 +242,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const int offset ) { return @@ -260,7 +260,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const X, const B ) { return stencil_O8_X( t, x, y, z, g, 0 ); @@ -270,7 +270,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const X, const F ) { return stencil_O8_X( t, x, y, z, g, 1 ); @@ -282,15 +282,15 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g ) + yc_var_proxy &g ) { return stencil_O8( t, x, y, z, g, Dim(), Dir() ); } - // Velocity-grid define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress grids at t. Note that the t, - // x, y, z parameters are integer grid indices, not actual offsets in - // time or space, so half-steps due to staggered grids are adjusted + // Velocity-var define functions. For each D in x, y, z, define vel_D + // at t+1 based on vel_x at t and stress vars at t. Note that the t, + // x, y, z parameters are integer var indices, not actual offsets in + // time or space, so half-steps due to staggered vars are adjusted // appropriately. template @@ -298,10 +298,10 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &v, - yc_grid_var &sx, - yc_grid_var &sy, - yc_grid_var &sz) { + yc_var_proxy &v, + yc_var_proxy &sx, + yc_var_proxy &sy, + yc_var_proxy &sz) { auto lrho = interp_rho( x, y, z ); @@ -323,7 +323,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const int offset ) { return @@ -335,7 +335,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const B ) { return stencil_O2_Z( t, x, y, z, g,-1 ); @@ -345,7 +345,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const F ) { return stencil_O2_Z( t, x, y, z, g, 1 ); @@ -356,7 +356,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g ) + yc_var_proxy &g ) { return stencil_O2_Z( t, x, y, z, g, D() ); } @@ -365,7 +365,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const int offset ) { return @@ -377,7 +377,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const B ) { return stencil_O2_Y( t, x, y, z, g,-1 ); @@ -387,7 +387,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const F ) { return stencil_O2_Y( t, x, y, z, g, 1 ); @@ -398,7 +398,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g ) + yc_var_proxy &g ) { return stencil_O2_Y( t, x, y, z, g, D() ); } @@ -407,7 +407,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const int offset ) { return @@ -419,7 +419,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const B ) { return stencil_O2_X( t, x, y, z, g,-1 ); @@ -429,7 +429,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g, + yc_var_proxy &g, const F ) { return stencil_O2_X( t, x, y, z, g, 1 ); @@ -441,7 +441,7 @@ class ElasticStencilBase : public yc_solution_base { yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &g ) + yc_var_proxy &g ) { return stencil_O2_X( t, x, y, z, g, D() ); } diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index 4477d12c..ec8b75fe 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -25,8 +25,8 @@ IN THE SOFTWARE. // Stencil equations for FSG elastic numerics. // Contributed by Albert Farres from the Barcelona Supercomputing Center. -// This version varies from the original by grouping related grids into -// larger grids with an added dimension. +// This version varies from the original by grouping related vars into +// larger vars with an added dimension. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. #include "yask_compiler_utility_api.hpp" @@ -54,21 +54,21 @@ namespace fsg { protected: - // Velocity and stress grids. - yc_grid_var v = yc_grid_var("v", get_soln(), { t, x, y, z, vidx }); + // Velocity and stress vars. + yc_var_proxy v = yc_var_proxy("v", get_soln(), { t, x, y, z, vidx }); enum VIDX { V_BL_U, V_BL_V, V_BL_W, V_BR_U, V_BR_V, V_BR_W, V_TL_U, V_TL_V, V_TL_W, V_TR_U, V_TR_V, V_TR_W }; - yc_grid_var s = yc_grid_var("s", get_soln(), { t, x, y, z, sidx }); + yc_var_proxy s = yc_var_proxy("s", get_soln(), { t, x, y, z, sidx }); enum SIDX { S_BL_XX, S_BL_YY, S_BL_ZZ, S_BL_YZ, S_BL_XZ, S_BL_XY, S_BR_XX, S_BR_YY, S_BR_ZZ, S_BR_YZ, S_BR_XZ, S_BR_XY, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TL_YZ, S_TL_XZ, S_TL_XY, S_TR_XX, S_TR_YY, S_TR_ZZ, S_TR_YZ, S_TR_XZ, S_TR_XY }; // 3D-spatial coefficients. - yc_grid_var c = yc_grid_var("c", get_soln(), { x, y, z, cidx }); + yc_var_proxy c = yc_var_proxy("c", get_soln(), { x, y, z, cidx }); enum CIDX { C11, C12, C13, C14, C15, C16, C22, C23, C24, C25, C26, C33, C34, C35, C36, @@ -86,7 +86,7 @@ namespace fsg { } yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const BR) + yc_var_proxy &c, yc_number_node_ptr cidx, const BR) { return 1.0 / (0.25*(c(x , y , z, cidx) + c(x , y+1, z, cidx) + @@ -94,7 +94,7 @@ namespace fsg { c(x , y+1, z+1, cidx))); } yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const BL) + yc_var_proxy &c, yc_number_node_ptr cidx, const BL) { return 1.0 / (0.25*(c(x , y , z, cidx) + c(x+1, y , z, cidx) + @@ -102,7 +102,7 @@ namespace fsg { c(x+1, y , z+1, cidx))); } yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const TR) + yc_var_proxy &c, yc_number_node_ptr cidx, const TR) { return 1.0 / (0.25*(c(x , y , z, cidx) + c(x , y+1, z, cidx) + @@ -110,19 +110,19 @@ namespace fsg { c(x+1, y+1, z, cidx))); } yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const TL) + yc_var_proxy &c, yc_number_node_ptr cidx, const TL) { return 1.0 / c(x , y , z, cidx); } template yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_any_arg cidx) + yc_var_proxy &c, yc_number_any_arg cidx) { return cell_coeff( x, y, z, c, cidx, N()); } yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const BR) + yc_var_proxy &c, yc_number_node_ptr cidx, const BR) { return 0.25 *( 1.0 / c(x , y , z, cidx) + 1.0 / c(x , y+1, z, cidx) + @@ -130,7 +130,7 @@ namespace fsg { 1.0 / c(x , y+1, z+1, cidx)); } yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const BL) + yc_var_proxy &c, yc_number_node_ptr cidx, const BL) { return 0.25 *( 1.0 / c(x , y , z, cidx) + 1.0 / c(x+1, y , z, cidx) + @@ -138,7 +138,7 @@ namespace fsg { 1.0 / c(x+1, y , z+1, cidx)); } yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const TR) + yc_var_proxy &c, yc_number_node_ptr cidx, const TR) { return 0.25 *( 1.0 / c(x , y , z, cidx) + 1.0 / c(x , y+1, z, cidx) + @@ -146,13 +146,13 @@ namespace fsg { 1.0 / c(x+1, y+1, z, cidx)); } yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_node_ptr cidx, const TL) + yc_var_proxy &c, yc_number_node_ptr cidx, const TL) { return 1.0 / c(x , y , z, cidx); } template yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, - yc_grid_var &c, yc_number_any_arg cidx) + yc_var_proxy &c, yc_number_any_arg cidx) { return cell_coeff_artm( x, y, z, c, cidx, N()); } @@ -172,12 +172,12 @@ namespace fsg { } // - // Stress-grid define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel grids at t+1. - // This implies that the velocity-grid define functions must be called + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z - // parameters are integer grid indices, not actual offsets in time or - // space, so half-steps due to staggered grids are adjusted + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted // appropriately. template @@ -301,7 +301,7 @@ namespace fsg { // Sponge coefficients. yc_index_node_ptr spidx = new_misc_index("spidx"); - yc_grid_var sponge = yc_grid_var("sponge", get_soln(), { x, y, z, spidx }); + yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z, spidx }); enum SPONGE_IDX { SPONGE_LX, SPONGE_RX, SPONGE_BZ, SPONGE_TZ, SPONGE_FY, SPONGE_BY, SPONGE_SQ_LX, SPONGE_SQ_RX, SPONGE_SQ_BZ, diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index 65584b40..1a9770b8 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -50,66 +50,66 @@ namespace fsg { protected: - yc_grid_var v_bl_u = yc_grid_var("v_bl_u", get_soln(), { t, x, y, z }); - yc_grid_var v_bl_v = yc_grid_var("v_bl_v", get_soln(), { t, x, y, z }); - yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_soln(), { t, x, y, z }); - yc_grid_var v_br_u = yc_grid_var("v_br_u", get_soln(), { t, x, y, z }); - yc_grid_var v_br_v = yc_grid_var("v_br_v", get_soln(), { t, x, y, z }); - yc_grid_var v_br_w = yc_grid_var("v_br_w", get_soln(), { t, x, y, z }); - yc_grid_var v_tl_u = yc_grid_var("v_tl_u", get_soln(), { t, x, y, z }); - yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_soln(), { t, x, y, z }); - yc_grid_var v_tl_w = yc_grid_var("v_tl_w", get_soln(), { t, x, y, z }); - yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_soln(), { t, x, y, z }); - yc_grid_var v_tr_v = yc_grid_var("v_tr_v", get_soln(), { t, x, y, z }); - yc_grid_var v_tr_w = yc_grid_var("v_tr_w", get_soln(), { t, x, y, z }); - - yc_grid_var s_bl_xx = yc_grid_var("s_bl_xx", get_soln(), { t, x, y, z }); - yc_grid_var s_bl_yy = yc_grid_var("s_bl_yy", get_soln(), { t, x, y, z }); - yc_grid_var s_bl_zz = yc_grid_var("s_bl_zz", get_soln(), { t, x, y, z }); - yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_soln(), { t, x, y, z }); - yc_grid_var s_bl_xz = yc_grid_var("s_bl_xz", get_soln(), { t, x, y, z }); - yc_grid_var s_bl_xy = yc_grid_var("s_bl_xy", get_soln(), { t, x, y, z }); - yc_grid_var s_br_xx = yc_grid_var("s_br_xx", get_soln(), { t, x, y, z }); - yc_grid_var s_br_yy = yc_grid_var("s_br_yy", get_soln(), { t, x, y, z }); - yc_grid_var s_br_zz = yc_grid_var("s_br_zz", get_soln(), { t, x, y, z }); - yc_grid_var s_br_yz = yc_grid_var("s_br_yz", get_soln(), { t, x, y, z }); - yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_soln(), { t, x, y, z }); - yc_grid_var s_br_xy = yc_grid_var("s_br_xy", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_yz = yc_grid_var("s_tl_yz", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_xz = yc_grid_var("s_tl_xz", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_xy = yc_grid_var("s_tl_xy", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_xx = yc_grid_var("s_tr_xx", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_yy = yc_grid_var("s_tr_yy", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_zz = yc_grid_var("s_tr_zz", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_yz = yc_grid_var("s_tr_yz", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_xz = yc_grid_var("s_tr_xz", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_soln(), { t, x, y, z }); + yc_var_proxy v_bl_u = yc_var_proxy("v_bl_u", get_soln(), { t, x, y, z }); + yc_var_proxy v_bl_v = yc_var_proxy("v_bl_v", get_soln(), { t, x, y, z }); + yc_var_proxy v_bl_w = yc_var_proxy("v_bl_w", get_soln(), { t, x, y, z }); + yc_var_proxy v_br_u = yc_var_proxy("v_br_u", get_soln(), { t, x, y, z }); + yc_var_proxy v_br_v = yc_var_proxy("v_br_v", get_soln(), { t, x, y, z }); + yc_var_proxy v_br_w = yc_var_proxy("v_br_w", get_soln(), { t, x, y, z }); + yc_var_proxy v_tl_u = yc_var_proxy("v_tl_u", get_soln(), { t, x, y, z }); + yc_var_proxy v_tl_v = yc_var_proxy("v_tl_v", get_soln(), { t, x, y, z }); + yc_var_proxy v_tl_w = yc_var_proxy("v_tl_w", get_soln(), { t, x, y, z }); + yc_var_proxy v_tr_u = yc_var_proxy("v_tr_u", get_soln(), { t, x, y, z }); + yc_var_proxy v_tr_v = yc_var_proxy("v_tr_v", get_soln(), { t, x, y, z }); + yc_var_proxy v_tr_w = yc_var_proxy("v_tr_w", get_soln(), { t, x, y, z }); + + yc_var_proxy s_bl_xx = yc_var_proxy("s_bl_xx", get_soln(), { t, x, y, z }); + yc_var_proxy s_bl_yy = yc_var_proxy("s_bl_yy", get_soln(), { t, x, y, z }); + yc_var_proxy s_bl_zz = yc_var_proxy("s_bl_zz", get_soln(), { t, x, y, z }); + yc_var_proxy s_bl_yz = yc_var_proxy("s_bl_yz", get_soln(), { t, x, y, z }); + yc_var_proxy s_bl_xz = yc_var_proxy("s_bl_xz", get_soln(), { t, x, y, z }); + yc_var_proxy s_bl_xy = yc_var_proxy("s_bl_xy", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_xx = yc_var_proxy("s_br_xx", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_yy = yc_var_proxy("s_br_yy", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_zz = yc_var_proxy("s_br_zz", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_yz = yc_var_proxy("s_br_yz", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_xz = yc_var_proxy("s_br_xz", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_xy = yc_var_proxy("s_br_xy", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_xx = yc_var_proxy("s_tl_xx", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_yy = yc_var_proxy("s_tl_yy", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_zz = yc_var_proxy("s_tl_zz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_yz = yc_var_proxy("s_tl_yz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_xz = yc_var_proxy("s_tl_xz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_xy = yc_var_proxy("s_tl_xy", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_xx = yc_var_proxy("s_tr_xx", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_yy = yc_var_proxy("s_tr_yy", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_zz = yc_var_proxy("s_tr_zz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_yz = yc_var_proxy("s_tr_yz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_xz = yc_var_proxy("s_tr_xz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_xy = yc_var_proxy("s_tr_xy", get_soln(), { t, x, y, z }); // 3D-spatial coefficients. - yc_grid_var c11 = yc_grid_var("c11", get_soln(), { x, y, z }); - yc_grid_var c12 = yc_grid_var("c12", get_soln(), { x, y, z }); - yc_grid_var c13 = yc_grid_var("c13", get_soln(), { x, y, z }); - yc_grid_var c14 = yc_grid_var("c14", get_soln(), { x, y, z }); - yc_grid_var c15 = yc_grid_var("c15", get_soln(), { x, y, z }); - yc_grid_var c16 = yc_grid_var("c16", get_soln(), { x, y, z }); - yc_grid_var c22 = yc_grid_var("c22", get_soln(), { x, y, z }); - yc_grid_var c23 = yc_grid_var("c23", get_soln(), { x, y, z }); - yc_grid_var c24 = yc_grid_var("c24", get_soln(), { x, y, z }); - yc_grid_var c25 = yc_grid_var("c25", get_soln(), { x, y, z }); - yc_grid_var c26 = yc_grid_var("c26", get_soln(), { x, y, z }); - yc_grid_var c33 = yc_grid_var("c33", get_soln(), { x, y, z }); - yc_grid_var c34 = yc_grid_var("c34", get_soln(), { x, y, z }); - yc_grid_var c35 = yc_grid_var("c35", get_soln(), { x, y, z }); - yc_grid_var c36 = yc_grid_var("c36", get_soln(), { x, y, z }); - yc_grid_var c44 = yc_grid_var("c44", get_soln(), { x, y, z }); - yc_grid_var c45 = yc_grid_var("c45", get_soln(), { x, y, z }); - yc_grid_var c46 = yc_grid_var("c46", get_soln(), { x, y, z }); - yc_grid_var c55 = yc_grid_var("c55", get_soln(), { x, y, z }); - yc_grid_var c56 = yc_grid_var("c56", get_soln(), { x, y, z }); - yc_grid_var c66 = yc_grid_var("c66", get_soln(), { x, y, z }); + yc_var_proxy c11 = yc_var_proxy("c11", get_soln(), { x, y, z }); + yc_var_proxy c12 = yc_var_proxy("c12", get_soln(), { x, y, z }); + yc_var_proxy c13 = yc_var_proxy("c13", get_soln(), { x, y, z }); + yc_var_proxy c14 = yc_var_proxy("c14", get_soln(), { x, y, z }); + yc_var_proxy c15 = yc_var_proxy("c15", get_soln(), { x, y, z }); + yc_var_proxy c16 = yc_var_proxy("c16", get_soln(), { x, y, z }); + yc_var_proxy c22 = yc_var_proxy("c22", get_soln(), { x, y, z }); + yc_var_proxy c23 = yc_var_proxy("c23", get_soln(), { x, y, z }); + yc_var_proxy c24 = yc_var_proxy("c24", get_soln(), { x, y, z }); + yc_var_proxy c25 = yc_var_proxy("c25", get_soln(), { x, y, z }); + yc_var_proxy c26 = yc_var_proxy("c26", get_soln(), { x, y, z }); + yc_var_proxy c33 = yc_var_proxy("c33", get_soln(), { x, y, z }); + yc_var_proxy c34 = yc_var_proxy("c34", get_soln(), { x, y, z }); + yc_var_proxy c35 = yc_var_proxy("c35", get_soln(), { x, y, z }); + yc_var_proxy c36 = yc_var_proxy("c36", get_soln(), { x, y, z }); + yc_var_proxy c44 = yc_var_proxy("c44", get_soln(), { x, y, z }); + yc_var_proxy c45 = yc_var_proxy("c45", get_soln(), { x, y, z }); + yc_var_proxy c46 = yc_var_proxy("c46", get_soln(), { x, y, z }); + yc_var_proxy c55 = yc_var_proxy("c55", get_soln(), { x, y, z }); + yc_var_proxy c56 = yc_var_proxy("c56", get_soln(), { x, y, z }); + yc_var_proxy c66 = yc_var_proxy("c66", get_soln(), { x, y, z }); public: @@ -119,64 +119,64 @@ namespace fsg { { } - yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BR ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const BR ) { return 1.0 / (0.25*(c(x , y , z ) + c(x , y+1, z ) + c(x , y , z+1) + c(x , y+1, z+1))); } - yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BL ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const BL ) { return 1.0 / (0.25*(c(x , y , z ) + c(x+1, y , z ) + c(x , y , z+1) + c(x+1, y , z+1))); } - yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TR ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const TR ) { return 1.0 / (0.25*(c(x , y , z ) + c(x , y+1, z ) + c(x+1, y , z ) + c(x+1, y+1, z ))); } - yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TL ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const TL ) { return 1.0 / c(x , y , z ); } template - yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c ) + yc_number_node_ptr cell_coeff( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c ) { return cell_coeff( x, y, z, c, N() ); } - yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BR ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const BR ) { return 0.25 *( 1.0 / c(x , y , z ) + 1.0 / c(x , y+1, z ) + 1.0 / c(x , y , z+1) + 1.0 / c(x , y+1, z+1) ); } - yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const BL ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const BL ) { return 0.25 *( 1.0 / c(x , y , z ) + 1.0 / c(x+1, y , z ) + 1.0 / c(x , y , z+1) + 1.0 / c(x+1, y , z+1) ); } - yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TR ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const TR ) { return 0.25 *( 1.0 / c(x , y , z ) + 1.0 / c(x , y+1, z ) + 1.0 / c(x+1, y , z ) + 1.0 / c(x+1, y+1, z ) ); } - yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c, const TL ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c, const TL ) { return 1.0 / c(x , y , z ); } template - yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_grid_var &c ) + yc_number_node_ptr cell_coeff_artm( const yc_number_node_ptr x, const yc_number_node_ptr y, const yc_number_node_ptr z, yc_var_proxy &c ) { return cell_coeff_artm( x, y, z, c, N() ); } @@ -196,18 +196,18 @@ namespace fsg { } // - // Stress-grid define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel grids at t+1. - // This implies that the velocity-grid define functions must be called + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z - // parameters are integer grid indices, not actual offsets in time or - // space, so half-steps due to staggered grids are adjusted + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted // appropriately. template void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &sxx, yc_grid_var &syy, yc_grid_var &szz, yc_grid_var &sxy, yc_grid_var &sxz, yc_grid_var &syz, - yc_grid_var &vxu, yc_grid_var &vxv, yc_grid_var &vxw, yc_grid_var &vyu, yc_grid_var &vyv, yc_grid_var &vyw, yc_grid_var &vzu, yc_grid_var &vzv, yc_grid_var &vzw ) { + yc_var_proxy &sxx, yc_var_proxy &syy, yc_var_proxy &szz, yc_var_proxy &sxy, yc_var_proxy &sxz, yc_var_proxy &syz, + yc_var_proxy &vxu, yc_var_proxy &vxv, yc_var_proxy &vxw, yc_var_proxy &vyu, yc_var_proxy &vyv, yc_var_proxy &vyw, yc_var_proxy &vzu, yc_var_proxy &vzv, yc_var_proxy &vzw ) { // Interpolate coeffs. auto ic11 = cell_coeff (x, y, z, c11); @@ -321,18 +321,18 @@ namespace fsg { const int abc_width = 20; // Sponge coefficients. - yc_grid_var sponge_lx = yc_grid_var("sponge_lx", get_soln(), { x, y, z }); - yc_grid_var sponge_rx = yc_grid_var("sponge_rx", get_soln(), { x, y, z }); - yc_grid_var sponge_bz = yc_grid_var("sponge_bz", get_soln(), { x, y, z }); - yc_grid_var sponge_tz = yc_grid_var("sponge_tz", get_soln(), { x, y, z }); - yc_grid_var sponge_fy = yc_grid_var("sponge_fy", get_soln(), { x, y, z }); - yc_grid_var sponge_by = yc_grid_var("sponge_by", get_soln(), { x, y, z }); - yc_grid_var sponge_sq_lx = yc_grid_var("sponge_sq_lx", get_soln(), { x, y, z }); - yc_grid_var sponge_sq_rx = yc_grid_var("sponge_sq_rx", get_soln(), { x, y, z }); - yc_grid_var sponge_sq_bz = yc_grid_var("sponge_sq_bz", get_soln(), { x, y, z }); - yc_grid_var sponge_sq_tz = yc_grid_var("sponge_sq_tz", get_soln(), { x, y, z }); - yc_grid_var sponge_sq_fy = yc_grid_var("sponge_sq_fy", get_soln(), { x, y, z }); - yc_grid_var sponge_sq_by = yc_grid_var("sponge_sq_by", get_soln(), { x, y, z }); + yc_var_proxy sponge_lx = yc_var_proxy("sponge_lx", get_soln(), { x, y, z }); + yc_var_proxy sponge_rx = yc_var_proxy("sponge_rx", get_soln(), { x, y, z }); + yc_var_proxy sponge_bz = yc_var_proxy("sponge_bz", get_soln(), { x, y, z }); + yc_var_proxy sponge_tz = yc_var_proxy("sponge_tz", get_soln(), { x, y, z }); + yc_var_proxy sponge_fy = yc_var_proxy("sponge_fy", get_soln(), { x, y, z }); + yc_var_proxy sponge_by = yc_var_proxy("sponge_by", get_soln(), { x, y, z }); + yc_var_proxy sponge_sq_lx = yc_var_proxy("sponge_sq_lx", get_soln(), { x, y, z }); + yc_var_proxy sponge_sq_rx = yc_var_proxy("sponge_sq_rx", get_soln(), { x, y, z }); + yc_var_proxy sponge_sq_bz = yc_var_proxy("sponge_sq_bz", get_soln(), { x, y, z }); + yc_var_proxy sponge_sq_tz = yc_var_proxy("sponge_sq_tz", get_soln(), { x, y, z }); + yc_var_proxy sponge_sq_fy = yc_var_proxy("sponge_sq_fy", get_soln(), { x, y, z }); + yc_var_proxy sponge_sq_by = yc_var_proxy("sponge_sq_by", get_soln(), { x, y, z }); FSGElasticStencilBase &fsg; @@ -358,8 +358,8 @@ namespace fsg { template void define_vel_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &v, yc_grid_var &sx, yc_grid_var &sy, yc_grid_var &sz, - yc_grid_var &abc_x, yc_grid_var &abc_y, yc_grid_var &abc_z, yc_grid_var &abc_sq_x, yc_grid_var &abc_sq_y, yc_grid_var &abc_sq_z) { + yc_var_proxy &v, yc_var_proxy &sx, yc_var_proxy &sy, yc_var_proxy &sz, + yc_var_proxy &abc_x, yc_var_proxy &abc_y, yc_var_proxy &abc_z, yc_var_proxy &abc_sq_x, yc_var_proxy &abc_sq_y, yc_var_proxy &abc_sq_z) { yc_bool_node_ptr at_abc = is_at_boundary(); @@ -408,9 +408,9 @@ namespace fsg { template void define_str_abc(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &sxx, yc_grid_var &syy, yc_grid_var &szz, yc_grid_var &sxy, yc_grid_var &sxz, yc_grid_var &syz, - yc_grid_var &vxu, yc_grid_var &vxv, yc_grid_var &vxw, yc_grid_var &vyu, yc_grid_var &vyv, yc_grid_var &vyw, yc_grid_var &vzu, yc_grid_var &vzv, yc_grid_var &vzw, - yc_grid_var &abc_x, yc_grid_var &abc_y, yc_grid_var &abc_z, yc_grid_var &abc_sq_x, yc_grid_var &abc_sq_y, yc_grid_var &abc_sq_z) { + yc_var_proxy &sxx, yc_var_proxy &syy, yc_var_proxy &szz, yc_var_proxy &sxy, yc_var_proxy &sxz, yc_var_proxy &syz, + yc_var_proxy &vxu, yc_var_proxy &vxv, yc_var_proxy &vxw, yc_var_proxy &vyu, yc_var_proxy &vyv, yc_var_proxy &vyw, yc_var_proxy &vzu, yc_var_proxy &vzv, yc_var_proxy &vzw, + yc_var_proxy &abc_x, yc_var_proxy &abc_y, yc_var_proxy &abc_z, yc_var_proxy &abc_sq_x, yc_var_proxy &abc_sq_y, yc_var_proxy &abc_sq_z) { auto abc = abc_x(x,y,z) * abc_y(x,y,z) * abc_z(x,y,z); auto next_sxx = sxx(t, x, y, z) * abc; diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 7ad84634..ddb725f7 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -42,11 +42,11 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { yc_index_node_ptr y = new_domain_index("y"); // spatial dim. yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // Grid vars. - yc_grid_var pressure = - yc_grid_var("pressure", get_soln(), { t, x, y, z }); // time-varying 3D pressure grid. - yc_grid_var vel = - yc_grid_var("vel", get_soln(), { x, y, z }); // constant 3D vel grid (c(x,y,z)^2 * delta_t^2). + // Vars. + yc_var_proxy pressure = + yc_var_proxy("pressure", get_soln(), { t, x, y, z }); // time-varying 3D pressure var. + yc_var_proxy vel = + yc_var_proxy("vel", get_soln(), { x, y, z }); // constant 3D vel var (c(x,y,z)^2 * delta_t^2). public: @@ -61,7 +61,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Define RHS expression for pressure at t+1 based on values from vel and pressure at t. virtual yc_number_node_ptr get_next_p() { - // yc_grid_var spacing. + // yc_var_proxy spacing. // In this implementation, it's a constant. // Could make this a YASK variable to allow setting at run-time. double delta_xyz = 50.0; @@ -126,7 +126,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Solve wave equation for p(t+1): // p(t+1) = 2 * p(t) - p(t-1) + c^2 * fd_sum * delta_t^2. - // Let vel = c^2 * delta_t^2 for each grid point. + // Let vel = c^2 * delta_t^2 for each var point. auto next_p = (2.0 * pressure(t, x, y, z)) - pressure(t-1, x, y, z) + (fd_sum * vel(x, y, z)); @@ -167,9 +167,9 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { // In practice, the interior values would be set to 1.0, // and values nearer the boundary would be set to values // increasingly approaching 0.0. - yc_grid_var cr_x("cr_x", get_soln(), { x }); - yc_grid_var cr_y("cr_y", get_soln(), { y }); - yc_grid_var cr_z("cr_z", get_soln(), { z }); + yc_var_proxy cr_x("cr_x", get_soln(), { x }); + yc_var_proxy cr_y("cr_y", get_soln(), { y }); + yc_var_proxy cr_z("cr_z", get_soln(), { z }); // Get equation for RHS. auto next_p = get_next_p(); diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index 8b9c7784..cb7a6250 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -25,8 +25,8 @@ IN THE SOFTWARE. // Stencil equations for SSG elastic numerics. // Contributed by Albert Farres from the Barcelona Supercomputing Center. -// This version varies from the original by grouping related grids into -// larger grids with an added dimension. +// This version varies from the original by grouping related vars into +// larger vars with an added dimension. #include "ElasticStencil/Elastic2Stencil.hpp" @@ -34,16 +34,16 @@ class SSGElastic2Stencil : public Elastic2StencilBase { protected: - // Time-varying 3D-spatial velocity grids. - yc_grid_var v = yc_grid_var("v", get_soln(), { t, x, y, z, vidx }); + // Time-varying 3D-spatial velocity vars. + yc_var_proxy v = yc_var_proxy("v", get_soln(), { t, x, y, z, vidx }); enum VIDX { V_BL_W, V_TL_V, V_TR_U }; - // Time-varying 3D-spatial Stress grids. - yc_grid_var s = yc_grid_var("s", get_soln(), { t, x, y, z, sidx }); + // Time-varying 3D-spatial Stress vars. + yc_var_proxy s = yc_var_proxy("s", get_soln(), { t, x, y, z, sidx }); enum SIDX { S_BL_YZ, S_BR_XZ, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TR_XY }; // Merged. - yc_grid_var coef = yc_grid_var("c", get_soln(), { t, x, y, z, cidx }); + yc_var_proxy coef = yc_var_proxy("c", get_soln(), { t, x, y, z, cidx }); enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2 }; public: @@ -84,12 +84,12 @@ class SSGElastic2Stencil : public Elastic2StencilBase { } - // Stress-grid define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel grids at t+1. - // This implies that the velocity-grid define functions must be called + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z - // parameters are integer grid indices, not actual offsets in time or - // space, so half-steps due to staggered grids are adjusted + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted // appropriately. template diff --git a/src/stencils/SSGElasticStencil.cpp b/src/stencils/SSGElasticStencil.cpp index a8371bb1..ea217ab8 100644 --- a/src/stencils/SSGElasticStencil.cpp +++ b/src/stencils/SSGElasticStencil.cpp @@ -32,23 +32,23 @@ class SSGElasticStencil : public ElasticStencilBase { protected: - // Time-varying 3D-spatial velocity grids. - yc_grid_var v_bl_w = yc_grid_var("v_bl_w", get_soln(), { t, x, y, z }); - yc_grid_var v_tl_v = yc_grid_var("v_tl_v", get_soln(), { t, x, y, z }); - yc_grid_var v_tr_u = yc_grid_var("v_tr_u", get_soln(), { t, x, y, z }); - - // Time-varying 3D-spatial Stress grids. - yc_grid_var s_bl_yz = yc_grid_var("s_bl_yz", get_soln(), { t, x, y, z }); - yc_grid_var s_br_xz = yc_grid_var("s_br_xz", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_xx = yc_grid_var("s_tl_xx", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_yy = yc_grid_var("s_tl_yy", get_soln(), { t, x, y, z }); - yc_grid_var s_tl_zz = yc_grid_var("s_tl_zz", get_soln(), { t, x, y, z }); - yc_grid_var s_tr_xy = yc_grid_var("s_tr_xy", get_soln(), { t, x, y, z }); + // Time-varying 3D-spatial velocity vars. + yc_var_proxy v_bl_w = yc_var_proxy("v_bl_w", get_soln(), { t, x, y, z }); + yc_var_proxy v_tl_v = yc_var_proxy("v_tl_v", get_soln(), { t, x, y, z }); + yc_var_proxy v_tr_u = yc_var_proxy("v_tr_u", get_soln(), { t, x, y, z }); + + // Time-varying 3D-spatial Stress vars. + yc_var_proxy s_bl_yz = yc_var_proxy("s_bl_yz", get_soln(), { t, x, y, z }); + yc_var_proxy s_br_xz = yc_var_proxy("s_br_xz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_xx = yc_var_proxy("s_tl_xx", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_yy = yc_var_proxy("s_tl_yy", get_soln(), { t, x, y, z }); + yc_var_proxy s_tl_zz = yc_var_proxy("s_tl_zz", get_soln(), { t, x, y, z }); + yc_var_proxy s_tr_xy = yc_var_proxy("s_tr_xy", get_soln(), { t, x, y, z }); // 3D-spatial coefficients. - yc_grid_var mu = yc_grid_var("mu", get_soln(), { x, y, z }); - yc_grid_var lambda = yc_grid_var("lambda", get_soln(), { x, y, z }); - yc_grid_var lambdamu2 = yc_grid_var("lambdamu2", get_soln(), { x, y, z }); + yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); + yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); + yc_var_proxy lambdamu2 = yc_var_proxy("lambdamu2", get_soln(), { x, y, z }); public: @@ -88,17 +88,17 @@ class SSGElasticStencil : public ElasticStencilBase { } - // Stress-grid define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel grids at t+1. - // This implies that the velocity-grid define functions must be called + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z - // parameters are integer grid indices, not actual offsets in time or - // space, so half-steps due to staggered grids are adjusted + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted // appropriately. template void define_str(yc_number_node_ptr t, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, - yc_grid_var &s, yc_grid_var &va, yc_grid_var &vb) { + yc_var_proxy &s, yc_var_proxy &va, yc_var_proxy &vb) { auto lcoeff = interp_mu( x, y, z ); diff --git a/src/stencils/ExampleStencil.cpp b/src/stencils/SimpleStencils.cpp similarity index 98% rename from src/stencils/ExampleStencil.cpp rename to src/stencils/SimpleStencils.cpp index 75213597..8ab62c85 100644 --- a/src/stencils/ExampleStencil.cpp +++ b/src/stencils/SimpleStencils.cpp @@ -24,7 +24,7 @@ IN THE SOFTWARE. *****************************************************************************/ // Implement various example symmetric 3D stencil shapes that read and -// write from only one 3D grid variable. +// write from only one 3D variable. // All these stencils compute the average of the points read a la the // heat-dissipation kernels in the miniGhost benchmark. @@ -44,7 +44,7 @@ class AvePtsStencil : public yc_solution_with_radius_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying 3D grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying 3D var. // Add additional points to expression v. // Returns number of points added. diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index ffa56e04..5a438da3 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -42,21 +42,21 @@ class TTIStencil:public yc_solution_with_radius_base yc_index_node_ptr y = new_domain_index("y"); // spatial dim. yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // Grid vars. - yc_grid_var u = yc_grid_var("u", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield grid. - yc_grid_var v = yc_grid_var("v", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield grid. - yc_grid_var m = yc_grid_var("m", get_soln(), { x, y, z }); // Square slowness of the model. - yc_grid_var damp = yc_grid_var("damp", get_soln(), { x, y, z }); // Boundary damping. - yc_grid_var phi = yc_grid_var("phi", get_soln(), { x, y, z }); - yc_grid_var theta = yc_grid_var("theta", get_soln(), { x, y, z }); - yc_grid_var delta = yc_grid_var("delta", get_soln(), { x, y, z }); - yc_grid_var epsilon = yc_grid_var("epsilon", get_soln(), { x, y, z }); + // Vars. + yc_var_proxy u = yc_var_proxy("u", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield var. + yc_var_proxy v = yc_var_proxy("v", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield var. + yc_var_proxy m = yc_var_proxy("m", get_soln(), { x, y, z }); // Square slowness of the model. + yc_var_proxy damp = yc_var_proxy("damp", get_soln(), { x, y, z }); // Boundary damping. + yc_var_proxy phi = yc_var_proxy("phi", get_soln(), { x, y, z }); + yc_var_proxy theta = yc_var_proxy("theta", get_soln(), { x, y, z }); + yc_var_proxy delta = yc_var_proxy("delta", get_soln(), { x, y, z }); + yc_var_proxy epsilon = yc_var_proxy("epsilon", get_soln(), { x, y, z }); // Hoisted misc time-invariant data. - yc_grid_var ti0 = yc_grid_var("ti0", get_soln(), { x, y, z }); - yc_grid_var ti1 = yc_grid_var("ti1", get_soln(), { x, y, z }); - yc_grid_var ti2 = yc_grid_var("ti2", get_soln(), { x, y, z }); - yc_grid_var ti3 = yc_grid_var("ti3", get_soln(), { x, y, z }); + yc_var_proxy ti0 = yc_var_proxy("ti0", get_soln(), { x, y, z }); + yc_var_proxy ti1 = yc_var_proxy("ti1", get_soln(), { x, y, z }); + yc_var_proxy ti2 = yc_var_proxy("ti2", get_soln(), { x, y, z }); + yc_var_proxy ti3 = yc_var_proxy("ti3", get_soln(), { x, y, z }); public: diff --git a/src/stencils/SimpleTestStencils.cpp b/src/stencils/TestStencils.cpp similarity index 84% rename from src/stencils/SimpleTestStencils.cpp rename to src/stencils/TestStencils.cpp index dac0b3cc..20d37029 100644 --- a/src/stencils/SimpleTestStencils.cpp +++ b/src/stencils/TestStencils.cpp @@ -48,7 +48,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from var 'V' at 't0' centered around 'x0'. // Extend given radius left and/or right w/'*_ext'. - virtual yc_number_node_ptr def_1d(yc_grid_var& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, + virtual yc_number_node_ptr def_1d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, int left_ext, int right_ext) { yc_number_node_ptr v; int n = 1; @@ -59,7 +59,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from scratch or read-only var 'V' centered // around 'x0'. Similar to 'def_1d()', but doesn't use step var. - virtual yc_number_node_ptr def_no_t_1d(yc_grid_var& V, const yc_number_node_ptr& x0, + virtual yc_number_node_ptr def_no_t_1d(yc_var_proxy& V, const yc_number_node_ptr& x0, int left_ext, int right_ext) { yc_number_node_ptr v; int n = 1; @@ -71,7 +71,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0'. // Extend given radius left and/or right w/'*_ext'. // Use some points from the entire rectangle, not just on the axes. - virtual yc_number_node_ptr def_2d(yc_grid_var& V, const yc_number_node_ptr& t0, + virtual yc_number_node_ptr def_2d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, const yc_number_node_ptr& y0, @@ -88,7 +88,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from scratch or read-only var 'V' at 't0' // centered around 'x0', 'y0'. Extend given radius left and/or right // w/'*_ext'. - virtual yc_number_node_ptr def_no_t_2d(yc_grid_var& V, + virtual yc_number_node_ptr def_no_t_2d(yc_var_proxy& V, const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, const yc_number_node_ptr& y0, @@ -105,7 +105,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0', 'z0'. // Extend given radius left and/or right w/'*_ext'. // Use some points from the entire rectangular polytope, not just on the axes. - virtual yc_number_node_ptr def_3d(yc_grid_var& V, const yc_number_node_ptr& t0, + virtual yc_number_node_ptr def_3d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, const yc_number_node_ptr& y0, @@ -125,7 +125,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from scratch or read-only var 'V' centered // around 'x0', 'y0', 'z0'. Extend given radius left and/or right // w/'*_ext'. - virtual yc_number_node_ptr def_no_t_3d(yc_grid_var& V, + virtual yc_number_node_ptr def_no_t_3d(yc_var_proxy& V, const yc_number_node_ptr& x0, int x_left_ext, int x_right_ext, const yc_number_node_ptr& y0, @@ -145,7 +145,7 @@ class TestBase : public yc_solution_with_radius_base { // Define simple stencil from var 'V' at 't0' centered around 'w0', 'x0', 'y0', 'z0'. // Extend given radius left and/or right w/'*_ext'. // Use some points from the entire rectangular polytope, not just on the axes. - virtual yc_number_node_ptr def_4d(yc_grid_var& V, const yc_number_node_ptr& t0, + virtual yc_number_node_ptr def_4d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& w0, int w_left_ext, int w_right_ext, const yc_number_node_ptr& x0, @@ -179,14 +179,14 @@ class Test1dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. public: Test1dStencil(int radius=2) : TestBase("test_1d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // define the value at t+1 using asymmetric stencil. @@ -205,14 +205,14 @@ class Test2dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. public: Test2dStencil(int radius=2) : TestBase("test_2d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // define the value at t+1 using asymmetric stencil. @@ -231,14 +231,14 @@ class Test3dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. public: Test3dStencil(int radius=2) : TestBase("test_3d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // define the value at t+1 using asymmetric stencil. @@ -257,14 +257,14 @@ class Test4dStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, w, x, y, z }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, w, x, y, z }); // time-varying var. public: Test4dStencil(int radius=1) : TestBase("test_4d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // define the value at t+1 using asymmetric stencil. @@ -283,22 +283,22 @@ class TestPartialStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_soln(), { x }); - yc_grid_var C = yc_grid_var("C", get_soln(), { y }); - yc_grid_var D = yc_grid_var("D", get_soln(), { z }); - yc_grid_var E = yc_grid_var("E", get_soln(), { x, y }); - yc_grid_var F = yc_grid_var("F", get_soln(), { y, z }); - yc_grid_var G = yc_grid_var("G", get_soln(), { z, y }); - yc_grid_var H = yc_grid_var("H", get_soln(), { y, z, x }); // different order. - yc_grid_var I = yc_grid_var("I", get_soln(), { }); + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }); + yc_var_proxy C = yc_var_proxy("C", get_soln(), { y }); + yc_var_proxy D = yc_var_proxy("D", get_soln(), { z }); + yc_var_proxy E = yc_var_proxy("E", get_soln(), { x, y }); + yc_var_proxy F = yc_var_proxy("F", get_soln(), { y, z }); + yc_var_proxy G = yc_var_proxy("G", get_soln(), { z, y }); + yc_var_proxy H = yc_var_proxy("H", get_soln(), { y, z, x }); // different order. + yc_var_proxy I = yc_var_proxy("I", get_soln(), { }); public: TestPartialStencil3(int radius=2) : TestBase("test_partial_3d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // define the value at t+1 using asymmetric stencil. @@ -332,16 +332,16 @@ class TestMisc2dStencil : public yc_solution_with_radius_base { yc_index_node_ptr b = new_misc_index("b"); yc_index_node_ptr c = new_misc_index("c"); - // Time-varying grid. Intermix last domain dim with misc dims to make + // Time-varying var. Intermix last domain dim with misc dims to make // sure compiler creates correct layout. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, a, y, b, c }); + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, a, y, b, c }); public: TestMisc2dStencil(int radius=2) : yc_solution_with_radius_base("test_misc_2d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Define the value at t+1 using asymmetric stencil @@ -382,7 +382,7 @@ class StreamStencil : public yc_solution_with_radius_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying 3D grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying 3D var. public: @@ -417,7 +417,7 @@ class TestReverseStencil : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); public: @@ -445,15 +445,15 @@ class TestDepStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_soln(), { t, x }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x }); // time-varying var. public: TestDepStencil1(int radius=2) : TestBase("test_dep_1d", radius) { } - // Define equation to apply to all points in 'A' and 'B' grids. + // Define equation to apply to all points in 'A' and 'B' vars. virtual void define() { // Define A(t+1) from A(t) & stencil at B(t). @@ -474,15 +474,15 @@ class TestDepStencil2 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_soln(), { t, x, y }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x, y }); // time-varying var. public: TestDepStencil2(int radius=2) : TestBase("test_dep_2d", radius) { } - // Define equation to apply to all points in 'A' and 'B' grids. + // Define equation to apply to all points in 'A' and 'B' vars. virtual void define() { // Define A(t+1) from A(t) & stencil at B(t). @@ -503,15 +503,15 @@ class TestDepStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_soln(), { t, x, y, z }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x, y, z }); // time-varying var. public: TestDepStencil3(int radius=2) : TestBase("test_dep_3d", radius) { } - // Define equation to apply to all points in 'A' and 'B' grids. + // Define equation to apply to all points in 'A' and 'B' vars. virtual void define() { // Define A(t+1) from A(t) & stencil at B(t). @@ -529,24 +529,24 @@ class TestDepStencil3 : public TestBase { // '-stencil' commmand-line option or the 'stencil=' build option. static TestDepStencil3 TestDepStencil3_instance; -// Test the use of scratch-pad grids. +// Test the use of scratch-pad vars. class TestScratchStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. // Temporary storage. - yc_grid_var B = yc_grid_var("B", get_soln(), { x }, true); + yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }, true); public: TestScratchStencil1(int radius=2) : TestBase("test_scratch_1d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Define values in scratch var 'B'. @@ -567,19 +567,19 @@ class TestScratchStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. // Temporary storage. - yc_grid_var t1 = yc_grid_var("t1", get_soln(), { x, y, z }, true); - yc_grid_var t2 = yc_grid_var("t2", get_soln(), { x, y, z }, true); - yc_grid_var t3 = yc_grid_var("t3", get_soln(), { x, y, z }, true); + yc_var_proxy t1 = yc_var_proxy("t1", get_soln(), { x, y, z }, true); + yc_var_proxy t2 = yc_var_proxy("t2", get_soln(), { x, y, z }, true); + yc_var_proxy t3 = yc_var_proxy("t3", get_soln(), { x, y, z }, true); public: TestScratchStencil3(int radius=2) : TestBase("test_scratch_3d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Set scratch vars. @@ -607,14 +607,14 @@ class TestBoundaryStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. public: TestBoundaryStencil1(int radius=2) : TestBase("test_boundary_1d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Define interior sub-domain. @@ -639,14 +639,14 @@ class TestBoundaryStencil2 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. public: TestBoundaryStencil2(int radius=2) : TestBase("test_boundary_2d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Sub-domain is rectangle interior. @@ -670,14 +670,14 @@ class TestBoundaryStencil3 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y, z }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. public: TestBoundaryStencil3(int radius=2) : TestBase("test_boundary_3d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Sub-domain is rectangle interior. @@ -706,15 +706,15 @@ class TestStepCondStencil1 : public TestBase { yc_index_node_ptr b = new_misc_index("b"); // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. - yc_grid_var B = yc_grid_var("B", get_soln(), { b }); + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { b }); public: TestStepCondStencil1(int radius=2) : TestBase("test_step_cond_1d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Time condition. @@ -744,23 +744,23 @@ class TestStepCondStencil1 : public TestBase { // '-stencil' commmand-line option or the 'stencil=' build option. static TestStepCondStencil1 TestStepCondStencil1_instance; -// Test the use of conditional updates with scratch-pad grids. +// Test the use of conditional updates with scratch-pad vars. class TestScratchBoundaryStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. // Temporary storage. - yc_grid_var B = yc_grid_var("B", get_soln(), { x }, true); + yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }, true); public: TestScratchBoundaryStencil1(int radius=2) : TestBase("test_scratch_boundary_1d", radius) { } - // Define equation to apply to all points in 'A' grid. + // Define equation to apply to all points in 'A' var. virtual void define() { // Define values in scratch var 'B' using current values from 'A'. @@ -787,9 +787,9 @@ class TestFuncStencil1 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x }); - yc_grid_var B = yc_grid_var("B", get_soln(), { t, x }); - yc_grid_var C = yc_grid_var("C", get_soln(), { t, x }); + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x }); + yc_var_proxy C = yc_var_proxy("C", get_soln(), { t, x }); public: @@ -808,13 +808,13 @@ class TestFuncStencil1 : public TestBase { // '-stencil' commmand-line option or the 'stencil=' build option. static TestFuncStencil1 TestFuncStencil1_instance; -// A stencil that has grids but no stencil equation. +// A stencil that has vars but no stencil equation. class TestEmptyStencil2 : public TestBase { protected: // Vars. - yc_grid_var A = yc_grid_var("A", get_soln(), { t, x, y }); // time-varying grid. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. public: @@ -829,7 +829,7 @@ class TestEmptyStencil2 : public TestBase { // '-stencil' commmand-line option or the 'stencil=' build option. static TestEmptyStencil2 TestEmptyStencil2_instance; -// A stencil that no grids and no stencil equation. +// A stencil that no vars and no stencil equation. // Kernel must be built with domain_dims and step_dim options. class TestEmptyStencil0: public TestBase { diff --git a/utils/bin/analyze_trace.pl b/utils/bin/analyze_trace.pl index da61147b..ba671725 100755 --- a/utils/bin/analyze_trace.pl +++ b/utils/bin/analyze_trace.pl @@ -23,7 +23,7 @@ ## IN THE SOFTWARE. ############################################################################## -# Purpose: Process the output of a log from a binary and compare every grid write. +# Purpose: Process the output of a log from a binary and compare every write. # Build with the following options: real_bytes=8 trace_mem=1 # Run kernel with '-v -force_scalar -trace' and pipe output to this script. @@ -65,18 +65,18 @@ # writeElem: pressure[t=0, x=0, y=0, z=0] = 5.7 at line 287 elsif (/^(YASK: )?writeElem:\s*(\w+)\[(.*)\]\s*=\s*(\S+)/) { - my ($grid, $indices, $val) = ($2, $3, $4); + my ($var, $indices, $val) = ($2, $3, $4); if (defined $key) { $indices =~ s/\b\d\b/0$&/g; # make indices 2 digits. # track last value. - $vals{$key}{$grid}{$indices} = $val; + $vals{$key}{$var}{$indices} = $val; # track all pts written. - $pts{$grid}{$indices} = 1; + $pts{$var}{$indices} = 1; # track writes in order. - push @{$writes{$key}}, [ $grid, $indices, $val ]; + push @{$writes{$key}}, [ $var, $indices, $val ]; } } @@ -87,18 +87,18 @@ my $nissues = 0; sub comp($$$) { - my $grid = shift; + my $var = shift; my $indices = shift; my $pval = shift; - print "$grid\[$indices\] ="; + print "$var\[$indices\] ="; if (defined $pval) { print "\t $pval"; } else { print " NOT written in perf"; $nissues++; } - my $val = $vals{val}{$grid}{$indices}; + my $val = $vals{val}{$var}{$indices}; if (defined $val) { print "\t $val"; if (defined $pval && $pval) { @@ -121,20 +121,20 @@ ($$$) print "Values are from perf, then validation trial\n"; my %nwrites; for my $pw (@{$writes{perf}}) { - my ($grid, $indices, $pval) = ($pw->[0], $pw->[1], $pw->[2]); - comp($grid, $indices, $pval); - my $nw = ++$nwrites{$grid}{$indices}; + my ($var, $indices, $pval) = ($pw->[0], $pw->[1], $pw->[2]); + comp($var, $indices, $pval); + my $nw = ++$nwrites{$var}{$indices}; if ($nw > 1) { print "^^^^^^^^ $nw writes!!!\n"; $nissues++; } } -print "\n===== Comparisons in grid & index order =====\n"; +print "\n===== Comparisons in var & index order =====\n"; print "Values are from perf, then validation trial\n"; -for my $grid (sort keys %pts) { - for my $indices (sort keys %{$pts{$grid}}) { - comp($grid, $indices, $vals{perf}{$grid}{$indices}); +for my $var (sort keys %pts) { + for my $indices (sort keys %{$pts{$var}}) { + comp($var, $indices, $vals{perf}{$var}{$indices}); } } diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index abeed353..261a83cf 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -108,22 +108,22 @@ ($) s/\bfirst_index\b/first_domain_index/g; s/\blast_index\b/last_domain_index/g; - # Grid creation. - s/MAKE_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 })/g; - s/MAKE_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 })/g; - s/MAKE_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { })/g; - s/MAKE_SCRATCH_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 }, true)/g; - s/MAKE_SCRATCH_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { $2 }, true)/g; - s/MAKE_SCRATCH_SCALAR\s*[(]([^,]+)[)]/yc_grid_var $1 = yc_grid_var("$1", get_soln(), { }, true)/g; + # Var creation. + s/MAKE_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_var_proxy $1 = yc_var_proxy("$1", get_soln(), { $2 })/g; + s/MAKE_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_var_proxy $1 = yc_var_proxy("$1", get_soln(), { $2 })/g; + s/MAKE_SCALAR\s*[(]([^,]+)[)]/yc_var_proxy $1 = yc_var_proxy("$1", get_soln(), { })/g; + s/MAKE_SCRATCH_GRID\s*[(]([^,]+),\s*([^)]+)[)]/yc_var_proxy $1 = yc_var_proxy("$1", get_soln(), { $2 }, true)/g; + s/MAKE_SCRATCH_ARRAY\s*[(]([^,]+),\s*([^)]+)[)]/yc_var_proxy $1 = yc_var_proxy("$1", get_soln(), { $2 }, true)/g; + s/MAKE_SCRATCH_SCALAR\s*[(]([^,]+)[)]/yc_var_proxy $1 = yc_var_proxy("$1", get_soln(), { }, true)/g; # Typenames. s/\bStencilBase\b/yc_solution_base/g; s/\bStencilRadiusBase\b/yc_solution_with_radius_base/g; - s/\bGrid\b/yc_grid_var/g; + s/\bGrid\b/yc_var_proxy/g; s/\bGridIndex\b/yc_number_node_ptr/g; s/\bGridValue\b/yc_number_node_ptr/g; s/\bCondition\b/yc_bool_node_ptr/g; - s/\bGridPointPtr\b/yc_grid_point_node_ptr/g; + s/\bGridPointPtr\b/yc_var_point_node_ptr/g; s/\bExprPtr\b/yc_expr_node_ptr/g; s/\bNumExprPtr\b/yc_number_node_ptr/g; s/\bIndexExprPtr\b/yc_index_node_ptr/g; diff --git a/utils/bin/gen_layouts.pl b/utils/bin/gen_layouts.pl index b9352f43..62441ff6 100755 --- a/utils/bin/gen_layouts.pl +++ b/utils/bin/gen_layouts.pl @@ -30,7 +30,7 @@ sub usage { "options:\n". " -p generate perl lists of permutes\n". " -d generate C++ class definitions\n". - " -g generate C++ grid-creation code\n". + " -v generate C++ var-creation code\n". " -m generate CPP layout/unlayout macros\n"; } @@ -266,8 +266,8 @@ END } @a; } - # grid-creation code. - elsif ($opt eq '-g') { + # YASK ar-creation code. + elsif ($opt eq '-v') { # Make type name. my $layout = "Layout_" . join('', 1 .. $n); @@ -277,7 +277,7 @@ END # Creation. print " else if (ndims == $n && step_used == $wrap)\n", - " gp = make_shared>(*this, name, gdims);\n"; + " gp = make_shared>(*this, name, gdims);\n"; } } diff --git a/utils/bin/gen_loops.pl b/utils/bin/gen_loops.pl index 527681a9..b7801b2c 100755 --- a/utils/bin/gen_loops.pl +++ b/utils/bin/gen_loops.pl @@ -923,7 +923,7 @@ ($) # header. print OUT "/*\n", - " * ".scalar(@dims)."-D grid-scanning code.\n", + " * ".scalar(@dims)."-D var-scanning code.\n", " * Generated automatically from the following pseudo-code:\n", " *\n", " * N = ",$#dims,";\n"; @@ -965,7 +965,7 @@ () my $script = basename($0); if (!$command_line || $OPT{help} || @ARGV < 1) { - print "Outputs C++ code to scan N-D grids.\n", + print "Outputs C++ code to scan N-D vars.\n", "Usage: $script [options] \n", "The contains optionally-nested scans across the given\n", " indices between 0 and N-1 indicated by 'loop()'\n", @@ -1009,7 +1009,7 @@ () } @dims = 0 .. ($OPT{ndims} - 1); - print "info: generating scanning code for ".scalar(@dims)."-D grids...\n"; + print "info: generating scanning code for ".scalar(@dims)."-D vars...\n"; $inputVar = $OPT{inVar}; my $codeString = join(' ', @ARGV); # just concat all non-options params together. diff --git a/utils/bin/yask_tuner.pl b/utils/bin/yask_tuner.pl index a5969cf4..025c7dc9 100755 --- a/utils/bin/yask_tuner.pl +++ b/utils/bin/yask_tuner.pl @@ -777,28 +777,28 @@ ($) } # return estimate of mem footprint in bytes. -my $numSpatialGrids = 0; +my $numSpatialVars = 0; sub calcSize($$$) { my $sizes = shift; # ref to size array. my $pads = shift; # ref to pad array. my $mults = shift; # ref to array of multiples. - # need to determine how many XYZ grids will be allocated for this stencil. + # need to determine how many XYZ vars will be allocated for this stencil. # TODO: get info from compiler report. - if (!$numSpatialGrids) { + if (!$numSpatialVars) { my ( $makeCmd, $tag ) = getMakeCmd('', 'EXTRA_CXXFLAGS=-O1'); my $runCmd = getRunCmd($tag)." -t 0 -l 32 $runArgs"; my $cmd = "$makeCmd 2>&1 && $runCmd"; my $timeDim = 0; - my $numGrids = 0; - my $numUpdatedGrids = 0; + my $numVars = 0; + my $numUpdatedVars = 0; my @cmdOut; if ($testing) { - $numSpatialGrids = 1; + $numSpatialVars = 1; } else { - print "Running '$cmd' to determine number of grids...\n"; + print "Running '$cmd' to determine number of vars...\n"; open CMD, "$cmd 2>&1 |" or die "error: cannot run '$cmd'\n"; while () { chomp; @@ -807,27 +807,27 @@ ($$$) # E.g., # 'A' 4-D var (t=2 * x=8 * y=48 * z=49) with storage at 0x2aba63016000 ... - my $ngrids = 1; + my $nvars = 1; if (/\d-?D .*x=.*y=.*z=/) { for my $w (split ' ',$line) { if ($w =~ /(\w+)=(\d+)/) { my ($dim, $sz) = ($1, $2); if ($dim eq 't') { - $ngrids *= $sz; + $nvars *= $sz; } } } - $numSpatialGrids += $ngrids; - print "$line => $ngrids XYZ grids\n"; + $numSpatialVars += $nvars; + print "$line => $nvars XYZ vars\n"; } } close CMD; } - if (!$numSpatialGrids) { + if (!$numSpatialVars) { map { print ">> $_\n"; } @cmdOut; - die "error: no relevant grid allocations found in '$cmd'; $0 only works with 'x, y, z' 3-D stencils.\n"; + die "error: no relevant var allocations found in '$cmd'; $0 only works with 'x, y, z' 3-D stencils.\n"; } - print "Determined that $numSpatialGrids XYZ grids are allocated.\n"; + print "Determined that $numSpatialVars XYZ vars are allocated.\n"; } # estimate each dim of allocated memory as size + 2 * (halo + pad). @@ -837,8 +837,8 @@ ($$$) my $n = mult(@sizes); # mult sizes plus padding & halos. my $nb = $n * $realBytes; - # mult by number of grids. - $nb *= $numSpatialGrids; + # mult by number of vars. + $nb *= $numSpatialVars; return $nb; } diff --git a/utils/lib/YaskUtils.pm b/utils/lib/YaskUtils.pm index a8ef5dac..f4e71e8e 100644 --- a/utils/lib/YaskUtils.pm +++ b/utils/lib/YaskUtils.pm @@ -199,6 +199,8 @@ sub getResultsFromLine($$) { # Substitutions to handle old formats. $line =~ s/overall.problem/global-domain/g; $line =~ s/rank.domain/local-domain/g; + $line =~ s/grid/var/g; + $line =~ s/Grid/Var/g; # special cases for manual parsing... # TODO: catch output of auto-tuner and update relevant results. From f163ab57bffddc5b771a9bb10407cb3334bcd2dd Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 10 May 2019 11:33:13 -0700 Subject: [PATCH 22/62] Test and doc updates. --- include/yask_compiler_api.hpp | 2 +- src/kernel/Makefile | 4 ++-- src/stencils/SimpleStencils.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 7bf1a769..b3f3d09e 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -693,7 +693,7 @@ namespace yask { /**< [in] Number of elements to allocate in the step dimension. */) =0; }; - /// A wrapper class around a \ref yc_var pointer. + /// A wrapper or "proxy" class around a \ref yc_var pointer. /** Using this class provides a syntactic alternative to calling yc_solution::new_var() (or yc_solution::new_scratch_var()) followed by yc_var::new_var_point(). diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 99224ae6..be925dc8 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -846,11 +846,11 @@ stencil-tests: $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=3plane fold=y=2,z=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=cube fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=ssg fold=x=2,y=2 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=ssg2 fold=x=2,y=2 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=ssg_merged fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=awp fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=awp_elastic fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=fsg_abc fold=x=2,y=2 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=fsg2 fold=x=2,y=2 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=fsg_merged fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=tti fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=test_4d fold=w=2,x=2 diff --git a/src/stencils/SimpleStencils.cpp b/src/stencils/SimpleStencils.cpp index 8ab62c85..17be7715 100644 --- a/src/stencils/SimpleStencils.cpp +++ b/src/stencils/SimpleStencils.cpp @@ -25,7 +25,7 @@ IN THE SOFTWARE. // Implement various example symmetric 3D stencil shapes that read and // write from only one 3D variable. -// All these stencils compute the average of the points read a la the +// All these stencils compute the average of the points read similar to the // heat-dissipation kernels in the miniGhost benchmark. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. From b42c1d323a3b39daa1cca3e84e43945a5a6ef059 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 10 May 2019 13:54:38 -0700 Subject: [PATCH 23/62] Fix bug in refactored stencil. --- src/stencils/SSGElastic2Stencil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index cb7a6250..f2d4034b 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -43,7 +43,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { enum SIDX { S_BL_YZ, S_BR_XZ, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TR_XY }; // Merged. - yc_var_proxy coef = yc_var_proxy("c", get_soln(), { t, x, y, z, cidx }); + yc_var_proxy coef = yc_var_proxy("c", get_soln(), { x, y, z, cidx }); enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2 }; public: From 573e4d45e2dc1ded686827e9e7c9c39d9c47449c Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 10 May 2019 16:03:53 -0700 Subject: [PATCH 24/62] Doc improvements. --- docs/api/mainpage.txt | 92 +++++++++++++++++++---------- src/stencils/SSGElastic2Stencil.cpp | 2 +- 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/docs/api/mainpage.txt b/docs/api/mainpage.txt index 518fb22e..2f728bab 100644 --- a/docs/api/mainpage.txt +++ b/docs/api/mainpage.txt @@ -42,29 +42,35 @@ consisting of other points, constants, mathematical operators, etc. - Example equation: `u(t+1, x, y) EQUALS (u(t, x, y) + u(t, x+1, y) + u(t, x, y+1)) / 3`. A new stencil solution may be defined in one of the following ways: --# Write a stencil in C++ that will be compiled into the standard YASK stencil compiler, `bin/yask_compiler.exe`. +-# Write a stencil in C++ that will be compiled into the standard YASK stencil compiler +utility, `bin/yask_compiler.exe`. - This approach is typically taken when the programmer or scientist wants to express - the equations of the stencil directly. - - In this case, the equations can be typed exactly as shown in the above example - (C++ operator overloading is used automatically to construct an internal representation of each equation). + the equations of the stencil directly, e.g., in a text editor or IDE. + - In this case, you must extend the provided base class \ref yc_solution_base + (or \ref yc_solution_with_radius_base). Equations can be typed exactly as shown in the above example + (C++ operator overloading is used automatically to construct an internal representation of each equation), + and they must be part of the code accessed via the overloaded method yc_solution_base::define(). + All classes and methods used to create expressions in the YASK compiler API may be used. - To generate the kernel code for the defined stencil, [re]compile and run the YASK stencil compiler. This is done automatically when building a YASK kernel using the YASK `Makefile`, or you can build it explicity via `make compiler` and run it from your shell command-prompt. - - See example stencils in `src/stencils`. - These stencils are written as classes inherited from the `StencilBase` class. --# Use the YASK compiler API to create another application that defines stencils. + - When you run `make` to build the kernel library, the generated output from the compiler utility + is automatically written to `src/kernel/gen/yask_stencil_code.hpp` + and compiled into the optimized kernel library. + - See example stencils of this type in `src/stencils`. +-# Create a custom application that defines stencils. - This approach is typically taken when a 3rd-party front-end tool will be creating stencils - from another, possibly higher-level, description, - e.g., applying finite-difference methods to differential equations. - - In this case, the equations are built up programmatically into an abstract syntax tree (AST). - - The mechanism to generate the kernel code in this approach depends on the application - created from the APIs. The application might be run from a command-prompt, or the user - might control it interactively. - - See `src/compiler/tests/yask_compiler_api_test.cpp` for an example stencil definition in C++. - - See `bin/yask_compiler_api_test.py` for an example stencil definition in Python. - - See \ref sec_yc for documentation on the compiler API. - -In either case, the resulting generated code should written to the C++ stencil-code file, + automatically from some other existing format or description. + - In this case, you don't use the provided \ref yc_solution_base class or overload yc_solution_base::define(), + but equations may be expressed in the same way, because both techniques use the YASK compiler API. + - The output from the custom application may be written to `src/kernel/gen/yask_stencil_code.hpp` + and compiled into the optimized kernel library. Or, it can write the output to any file + that is then specified via `YK_CODE_FILE=`filename when running `make` to build the kernel library. + - See `src/compiler/tests/yask_compiler_api_test.cpp` for an example stencil definition in C++ or + `bin/yask_compiler_api_test.py` for an example stencil definition in Python. + +In either case, the resulting generated code should written to the C++ stencil-code file +to be compiled into the kernel library. `src/kernel/gen/yask_stencil_code.hpp`. @subsection yk_intro Create a Stencil Kernel Library and Stencil-based Application @@ -73,9 +79,10 @@ Once the stencil-code file is created, it must be compiled into a YASK kernel li - There will be a separate library created for each stencil solution and target architecture combination. - This is done automatically when building a YASK kernel using the YASK `Makefile`, e.g., via `make -j stencil=iso3dfd arch=knl`, which builds the "iso3dfd" stencil for the Intel Xeon Phi processor. -- If you generated the stencil-code file via another means (e.g., by running the compiler manually - or using a program using the compiler API), you may still create a kernel library using - the `Makefile`; you'll just need to use the special target `kernel-only` to avoid running the compiler. +- If you generated the stencil-code file via a custom application, + you may still create a kernel library using + the `Makefile`; you'll just need to specify the filename via `YK_CODE_FILE=`filename + as described above. You'll also still need to specify the target architecture and give a descriptive name to the stencil. Example: `make stencil=my-stencil arch=hsw kernel-only`. @@ -92,8 +99,8 @@ This may be done in one of the following ways: - This approach would be taken to integrate the kernel into a larger application that would inject real-world initial-state data into the YASK variables and extract the final-state data for analysis or further processing. - - See `src/kernel/tests/yask_kernel_api_test.cpp` for an example kernel usage in C++. - - See `bin/yask_kernel_api_test.py` for an example kernel usage in Python. + - See `src/kernel/tests/yask_kernel_api_test.cpp` for an example kernel usage in C++ or + `bin/yask_kernel_api_test.py` for an example kernel usage in Python. - See \ref sec_yk for documentation on the kernel API. @note Anytime you want to change the name or any compile-time properties of the kernel, be sure to run @@ -114,33 +121,56 @@ The types, classes, and functions are listed in \ref yc. @subsection yc_usage Typical Program Flow using the Compiler API - Create a yc_factory. This is the "bootstrap" object that will be used to create others. - Create a yc_solution object via yc_factory::new_solution(). + Alternatively, if using the provided YASK compiler utility, derive a new class from + \ref yc_solution_base. +- Create index variable for solution domain dimensions via yc_node_factory::new_domain_index() and + via yc_node_factory::new_step_index() for the step dimension (often "t" for time). - Create one or more \ref yc_var objects via yc_solution::new_var() as needed by the stencil(s) being implemented. Calls to yc_solution::new_var() specify the name and dimensions of each var. Vars may be read-only (constants) or read-write. Each var will be a part of the solution from which it was created. + (Or, you may construct a \ref yc_var_proxy object, which is a wrapper around + a \ref yc_var pointer providing some syntactic alternatives that you may prefer.) - Create an equation for each read-write var. - - Create expressions "bottom-up" by creating the leaf nodes first. + - Think of expressions as abstract syntax trees (ASTs) that describe the + mathematical formula that defines each point to be calculated at each new time-step. - Leaf nodes may be floating-point (FP) constants or references to var points. - - Constants are created via yc_node_factory::new_number_node(). + - Constants may created via yc_node_factory::new_number_node(), but this is seldom + needed explicitly thanks to operator overloading. - References to points are created via yc_var::new_var_point(), which specifies the indices relative to the point being evaluated within the problem domain. + (If you created \ref yc_var_proxy objects, see the alternative syntax shown + in the documentation for that class.) - Create operator nodes via normal math operators (`+`, `*`, etc.), to build up - larger expressions. + larger expressions. Some math functions like square-root and cosine are also available. - To complete each equation, use the special `EQUALS` operator to specify an expression on the right-hand side (RHS) and the point in a variable that is defined to be equal to it on the left-hand side (LHS). - - Specify the solution domain dimension via yc_node_factory::new_domain_index(). - - Specify the solution step dimension via yc_node_factory::new_step_index(). - (This is usually "t" for time.) + - Boolean expressions may be added to equations to specify sub-domains in which they + are applied. In this way, boundary layers and conditions may be implemented. + It is also possible to add boolean expressions to specify certain time-steps + in which equations are valid. + - Many examples of using the YASK compiler API to create stencil equations are provided + in the `src/stencils` directory. - Specify the number of bytes in a floating-point element via yc_solution::set_element_bytes(). This should be 4 or 8. + If you are using the provided YASK compiler utility, this controlled via the + `real_bytes=`4|8 `make` parameter. - Optionally specify the vector-folding and/or vector-clustering via yc_solution::set_fold_len() and/or yc_solution::set_cluster_mult(). + If you are using the provided YASK compiler utility, these are controlled via the + `fold=`fold-spec and `cluster=`cluster-spec `make` parameters. - Format the equations for additional processing via yc_solution::format(). + If you are using the provided YASK compiler utility, this call will be done for you + with the proper parameters based on the target architecture. @section sec_yk YASK Stencil Kernel API +As discussed earlier, the kernel API is only needed for integrating a YASK kernel into +your final application. For evaluating performance, use the provided `bin/yask.sh` utility, +which makes the needed calls to the kernel API for you. + @subsection yk_oview Kernel Overview This section provides usage information for the YASK stencil kernel API (application-programmer interface).\n @@ -151,6 +181,7 @@ this distinguishes them from the 'yc_'-prefixed types used in the "YASK compiler The types, classes, and functions are listed in \ref yk. @subsection yk_usage Typical Program Flow using the Kernel API + - Create a \ref yk_factory. This is the "bootstrap" object that will be used to create others. - Create a \ref yk_env object via yk_factory::new_env(). This initializes MPI if you have enabled it. - Create a \ref yk_solution object via yk_factory::new_solution(). @@ -172,7 +203,8 @@ The types, classes, and functions are listed in \ref yk. @section sec_tests Example Tests -The following examples illustrate possible combinations of compilers and kernels. +The following examples illustrate possible combinations of compilers and kernels and show +how to invoke a set of tests for each combination. - You can add `stencil=`_stencil-name_ to use a specific stencil for testing. - You can add `arch=`_arch-name_ to target one of the architectures listed in the `Makefile` if desired. - Run `make clean` before all of the example commands to ensure consistent builds. diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index f2d4034b..5291c006 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -42,7 +42,7 @@ class SSGElastic2Stencil : public Elastic2StencilBase { yc_var_proxy s = yc_var_proxy("s", get_soln(), { t, x, y, z, sidx }); enum SIDX { S_BL_YZ, S_BR_XZ, S_TL_XX, S_TL_YY, S_TL_ZZ, S_TR_XY }; - // Merged. + // 3D-spatial coefficients. yc_var_proxy coef = yc_var_proxy("c", get_soln(), { x, y, z, cidx }); enum CIDX { C_MU, C_LAMBDA, C_LAMBDA_MU2 }; From c6fdae67df2f82cbb332aa55319cab41bba70f51 Mon Sep 17 00:00:00 2001 From: chuckyount Date: Fri, 10 May 2019 17:06:27 -0700 Subject: [PATCH 25/62] update tutorial for v3 --- docs/YASK-tutorial.pdf | Bin 1598284 -> 1599058 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/YASK-tutorial.pdf b/docs/YASK-tutorial.pdf index c2707b91877188ad75c627f4a22fa44841da46ef..c513909cf036370cd7e39a874096263a3355600b 100644 GIT binary patch delta 360269 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
wSjkadu&nL(Szq1DVmX?63dS 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�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%0DQCVhZ>}2Hs<) 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%0DE|A(uufQn=3y2af?aDuzLyA#|U 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%0Ah@C2#hgTf9#@C!!gf1)Rr7Rm>EO* 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

2ib>KUd#@|jQ}anTt_&lh;O^aYh+ zyusn2ko7NwnF#5L?@KiJ_NCC0q`Wjw7o4$A*RNPaAp4@#61_rzl5+(G^q`t+I!*7K>(EFp_;qR62AVOo`TSjv# zfig`34gU8B>l23`Vp{z{_$c|rM1XnN_V?HQ;vLdigoK-GbF7NQlp_(nXjHJ@MQlW# zx`?AmjH^gD47m%3GZF7963)7!Al#AVAwgBdLs(mJ6|s@Yv#J>9!n)*mC6dRs>Da^# zw@6fEi5mt#>L%_XuBYi~t}fyR z+cmZ+klNl@tBUORrabc&Uy!$Ttc@Isi&XIu50TDSaQ*;b+R*}1;vL?mjd*o}&V6pdC&#XrdRf~Aqubplg_AR?ec$RVQDUQujG-ip>%j-p*t z6`7cUVC*K?m01^jy-*jgTj(cxxnfMx_dL$}YCo|9mBizIV3bQe5!&1JA3ARuO4|fw zb$xM)3l?3a0UEVwAa<$7o&HMIRHo%kM4TG0W|k@8`wKSqnPkoA4lZnAo5N)~hZbUg zvbZA^Px^Hn+o-j_6txmEI8dzZhv{LI+-X7^ z2LxqG4H56dpBYSt0kY~y1DKW!78^;Z&RQR89R`lcbNp>?=%@f7wZp`-r1J&rBY<&x zxU_T#sCR}?)@$Tul!;Uf5uahL#Y4d!&v2Z&$KjS?osp)Ba50(&_}@jKRdR%QlNg6t zS~-DDBx#s9i!_L|K5(E(q=9xN>3@SB_z{p`VWjvod4`|pjxr*fsAP_$EXx>W?e8>r_9&e2W}__+oIdwW zY0X8Ldhui$MWgh=5I&iZLTDHhDZ^d)S1|n!!tz>7ch1IZ2WjSTYUIA=Rjgd9YLY#-3IZp z3%R#htQ|=A+7T7n3?1rR?V@g{k+{Z!k2@aOxoDFADZ09niN#m~WWi1+eYT1XINqUb z#3{^7-HLPKwavUTRCd@+ze%=DyvS=DT)c49*%0?k@r)~~9Z5;1I0Y*Y&N8bP)^=M>zS<%Bk?0*zx%YQirsY)hOrGz6l~a=D zJFzQ6cS5{7m(W$?yD7Gpl7_pWP)xgMU+kw744ShGn+4BdH~JpkE&dD_Ms31gjWIze z@!&x=el*%6o^MEMUAA_2q?1g(m&GC%^7tx!g4~)DZc=g8s_3ra&B@nbRgYb>v~q?? z&Rr7`82oj^`oswz*?B{p1@?VWg6@M$AZqtZM6W;$;slA<_n#IuRpKA87Sh+9$^@$J zZI4Xyn<8Q$Q>kS%d==3yvpJ<;A@qMKM*Ff%>_m)ZmPQEe?TwPk;I8P1`X4kJ^N;uk zXM1qN)Co!nx+TuyBn@RbPO;zdTVglT-y4p0?c31E+S}qEtRzqj2+mZc)ggewJrLWx zOzwBEEX;n~T}*84U2&Q#{>KO6{x5d!>wiUmGcasHuBG!~aL{L58C{iE|Ysw&$mIt_`V0Uat4t)@Hmnz6wGAPJeGK~w=PLhWVhQmYl zGxhsC@%K0vJwX)Ai zu2wdX1nR7>0^jYgQtM>&%&*sB#7jEa1?nd+Z-Xvp+Q|M(rnI$naa=|TWlDNP+I>aW`IRhyav-4-eq?o$ zJ@q7}KGqjFeTmwX(?^CtvGReSj zdJi(c7!@my%$6x+kPP0}_o3EDfH`gNBN3spwM82+Ygc&Q|*dBJ?ynYdya0Rb1ViJ8<8Qq-_t>u;h*#x%s1gG=;RaA-Sxr9~s}g6|xm zB&stIy|2}s6o$^&{Z7GOE4p^pwC(VJY|>#!!wwxhYEGOqY{I1Y2_sN@1F#g=(&Z#| zgshqI|8)lcR}*O6XTpfd4Xxw04(T^yWdBLy8&ak<1c%t^A((=x_o&&VNtfPT|3A%^ BtResa From 57d8d188058ff1631f3d282fa6b1c6c25e4ce08b Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 10 May 2019 17:32:20 -0700 Subject: [PATCH 26/62] Improve change notice. --- README.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f8671640..02fef3bc 100644 --- a/README.md +++ b/README.md @@ -70,13 +70,24 @@ YASK contains a domain-specific compiler to convert stencil-equation specificati ## Backward-compatibility notices, including changes in default behavior ### Version 3 -* Version 3.00.00 implemented a unification of the old (v2) internal DSL with the YASK compiler API. -Canonical v2 DSL code should still work using the `Soln.hpp` backward-compatibility header file. -To convert v2 DSL code to v3 format, use the `./utils/bin/convert_v2_stencil.pl` utility. -All references to the term "grid" has been changed to "var"; backward-compatibility APIs should maintain -functionality of v2 DSL and kernel code. -DSL and kernel code and any local output-parsing scripts that has used any undocumented files, -data, or types may have to be updated. + +* Version 3.00.00 implemented a unification of the old (v1 and v2) internal +DSL that used undocumented types such as `SolutionBase` and `GridValue` and +undocumented macros such as `MAKE_GRID` with the newer documented YASK +compiler API. Canonical v2 DSL code should still work using the `Soln.hpp` +backward-compatibility header file. To convert v2 DSL code to v3 format, +use the `./utils/bin/convert_v2_stencil.pl` utility. Also, for both the +compiler and kernel APIs, all uses of the term "grid" were changed to "var". +(Historically, early versions of YASK allowed only variables whose elements +were points on the domain grid, so the terms were essentially +interchangeable. Later, variables became more flexible. They could be +defined with a subset of the domain dimensions, include non-domain or +"miscellaneous" indices, or even be simple scalar values, so the term "grid" +to describe any variable became inaccurate. This change addresses that +contradiction.) Again, backward-compatibility features in the API should +maintain functionality of v2 DSL and kernel code. However, old DSL and +kernel code or user-written output-parsing scripts that use any +undocumented files, data, or types may have to be updated. ### Version 2 * Version 2.22.00 changed the heuristic to determine vector-folding sizes when some From a30c32399551bdc052ffe21e3f8d87829cca2419 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 13 May 2019 14:52:44 -0700 Subject: [PATCH 27/62] Calculate needed MPI L1-norms automatically. Closes #84. --- include/aux/yk_var_api.hpp | 30 +++++++++++++++++ src/compiler/lib/Cpp.cpp | 2 ++ src/compiler/lib/Eqs.cpp | 20 +++++++---- src/compiler/lib/Eqs.hpp | 1 + src/compiler/lib/Expr.hpp | 21 ------------ src/compiler/lib/Var.cpp | 13 +++++++- src/compiler/lib/Var.hpp | 17 ++++++++-- src/compiler/lib/YaskKernel.cpp | 11 ++++++ src/kernel/Makefile | 15 --------- src/kernel/lib/alloc.cpp | 59 ++++++++++++++++----------------- src/kernel/lib/realv.hpp | 2 +- src/kernel/lib/yk_var.hpp | 11 ++++++ src/stencils/TestStencils.cpp | 47 ++++++++++++++------------ 13 files changed, 149 insertions(+), 100 deletions(-) diff --git a/include/aux/yk_var_api.hpp b/include/aux/yk_var_api.hpp index 9fb35322..5c8210bd 100644 --- a/include/aux/yk_var_api.hpp +++ b/include/aux/yk_var_api.hpp @@ -731,6 +731,36 @@ namespace yask { /* Advanced APIs for yk_var found below are not needed for most applications. */ + /// **[Advanced]** Get the maximum L1-norm of a neighbor rank for halo exchange. + /** + This setting determines which MPI neighbors participate in a halo exchange. + The L1-norm is also known as the "Manhattan distance" or "taxicab norm". + In this case, the distance in *each* domain dimension can be only zero or one, + so the sum can range from zero to the number of domain dimensions. + + Examples for a domain size with 2 spatial dimensions (e.g., "x" and "y"): + * L1-norm = 0: no halos are exchanged for this var. + * L1-norm = 1: halos are exchanged between "up", "down", "left" and "right" + neighbors. + * L1-norm = 2: halos are exchanged as above plus diagonal neighbors. + + The actual exchanges are further controlled by the size of the halo in each + direction per get_halo_size(). + + @returns L1-norm, ranging from zero to number of domain dimensions. + */ + virtual int + get_halo_exchange_l1_norm() const =0; + + /// **[Advanced]** Set the maximum L1-norm of a neighbor rank for halo exchange. + /** + @see get_halo_exchange_l1_norm(). + */ + virtual void + set_halo_exchange_l1_norm(int norm + /**< [in] Maximum L1-norm of neighbor rank + with which to exchange halos. */) =0; + /// **[Advanced]** Get whether the allocation of the step dimension of this var can be modified at run-time. /** See set_alloc_size(). diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index 23085131..46f972c8 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -35,6 +35,8 @@ namespace yask { string CppPrintHelper::formatReal(double v) { // Int representation equivalent? + // This is needed to properly format int expressions + // like 'x > 5'. if (double(int(v)) == v) return to_string(int(v)); diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index 60be5b7f..0ce6cca7 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -1089,14 +1089,15 @@ namespace yask { // Next, propagate halos through scratch vars as needed. - // Example: - // eq1: scr(x) EQUALS u(t,x+1); <-- orig halo of u = 1. - // eq2: u(t+1,x) EQUALS scr(x+2); <-- orig halo of scr = 2. + // Example 1: + // eq1: scr1(x) EQUALS u(t,x+1); <-- orig halo of u = 1. + // eq2: u(t+1,x) EQUALS scr1(x+2); <-- orig halo of scr1 = 2. // Direct deps: eq2 -> eq1(s). // Halo of u must be increased to 1 + 2 = 3 due to - // eq1: u(t,x+1) on rhs and orig halo of scr on lhs. + // eq1: u(t,x+1) on rhs and orig halo of scr1 on lhs, + // i.e., because u(t+1,x) EQUALS u(t,(x+2)+1) by subst. - // Example: + // Example 2: // eq1: scr1(x) EQUALS u(t,x+1); <-- orig halo of u = 1. // eq2: scr2(x) EQUALS scr1(x+2); <-- orig halo of scr1 = 2. // eq3: u(t+1,x) EQUALS scr2(x+4); <-- orig halo of scr2 = 4. @@ -1105,15 +1106,18 @@ namespace yask { // eq2: scr1(x+2) on rhs and orig halo of scr2 on lhs. // Then, halo of u must be increased to 1 + 6 = 7 due to // eq1: u(t,x+1) on rhs and new halo of scr1 on lhs. + // Or, u(t+1,x) EQUALS u(t,((x+4)+2)+1) by subst. - // Example: + // Example 3: // eq1: scr1(x) EQUALS u(t,x+1); <--| // eq2: scr2(x) EQUALS u(t,x+2); <--| orig halo of u = max(1,2) = 2. // eq3: u(t+1,x) EQUALS scr1(x+3) + scr2(x+4); // eq1 and eq2 are bundled => scr1 and scr2 halos are max(3,4) = 4. // Direct deps: eq3 -> eq1(s), eq3 -> eq2(s). + // Halo of u is 4 + 2 = 6. + // Or, u(t+1,x) EQUALS u(t,(x+3)+1) + u(t,(x+4)+2) by subst. - // Keep a list of maps of shadow vars. + // Algo: Keep a list of maps of shadow vars. // Each map: key=real-var ptr, val=shadow-var ptr. // These shadow vars will be used to track // updated halos for each path. @@ -1227,6 +1231,7 @@ namespace yask { // also be written to. auto left_ohalo = og1->getHaloSizes(pname, true); auto right_ohalo = og1->getHaloSizes(pname, false); + auto l1Dist = og1->getL1Dist(); #ifdef DEBUG_SCRATCH cout << "** cH: processing " << b2->getDescr() << "...\n" @@ -1251,6 +1256,7 @@ namespace yask { ig->updateHalo(pname, left_ihalo); auto right_ihalo = ao.addElements(right_ohalo, false); ig->updateHalo(pname, right_ihalo); + ig->updateL1Dist(l1Dist); #ifdef DEBUG_SCRATCH cout << "*** cH: updated min halos of '" << ig->get_name() << "' to " << left_ihalo.makeDimValStr() << diff --git a/src/compiler/lib/Eqs.hpp b/src/compiler/lib/Eqs.hpp index 513dfb5e..477b1f32 100644 --- a/src/compiler/lib/Eqs.hpp +++ b/src/compiler/lib/Eqs.hpp @@ -64,6 +64,7 @@ namespace yask { return; // Add 'a' to copy of path. + // Important to make a separate copy for recursive calls. TpList seen1; if (seen) seen1 = *seen; // copy nodes already seen. diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index a3b699ae..b2b2f3b2 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -1039,26 +1039,5 @@ namespace yask { typedef set varPointPtrSet; typedef vector VarPointVec; - // Use SET_VALUE_FROM_EXPR for creating a string to insert any C++ code - // that evaluates to a real_t. - // The 1st arg must be the LHS of an assignment statement. - // The 2nd arg must evaluate to a real_t (float or double) expression, - // but it must NOT include access to a var. - // The code string is constructed as if writing to an ostream, - // so '<<' operators may be used to evaluate local variables. - // Floating-point variables will be printed w/o loss of precision. - // The code may access the following: - // - Any parameter to the 'calc_stencil_{cluster,scalar}' generated functions, - // including fields of the user-defined 'context' object. - // - A variable within the global or current namespace where it will be used. - // - A local variable in the 'value' method; in this case, the value - // of the local var must be evaluated and inserted in the expr. -#define SET_VALUE_FROM_EXPR(lhs, rhs) do { \ - ostringstream oss; \ - oss << setprecision(15) << scientific; \ - oss << "(" << rhs << ")"; \ - lhs make_shared(oss.str()); \ - } while(0) - } // namespace yask. diff --git a/src/compiler/lib/Var.cpp b/src/compiler/lib/Var.cpp index 381c818c..2aefd5ac 100644 --- a/src/compiler/lib/Var.cpp +++ b/src/compiler/lib/Var.cpp @@ -224,6 +224,7 @@ namespace yask { } } } + updateL1Dist(other._l1Dist); } // Update halos based on each value in 'offsets' in some @@ -240,6 +241,9 @@ namespace yask { stepVal = *p; } + // Manhattan dist of halo. + int l1Dist = 0; + // Update halo vals. for (auto& dim : offsets.getDims()) { auto& dname = dim.getName(); @@ -251,9 +255,13 @@ namespace yask { if (stepDim && dname == stepDim->getName()) continue; - // Store abs value. + // Store abs value (neg values are on "left"). val = abs(val); + // Track num dims. + if (val > 0) + l1Dist++; + // Any existing value? auto* p = halos.lookup(dname); @@ -267,6 +275,9 @@ namespace yask { // Else, current value is larger than val, so don't update. } + + // Update L1. + updateL1Dist(l1Dist); } // Update const indices based on 'indices'. diff --git a/src/compiler/lib/Var.hpp b/src/compiler/lib/Var.hpp index 322c74e1..facc25db 100644 --- a/src/compiler/lib/Var.hpp +++ b/src/compiler/lib/Var.hpp @@ -72,6 +72,9 @@ namespace yask { // int key: step-dim offset or 0 if no step-dim. map>> _halos; + // Greatest L1 dist of any halo point that accesses this var. + int _l1Dist = 0; + public: // Ctors. Var(string name, @@ -150,6 +153,11 @@ namespace yask { return h; } + // Get max L1 dist of halos. + virtual int getL1Dist() const { + return _l1Dist; + } + // Determine whether dims are same. virtual bool areDimsSame(const Var& other) const { if (_dims.size() != other._dims.size()) @@ -173,12 +181,17 @@ namespace yask { // Determine whether halo sizes are equal. virtual bool isHaloSame(const Var& other) const; - // Update halos based on halo in 'other' var. + // Update halos and L1 dist based on halo in 'other' var. virtual void updateHalo(const Var& other); - // Update halos based on each value in 'offsets'. + // Update halos and L1 dist based on each value in 'offsets'. virtual void updateHalo(const string& packName, const IntTuple& offsets); + // Update L1 dist. + virtual void updateL1Dist(int l1Dist) { + _l1Dist = max(_l1Dist, l1Dist); + } + // Update const indices based on 'indices'. virtual void updateConstIndices(const IntTuple& indices); diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 82d2edce..1ab3d7c5 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -354,12 +354,14 @@ namespace yask { } // Alloc-setting code. + bool gotDomain = false; for (auto& dim : gp->getDims()) { auto& dname = dim->getName(); auto dtype = dim->getType(); // domain dimension. if (dtype == DOMAIN_INDEX) { + gotDomain = true; // Halos for this dimension. for (bool left : { true, false }) { @@ -406,6 +408,15 @@ namespace yask { } } // dims. + // L1 dist. + if (gotDomain) { + auto l1var = var + "_l1_norm"; + os << " const int " << l1var << " = " << gp->getL1Dist() << + "; // Max L1-norm of MPI neighbor for halo exchanges.\n"; + initCode += " " + var + "_ptr->set_halo_exchange_l1_norm(" + + l1var + ");\n"; + } + // Allow dynamic misc alloc setting if not interleaved. initCode += " " + var + "_base_ptr->_set_dynamic_misc_alloc(" + (_settings._innerMisc ? "false" : "true") + diff --git a/src/kernel/Makefile b/src/kernel/Makefile index be925dc8..52402455 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -58,20 +58,7 @@ YC_STENCIL := $(stencil) ifeq ($(YC_STENCIL),) $(error Stencil not specified) -else ifeq ($(YC_STENCIL),3axis) - MACROS += MAX_EXCH_DIST=1 - -else ifeq ($(YC_STENCIL),3axis_with_diags) - MACROS += MAX_EXCH_DIST=2 - -else ifeq ($(YC_STENCIL),3plane) - MACROS += MAX_EXCH_DIST=2 - -else ifeq ($(YC_STENCIL),cube) - MACROS += MAX_EXCH_DIST=3 - else ifneq ($(findstring iso3dfd,$(YC_STENCIL)),) - MACROS += MAX_EXCH_DIST=1 def_pad_args := -ep 1 ifeq ($(arch),knl) fold := x=2,y=8 @@ -130,13 +117,11 @@ else ifneq ($(findstring fsg,$(YC_STENCIL)),) endif else ifeq ($(YC_STENCIL),tti) - MACROS += MAX_EXCH_DIST=3 ifneq ($(filter $(arch),skx skl clx),) def_block_args := -bx 80 -by 16 -bz 40 endif else ifeq ($(YC_STENCIL),stream) - MACROS += MAX_EXCH_DIST=0 cluster := x=2 endif # stencil-specific. diff --git a/src/kernel/lib/alloc.cpp b/src/kernel/lib/alloc.cpp index 8d1978df..3d3a28e9 100644 --- a/src/kernel/lib/alloc.cpp +++ b/src/kernel/lib/alloc.cpp @@ -255,30 +255,6 @@ namespace yask { if (neigh_rank == MPI_PROC_NULL) return; // from lambda fn. - // Determine max dist needed. TODO: determine max dist - // automatically from stencils; may not be same for all - // vars. -#ifndef MAX_EXCH_DIST -#define MAX_EXCH_DIST (NUM_STENCIL_DIMS - 1) -#endif - // Always use max dist with WF. Do this because edge - // and/or corner values may be needed in WF extensions - // even it not needed w/o WFs. - // TODO: determine if max is always needed. - int maxdist = MAX_EXCH_DIST; - if (wf_steps > 0) - maxdist = NUM_STENCIL_DIMS - 1; - - // Manhattan dist. of current neighbor. - int mandist = mpiInfo->man_dists.at(neigh_idx); - - // Check distance. - if (mandist > maxdist) { - TRACE_MSG("no halo exchange needed with rank " << neigh_rank << - " because L1-norm = " << mandist); - return; // from lambda fn. - } - // Is vectorized exchange allowed based on domain sizes? // Both my rank and neighbor rank must have *all* domain sizes // of vector multiples. @@ -300,6 +276,29 @@ namespace yask { auto& gname = gp->get_name(); bool var_vec_ok = vec_ok; + + // Get calculated max dist needed for this var. + int maxdist = gp->get_halo_exchange_l1_norm(); + + // Always use max dist with WF. Do this because edge + // and/or corner values may be needed in WF extensions + // even it not needed w/o WFs. + // TODO: determine if max is always needed. + if (wf_steps > 0) + maxdist = NUM_STENCIL_DIMS - 1; + + // Manhattan dist. of current neighbor. + int mandist = mpiInfo->man_dists.at(neigh_idx); + + // Check distance. + if (mandist > maxdist) { + TRACE_MSG("no halo exchange needed with rank " << neigh_rank << + " (L1-norm = " << mandist << + ") for var '" << gname << + "' (max L1-norm = " << maxdist << ")"); + continue; // to next var. + } + // Lookup first & last domain indices and calc exchange sizes // for this var. bool found_delta = false; @@ -578,17 +577,15 @@ namespace yask { } // all dims in this var. // Unique name for buffer based on var name, direction, and ranks. - ostringstream oss; - oss << gname; + string bname = gname; if (bd == MPIBufs::bufSend) - oss << "_send_halo_from_" << me << "_to_" << neigh_rank; + bname += "_send_halo_from_" + to_string(me) + "_to_" + to_string(neigh_rank); else if (bd == MPIBufs::bufRecv) - oss << "_recv_halo_from_" << neigh_rank << "_to_" << me; - string bufname = oss.str(); + bname += "_recv_halo_from_" + to_string(neigh_rank) + "_to_" + to_string(me); // Does buffer have non-zero size? if (buf_sizes.size() == 0 || buf_sizes.product() == 0) { - TRACE_MSG("MPI buffer '" << bufname << + TRACE_MSG("MPI buffer '" << bname << "' not needed because there is no data to exchange"); continue; } @@ -610,7 +607,7 @@ namespace yask { buf.begin_pt = copy_begin; buf.last_pt = copy_last; buf.num_pts = buf_sizes; - buf.name = bufname; + buf.name = bname; buf.vec_copy_ok = buf_vec_ok; TRACE_MSG("MPI buffer '" << buf.name << diff --git a/src/kernel/lib/realv.hpp b/src/kernel/lib/realv.hpp index 1cf9bcb4..765bf55b 100644 --- a/src/kernel/lib/realv.hpp +++ b/src/kernel/lib/realv.hpp @@ -23,7 +23,7 @@ IN THE SOFTWARE. *****************************************************************************/ -// This file defines a union to use for folded vectors of floats or doubles. +// This file defines a union to use for optionally-folded vectors of floats or doubles. #ifndef _REAL_VEC_H #define _REAL_VEC_H diff --git a/src/kernel/lib/yk_var.hpp b/src/kernel/lib/yk_var.hpp index 7ce67eaa..89112302 100644 --- a/src/kernel/lib/yk_var.hpp +++ b/src/kernel/lib/yk_var.hpp @@ -95,6 +95,9 @@ namespace yask { bool _is_dynamic_step_alloc = false; bool _is_dynamic_misc_alloc = false; + // Max L1 dist of halo accesses to this var. + int _l1Dist = 0; + // Data that needs to be copied to neighbor's halos if using MPI. // If this var has the step dim, there is one bit per alloc'd step. // Otherwise, only bit 0 is used. @@ -477,6 +480,14 @@ namespace yask { return gb()._local_offsets[+Indices::step_posn] + gb()._domains[+Indices::step_posn] - 1; } + virtual int + get_halo_exchange_l1_norm() const { + return gb()._l1Dist; + } + virtual void + set_halo_exchange_l1_norm(int norm) { + gb()._l1Dist = norm; + } #define GET_VAR_API(api_name) \ virtual idx_t api_name(const std::string& dim) const; \ diff --git a/src/stencils/TestStencils.cpp b/src/stencils/TestStencils.cpp index 20d37029..1e794eaf 100644 --- a/src/stencils/TestStencils.cpp +++ b/src/stencils/TestStencils.cpp @@ -51,7 +51,7 @@ class TestBase : public yc_solution_with_radius_base { virtual yc_number_node_ptr def_1d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, int left_ext, int right_ext) { yc_number_node_ptr v; - int n = 1; + int n = 0; for (int i = -_radius - left_ext; i <= _radius + right_ext; i++, n++) v += V(t0, x0+i); return v / n; @@ -62,7 +62,7 @@ class TestBase : public yc_solution_with_radius_base { virtual yc_number_node_ptr def_no_t_1d(yc_var_proxy& V, const yc_number_node_ptr& x0, int left_ext, int right_ext) { yc_number_node_ptr v; - int n = 1; + int n = 0; for (int i = -_radius - left_ext; i <= _radius + right_ext; i++, n++) v += V(x0+i); return v / n; @@ -78,10 +78,11 @@ class TestBase : public yc_solution_with_radius_base { int y_left_ext, int y_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) - for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++, n++) - if (i * j == 0 || i == j) - v += V(t0, x0+i, y0+j); + for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) + for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) { + v += V(t0, x0+i, y0+j); + n++; + } return v / n; } @@ -95,10 +96,11 @@ class TestBase : public yc_solution_with_radius_base { int y_left_ext, int y_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) - for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++, n++) - if (i * j == 0 || i == j) - v += V(x0+i, y0+j); + for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) + for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) { + v += V(x0+i, y0+j); + n++; + } return v / n; } @@ -114,11 +116,12 @@ class TestBase : public yc_solution_with_radius_base { int z_left_ext, int z_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) - for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++) - for (int k = -_radius - z_left_ext; k <= _radius + z_right_ext; k++, n++) - if (i * j * k == 0 || (i == j && j == k)) - v += V(t0, x0+i, y0+j, z0+k); + for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) + for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) + for (int k : { -_radius - z_left_ext, 0, _radius + z_right_ext }) { + v += V(t0, x0+i, y0+j, z0+k); + n++; + } return v / n; } @@ -134,11 +137,12 @@ class TestBase : public yc_solution_with_radius_base { int z_left_ext, int z_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i = -_radius - x_left_ext; i <= _radius + x_right_ext; i++) - for (int j = -_radius - y_left_ext; j <= _radius + y_right_ext; j++) - for (int k = -_radius - z_left_ext; k <= _radius + z_right_ext; k++, n++) - if (i * j * k == 0 || (i == j && j == k)) - v += V(x0+i, y0+j, z0+k); + for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) + for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) + for (int k : { -_radius - z_left_ext, 0, _radius + z_right_ext }) { + v += V(x0+i, y0+j, z0+k); + n++; + } return v / n; } @@ -160,9 +164,8 @@ class TestBase : public yc_solution_with_radius_base { for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) for (int k : { -_radius - z_left_ext, 0, _radius + z_right_ext }) { + v += V(t0, w0+h, x0+i, y0+j, z0+k); n++; - if (h * i * j * k == 0 || (h == i && i == j && j == k)) - v += V(t0, w0+h, x0+i, y0+j, z0+k); } return v / n; } From a4fb36cfd5d2ff3f90d8bfc4770c5738667bb790 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 14 May 2019 09:28:05 -0700 Subject: [PATCH 28/62] Add some missing backward-compat methods. Also, - bit of cleanup. - make deprecated methods inline calls. - remove stream-soln cluster setting. --- include/aux/yc_node_api.hpp | 2 +- include/aux/yk_solution_api.hpp | 16 ++--- include/aux/yk_var_api.hpp | 58 ++++++---------- include/yask_compiler_api.hpp | 98 +++++++++++++++++---------- include/yask_compiler_utility_api.hpp | 6 +- src/compiler/swig/yask_compiler_api.i | 14 ++++ src/kernel/Makefile | 3 - src/kernel/lib/yk_var.hpp | 3 - src/kernel/lib/yk_var_apis.cpp | 6 -- src/kernel/swig/yask_kernel_api.i | 10 +++ 10 files changed, 117 insertions(+), 99 deletions(-) diff --git a/include/aux/yc_node_api.hpp b/include/aux/yc_node_api.hpp index a2aba73a..80dd4191 100644 --- a/include/aux/yc_node_api.hpp +++ b/include/aux/yc_node_api.hpp @@ -289,7 +289,7 @@ namespace yask { get_var() =0; /// **[Deprecated]** Use get_var(). - virtual yc_var_ptr + inline yc_var_ptr get_grid() { return get_var(); } diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index e3af6f59..c04c657c 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -869,25 +869,25 @@ namespace yask { get_step_wrap() const =0; /// **[Deprecated]** Use get_num_vars(). - virtual int + inline int get_num_grids() const { return get_num_vars(); } /// **[Deprecated]** Use get_var(). - virtual yk_var_ptr + inline yk_var_ptr get_grid(const std::string& name) { return get_var(name); } /// **[Deprecated]** Use get_vars(). - virtual std::vector + inline std::vector get_grids() { return get_vars(); } /// **[Deprecated]** Use new_var(). - virtual yk_var_ptr + inline yk_var_ptr new_grid(const std::string& name, const std::vector& dims) { return new_var(name, dims); @@ -895,7 +895,7 @@ namespace yask { #ifndef SWIG /// **[Deprecated]** Use new_var(). - virtual yk_var_ptr + inline yk_var_ptr new_grid(const std::string& name, const std::initializer_list& dims) { return new_var(name, dims); @@ -903,7 +903,7 @@ namespace yask { #endif /// **[Deprecated]** Use new_fixed_size_var(). - virtual yk_var_ptr + inline yk_var_ptr new_fixed_size_grid(const std::string& name, const std::vector& dims, const std::vector& dim_sizes) { @@ -912,7 +912,7 @@ namespace yask { #ifndef SWIG /// **[Deprecated]** Use new_fixed_size_var(). - virtual yk_var_ptr + inline yk_var_ptr new_fixed_size_grid(const std::string& name, const std::initializer_list& dims, const std::vector& dim_sizes) { @@ -921,7 +921,7 @@ namespace yask { #endif /// **[Deprecated]** Use fuse_vars(). - virtual void + inline void fuse_grids(yk_solution_ptr source) { fuse_vars(source); } diff --git a/include/aux/yk_var_api.hpp b/include/aux/yk_var_api.hpp index 5c8210bd..892dd198 100644 --- a/include/aux/yk_var_api.hpp +++ b/include/aux/yk_var_api.hpp @@ -1093,50 +1093,32 @@ namespace yask { /* Deprecated APIs for yk_var found below should be avoided. Use the more explicit form found in the documentation. */ - /// **[Deprecated]** Get the left halo size in the specified dimension. - /** - Alias for get_left_halo_size(dim, size). - @returns Elements in halo in given dimension before the domain. - */ - virtual idx_t - get_halo_size(const std::string& dim - /**< [in] Name of dimension to get. - Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; - - /// **[Deprecated]** Get the left padding in the specified dimension. - /** - Alias for get_left_pad_size(dim). - @returns Elements in left padding in given dimension. - */ - virtual idx_t - get_pad_size(const std::string& dim - /**< [in] Name of dimension to get. - Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; - - /// **[Deprecated]** Get the extra left padding in the specified dimension. - /** - Alias for get_extra_left_pad_size(dim). - @returns Elements in padding in given dimension before the - left halo area. - */ - virtual idx_t - get_extra_pad_size(const std::string& dim - /**< [in] Name of dimension to get. - Must be one of - the names from yk_solution::get_domain_dim_names(). */ ) const =0; + /// **[Deprecated]** Use get_left_halo_size() and get_right_halo_size(). + inline idx_t + get_halo_size(const std::string& dim) const { + return get_left_halo_size(dim); + } + /// **[Deprecated]** Use get_left_pad_size() and get_right_pad_size(). + inline idx_t + get_pad_size(const std::string& dim) const { + return get_left_pad_size(dim); + } + /// **[Deprecated]** Use get_left_extra_pad_size() and get_right_extra_pad_size(). + inline idx_t + get_extra_pad_size(const std::string& dim) const { + return get_left_extra_pad_size(dim); + } - /// **[Deprecated]** Use are_indices_local() instead. - virtual bool + /// **[Deprecated]** Use are_indices_local(). + inline bool is_element_allocated(const std::vector& indices /**< [in] List of indices, one for each var dimension. */ ) const { return are_indices_local(indices); } #ifndef SWIG - /// **[Deprecated]** Use are_indices_local() instead. - virtual bool + /// **[Deprecated]** Use are_indices_local(). + inline bool is_element_allocated(const std::initializer_list& indices /**< [in] List of indices, one for each var dimension. */ ) const { return are_indices_local(indices); @@ -1144,7 +1126,7 @@ namespace yask { #endif /// **[Deprecated]** Use fuse_vars(). - virtual void + inline void fuse_grids(yk_var_ptr source) { fuse_vars(source); } diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index b3f3d09e..3717910b 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -517,7 +517,7 @@ namespace yask { clear_dependencies() =0; /// **[Deprecated]** Use new_var(). - virtual yc_var_ptr + inline yc_var_ptr new_grid(const std::string& name, const std::vector& dims) { return new_var(name, dims); @@ -525,7 +525,7 @@ namespace yask { #ifndef SWIG /// **[Deprecated]** Use new_var(). - virtual yc_var_ptr + inline yc_var_ptr new_grid(const std::string& name, const std::initializer_list& dims) { return new_var(name, dims); @@ -533,7 +533,7 @@ namespace yask { #endif /// **[Deprecated]** Use new_scratch_var(). - virtual yc_var_ptr + inline yc_var_ptr new_scratch_grid(const std::string& name, const std::vector& dims) { return new_scratch_var(name, dims); @@ -541,7 +541,7 @@ namespace yask { #ifndef SWIG /// **[Deprecated]** Use new_scratch_var(). - virtual yc_var_ptr + inline yc_var_ptr new_scratch_grid(const std::string& name, const std::initializer_list& dims) { return new_scratch_var(name, dims); @@ -549,23 +549,23 @@ namespace yask { #endif /// **[Deprecated]** Use get_num_vars(). - virtual int + inline int get_num_grids() const { return get_num_vars(); } /// **[Deprecated]** Use get_vars(). - virtual std::vector + inline std::vector get_grids() { return get_vars(); } /// **[Deprecated]** Use get_var(). - virtual yc_var_ptr + inline yc_var_ptr get_grid(const std::string& name) { return get_var(name); } - }; + }; // yc_solution. /// A compile-time data variable. /** "Var" is a generic term for any n-dimensional variable. A 0-dim var @@ -691,7 +691,29 @@ namespace yask { virtual void set_step_alloc_size(idx_t size /**< [in] Number of elements to allocate in the step dimension. */) =0; - }; + + /// **[Deprecated]** Use new_var_point(). + inline yc_var_point_node_ptr + new_grid_point(const std::vector& index_exprs) { + return new_var_point(index_exprs); + } + /// **[Deprecated]** Use new_var_point(). + inline yc_var_point_node_ptr + new_grid_point(const std::initializer_list& index_exprs) { + return new_var_point(index_exprs); + } + /// **[Deprecated]** Use new_relative_var_point(). + inline yc_var_point_node_ptr + new_relative_grid_point(const std::vector& dim_offsets) { + return new_relative_var_point(dim_offsets); + } + /// **[Deprecated]** Use new_relative_var_point(). + inline yc_var_point_node_ptr + new_relative_grid_point(const std::initializer_list& dim_offsets) { + return new_relative_var_point(dim_offsets); + } + + }; // yc_var. /// A wrapper or "proxy" class around a \ref yc_var pointer. /** @@ -718,10 +740,10 @@ namespace yask { ~~~ Compare to the example shown in yc_solution::new_var(). - *Scoping and lifetime:* Since the \ref yc_var pointer in a \ref + _Scoping and lifetime:_ Since the \ref yc_var pointer in a \ref yc_var_proxy object is a shared pointer also owned by the \ref yc_solution object used to construct the \ref yc_var_proxy object, the - underlying var will not be destroyed until both the \ref yc_var_proxy + underlying YASK var will not be destroyed until both the \ref yc_var_proxy object and the \ref yc_solution object are destroyed. A \ref yc_var_proxy object created from an existing \ref yc_var object will have the same properties. @@ -741,7 +763,7 @@ namespace yask { /**< [in] Name of the new var; must be a valid C++ identifier and unique across vars. */, yc_solution_ptr soln - /**< [in] Pointer to solution that will own the var. */, + /**< [in] Shared pointer to solution that will share ownership of the \ref yc_var. */, const std::vector< yc_index_node_ptr > &dims /**< [in] Dimensions of the var. Each dimension is identified by an associated index. */, @@ -835,34 +857,11 @@ namespace yask { return _var->new_var_point(index_exprs); } - /// Create an expression for a point in a zero-dim (scalar) var using implicit conversion. - /** - A wrapper around yc_var::new_var_point(). - - Example w/0D var `B`: `A(t+1, x) EQUALS A(t, x) + B`. - @note Not available in Python API. - Use vector version with empty vector. - */ - virtual operator yc_number_ptr_arg() { - return _var->new_var_point({}); - } - - /// Create an expression for a point in a one-dim (array) var. - /** - A wrapper around yc_var::new_var_point(). - - Example w/1D var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. - @note Not available in Python API. - Use vector version with 1-element vector. - */ - virtual yc_var_point_node_ptr operator[](const yc_number_any_arg i1) { - return _var->new_var_point({i1}); - } - /// Create an expression for a point in a 1-6 dim var. /** A wrapper around yc_var::new_var_point(). The number of non-null arguments must match the dimensionality of the var. + For more than 6 dims, use the vector or initializer-list version. Example w/2D var `B`: `A(t+1, x) EQUALS A(t, x) + B(x, 3)`. @note Not available in Python API. Use vector version. @@ -888,9 +887,34 @@ namespace yask { args.push_back(i6); return _var->new_var_point(args); } + + /// Create an expression for a point in a zero-dim (scalar) var using implicit conversion. + /** + A wrapper around yc_var::new_var_point(). + + Example w/0D var `B`: `A(t+1, x) EQUALS A(t, x) + B`. + @note Not available in Python API. + Use vector version with empty vector. + */ + virtual operator yc_number_ptr_arg() { + return _var->new_var_point({}); + } + + /// Create an expression for a point in a one-dim (array) var. + /** + A wrapper around yc_var::new_var_point(). + + Example w/1D var `B`: `A(t+1, x) EQUALS A(t, x) + B[x]`. + @note Not available in Python API. + Use vector version with 1-element vector. + */ + virtual yc_var_point_node_ptr operator[](const yc_number_any_arg i1) { + return _var->new_var_point({i1}); + } + #endif - }; + }; // yc_var_proxy. /** @}*/ /// **[Deprecated]** Use yc_var. diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index 4d4c951f..5748116c 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -47,15 +47,15 @@ namespace yask { * @{ */ - /// The class all C++ stencil solutions written for the YASK compiler utility `yask_compiler.exe` must implement. + /// All C++ stencil solutions written for the YASK compiler utility must implement this class. /** - Mostly, this is a wrapper around a \ref yc_solution pointer. + This is a wrapper around a \ref yc_solution pointer. The `define()` method must be overloaded by the YASK DSL programmer to add stencil equations. Not to be used by DSL code that is not a part of the YASK compiler utility `yask_compiler.exe`. For DSL code not using this utility, - call yc_factory::new_solution directly. + call yc_factory::new_solution(), yc_solution::format(), etc. directly. */ class yc_solution_base { private: diff --git a/src/compiler/swig/yask_compiler_api.i b/src/compiler/swig/yask_compiler_api.i index a0f5c786..72b7fc9c 100644 --- a/src/compiler/swig/yask_compiler_api.i +++ b/src/compiler/swig/yask_compiler_api.i @@ -70,6 +70,20 @@ IN THE SOFTWARE. %shared_ptr(yask::yc_number_const_arg) %shared_ptr(yask::yc_number_any_arg) +// From http://www.swig.org/Doc4.0/SWIG.html#SWIG_nn2: Everything in the %{ +// ... %} block is simply copied verbatim to the resulting wrapper file +// created by SWIG. This section is almost always used to include header +// files and other declarations that are required to make the generated +// wrapper code compile. It is important to emphasize that just because you +// include a declaration in a SWIG input file, that declaration does not +// automatically appear in the generated wrapper code---therefore you need +// to make sure you include the proper header files in the %{ ... %} +// section. It should be noted that the text enclosed in %{ ... %} is not +// parsed or interpreted by SWIG. +%{ +#define SWIG_FILE_WITH_INIT +#include "yask_kernel_api.hpp" +%} %{ #define SWIG_FILE_WITH_INIT #include "yask_compiler_api.hpp" diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 52402455..b89012cd 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -121,9 +121,6 @@ else ifeq ($(YC_STENCIL),tti) def_block_args := -bx 80 -by 16 -bz 40 endif -else ifeq ($(YC_STENCIL),stream) - cluster := x=2 - endif # stencil-specific. # Defaut settings based on architecture. diff --git a/src/kernel/lib/yk_var.hpp b/src/kernel/lib/yk_var.hpp index 89112302..958a43cb 100644 --- a/src/kernel/lib/yk_var.hpp +++ b/src/kernel/lib/yk_var.hpp @@ -523,15 +523,12 @@ namespace yask { GET_VAR_API(get_last_rank_domain_index) GET_VAR_API(get_left_halo_size) GET_VAR_API(get_right_halo_size) - GET_VAR_API(get_halo_size) GET_VAR_API(get_first_rank_halo_index) GET_VAR_API(get_last_rank_halo_index) GET_VAR_API(get_left_extra_pad_size) GET_VAR_API(get_right_extra_pad_size) - GET_VAR_API(get_extra_pad_size) GET_VAR_API(get_left_pad_size) GET_VAR_API(get_right_pad_size) - GET_VAR_API(get_pad_size) GET_VAR_API(get_alloc_size) GET_VAR_API(get_first_rank_alloc_index) GET_VAR_API(get_last_rank_alloc_index) diff --git a/src/kernel/lib/yk_var_apis.cpp b/src/kernel/lib/yk_var_apis.cpp index 19760902..b36cfaf1 100644 --- a/src/kernel/lib/yk_var_apis.cpp +++ b/src/kernel/lib/yk_var_apis.cpp @@ -82,12 +82,6 @@ namespace yask { gb()._right_halos[posn] - 1, false, true, false, true) GET_VAR_API(get_first_rank_alloc_index, gb().get_first_local_index(posn), false, true, false, true) GET_VAR_API(get_last_rank_alloc_index, gb().get_last_local_index(posn), false, true, false, true) - - // Deprecated APIs. - GET_VAR_API(get_pad_size, gb()._actl_left_pads[posn]; DEPRECATED(get_pad_size), false, true, false, false) - GET_VAR_API(get_halo_size, gb()._left_halos[posn]; DEPRECATED(get_halo_size), false, true, false, false) - GET_VAR_API(get_extra_pad_size, gb()._actl_left_pads[posn] - gb()._left_halos[posn]; - DEPRECATED(get_extra_pad_size), false, true, false, false) #undef GET_VAR_API // APIs to set vars. diff --git a/src/kernel/swig/yask_kernel_api.i b/src/kernel/swig/yask_kernel_api.i index 7e6bf8fd..cff20a5e 100644 --- a/src/kernel/swig/yask_kernel_api.i +++ b/src/kernel/swig/yask_kernel_api.i @@ -48,6 +48,16 @@ IN THE SOFTWARE. // Mutable buffer to access raw data. %pybuffer_mutable_string(void* buffer_ptr) +// From http://www.swig.org/Doc4.0/SWIG.html#SWIG_nn2: Everything in the %{ +// ... %} block is simply copied verbatim to the resulting wrapper file +// created by SWIG. This section is almost always used to include header +// files and other declarations that are required to make the generated +// wrapper code compile. It is important to emphasize that just because you +// include a declaration in a SWIG input file, that declaration does not +// automatically appear in the generated wrapper code---therefore you need +// to make sure you include the proper header files in the %{ ... %} +// section. It should be noted that the text enclosed in %{ ... %} is not +// parsed or interpreted by SWIG. %{ #define SWIG_FILE_WITH_INIT #include "yask_kernel_api.hpp" From d49cbf115a0046c776273053893ee4ed23f88910 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 14 May 2019 14:24:39 -0700 Subject: [PATCH 29/62] Replace codenames with ISA names. Closes #205. --- README.md | 49 +++++++++----- src/kernel/Makefile | 127 +++++++++++++++++++---------------- src/kernel/lib/soln_apis.cpp | 9 ++- src/kernel/yask.sh | 6 +- utils/lib/YaskUtils.pm | 14 +++- 5 files changed, 120 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 02fef3bc..a0d25627 100644 --- a/README.md +++ b/README.md @@ -71,23 +71,38 @@ YASK contains a domain-specific compiler to convert stencil-equation specificati ## Backward-compatibility notices, including changes in default behavior ### Version 3 -* Version 3.00.00 implemented a unification of the old (v1 and v2) internal -DSL that used undocumented types such as `SolutionBase` and `GridValue` and -undocumented macros such as `MAKE_GRID` with the newer documented YASK -compiler API. Canonical v2 DSL code should still work using the `Soln.hpp` -backward-compatibility header file. To convert v2 DSL code to v3 format, -use the `./utils/bin/convert_v2_stencil.pl` utility. Also, for both the -compiler and kernel APIs, all uses of the term "grid" were changed to "var". -(Historically, early versions of YASK allowed only variables whose elements -were points on the domain grid, so the terms were essentially -interchangeable. Later, variables became more flexible. They could be -defined with a subset of the domain dimensions, include non-domain or -"miscellaneous" indices, or even be simple scalar values, so the term "grid" -to describe any variable became inaccurate. This change addresses that -contradiction.) Again, backward-compatibility features in the API should -maintain functionality of v2 DSL and kernel code. However, old DSL and -kernel code or user-written output-parsing scripts that use any -undocumented files, data, or types may have to be updated. +* Version 3.00.00 was a major release with a number of backward-compatibility notices: + + - The old (v1 and v2) internal DSL that used undocumented types such as + `SolutionBase` and `GridValue` and undocumented macros such as + `MAKE_GRID` was replaced with an expanded version of the documented YASK + compiler API. Canonical v2 DSL code should still work using the + `Soln.hpp` backward-compatibility header file. To convert v2 DSL code + to v3 format, use the `./utils/bin/convert_v2_stencil.pl` utility. + Conversion is recommended. + + - For both the compiler and kernel APIs, all uses of the term "grid" were + changed to "var". (Historically, early versions of YASK allowed only + variables whose elements were points on the domain grid, so the terms + were essentially interchangeable. Later, variables became more flexible. + They could be defined with a subset of the domain dimensions, include + non-domain or "miscellaneous" indices, or even be simple scalar values, + so the term "grid" to describe any variable became inaccurate. This + change addresses that contradiction.) Again, backward-compatibility + features in the API should maintain functionality of v2 DSL and kernel + code. + + - The default strings used in the kernel library and filenames to identify + the targeted architecture were changed from Intel CPU codenames to + [approximate] instruction-set architecture (ISA) names "avx512", "avx2", + "avx", "knl", "knc", or "intel64". + + - The "mid" (roughly, median) performance results are now the first + ones printed by the `utils/bin/yask_log_to_csv.pl` script. + + - In general, any old DSL and kernel code or user-written output-parsing + scripts that use any undocumented files, data, or types may have to be + updated. ### Version 2 * Version 2.22.00 changed the heuristic to determine vector-folding sizes when some diff --git a/src/kernel/Makefile b/src/kernel/Makefile index b89012cd..55f86555 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -43,105 +43,122 @@ check ?= 0 # it adds a few MiB to the binary and can impact perfomance # even if not used, but only around 1%. -# Determine default architecture by running kernel script w/special knob. -# Do not assume it has been installed in $(BIN_OUT_DIR) yet. -arch ?= $(shell $(BASH) ./yask.sh -show_arch) +# If 'arch' isn't set, determine default architecture by running kernel +# script w/special knob. Do not assume it has been installed in +# $(BIN_OUT_DIR) yet. +arch ?= $(shell $(BASH) ./yask.sh -show_arch) -# Specify YK_STENCIL and/or YK_ARCH to name binaries differently. +# Specify YK_STENCIL and/or YK_ARCH on 'make' cmd-line to name binaries differently. YK_STENCIL := $(stencil) YK_ARCH := $(arch) -# Specify YC_STENCIL to pass different stencil name to YASK compiler. +# Specify YC_STENCIL on 'make' cmd-line to pass different stencil name to YASK compiler. YC_STENCIL := $(stencil) +# Set 'ARCH', converting old codenames to ISA names. +ifneq ($(filter $(arch),avx snb ivb),) + ARCH := avx +else ifneq ($(filter $(arch),avx2 hsw bdw),) + ARCH := avx2 +else ifneq ($(filter $(arch),avx512 skx skl clx),) + ARCH := avx512 +else ifneq ($(filter $(arch),knl),) + ARCH := knl +else ifneq ($(filter $(arch),knc),) + ARCH := knc +else ifneq ($(filter $(arch),intel64),) + ARCH := intel64 +else + $(error Instruction-set architecture (ISA) not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64 (no explicit vectorization)) +endif + # Defaults based on stencil type (and arch for some stencils). ifeq ($(YC_STENCIL),) $(error Stencil not specified) else ifneq ($(findstring iso3dfd,$(YC_STENCIL)),) def_pad_args := -ep 1 - ifeq ($(arch),knl) + ifeq ($(ARCH),knl) fold := x=2,y=8 cluster := x=2 def_block_args := -bx 160 -by 256 -bz 96 pfd_l1 := 1 pfd_l2 := 0 - else ifneq ($(filter $(arch),hsw bdw),) - def_block_args := -bx 48 -by 60 -bz 112 - pfd_l1 := 0 - pfd_l2 := 0 - else ifneq ($(filter $(arch),skx skl clx),) + else ifeq ($(arch),avx512) def_block_args := -bx 108 -by 28 -bz 132 pfd_l1 := 0 pfd_l2 := 2 + else + def_block_args := -bx 48 -by 60 -bz 112 + pfd_l1 := 0 + pfd_l2 := 0 endif else ifneq ($(findstring awp,$(YC_STENCIL)),) YC_FLAGS += -min-es 1 def_pad_args := -ep 1 - ifeq ($(arch),knl) + ifeq ($(ARCH),knl) def_thread_divisor := 2 def_block_threads := 4 def_block_args := -bx 48 -by 48 -bx 112 pfd_l1 := 1 pfd_l2 := 0 - else ifneq ($(filter $(arch),hsw bdw),) - def_block_args := -bx 64 -by 8 -bz 64 - pfd_l1 := 1 - pfd_l2 := 2 - else ifneq ($(filter $(arch),skx skl clx),) + else ifeq ($(ARCH),avx512) def_block_args := -bx 64 -by 8 -bz 108 pfd_l1 := 1 pfd_l2 := 0 + else + def_block_args := -bx 64 -by 8 -bz 64 + pfd_l1 := 1 + pfd_l2 := 2 endif else ifneq ($(findstring ssg,$(YC_STENCIL)),) - ifneq ($(filter $(arch),hsw bdw),) - def_block_args := -bx 64 -by 16 -bz 96 - else ifneq ($(filter $(arch),skx skl clx),) + ifeq ($(ARCH),avx512) def_block_args := -bx 96 -by 16 -bz 80 + else + def_block_args := -bx 64 -by 16 -bz 96 endif else ifneq ($(findstring fsg,$(YC_STENCIL)),) - ifeq ($(arch),knl) + ifeq ($(ARCH),knl) omp_region_schedule := guided def_block_args := -b 16 def_thread_divisor := 4 def_block_threads := 2 pfd_l1 := 0 pfd_l2 := 2 - else ifneq ($(filter $(arch),hsw bdw),) - def_block_args := -bx 48 -by 4 -bz 128 - else ifneq ($(filter $(arch),skx skl clx),) + else ifeq ($(ARCH),avx512) def_block_args := -bx 188 -by 12 -bz 24 + else + def_block_args := -bx 48 -by 4 -bz 128 endif else ifeq ($(YC_STENCIL),tti) - ifneq ($(filter $(arch),skx skl clx),) + ifeq ($(ARCH),avx512) def_block_args := -bx 80 -by 16 -bz 40 endif endif # stencil-specific. -# Defaut settings based on architecture. -# (Use '?=' to avoid replacing above settings.) -ifeq ($(arch),knc) +# Default settings based on architecture. +ifeq ($(ARCH),knc) - ISA ?= -mmic + ICC_ISA ?= -mmic MACROS += USE_INTRIN512 YC_TARGET ?= knc def_block_threads ?= 4 pfd_l1 ?= 1 pfd_l2 ?= 2 -else ifeq ($(arch),knl) +else ifeq ($(ARCH),knl) # NUMA_PREF=1 causes YASK to use MCDRAM on a node in "flat" memory mode. It # will fall-back to NUMA node 0 in "cache" memory mode. It will *NOT* do # the right thing by default in SNC-2 or SNC-4 clustering modes (using # either flat or cache memory modes, but these configurations are uncommon. - ISA ?= -xMIC-AVX512 - GCXX_ISA ?= -march=knl + ICC_ISA ?= -xMIC-AVX512 + GCC_ISA ?= -march=knl MACROS += USE_INTRIN512 USE_RCP28 NUMA_PREF=1 YC_TARGET ?= avx512 def_block_args ?= -b 64 @@ -149,45 +166,36 @@ else ifeq ($(arch),knl) pfd_l1 ?= 1 pfd_l2 ?= 0 -else ifneq ($(filter $(arch),skx skl clx),) +else ifeq ($(ARCH),avx512) - # Note that 'skl' targets the server SKUs with avx512 ISA, - # not the client SKUs without. - ISA ?= -xCORE-AVX512 - GCXX_ISA ?= -march=knl -mno-avx512er -mno-avx512pf + ICC_ISA ?= -xCORE-AVX512 + GCC_ISA ?= -march=knl -mno-avx512er -mno-avx512pf MACROS += USE_INTRIN512 YC_TARGET ?= avx512 -else ifneq ($(filter $(arch),hsw bdw),) +else ifeq ($(ARCH),avx2) - ISA ?= -xCORE-AVX2 - GCXX_ISA ?= -march=haswell + ICC_ISA ?= -xCORE-AVX2 + GCC_ISA ?= -march=haswell MACROS += USE_INTRIN256 USE_AVX2 YC_TARGET ?= avx2 -else ifeq ($(arch),ivb) - - ISA ?= -xCORE-AVX-I - GCXX_ISA ?= -march=ivybridge - MACROS += USE_INTRIN256 - YC_TARGET ?= avx - -else ifeq ($(arch),snb) +else ifeq ($(ARCH),avx) - ISA ?= -xAVX - GCXX_ISA ?= -march=sandybridge + ICC_ISA ?= -xAVX + GCC_ISA ?= -march=sandybridge MACROS += USE_INTRIN256 YC_TARGET ?= avx -else ifeq ($(arch),intel64) +else ifeq ($(ARCH),intel64) - ISA ?= -xHOST - GCXX_ISA ?= -march=native + ICC_ISA ?= -xHOST + GCC_ISA ?= -march=native YC_TARGET ?= cpp else -$(error Architecture not recognized; use arch=knl, knc, clx, skx, hsw, bdw, ivb, snb, or intel64 (no explicit vectorization)) +$(error Internal error: arch lists are not consistent) endif # arch-specific. @@ -256,7 +264,7 @@ YK_OUT_DIR := $(BUILD_OUT_DIR)/kernel # Dir for output files dependent on arch but # not on the stencil. -YK_ARCH_DIR := $(YK_OUT_DIR)/$(arch) +YK_ARCH_DIR := $(YK_OUT_DIR)/$(YK_ARCH) YK_OBJ_DIR := $(YK_ARCH_DIR)/obj # Dirs for stencil-specific output files. @@ -387,8 +395,8 @@ DEF_ARGS += $(def_block_args) $(def_pad_args) $(more_def_args) YK_CXXFLAGS += -DDEF_ARGS='"$(DEF_ARGS) $(EXTRA_DEF_ARGS)"' # arch. -ARCH := $(shell echo $(arch) | tr '[:lower:]' '[:upper:]') -MACROS += ARCH_$(ARCH) +UC_ARCH := $(shell echo $(ARCH) | tr '[:lower:]' '[:upper:]') +MACROS += ARCH_$(UC_ARCH) ARCH_NAME=$(ARCH) # MPI settings. ifeq ($(mpi),1) @@ -433,7 +441,7 @@ ifneq ($(filter %icpc %icc,$(notdir $(YK_CXX))),) # Intel compiler # Use 512-bit code on SKX and CLX. # (Commented out because it doesn't help performance, and it breaks Devito.) -ifneq ($(filter $(arch),skx skl clx),) +ifeq ($(ARCH),avx512) #YK_CXXFLAGS += -qopt-zmm-usage=high endif @@ -869,6 +877,7 @@ realclean: clean echo-settings: @echo "Build environment for" $(YK_EXEC) on `date`; \ $(YK_CXX) --version; \ + echo ARCH=$(ARCH); \ echo BLOCK_LOOP_CODE="\"$(BLOCK_LOOP_CODE)\""; \ echo BLOCK_LOOP_INNER_MODS="\"$(BLOCK_LOOP_INNER_MODS)\""; \ echo BLOCK_LOOP_OPTS="\"$(BLOCK_LOOP_OPTS)\""; \ @@ -969,7 +978,7 @@ help: echo " "; \ echo "Example debug builds of kernel cmd-line tool:"; \ echo " $(MAKE) clean; $(MAKE) -j stencil=iso3dfd mpi=0 OMPFLAGS='-qopenmp-stubs' YK_CXXOPT='-O0' check=1 # No optimization, OpenMP or MPI; internal checking."; \ - echo " $(MAKE) clean; $(MAKE) -j arch=intel64 stencil=test_2d mpi=0 OMPFLAGS='-qopenmp-stubs' YK_CXXOPT='-O0' trace=1 # Enable tracing; run with '-trace' to get trace."; \ + echo " $(MAKE) clean; $(MAKE) -j arch=avx stencil=test_2d mpi=0 OMPFLAGS='-qopenmp-stubs' YK_CXXOPT='-O0' trace=1 # Enable tracing; run with '-trace' to get trace."; \ echo " $(MAKE) clean; $(MAKE) -j arch=intel64 stencil=3axis radius=0 fold='x=1,y=1,z=1' mpi=0 YK_CXX=g++ OMPFLAGS='' YK_CXXOPT='-O0' trace_mem=1 # Trace all mem accesses with '-trace'."; \ echo " "; \ echo "Example builds with test runs:"; \ diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 088ad905..4e49933b 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -190,8 +190,11 @@ namespace yask { STATE_VARS(this); os << - " num-wave-front-steps: " << wf_steps << endl; - if (wf_steps > 0) { + " num-wave-front-steps: " << wf_steps << endl << + " num-temporal-block-steps: " << tb_steps << endl; + + // Print detailed info only if temporal tiling enabled. + if (wf_steps > 0 || tb_steps > 0) { os << " wave-front-angles: " << wf_angles.makeDimValStr() << endl << " num-wave-front-shifts: " << num_wf_shifts << endl << @@ -200,7 +203,6 @@ namespace yask { " right-wave-front-exts: " << right_wf_exts.makeDimValStr() << endl << " ext-local-domain: " << ext_bb.bb_begin.makeDimValStr() << " ... " << ext_bb.bb_end.subElements(1).makeDimValStr() << endl << - " num-temporal-block-steps: " << tb_steps << endl << " temporal-block-angles: " << tb_angles.makeDimValStr() << endl << " num-temporal-block-shifts: " << num_tb_shifts << endl << " temporal-block-long-base: " << tb_widths.makeDimValStr(" * ") << endl << @@ -243,6 +245,7 @@ namespace yask { #endif os << "\nOther settings:\n" " yask-version: " << yask_get_version_string() << endl << + " target-ISA: " << YSTR2(ARCH_NAME) << endl << " stencil-name: " << get_name() << endl << " stencil-description: " << get_description() << endl << " element-size: " << makeByteStr(get_element_bytes()) << endl << diff --git a/src/kernel/yask.sh b/src/kernel/yask.sh index bf1f02fc..79cf052b 100755 --- a/src/kernel/yask.sh +++ b/src/kernel/yask.sh @@ -49,13 +49,13 @@ fi # Default arch. cpu_flags=`grep -m1 '^flags' /proc/cpuinfo` if [[ $cpu_flags =~ avx512dq ]]; then - arch=skx + arch=avx512 elif [[ $cpu_flags =~ avx512pf ]]; then arch=knl elif [[ $cpu_flags =~ avx2 ]]; then - arch=hsw + arch=avx2 elif [[ $cpu_flags =~ avx ]]; then - arch=snb + arch=avx else arch=intel64 fi diff --git a/utils/lib/YaskUtils.pm b/utils/lib/YaskUtils.pm index f4e71e8e..ff3e5ef9 100644 --- a/utils/lib/YaskUtils.pm +++ b/utils/lib/YaskUtils.pm @@ -45,16 +45,23 @@ our @special_log_keys = our @log_keys = ( # values from binary. + 'mid throughput (num-points/sec)', + 'mid throughput (num-reads/sec)', + 'mid throughput (num-writes/sec)', + 'mid throughput (est-FLOPS)', + 'mid elapsed time (sec)', + 'mid num-steps-done', 'best throughput (num-points/sec)', 'best throughput (num-reads/sec)', 'best throughput (num-writes/sec)', 'best throughput (est-FLOPS)', 'best elapsed time (sec)', 'best num-steps-done', - 'mid throughput (num-points/sec)', - 'version', + 'yask version', + 'target ISA', 'stencil name', 'stencil description', + 'element size', 'invocation', 'binary invocation', 'num MPI ranks', @@ -307,7 +314,8 @@ sub printCsvValues($$) { for my $m (@all_log_keys) { my $r = $results->{$m}; $r = '' if !defined $r; - $r = '"'.$r.'"' if $r !~ /^[0-9.e+-]+$/; # add quotes if not a number. + $r = '"'.$r.'"' # add quotes if not a number. + if $r !~ /^[0-9.e+-]+$/ || $r =~ /[.].*[.]/; push @cols, $r; } print $fh join(',', @cols); From de7321f89e7b94331202da9bfaef407a345df162 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 14 May 2019 14:32:06 -0700 Subject: [PATCH 30/62] Small fix for formatting byte-counts. Add csv-usage note to yask.sh. --- src/kernel/yask.sh | 1 + utils/lib/YaskUtils.pm | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/kernel/yask.sh b/src/kernel/yask.sh index 79cf052b..770a8400 100755 --- a/src/kernel/yask.sh +++ b/src/kernel/yask.sh @@ -345,6 +345,7 @@ fi echo $invo echo "Log saved in '$logfile'." +echo "Run 'utils/bin/yask_log_to_csv.pl $logfile' to output in CSV format." # A summary of the command to print. exe_str="'$mpi_cmd $exe_prefix $exe $opts'" diff --git a/utils/lib/YaskUtils.pm b/utils/lib/YaskUtils.pm index ff3e5ef9..131c8740 100644 --- a/utils/lib/YaskUtils.pm +++ b/utils/lib/YaskUtils.pm @@ -133,7 +133,9 @@ sub removeSuf($) { return $val if $val !~ /^[0-9]/; # Look for suffix. - if ($val =~ /^([0-9.e+-]+)\s*Ki?B$/i) { + if ($val =~ /^([0-9.e+-]+)B$/i) { + $val = $1; + } elsif ($val =~ /^([0-9.e+-]+)\s*Ki?B$/i) { $val = $1 * $oneKi; } elsif ($val =~ /^([0-9.e+-]+)\s*Mi?B$/i) { $val = $1 * $oneMi; From 904e70c82c85a39cd238fd2e10220fcfcdb7bb46 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 16 May 2019 08:22:57 -0700 Subject: [PATCH 31/62] Add user-code kernel callback hooks. --- docs/api/mainpage.txt | 6 +- include/aux/yk_solution_api.hpp | 63 ++++++++++--- include/yask_compiler_api.hpp | 91 +++++++++++++++--- include/yask_kernel_api.hpp | 5 +- src/compiler/lib/Solution.hpp | 18 ++-- src/compiler/lib/YaskKernel.cpp | 32 +++++-- src/kernel/Makefile | 10 +- src/kernel/lib/context.cpp | 11 ++- src/kernel/lib/context.hpp | 14 +++ src/kernel/lib/settings.cpp | 11 ++- src/kernel/lib/settings.hpp | 2 +- src/kernel/lib/soln_apis.cpp | 35 ++++--- src/kernel/lib/utils.cpp | 39 +++++--- src/kernel/lib/utils.hpp | 46 ++++++---- src/kernel/yask_main.cpp | 158 ++++++++++++++++---------------- src/stencils/Iso3dfdStencil.cpp | 37 ++++++++ 16 files changed, 384 insertions(+), 194 deletions(-) diff --git a/docs/api/mainpage.txt b/docs/api/mainpage.txt index 2f728bab..9547a5df 100644 --- a/docs/api/mainpage.txt +++ b/docs/api/mainpage.txt @@ -55,16 +55,14 @@ utility, `bin/yask_compiler.exe`. This is done automatically when building a YASK kernel using the YASK `Makefile`, or you can build it explicity via `make compiler` and run it from your shell command-prompt. - When you run `make` to build the kernel library, the generated output from the compiler utility - is automatically written to `src/kernel/gen/yask_stencil_code.hpp` - and compiled into the optimized kernel library. + is automatically written to a pre-determined temporary file and compiled into the optimized kernel library. - See example stencils of this type in `src/stencils`. -# Create a custom application that defines stencils. - This approach is typically taken when a 3rd-party front-end tool will be creating stencils automatically from some other existing format or description. - In this case, you don't use the provided \ref yc_solution_base class or overload yc_solution_base::define(), but equations may be expressed in the same way, because both techniques use the YASK compiler API. - - The output from the custom application may be written to `src/kernel/gen/yask_stencil_code.hpp` - and compiled into the optimized kernel library. Or, it can write the output to any file + - The output from the custom application may be written to any file that is then specified via `YK_CODE_FILE=`filename when running `make` to build the kernel library. - See `src/compiler/tests/yask_compiler_api_test.cpp` for an example stencil definition in C++ or `bin/yask_compiler_api_test.py` for an example stencil definition in Python. diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index c04c657c..853d5646 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -86,6 +86,15 @@ namespace yask { virtual const std::string& get_name() const =0; + /// Get the target ISA. + /** + @returns String describing the instruction-set architecture targeted + during kernel compilation. + This is currently "avx512", "avx2", "avx", "knl", "knc", or "intel64". + */ + virtual std::string + get_target_isa() const =0; + /// Get the floating-point precision size. /** @returns Number of bytes in each FP element: 4 or 8. @@ -335,6 +344,45 @@ namespace yask { /**< [in] Name of dimension to get. Must be one of the names from get_domain_dim_names(). */ ) const =0; + /// Set kernel options from a string. + /** + Parses the string for options as if from a command-line. + Example: "-bx 64 -block_threads 4" sets the block-size in the *x* + dimension to 64 and the number of threads used to process each + block to 4. + See the help message from the YASK kernel binary for documentation + on the command-line options. + Used to set less-common options not directly supported by the + APIs above (set_block_size(), etc.). + + @returns Any parts of `args` that were not recognized by the parser as options. + Thus, a non-empty returned string may be used to signal an error or + interpreted by a custom application in another way. + */ + virtual std::string + apply_command_line_options(const std::string& args + /**< [in] String of arguments to parse. */ ) =0; + + /// Set kernel options from standard C or C++ `argc` and `argv` parameters to `main()`. + /** + Discards `argv[0]`, which is the executable name. + Then, parses the remaining `argv` values for options as + described in apply_command_line_options() with a string argument. + + @returns Any parts of `argv` that were not recognized by the parser as options. + */ + virtual std::string + apply_command_line_options(int argc, char* argv[]) =0; + + /// Set kernel options from a vector of strings. + /** + Parses `args` values for options as + described in apply_command_line_options() with a string argument. + + @returns Any parts of `args` that were not recognized by the parser as options. + */ + virtual std::string + apply_command_line_options(const std::vector& args) =0; /// Get the number of vars in the solution. /** @@ -831,21 +879,6 @@ namespace yask { virtual int get_default_numa_preferred() const =0; - /// **[Advanced]** Set performance parameters from an option string. - /** - Parses the string for options as if from a command-line. - Example: "-bx 64 -block_threads 4" sets the block-size in the *x* - dimension to 64 and the number of threads used to process each - block to 4. - See the help message from the YASK kernel binary for documentation - on the command-line options. - - @returns Any strings that were not recognized by the parser as options. - */ - virtual std::string - apply_command_line_options(const std::string& args - /**< [in] String of arguments to parse. */ ) =0; - /// **[Advanced]** Merge YASK variables with another solution. /** Calls yk_var::fuse_vars() for each pair of vars that have the same name diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 3717910b..4d9544c6 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -111,7 +111,7 @@ namespace yask { virtual yc_solution_ptr new_solution(const std::string& name /**< [in] Name of the solution; must be a valid C++ identifier. */ ) const; - }; + }; // yc_factory. /// Stencil solution. /** @@ -373,23 +373,90 @@ namespace yask { /**< [out] Pointer to object to receive formatted output. See \ref yask_output_factory. */) =0; - /// **[Advanced]** Explicitly list the domain dimensions in the solution. + /// Keys for calling insert_kernel_code(). + enum kernel_code_key + { + /// Code to be called at the end of constructing a \ref yk_solution via + /// yk_factory::new_solution(). + after_new_solution, + + /// Code to be called at the beginning of yk_solution::prepare_solution(). + before_prepare_solution, + + /// Code to be called at the end of yk_solution::prepare_solution(). + after_prepare_solution, + + /// Code to be called at the beginning of each call to yk_solution::run_solution(). + /** The `idx_t`-type variables `first_step_index` and `last_step_index` are + available to the inserted code with the values passed to + yk_solution::run_solution(). + + @note yk_solution::run_solution() may be called several times + by the `bin/yask.sh` utility or any custom application. + */ + before_run_solution, + + /// Code to be called at the end of each call to yk_solution::prepare_solution(). + /** The `idx_t`-type variables `first_step_index` and `last_step_index` are + available to the inserted code with the values passed to + yk_solution::run_solution(). + */ + after_run_solution + + }; + + /// **[Advanced]** Add block of code to be run in the kernel at the specified time. + /** + This is a mechanism to insert any valid code into the kernel library + that will be built from the file(s) generated by the YASK compiler. + The code will be run when indicated by the `key` argument. + If this API is called more than once with the same key, the code will + be appended. + Be sure that your code is well-formed, including a closing semicolon + if applicable. + If there are any syntax errors or other issues, they will not be visible until + the kernel is compiled. + + Code is inserted as methods in the created solution. Thus, the "`this`" pointer + refers to the current \ref yk_solution object, and \ref yk_solution + methods may be called directly. + + Of course, equivalent code can be added directly to any custom application using + the kernel library. + However, the method provided by insert_kernel_code() is useful when using the + provided YASK kernel-performance utility launched via `bin/yask.sh`. + It also provides a method to provide consistent kernel code when the + kernel library is used in multiple applications. + */ + virtual void + insert_kernel_code(kernel_code_key key + /**< [in] See \ref kernel_code_key. */, + std::string code + /**< [in] Code to be inserted. */) =0; + + /// A convenience macro for calling yask::yc_solution::insert_kernel_code(). /** - In addition, domain dimension(s) are added when new_var(), - new_scratch_var() is called with one or more domain dimensions. - Either way, the last unique domain dimension specified will become the 'inner' or - 'unit-stride' dimension in memory layouts. - Thus, this option can be used to override the default layout order. - It also allows specification of the domain dimensions in the - unusual case where a solution is defined without any - vars containing all of the domain dimensions. + Allows inserting code without the surrounding quotes, making it easier + to format in many IDEs. + */ +#define INSERT_YASK_KERNEL_CODE(key, ...) insert_kernel_code(key, #__VA_ARGS__) + + /// **[Advanced]** Explicitly define and order the domain dimensions used in the solution. + /** + The order of domain dimensions affects memory layout, looping + order, vector-folding, and rank layout. This API also allows + specification of the domain dimensions in the unusual case where + a solution is defined without any vars containing all of the + domain dimensions. Whether or not this API is called, domain + dimension(s) are added when new_var() or new_scratch_var() is + called with one or more domain dimensions not previously seen. */ virtual void set_domain_dims(const std::vector& dims /**< [in] Domain dimensions of the solution. */ ) =0; #ifndef SWIG - /// **[Advanced]** Explicitly list the domain dimensions in the solution. + /// **[Advanced]** Explicitly define and order the domain dimensions used in the solution. /** C++ initializer-list version with same semantics as the vector version of new_var(). @@ -411,7 +478,7 @@ namespace yask { virtual void set_step_dim(const yc_index_node_ptr dim /**< [in] Step dimension. */) =0; - + /// **[Advanced]** Enable or disable automatic dependency checker. /** Disabling the built-in dependency checker may be done when it is diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 0ae80f22..89e1f80f 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -158,7 +158,7 @@ namespace yask { const yk_solution_ptr source /**< [in] Pointer to existing \ref yk_solution from which the settings will be copied. */ ) const; - }; + }; // yk_factory. /// Kernel environment. class yk_env { @@ -184,7 +184,8 @@ namespace yask { */ virtual void global_barrier() const =0; - }; + + }; // yk_env. /// **[Deprecated]** Use yk_var. typedef yk_var yk_grid; diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index d0e38dc7..205d010e 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -36,15 +36,6 @@ using namespace std; namespace yask { - // TODO: add API to add to this. - typedef enum { STENCIL_CONTEXT } YASKSection; - typedef vector CodeList; - typedef map ExtensionsList; - -// Convenience macros for adding 'extension' code to a stencil. -#define _REGISTER_CODE_EXTENSION(section, code) _extensions[section].push_back(code); -#define _REGISTER_STENCIL_CONTEXT_EXTENSION(...) REGISTER_CODE_EXTENSION(STENCIL_CONTEXT, #__VA_ARGS__) - // A base class for whole stencil solutions. This is used by solutions // defined in C++ that are inherited from StencilBase as well as those // defined via the stencil-compiler API. @@ -73,6 +64,8 @@ namespace yask { // Code extensions that overload default functions from YASK in the // generated code for this solution. + typedef vector CodeList; + typedef map ExtensionsList; ExtensionsList _extensions; private: @@ -112,7 +105,7 @@ namespace yask { virtual const Dimensions& getDims() { return _dims; } // Get user-provided code for the given section. - CodeList * getExtensionCode(YASKSection section) + CodeList * getExtensionCode(kernel_code_key section) { auto elem = _extensions.find(section); if ( elem != _extensions.end() ) { @@ -197,6 +190,11 @@ namespace yask { ev.push_back(_eqs.getAll().at(i)); return ev; } + virtual void + insert_kernel_code(kernel_code_key key, + string code) { + _extensions[key].push_back(code); + } virtual void add_flow_dependency(yc_equation_node_ptr from, yc_equation_node_ptr to) { auto fp = dynamic_pointer_cast(from); diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 1ab3d7c5..8054dddb 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -877,7 +877,8 @@ namespace yask { os << " stPacks.push_back(" << bpName << ");\n"; } - os << " } // Ctor.\n"; + os << "\n after_new_solution_hook();\n" + " } // Ctor.\n"; // Dims creator. os << "\n // Create Dims object.\n" @@ -930,13 +931,28 @@ namespace yask { os << " return p;\n" " }\n"; - // Stencil provided code for StencilContext - CodeList *extraCode; - if ( (extraCode = _stencil.getExtensionCode(STENCIL_CONTEXT)) != NULL ) - { - os << "\n // Functions provided by user.\n"; - for ( auto code : *extraCode ) - os << code << endl; + os << "\n // Code provided by user.\n"; + map protos = + { { yc_solution::after_new_solution, "after_new_solution_hook()" }, + { yc_solution::before_prepare_solution, "before_prepare_solution_hook()" }, + { yc_solution::after_prepare_solution, "after_prepare_solution_hook()" }, + { yc_solution::before_run_solution, + "before_run_solution_hook(idx_t first_step_index, idx_t last_step_index)" }, + { yc_solution::after_run_solution, + "after_run_solution_hook(idx_t first_step_index, idx_t last_step_index)" } }; + for (auto& i : protos) { + auto key = i.first; + auto& proto = i.second; + os << " virtual void " << proto << " override {\n" + " STATE_VARS(this);\n" + " TRACE_MSG(\"" << proto << "...\");\n"; + auto *extraCode = _stencil.getExtensionCode(key); + if (extraCode) { + for ( auto code : *extraCode ) + os << " " << code << ";\n"; + } + os << " TRACE_MSG(\"" << proto << " done\");\n" + " }\n"; } os << "}; // " << _context << endl; diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 55f86555..321c8e40 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -55,7 +55,7 @@ YK_ARCH := $(arch) # Specify YC_STENCIL on 'make' cmd-line to pass different stencil name to YASK compiler. YC_STENCIL := $(stencil) -# Set 'ARCH', converting old codenames to ISA names. +# Set 'ARCH', converting codenames to ISA names. ifneq ($(filter $(arch),avx snb ivb),) ARCH := avx else ifneq ($(filter $(arch),avx2 hsw bdw),) @@ -389,10 +389,7 @@ endif MACROS += ALLOW_NEW_VARS=$(allow_new_var_types) # Default cmd-line args. -DEF_ARGS += -thread_divisor $(def_thread_divisor) -DEF_ARGS += -block_threads $(def_block_threads) -DEF_ARGS += $(def_block_args) $(def_pad_args) $(more_def_args) -YK_CXXFLAGS += -DDEF_ARGS='"$(DEF_ARGS) $(EXTRA_DEF_ARGS)"' +YK_CXXFLAGS += -DDEF_ARGS='"$(DEF_ARGS)"' # arch. UC_ARCH := $(shell echo $(ARCH) | tr '[:lower:]' '[:upper:]') @@ -884,7 +881,7 @@ echo-settings: echo BLOCK_LOOP_ORDER="\"$(BLOCK_LOOP_ORDER)\""; \ echo BLOCK_LOOP_OUTER_MODS="\"$(BLOCK_LOOP_OUTER_MODS)\""; \ echo BLOCK_LOOP_OUTER_VARS="\"$(BLOCK_LOOP_OUTER_VARS)\""; \ - echo EXTRA_DEF_ARGS=$(EXTRA_DEF_ARGS); \ + echo DEF_ARGS="\"$(DEF_ARGS)\""; \ echo EXTRA_MACROS="\"$(EXTRA_MACROS)\""; \ echo EXTRA_YC_FLAGS="\"$(EXTRA_YC_FLAGS)\""; \ echo EXTRA_YK_CXXFLAGS="\"$(EXTRA_YK_CXXFLAGS)\""; \ @@ -943,7 +940,6 @@ echo-settings: echo def_thread_divisor=$(def_thread_divisor); \ echo fold=$(fold); \ echo host=`hostname`; \ - echo more_def_args=$(more_def_args); \ echo omp_block_schedule=$(omp_block_schedule); \ echo omp_misc_schedule=$(omp_misc_schedule); \ echo omp_region_schedule=$(omp_region_schedule); \ diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index b8dcaa8b..b1a7aab5 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -184,6 +184,11 @@ namespace yask { idx_t last_step_index) { STATE_VARS(this); + + // User-provided code. + before_run_solution_hook(first_step_index, last_step_index); + + // Start timer. run_time.start(); // Start vtune collection. @@ -551,11 +556,13 @@ namespace yask { } #endif - // Stop vtune collection. + // Stop vtune collection & timer. VTUNE_PAUSE; - run_time.stop(); + // User-provided code. + after_run_solution_hook(first_step_index, last_step_index); + } // run_solution(). // Calculate results within a region. Each region is typically computed diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 8eb34b0a..a6fe3b66 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -494,6 +494,15 @@ namespace yask { const VarDimNames& dims, const VarDimSizes* sizes); + // Stubs for user-inserted code. + virtual void after_new_solution_hook() { } + virtual void before_prepare_solution_hook() { } + virtual void after_prepare_solution_hook() { } + virtual void before_run_solution_hook(idx_t first_step_index, + idx_t last_step_index) { } + virtual void after_run_solution_hook(idx_t first_step_index, + idx_t last_step_index) { } + // APIs. // See yask_kernel_api.hpp. virtual const std::string& get_name() const { @@ -508,6 +517,9 @@ namespace yask { virtual int get_element_bytes() const { return REAL_BYTES; } + virtual std::string get_target_isa() const { + return YSTR2(ARCH_NAME); + } virtual int get_num_vars() const { return int(varPtrs.size()); @@ -600,6 +612,8 @@ namespace yask { virtual idx_t get_num_ranks(const std::string& dim) const; virtual idx_t get_rank_index(const std::string& dim) const; virtual std::string apply_command_line_options(const std::string& args); + virtual std::string apply_command_line_options(int argc, char* argv[]); + virtual std::string apply_command_line_options(const std::vector& args); virtual bool get_step_wrap() const { STATE_VARS(this); return opts->_step_wrap; diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index 5a3367e0..b5d6511c 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -321,7 +321,7 @@ namespace yask { multi_vars)); } - // Add these settigns to a cmd-line parser. + // Add access to these options from a cmd-line parser. void KernelSettings::add_options(CommandLineParser& parser) { // Following options are in the 'yask' namespace, i.e., no object. @@ -446,14 +446,17 @@ namespace yask { // Print usage message. void KernelSettings::print_usage(ostream& os, - CommandLineParser& parser, + CommandLineParser& appParser, const string& pgmName, const string& appNotes, - const vector& appExamples) const + const vector& appExamples) { os << "Usage: " << pgmName << " [options]\n" "Options:\n"; - parser.print_help(os); + appParser.print_help(os); + CommandLineParser solnParser; + add_options(solnParser); + solnParser.print_help(os); os << "\nTerms for the various levels of tiling from smallest to largest:\n" " A 'point' is a single floating-point (FP) element.\n" " This binary uses " << REAL_BYTES << "-byte FP elements.\n" diff --git a/src/kernel/lib/settings.hpp b/src/kernel/lib/settings.hpp index 1c1b733d..83686692 100644 --- a/src/kernel/lib/settings.hpp +++ b/src/kernel/lib/settings.hpp @@ -279,7 +279,7 @@ namespace yask { CommandLineParser& parser, const std::string& pgmName, const std::string& appNotes, - const std::vector& appExamples) const; + const std::vector& appExamples); // Make sure all user-provided settings are valid by rounding-up // values as needed. diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 4e49933b..08702a37 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -82,6 +82,9 @@ namespace yask { void StencilContext::prepare_solution() { STATE_VARS(this); + // User-provided code. + before_prepare_solution_hook(); + // Don't continue until all ranks are this far. env->global_barrier(); @@ -164,6 +167,9 @@ namespace yask { init_stats(); + // User-provided code. + after_prepare_solution_hook(); + } // prepare_solution(). void StencilContext::print_warnings() const { @@ -319,28 +325,27 @@ namespace yask { } } - string StencilContext::apply_command_line_options(const string& args) { + string StencilContext::apply_command_line_options(const string& argstr) { + auto args = CommandLineParser::set_args(argstr); + return apply_command_line_options(args); + } + + string StencilContext::apply_command_line_options(int argc, char* argv[]) { + std::vector args; + for (int i = 1; i < argc; i++) + args.push_back(argv[i]); + return apply_command_line_options(args); + } + + string StencilContext::apply_command_line_options(const vector& args) { STATE_VARS(this); // Create a parser and add base options to it. CommandLineParser parser; opts->add_options(parser); - // Tokenize default args. - vector argsv; - parser.set_args(args, argsv); - // Parse cmd-line options, which sets values in settings. - parser.parse_args("YASK", argsv); - - // Return any left-over strings. - string rem; - for (auto r : argsv) { - if (rem.length()) - rem += " "; - rem += r; - } - return rem; + return parser.parse_args("YASK", args); } // Add a new var to the containers. diff --git a/src/kernel/lib/utils.cpp b/src/kernel/lib/utils.cpp index 989f108e..e21514e6 100644 --- a/src/kernel/lib/utils.cpp +++ b/src/kernel/lib/utils.cpp @@ -416,7 +416,7 @@ namespace yask { // Check for matching option to "-"str at args[argi]. // Return true and increment argi if match. - bool CommandLineParser::OptionBase::_check_arg(std::vector& args, + bool CommandLineParser::OptionBase::_check_arg(const std::vector& args, int& argi, const std::string& str) const { @@ -431,7 +431,7 @@ namespace yask { // Get one idx_t value from args[argi]. // On failure, print msg using string from args[argi-1] and exit. // On success, increment argi and return value. - idx_t CommandLineParser::OptionBase::_idx_val(vector& args, + idx_t CommandLineParser::OptionBase::_idx_val(const vector& args, int& argi) { if (size_t(argi) >= args.size() || args[argi].length() == 0) { @@ -450,7 +450,7 @@ namespace yask { } // Check for a boolean option. - bool CommandLineParser::BoolOption::check_arg(std::vector& args, + bool CommandLineParser::BoolOption::check_arg(const std::vector& args, int& argi) { if (_check_arg(args, argi, _name)) { _val = true; @@ -473,7 +473,7 @@ namespace yask { } // Check for an int option. - bool CommandLineParser::IntOption::check_arg(std::vector& args, + bool CommandLineParser::IntOption::check_arg(const std::vector& args, int& argi) { if (_check_arg(args, argi, _name)) { _val = (int)_idx_val(args, argi); // TODO: check for under/overflow. @@ -491,7 +491,7 @@ namespace yask { } // Check for an idx_t option. - bool CommandLineParser::IdxOption::check_arg(std::vector& args, + bool CommandLineParser::IdxOption::check_arg(const std::vector& args, int& argi) { if (_check_arg(args, argi, _name)) { _val = _idx_val(args, argi); @@ -522,7 +522,7 @@ namespace yask { } // Check for an multi-idx_t option. - bool CommandLineParser::MultiIdxOption::check_arg(std::vector& args, + bool CommandLineParser::MultiIdxOption::check_arg(const std::vector& args, int& argi) { if (_check_arg(args, argi, _name)) { idx_t val = _idx_val(args, argi); @@ -543,9 +543,9 @@ namespace yask { // Parse options from the command-line and set corresponding vars. // Recognized strings from args are consumed, and unused ones - // remain for further processing by the application. - void CommandLineParser::parse_args(const std::string& pgmName, - std::vector& args) { + // are returned. + string CommandLineParser::parse_args(const std::string& pgmName, + const std::vector& args) { vector non_args; // Loop through strings in args. @@ -566,21 +566,28 @@ namespace yask { // Save unused args. if (!matched) { - string& opt = args[argi]; + string opt = args[argi]; non_args.push_back(opt); argi++; } } - // Return unused args in args var. - args.swap(non_args); + // Return any left-over strings. + string rem; + for (auto r : non_args) { + if (rem.length()) + rem += " "; + // TODO: add quotes around 'r' if it has a space. + rem += r; + } + return rem; } // Tokenize args from a string. - void CommandLineParser::set_args(std::string arg_string, - std::vector& args) { + vector CommandLineParser::set_args(const string& arg_string) { string tmp; bool in_quotes = false; + vector args; for (char c : arg_string) { // If WS, start a new string unless in quotes. @@ -594,7 +601,8 @@ namespace yask { } } - // If quote, start or end quotes. + // If quote, start or end double-quotes. + // TODO: handle single-quotes. else if (c == '"') { if (in_quotes) { if (tmp.length()) @@ -614,5 +622,6 @@ namespace yask { // Last string. if (tmp.length()) args.push_back(tmp); + return args; } } diff --git a/src/kernel/lib/utils.hpp b/src/kernel/lib/utils.hpp index 40f1f54f..370fed1c 100644 --- a/src/kernel/lib/utils.hpp +++ b/src/kernel/lib/utils.hpp @@ -341,12 +341,12 @@ namespace yask { // Check for matching option to str at args[argi]. // Return true and increment argi if match. - virtual bool _check_arg(std::vector& args, int& argi, + virtual bool _check_arg(const std::vector& args, int& argi, const std::string& str) const; // Get one idx_t value from args[argi++]. // Exit on failure. - virtual idx_t _idx_val(std::vector& args, int& argi); + virtual idx_t _idx_val(const std::vector& args, int& argi); public: OptionBase(const std::string& name, @@ -373,7 +373,7 @@ namespace yask { // Check for matching option and any needed args at args[argi]. // Return true, set val, and increment argi if match. - virtual bool check_arg(std::vector& args, int& argi) =0; + virtual bool check_arg(const std::vector& args, int& argi) =0; }; // An allowed boolean option. @@ -388,7 +388,7 @@ namespace yask { virtual void print_help(std::ostream& os, int width) const; - virtual bool check_arg(std::vector& args, int& argi); + virtual bool check_arg(const std::vector& args, int& argi); }; // An allowed int option. @@ -403,7 +403,7 @@ namespace yask { virtual void print_help(std::ostream& os, int width) const; - virtual bool check_arg(std::vector& args, int& argi); + virtual bool check_arg(const std::vector& args, int& argi); }; // An allowed idx_t option. @@ -418,7 +418,7 @@ namespace yask { virtual void print_help(std::ostream& os, int width) const; - virtual bool check_arg(std::vector& args, int& argi); + virtual bool check_arg(const std::vector& args, int& argi); }; // An allowed idx_t option that sets multiple vars. @@ -435,7 +435,8 @@ namespace yask { virtual void print_help(std::ostream& os, int width) const; - virtual bool check_arg(std::vector& args, int& argi); + virtual bool check_arg(const std::vector& args, + int& argi); }; protected: @@ -456,6 +457,9 @@ namespace yask { } } + // Tokenize args from a string. + static std::vector set_args(const std::string& arg_string); + // Set help width. virtual void set_width(int width) { _width = width; @@ -470,26 +474,28 @@ namespace yask { // Print help info on all options. virtual void print_help(std::ostream& os) const; - // Parse options from the command-line and set corresponding vars. + // Parse options from 'args' and set corresponding vars. // Recognized strings from args are consumed, and unused ones // remain for further processing by the application. - virtual void parse_args(const std::string& pgmName, - std::vector& args); - + virtual std::string parse_args(const std::string& pgmName, + const std::vector& args); + + // Same as above, but splits 'arg_string' into tokens. + virtual std::string parse_args(const std::string& pgmName, + const std::string& arg_string) { + auto args = set_args(arg_string); + return parse_args(pgmName, args); + } + // Same as above, but pgmName is populated from argv[0] - // and args is appended from remainder of argv array. - // Unused strings are returned in args vector. - virtual void parse_args(int argc, char** argv, - std::vector& args) { + // and rest of argv is parsed. + virtual std::string parse_args(int argc, char** argv) { std::string pgmName = argv[0]; + std::vector args; for (int i = 1; i < argc; i++) args.push_back(argv[i]); - parse_args(pgmName, args); + return parse_args(pgmName, args); } - - // Tokenize args from a string. - virtual void set_args(std::string arg_string, - std::vector& args); }; } diff --git a/src/kernel/yask_main.cpp b/src/kernel/yask_main.cpp index 8850c915..ac344676 100644 --- a/src/kernel/yask_main.cpp +++ b/src/kernel/yask_main.cpp @@ -35,7 +35,7 @@ using namespace yask; // Add some command-line options for this application in addition to the // default ones provided by YASK. -struct AppSettings : public KernelSettings { +struct MySettings { bool help = false; // help requested. bool doWarmup = true; // whether to do warmup run. bool doPreAutoTune = true; // whether to do pre-auto-tuning. @@ -47,25 +47,28 @@ struct AppSettings : public KernelSettings { int pre_trial_sleep_time = 1; // sec to sleep before each trial. int debug_sleep = 0; // sec to sleep for debug attach. - AppSettings(DimsPtr dims, KernelEnvPtr env) : - KernelSettings(dims, env) { } + // Ptr to the soln. + yk_solution_ptr _ksoln; + + MySettings(yk_solution_ptr ksoln) : + _ksoln(ksoln) { } // A custom option-handler for '-v'. class ValOption : public CommandLineParser::OptionBase { - AppSettings& _as; + MySettings& _as; static constexpr idx_t _lsz=63, _bsz=24; public: - ValOption(AppSettings& as) : + ValOption(MySettings& as) : OptionBase("v", - "Minimal validation: shortcut for '-validate -no-pre-auto_tune -no-auto_tune" + "Minimal validation: shortcut for '-validate -no-pre_auto_tune -no-auto_tune" " -no-warmup -t 1 -trial_steps 1 -l " + to_string(_lsz) + " -b " + to_string(_bsz) + "'."), _as(as) { } // Set multiple vars. - virtual bool check_arg(std::vector& args, + virtual bool check_arg(const std::vector& args, int& argi) { if (_check_arg(args, argi, _name)) { _as.validate = true; @@ -73,10 +76,19 @@ struct AppSettings : public KernelSettings { _as.doWarmup = false; _as.num_trials = 1; _as.trial_steps = 1; - for (auto dim : _as._dims->_domain_dims.getDims()) { - auto& dname = dim.getName(); - _as._rank_sizes[dname] = _lsz; - _as._block_sizes[dname] = _bsz; + + // Create new args and parse them. + for (auto& dname : _as._ksoln->get_domain_dim_names()) { + + // Local domain size, e.g., "-lx 63". + string arg = "-l" + dname + " " + to_string(_lsz); + + // Block size, e.g., "-bx 24". + arg += " -b" + dname + " " + to_string(_bsz); + + // Parse 'arg'. + auto rem = _as._ksoln->apply_command_line_options(arg); + assert(rem.length() == 0); } return true; } @@ -88,15 +100,8 @@ struct AppSettings : public KernelSettings { // Exit with message on error or request for help. void parse(int argc, char** argv) { - // Create a parser and add base options to it. + // Create a parser and add options to it. CommandLineParser parser; - add_options(parser); - - // Add more options for this app. - parser.add_option(new CommandLineParser::BoolOption - ("h", - "Print help message.", - help)); parser.add_option(new CommandLineParser::BoolOption ("help", "Print help message.", @@ -155,13 +160,12 @@ struct AppSettings : public KernelSettings { validate)); parser.add_option(new ValOption(*this)); - // Tokenize default args. - vector args; - parser.set_args(DEF_ARGS, args); + // Parse 'args' and 'argv' cmd-line options, which sets values. + // Any remaining strings will be returned. + auto rem_args = parser.parse_args(argc, argv); - // Parse cmd-line options, which sets values. - // Any remaining strings will be left in args. - parser.parse_args(argc, argv, args); + // Parse standard args not handled by this parser. + rem_args = _ksoln->apply_command_line_options(rem_args); if (help) { string appNotes = @@ -170,21 +174,21 @@ struct AppSettings : public KernelSettings { " If validation fails, it may be due to rounding error;\n" " try building with 8-byte reals.\n"; vector appExamples; - appExamples.push_back("-g 768 -t 2"); + appExamples.push_back("-g 768 -num_trials 2"); appExamples.push_back("-v"); - print_usage(cout, parser, argv[0], appNotes, appExamples); + + // TODO: make an API for this. + auto context = dynamic_pointer_cast(_ksoln); + assert(context.get()); + auto& opts = context->get_settings(); + opts->print_usage(cout, parser, argv[0], appNotes, appExamples); exit_yask(1); } - if (args.size()) { - yask_exception e; - stringstream err; - err << "Error: extraneous parameter(s):"; - for (auto arg : args) - err << " '" << arg << "'"; - err << "; run with '-help' option for usage"; - THROW_YASK_EXCEPTION(err.str()); - } + if (rem_args.length()) + THROW_YASK_EXCEPTION("Error: extraneous parameter(s): '" + + rem_args + + "'; run with '-help' option for usage"); } // Print splash banner and invocation string. @@ -217,10 +221,10 @@ struct AppSettings : public KernelSettings { os << "Resuming...\n"; } } -}; +}; // AppSettings. // Override step allocation. -void alloc_steps(yk_solution_ptr soln, const AppSettings& opts) { +void alloc_steps(yk_solution_ptr soln, const MySettings& opts) { if (opts.step_alloc <= 0) return; @@ -254,36 +258,32 @@ int main(int argc, char** argv) auto ep = dynamic_pointer_cast(kenv); auto num_ranks = kenv->get_num_ranks(); - // Problem dimensions. - auto dims = YASK_STENCIL_CONTEXT::new_dims(); - - // Parse cmd-line options. - // TODO: do this through APIs. - auto opts = make_shared(dims, ep); - opts->parse(argc, argv); - - // Make sure warmup is on if needed. - if (opts->trial_steps <= 0 && opts->trial_time > 0) - opts->doWarmup = true; - - // Object containing data and parameters for stencil eval. + // Make solution object containing data and parameters for stencil eval. // TODO: do everything through API without cast to StencilContext. auto ksoln = kfac.new_solution(kenv); auto context = dynamic_pointer_cast(ksoln); assert(context.get()); + ostream& os = context->set_ostr(); + auto& copts = context->get_settings(); + assert(copts); - // Replace the default settings with 'opts'. - context->set_settings(opts); + // Parse cmd-line options and exit on -help or error. + // TODO: do this through APIs. + MySettings opts(ksoln); + opts.parse(argc, argv); + + // Make sure warmup is on if needed. + if (opts.trial_steps <= 0 && opts.trial_time > 0) + opts.doWarmup = true; // Make sure any MPI/OMP debug data is dumped from all ranks before continuing. kenv->global_barrier(); // Print splash banner and related info. - ostream& os = context->set_ostr(); - opts->splash(os, argc, argv); + opts.splash(os, argc, argv); // Override alloc if requested. - alloc_steps(ksoln, *opts); + alloc_steps(ksoln, opts); // Alloc memory, etc. ksoln->prepare_solution(); @@ -293,19 +293,19 @@ int main(int argc, char** argv) THROW_YASK_EXCEPTION("Exiting because there are no points in the domain"); // init data in vars and params. - if (opts->doWarmup || !opts->validate) + if (opts.doWarmup || !opts.validate) context->initData(); // Invoke auto-tuner. - if (opts->doPreAutoTune) + if (opts.doPreAutoTune) ksoln->run_auto_tuner_now(); // Enable/disable further auto-tuning. - ksoln->reset_auto_tuner(opts->_do_auto_tune); + ksoln->reset_auto_tuner(copts->_do_auto_tune); // Warmup caches, threading, etc. // Measure time to change number of steps. - if (opts->doWarmup) { + if (opts.doWarmup) { // Turn off debug. auto dbg_out = context->get_debug_output(); @@ -332,7 +332,7 @@ int main(int argc, char** argv) rate = (wtime > 0.) ? double(warmup_steps) / wtime : 0; // Done if time est. isn't needed. - if (opts->trial_steps > 0) + if (opts.trial_steps > 0) break; // Use time to set number of steps for next trial. @@ -347,20 +347,20 @@ int main(int argc, char** argv) } // Set final number of steps. - if (opts->trial_steps <= 0) { - idx_t tsteps = ceil(rate * opts->trial_time); + if (opts.trial_steps <= 0) { + idx_t tsteps = ceil(rate * opts.trial_time); tsteps = CEIL_DIV(sumOverRanks(tsteps, ep->comm), num_ranks); // Round up to multiple of temporal tiling if not too big. auto step_dim = ksoln->get_step_dim_name(); - auto rt = opts->_region_sizes[step_dim]; - auto bt = opts->_block_sizes[step_dim]; + auto rt = copts->_region_sizes[step_dim]; + auto bt = copts->_block_sizes[step_dim]; auto tt = max(rt, bt); const idx_t max_mult = 5; if (tt > 1 && tt < max_mult * tsteps) tsteps = ROUND_UP(tsteps, tt); - opts->trial_steps = tsteps; + opts.trial_steps = tsteps; } // Restore debug. @@ -369,9 +369,9 @@ int main(int argc, char** argv) kenv->global_barrier(); // Exit if nothing to do. - if (opts->num_trials < 1) + if (opts.num_trials < 1) THROW_YASK_EXCEPTION("Exiting because zero trials are specified"); - if (opts->trial_steps <= 0) + if (opts.trial_steps <= 0) THROW_YASK_EXCEPTION("Exiting because zero steps per trial are specified"); // Track results. @@ -379,26 +379,26 @@ int main(int argc, char** argv) // First & last steps. idx_t first_t = 0; - idx_t last_t = opts->trial_steps - 1; + idx_t last_t = opts.trial_steps - 1; // Stencils seem to be backward? // (This is just a heuristic, but the direction // is not usually critical to perf measurement.) - if (opts->_dims->_step_dir < 0) { + if (copts->_dims->_step_dir < 0) { first_t = last_t; last_t = 0; } /////// Performance run(s). os << endl << divLine << - "Running " << opts->num_trials << " performance trial(s) of " << - opts->trial_steps << " step(s) each...\n" << flush; - for (idx_t tr = 0; tr < opts->num_trials; tr++) { + "Running " << opts.num_trials << " performance trial(s) of " << + opts.trial_steps << " step(s) each...\n" << flush; + for (idx_t tr = 0; tr < opts.num_trials; tr++) { os << divLine << "Trial number: " << (tr + 1) << endl << flush; // init data before each trial for comparison if validating. - if (opts->validate) + if (opts.validate) context->initData(); // Warn if tuning. @@ -406,9 +406,9 @@ int main(int argc, char** argv) os << "auto-tuner is active during this trial, so results may not be representative.\n"; // Stabilize. - if (opts->pre_trial_sleep_time > 0) { + if (opts.pre_trial_sleep_time > 0) { os << flush; - sleep(opts->pre_trial_sleep_time); + sleep(opts.pre_trial_sleep_time); } kenv->global_barrier(); @@ -472,7 +472,7 @@ int main(int argc, char** argv) /////// Validation run. bool ok = true; - if (opts->validate) { + if (opts.validate) { kenv->global_barrier(); os << endl << divLine << "Setup for validation...\n"; @@ -504,7 +504,7 @@ int main(int argc, char** argv) #endif // Override allocations and prep solution as with ref soln. - alloc_steps(ref_soln, *opts); + alloc_steps(ref_soln, opts); ref_soln->prepare_solution(); // init to same value used in context. @@ -521,7 +521,7 @@ int main(int argc, char** argv) // Ref trial. // Do same number as last perf run. os << endl << divLine << - "Running " << opts->trial_steps << " step(s) for validation...\n" << flush; + "Running " << opts.trial_steps << " step(s) for validation...\n" << flush; ref_context->run_ref(first_t, last_t); // Discard perf report. diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index ddb725f7..856a6d6e 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -133,6 +133,37 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { return next_p; } + // Add some code to the kernel to set default options. + virtual void add_kernel_code() { + auto soln = get_soln(); + + // These best-known settings were found + // by automated and manual tuning. They are only applied + // for certain target configs. + + // Only valid for SP FP and radius 8. + if (soln->get_element_bytes() == 4 && + _radius == 8) { + + // Change the settings immediately after the kernel solution + // is created. + soln->INSERT_YASK_KERNEL_CODE + (yc_solution::after_new_solution, + if (get_target_isa() == "avx512") { + set_block_size("x", 108); + set_block_size("y", 28); + set_block_size("z", 132); + } + else { + set_block_size("x", 48); + set_block_size("y", 64); + set_block_size("z", 112); + } + ); + } + + } + // Define equation for pressure at t+1 based on values from vel and pressure at t. virtual void define() { @@ -143,6 +174,9 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Since this implements the finite-difference method, this // is actually an approximation. pressure(t+1, x, y, z) EQUALS next_p; + + // Insert custom kernel code. + add_kernel_code(); } }; @@ -179,6 +213,9 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { // Define the value at t+1 to be equal to next_p. pressure(t+1, x, y, z) EQUALS next_p; + + // Insert custom kernel code. + add_kernel_code(); } }; From 9c5df4f5208a5de419bb69a4d614107615299bab Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 16 May 2019 08:58:15 -0700 Subject: [PATCH 32/62] Remove exposure to '_radius' var. --- include/aux/Soln.hpp | 28 ++++++++++++---- include/yask_compiler_utility_api.hpp | 18 +++++------ src/stencils/Iso3dfdStencil.cpp | 8 ++--- src/stencils/SimpleStencils.cpp | 14 ++++---- src/stencils/TTIStencil.cpp | 2 +- src/stencils/TestStencils.cpp | 46 +++++++++++++-------------- utils/bin/convert_v2_stencil.pl | 3 ++ 7 files changed, 68 insertions(+), 51 deletions(-) diff --git a/include/aux/Soln.hpp b/include/aux/Soln.hpp index b85fb3f5..06664777 100644 --- a/include/aux/Soln.hpp +++ b/include/aux/Soln.hpp @@ -43,11 +43,7 @@ namespace yask { /// Dummy object from compiler utility for backward-compatibility. extern StencilList stub_stencils; - /// **[Deprecated]** The class all old-style C++ stencil solutions - /// written for the YASK compiler binary must implement. - /** - New DSL code should use yc_solution_base directly. - */ + /// **[Deprecated]** Use yc_solution_base. class StencilBase : public yc_solution_base { public: @@ -57,14 +53,32 @@ namespace yask { yc_solution_base(name) { } }; - /// **[Deprecated]** A base class for stencils that have a 'radius'. + /// **[Deprecated]** Use yc_solution_with_radius_base. class StencilRadiusBase : public yc_solution_with_radius_base { + protected: + + // Backward-compatibility bridge to emulate old `_radius` member var. + class RadiusBridge { + yc_solution_with_radius_base* _base; + + public: + RadiusBridge(yc_solution_with_radius_base* base) : + _base(base) { } + + // Access this object as an 'int' using implicit conversion. + inline operator int() { + return _base->get_radius(); + } + + } _radius; + public: /// Backward-compatibility constructor. StencilRadiusBase(const std::string& name, StencilList& stencils, int radius) : - yc_solution_with_radius_base(name, radius) { } + yc_solution_with_radius_base(name, radius), + _radius(this) { } }; // Aliases for backward-compatibility. diff --git a/include/yask_compiler_utility_api.hpp b/include/yask_compiler_utility_api.hpp index 5748116c..86c9707e 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/yask_compiler_utility_api.hpp @@ -161,18 +161,18 @@ namespace yask { } }; - /// A base class for stencils that have a 'radius' size parameter. + /// A base class for stencils that have a "radius" size parameter. + /** + For a symmetric finite-difference stencil, the "radius" is often the + number of points in the spatial dimension(s) from the center + point of a finite-difference approximation. However, any meaning + may be given to this variable. For example, it could be the + minimum or maximum radius for an asymmetical stencil. + */ class yc_solution_with_radius_base : public yc_solution_base { - protected: + private: /// A variable that controls the size the stencil. - /** - For a symmetric finite-difference stencil, this is often the - number of points in the spatial dimension(s) from the center - point of a finite-difference approximation. However, any meaning - may be given to this variable. For example, it could be the - minimum or maximum radius for an asymmetical stencil. - */ int _radius; public: diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 856a6d6e..908ab868 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -68,8 +68,8 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { double d2 = delta_xyz * delta_xyz; // Spatial FD coefficients for 2nd derivative. - auto coeff = get_center_fd_coefficients(2, _radius); - size_t c0i = _radius; // index of center sample. + auto coeff = get_center_fd_coefficients(2, get_radius()); + size_t c0i = get_radius(); // index of center sample. for (size_t i = 0; i < coeff.size(); i++) { @@ -87,7 +87,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Add values from x, y, and z axes multiplied by the // coeff for the given radius. - for (int r = 1; r <= _radius; r++) { + for (int r = 1; r <= get_radius(); r++) { // Add values from axes at radius r. fd_sum += ( @@ -143,7 +143,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Only valid for SP FP and radius 8. if (soln->get_element_bytes() == 4 && - _radius == 8) { + get_radius() == 8) { // Change the settings immediately after the kernel solution // is created. diff --git a/src/stencils/SimpleStencils.cpp b/src/stencils/SimpleStencils.cpp index 17be7715..58831368 100644 --- a/src/stencils/SimpleStencils.cpp +++ b/src/stencils/SimpleStencils.cpp @@ -80,7 +80,7 @@ class AxisStencil : public AvePtsStencil { virtual int addPoints(yc_number_node_ptr& v) { int pts = 0; - for (int r = 1; r <= _radius; r++) { + for (int r = 1; r <= get_radius(); r++) { v += // x-axis. @@ -122,7 +122,7 @@ class DiagStencil : public AxisStencil { int pts = AxisStencil::addPoints(v); // Add points from diagonals. - for (int r = 1; r <= _radius; r++) { + for (int r = 1; r <= get_radius(); r++) { v += // x-y diagonal. @@ -170,8 +170,8 @@ class PlaneStencil : public DiagStencil { int pts = DiagStencil::addPoints(v); // Add remaining points on planes. - for (int r = 1; r <= _radius; r++) { - for (int m = r+1; m <= _radius; m++) { + for (int r = 1; r <= get_radius(); r++) { + for (int m = r+1; m <= get_radius(); m++) { v += // x-y plane. @@ -232,9 +232,9 @@ class CubeStencil : public PlaneStencil { int pts = PlaneStencil::addPoints(v); // Add points from rest of cube. - for (int rx = 1; rx <= _radius; rx++) - for (int ry = 1; ry <= _radius; ry++) - for (int rz = 1; rz <= _radius; rz++) { + for (int rx = 1; rx <= get_radius(); rx++) + for (int ry = 1; ry <= get_radius(); ry++) + for (int rz = 1; rz <= get_radius(); rz++) { v += // Each quadrant. diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index 5a438da3..275da5a6 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -2487,7 +2487,7 @@ TTIStencil (int radius = 2): // Required stencil-definition method. virtual void define () { - switch (_radius) + switch (get_radius()) { case 2: define_so4 (); diff --git a/src/stencils/TestStencils.cpp b/src/stencils/TestStencils.cpp index 1e794eaf..3cb89f87 100644 --- a/src/stencils/TestStencils.cpp +++ b/src/stencils/TestStencils.cpp @@ -52,7 +52,7 @@ class TestBase : public yc_solution_with_radius_base { int left_ext, int right_ext) { yc_number_node_ptr v; int n = 0; - for (int i = -_radius - left_ext; i <= _radius + right_ext; i++, n++) + for (int i = -get_radius() - left_ext; i <= get_radius() + right_ext; i++, n++) v += V(t0, x0+i); return v / n; } @@ -63,7 +63,7 @@ class TestBase : public yc_solution_with_radius_base { int left_ext, int right_ext) { yc_number_node_ptr v; int n = 0; - for (int i = -_radius - left_ext; i <= _radius + right_ext; i++, n++) + for (int i = -get_radius() - left_ext; i <= get_radius() + right_ext; i++, n++) v += V(x0+i); return v / n; } @@ -78,8 +78,8 @@ class TestBase : public yc_solution_with_radius_base { int y_left_ext, int y_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) - for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) { + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) { v += V(t0, x0+i, y0+j); n++; } @@ -96,8 +96,8 @@ class TestBase : public yc_solution_with_radius_base { int y_left_ext, int y_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) - for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) { + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) { v += V(x0+i, y0+j); n++; } @@ -116,9 +116,9 @@ class TestBase : public yc_solution_with_radius_base { int z_left_ext, int z_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) - for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) - for (int k : { -_radius - z_left_ext, 0, _radius + z_right_ext }) { + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) + for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { v += V(t0, x0+i, y0+j, z0+k); n++; } @@ -137,9 +137,9 @@ class TestBase : public yc_solution_with_radius_base { int z_left_ext, int z_right_ext) { yc_number_node_ptr v; int n = 0; - for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) - for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) - for (int k : { -_radius - z_left_ext, 0, _radius + z_right_ext }) { + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) + for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { v += V(x0+i, y0+j, z0+k); n++; } @@ -160,10 +160,10 @@ class TestBase : public yc_solution_with_radius_base { int z_left_ext, int z_right_ext) { yc_number_node_ptr v; int n = 0; - for (int h : { -_radius - w_left_ext, 0, _radius + w_right_ext }) - for (int i : { -_radius - x_left_ext, 0, _radius + x_right_ext }) - for (int j : { -_radius - y_left_ext, 0, _radius + y_right_ext }) - for (int k : { -_radius - z_left_ext, 0, _radius + z_right_ext }) { + for (int h : { -get_radius() - w_left_ext, 0, get_radius() + w_right_ext }) + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) + for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { v += V(t0, w0+h, x0+i, y0+j, z0+k); n++; } @@ -350,13 +350,13 @@ class TestMisc2dStencil : public yc_solution_with_radius_base { // Define the value at t+1 using asymmetric stencil // with various pos & neg indices in misc dims. yc_number_node_ptr v = A(t, x, 0, y, -1, 2) + 1.0; - for (int r = 1; r <= _radius; r++) + for (int r = 1; r <= get_radius(); r++) v += A(t, x + r, 3, y, 0, 1); - for (int r = 1; r <= _radius + 1; r++) + for (int r = 1; r <= get_radius() + 1; r++) v += A(t, x - r, 4, y, 2, 1); - for (int r = 1; r <= _radius + 2; r++) + for (int r = 1; r <= get_radius() + 2; r++) v += A(t, x, -2, y + r, 2, 0); - for (int r = 1; r <= _radius + 3; r++) + for (int r = 1; r <= get_radius() + 3; r++) v += A(t, x, 0, y - r, 0, -1); A(t+1, x, 1, y, 2, 3) EQUALS v; } @@ -393,13 +393,13 @@ class StreamStencil : public yc_solution_with_radius_base { yc_solution_with_radius_base("test_stream_3d", radius) { } virtual ~StreamStencil() { } - // Define equation to read '_radius' values and write one. + // Define equation to read 'get_radius()' values and write one. virtual void define() { yc_number_node_ptr v; - // Add '_radius' values from past time-steps. - for (int r = 0; r < _radius; r++) + // Add 'get_radius()' values from past time-steps. + for (int r = 0; r < get_radius(); r++) v += A(t-r, x, y, z); // define the value at t+1 to be equivalent to v + 1. diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index 261a83cf..66d93a5e 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -129,6 +129,9 @@ ($) s/\bIndexExprPtr\b/yc_index_node_ptr/g; s/\bBoolExprPtr\b/yc_bool_node_ptr/g; + # Vars. + s/\b_radius\b/get_radius()/g; + # Other macros. s/\b(EQUALS_OPER|IS_EQUIV_TO|IS_EQUIVALENT_TO)\b/EQUALS/g; s/\b(IF|IF_OPER)\b/IF_DOMAIN/g; From 0339fdee6fe122854c4f7d5c035c85265cf278d8 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 16 May 2019 11:41:44 -0700 Subject: [PATCH 33/62] Allow yc_solution_base to be used outside of compiler utility. --- include/aux/Soln.hpp | 4 +- .../yc_solution_api.hpp} | 128 +++++++++--------- include/yask_compiler_api.hpp | 4 +- src/compiler/compiler_main.cpp | 27 +--- src/compiler/lib/Solution.cpp | 36 ++++- src/compiler/lib/YaskKernel.cpp | 2 +- src/stencils/AwpElasticStencil.cpp | 2 +- src/stencils/AwpStencil.cpp | 2 +- .../ElasticStencil/ElasticStencil.hpp | 2 +- src/stencils/FSGElastic2Stencil.cpp | 2 +- src/stencils/FSGElasticStencil.cpp | 2 +- src/stencils/Iso3dfdStencil.cpp | 61 ++++----- src/stencils/SimpleStencils.cpp | 2 +- src/stencils/TTIStencil.cpp | 2 +- src/stencils/TestStencils.cpp | 2 +- utils/bin/convert_v2_stencil.pl | 2 +- 16 files changed, 149 insertions(+), 131 deletions(-) rename include/{yask_compiler_utility_api.hpp => aux/yc_solution_api.hpp} (62%) diff --git a/include/aux/Soln.hpp b/include/aux/Soln.hpp index 06664777..82cec1c1 100644 --- a/include/aux/Soln.hpp +++ b/include/aux/Soln.hpp @@ -32,8 +32,8 @@ IN THE SOFTWARE. #pragma once -// These functions and macros are built upon the YASK compiler utility APIs. -#include "yask_compiler_utility_api.hpp" +// These functions and macros are built upon the YASK compiler APIs. +#include "yask_compiler_api.hpp" namespace yask { diff --git a/include/yask_compiler_utility_api.hpp b/include/aux/yc_solution_api.hpp similarity index 62% rename from include/yask_compiler_utility_api.hpp rename to include/aux/yc_solution_api.hpp index 86c9707e..ee8aa1fe 100644 --- a/include/yask_compiler_utility_api.hpp +++ b/include/aux/yc_solution_api.hpp @@ -25,55 +25,62 @@ IN THE SOFTWARE. // This file contains a base class and macros to create // stencils to be included in the YASK compiler binary utility. -/** @file yask_compiler_utility_api.hpp */ + +// This file uses Doxygen 1.8 markup for API documentation-generation. +// See http://www.stack.nl/~dimitri/doxygen. +/** @file yc_solution_api.hpp */ #pragma once -// Standard headers not provided by API. +// Standard headers. #include - -// These functions and macros are built upon the YASK compiler APIs. -#include "yask_compiler_api.hpp" +#include namespace yask { /** - * \defgroup ycu YASK Compiler Utility - * Wrappers around \ref yc_solution pointers used to create solutions that will - * be integrated into the provided `yask_compiler.exe` binary utility. - * Not to be used by YASK stencil code that is _not_ to be used with the compiler - * utility. In other words, if you write your own binary to generate optimized - * YASK stencil code, use the APIs in \ref sec_yc only. + * \addtogroup yc * @{ */ - /// All C++ stencil solutions written for the YASK compiler utility must implement this class. + /// A base class for defining solutions to be kept in a common registry. /** - This is a wrapper around a \ref yc_solution pointer. - The `define()` method must be overloaded by - the YASK DSL programmer to add stencil equations. - - Not to be used by DSL code that is not a part of the YASK compiler - utility `yask_compiler.exe`. For DSL code not using this utility, - call yc_factory::new_solution(), yc_solution::format(), etc. directly. + This is a wrapper around a \ref yc_solution pointer and a + static registry used to hold all \ref yc_solution_base objects. + + This base class must be extended via inheritance. + When using the provided YASK compiler utility, + the `define()` method must be overloaded to add stencil equations + and other functionality needed to implement the concrete + solution. */ class yc_solution_base { + + public: + /// Type for a common registry shared among all yc_solution_base objects. + typedef std::map soln_map; + private: /// Pointer to the YASK stencil solution. yc_solution_ptr _soln; + /// Factory to create new solutions. + yc_factory _yc_factory; + /// Factory to create new nodes. yc_node_factory _node_factory; + + /// A common registry shared among all yc_solution_base objects. + static soln_map _soln_registry; public: - /// Commonly-used constructor. + /// Constructor. /** - Creates a new yc_solution object and - registers this object in the list for the YASK compiler. - The define() method will be called from the YASK - compiler for the selected solution. + Creates a new yc_solution object and adds this object to the + registry. Throws an exception if a solution with this name + already exists. */ yc_solution_base(const std::string& name); @@ -82,80 +89,76 @@ namespace yask { This constructor allows the use of object-oriented composition instead of inheritance when creating classes that participate in solution definition. - When using this version, the define() method will - _not_ be called directly from the YASK compiler, but it (or any - other method) may be called by the parent `base` object - explicitly. */ - yc_solution_base(yc_solution_base& base) { - _soln = base.get_soln(); - assert(_soln.get()); - } + yc_solution_base(yc_solution_base& base); /// Destructor. virtual ~yc_solution_base() { } + /// Access to the registry. + /** + @returns Reference to the registry. + */ + static const soln_map& get_registry() { + return _soln_registry; + } + /// Define all functionality of this solution. /** - When a stencil solution is selected by naming it via `stencil=name` + If using the provided YASK compiler utility `yask_compiler.exe`, + when a stencil solution is selected via `stencil=name` when invoking `make` or via `-stencil name` on the YASK compiler command-line, this function in the named solution will be called. - This function must be implemented by each concrete stencil solution to + In this case, + this function must be implemented by each concrete stencil solution to add vars and equations as needed to define the stencil. In general, any YASK compiler API functions may be called from this function. - For DSL code not using the YASK compiler - utility `yask_compiler.exe`, the code that would be in define() - could be called from `main()` or any other called function. + For custom code using the YASK compiler library but not + the YASK compiler utility, calling define() is possible but optional. */ - virtual void define() { - yask_exception e("Error: no stencil equations are defined in solution '" + - get_soln()->get_name() + - "'. Implement the 'define()' method in the class " - "derived from 'yc_solution_base'"); - throw e; - } + virtual void define(); /// Access the underlying solution. - virtual yc_solution_ptr + inline yc_solution_ptr get_soln() { return _soln; } /// A simple wrapper for yc_node_factory::new_step_index(). - virtual yc_index_node_ptr + inline yc_index_node_ptr new_step_index(const std::string& name) { return _node_factory.new_step_index(name); } /// A simple wrapper for yc_node_factory::new_domain_index(). - virtual yc_index_node_ptr + inline yc_index_node_ptr new_domain_index(const std::string& name) { return _node_factory.new_domain_index(name); } /// A simple wrapper for yc_node_factory::new_misc_index(). - virtual yc_index_node_ptr + inline yc_index_node_ptr new_misc_index(const std::string& name) { return _node_factory.new_misc_index(name); } /// A simple wrapper for yc_node_factory::new_number_node(). - virtual yc_number_node_ptr + inline yc_number_node_ptr new_number_node(yc_number_any_arg arg) { return _node_factory.new_number_node(arg); } /// A simple wrapper for yc_node_factory::new_first_domain_index(). - virtual yc_number_node_ptr + inline yc_number_node_ptr first_domain_index(yc_index_node_ptr dim) { return _node_factory.new_first_domain_index(dim); } /// A simple wrapper for yc_node_factory::new_last_domain_index(). - virtual yc_number_node_ptr + inline yc_number_node_ptr last_domain_index(yc_index_node_ptr dim) { return _node_factory.new_last_domain_index(dim); } @@ -187,16 +190,14 @@ namespace yask { See yc_solution_base::define(). */ virtual void - define() override { - yask_exception e("Error: no stencil equations are defined in solution '" + - get_soln()->get_name() + - "'. Implement the 'define()' method in the class " - "derived from 'yc_solution_with_radius_base'"); - throw e; - } + define() override; - /// Set radius. - /** @returns `true` if successful. */ + /// Set radius and updates the solution decription. + /** + The DSL programmer can overload this method to set the description + differently and/or other side-effects. + @returns `true` if the `radius` is valid. + */ virtual bool set_radius(int radius) { _radius = radius; @@ -206,8 +207,13 @@ namespace yask { } /// Get radius. + /** + @returns current radius setting. + */ virtual int - get_radius() const { return _radius; } + get_radius() const { + return _radius; + } }; /** @}*/ diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 4d9544c6..2d484df6 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -437,7 +437,7 @@ namespace yask { /// A convenience macro for calling yask::yc_solution::insert_kernel_code(). /** Allows inserting code without the surrounding quotes, making it easier - to format in many IDEs. + to format in many editors and IDEs. */ #define INSERT_YASK_KERNEL_CODE(key, ...) insert_kernel_code(key, #__VA_ARGS__) @@ -995,3 +995,5 @@ namespace yask { } // namespace yask. +// More solution-based objects. +#include "aux/yc_solution_api.hpp" diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 847aaa1f..080074d8 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -28,10 +28,7 @@ IN THE SOFTWARE. // YASK compiler APIs. #include "yask_compiler_api.hpp" -// API for using this utility. -#include "yask_compiler_utility_api.hpp" - -// Backward-compatible API. +// Backward-compatible API for undocumented YASK v2 DSL. #include "aux/Soln.hpp" // YASK compiler-solution code. @@ -57,26 +54,9 @@ namespace yask { string solutionName; int radius = -1; - // Collection of known stencils. - typedef map StencilMap; - StencilMap stencils; - // Dummy object for backward-compatibility with old stencil DSL. StencilList stub_stencils; - // Constructor from the DSL API. - // Create new solution and register it. - yc_solution_base::yc_solution_base(const std::string& name) { - if (stencils.count(name)) - THROW_YASK_EXCEPTION("Error: stencil '" + name + - "' already defined"); - _soln = factory.new_solution(name); - assert(_soln.get()); - - // Add this new 'yc_solution_base' to the map. - stencils[name] = this; - } - } // yask namespace. void usage(const string& cmd) { @@ -92,8 +72,8 @@ void usage(const string& cmd) { cout << " Built-in test solutions:\n"; else cout << " Built-in example solutions:\n"; - for (auto si : stencils) { - auto name = si.first; + for (auto si : yc_solution_base::get_registry()) { + auto& name = si.first; if ((name.rfind("test_", 0) == 0) == show_test) { auto* sp = si.second; cout << " " << name; @@ -378,6 +358,7 @@ void parseOpts(int argc, const char* argv[]) } // Find the stencil in the registry. + auto& stencils = yc_solution_base::get_registry(); auto stencilIter = stencils.find(solutionName); if (stencilIter == stencils.end()) { cerr << "Error: unknown stencil solution '" << solutionName << "'." << endl; diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 175e4a03..e625729f 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -32,6 +32,9 @@ using namespace std; namespace yask { + // Static registry. + yc_solution_base::soln_map yc_solution_base::_soln_registry; + // Stencil-solution APIs. yc_var_ptr StencilSolution::newVar(const std::string& name, bool isScratch, @@ -53,7 +56,6 @@ namespace yask { return gp; } - // Stencil-solution APIs. void StencilSolution::set_fold_len(const yc_index_node_ptr dim, int len) { auto& fold = _settings._foldOptions; @@ -64,7 +66,37 @@ namespace yask { auto& cluster = _settings._clusterOptions; cluster.addDimBack(dim->get_name(), mult); } - + yc_solution_base::yc_solution_base(const std::string& name) { + if (_soln_registry.count(name)) { + yask_exception e("Error: solution '" + name + + "' is already defined"); + throw e; + } + _soln = _yc_factory.new_solution(name); + assert(_soln.get()); + + // Add this new 'yc_solution_base' to the map. + _soln_registry[name] = this; + } + yc_solution_base::yc_solution_base(yc_solution_base& base) { + _soln = base.get_soln(); + assert(_soln.get()); + } + void yc_solution_base::define() { + yask_exception e("Error: no stencil equations are defined in solution '" + + get_soln()->get_name() + + "'. Implement the 'define()' method in the class " + "derived from 'yc_solution_base'"); + throw e; + } + void yc_solution_with_radius_base::define() { + yask_exception e("Error: no stencil equations are defined in solution '" + + get_soln()->get_name() + + "'. Implement the 'define()' method in the class " + "derived from 'yc_solution_with_radius_base'"); + throw e; + } + // Create the intermediate data for printing. void StencilSolution::analyze_solution(int vlen, bool is_folding_efficient) { diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 8054dddb..e9e5c433 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -932,7 +932,7 @@ namespace yask { " }\n"; os << "\n // Code provided by user.\n"; - map protos = + map protos { { yc_solution::after_new_solution, "after_new_solution_hook()" }, { yc_solution::before_prepare_solution, "before_prepare_solution_hook()" }, { yc_solution::after_prepare_solution, "after_prepare_solution_hook()" }, diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp index b633e618..47c93f19 100644 --- a/src/stencils/AwpElasticStencil.cpp +++ b/src/stencils/AwpElasticStencil.cpp @@ -45,7 +45,7 @@ IN THE SOFTWARE. //#define USE_SCRATCH_VARS // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index 728a1760..6e66eb70 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -31,7 +31,7 @@ IN THE SOFTWARE. //#define FULL_SPONGE_VAR // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index 9e85a359..acca1cc1 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -28,7 +28,7 @@ IN THE SOFTWARE. #pragma once // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index ec8b75fe..d6ab5b17 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -29,7 +29,7 @@ IN THE SOFTWARE. // larger vars with an added dimension. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; #include "ElasticStencil/Elastic2Stencil.hpp" diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index 1a9770b8..ea256f09 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -27,7 +27,7 @@ IN THE SOFTWARE. // Contributed by Albert Farres from the Barcelona Supercomputing Center. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; #include "ElasticStencil/ElasticStencil.hpp" diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 908ab868..f2635806 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -28,7 +28,7 @@ IN THE SOFTWARE. // See https://software.intel.com/en-us/articles/eight-optimizations-for-3-dimensional-finite-difference-3dfd-code-with-an-isotropic-iso. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; @@ -43,10 +43,10 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { yc_index_node_ptr z = new_domain_index("z"); // spatial dim. // Vars. - yc_var_proxy pressure = - yc_var_proxy("pressure", get_soln(), { t, x, y, z }); // time-varying 3D pressure var. - yc_var_proxy vel = - yc_var_proxy("vel", get_soln(), { x, y, z }); // constant 3D vel var (c(x,y,z)^2 * delta_t^2). + yc_var_proxy p = + yc_var_proxy("p", get_soln(), { t, x, y, z }); // time-varying 3D var. + yc_var_proxy v = + yc_var_proxy("v", get_soln(), { x, y, z }); // constant 3D var = (c(x,y,z)^2 * delta_t^2). public: @@ -58,7 +58,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { yc_solution_with_radius_base("iso3dfd" + suffix, radius) { } virtual ~Iso3dfdStencil() { } - // Define RHS expression for pressure at t+1 based on values from vel and pressure at t. + // Define RHS expression for p at t+1 based on values from v and p at t. virtual yc_number_node_ptr get_next_p() { // yc_var_proxy spacing. @@ -83,7 +83,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Calculate FDx + FDy + FDz. // Start with center value multiplied by coeff 0. - auto fd_sum = pressure(t, x, y, z) * coeff[c0i]; + auto fd_sum = p(t, x, y, z) * coeff[c0i]; // Add values from x, y, and z axes multiplied by the // coeff for the given radius. @@ -92,43 +92,40 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Add values from axes at radius r. fd_sum += ( // x-axis. - pressure(t, x-r, y, z) + - pressure(t, x+r, y, z) + + p(t, x-r, y, z) + + p(t, x+r, y, z) + // y-axis. - pressure(t, x, y-r, z) + - pressure(t, x, y+r, z) + + p(t, x, y-r, z) + + p(t, x, y+r, z) + // z-axis. - pressure(t, x, y, z-r) + - pressure(t, x, y, z+r) + p(t, x, y, z-r) + + p(t, x, y, z+r) ) * coeff[c0i + r]; // R & L coeffs are identical. } - // Temporal FD coefficients. - // For this implementation, just check the known values to - // simplify the solution. - // But we could parameterize by accuracy-order in time as well. - int torder = 2; - auto tcoeff = get_forward_fd_coefficients(2, torder); - assert(tcoeff[0] == 1.0); // pressure(t+1). - assert(tcoeff[1] == -2.0); // -2 * pressure(t+1). - assert(tcoeff[2] == 1.0); // pressure(t-1). - // Wave equation is: - // 2nd time derivative(p) = c^2 * laplacian(p). + // 2nd_time_derivative(p) = c^2 * laplacian(p). // See https://en.wikipedia.org/wiki/Wave_equation. + // For this implementation, we are fixing the accuracy-order in time + // to 2 and using the known FD coefficients (1, -2, 1) to solve the + // equation manually. But we could parameterize by accuracy-order + // in time as well, starting with a call to + // 'get_forward_fd_coefficients(2, time_order)' for the temporal FD + // coefficients. + // So, wave equation with FD approximations is: // (p(t+1) - 2 * p(t) + p(t-1)) / delta_t^2 = c^2 * fd_sum. - // Solve wave equation for p(t+1): + // Solve for p(t+1): // p(t+1) = 2 * p(t) - p(t-1) + c^2 * fd_sum * delta_t^2. - // Let vel = c^2 * delta_t^2 for each var point. - auto next_p = (2.0 * pressure(t, x, y, z)) - - pressure(t-1, x, y, z) + (fd_sum * vel(x, y, z)); + // Let v = c^2 * delta_t^2 for each var point. + auto next_p = (2.0 * p(t, x, y, z)) - + p(t-1, x, y, z) + (fd_sum * v(x, y, z)); return next_p; } @@ -164,7 +161,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { } - // Define equation for pressure at t+1 based on values from vel and pressure at t. + // Define equation for p at t+1 based on values from v and p at t. virtual void define() { // Get equation for RHS. @@ -173,7 +170,7 @@ class Iso3dfdStencil : public yc_solution_with_radius_base { // Define the value at t+1 to be equal to next_p. // Since this implements the finite-difference method, this // is actually an approximation. - pressure(t+1, x, y, z) EQUALS next_p; + p(t+1, x, y, z) EQUALS next_p; // Insert custom kernel code. add_kernel_code(); @@ -194,7 +191,7 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { Iso3dfdStencil("_sponge", radius) { } virtual ~Iso3dfdSpongeStencil() { } - // Define equation for pressure at t+1 based on values from vel and pressure at t. + // Define equation for p at t+1 based on values from v and p at t. virtual void define() { // Sponge coefficients. @@ -212,7 +209,7 @@ class Iso3dfdSpongeStencil : public Iso3dfdStencil { next_p *= cr_x(x) * cr_y(y) * cr_z(z); // Define the value at t+1 to be equal to next_p. - pressure(t+1, x, y, z) EQUALS next_p; + p(t+1, x, y, z) EQUALS next_p; // Insert custom kernel code. add_kernel_code(); diff --git a/src/stencils/SimpleStencils.cpp b/src/stencils/SimpleStencils.cpp index 58831368..5d3501c9 100644 --- a/src/stencils/SimpleStencils.cpp +++ b/src/stencils/SimpleStencils.cpp @@ -29,7 +29,7 @@ IN THE SOFTWARE. // heat-dissipation kernels in the miniGhost benchmark. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index 275da5a6..f5a834ab 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -27,7 +27,7 @@ IN THE SOFTWARE. // TODO: provide a more readable TTI formulation. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; diff --git a/src/stencils/TestStencils.cpp b/src/stencils/TestStencils.cpp index 3cb89f87..e6525eac 100644 --- a/src/stencils/TestStencils.cpp +++ b/src/stencils/TestStencils.cpp @@ -26,7 +26,7 @@ IN THE SOFTWARE. // Tests for various YASK DSL features. // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_utility_api.hpp" +#include "yask_compiler_api.hpp" using namespace std; using namespace yask; diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index 66d93a5e..d6555054 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -84,7 +84,7 @@ ($) # Include file. elsif (/[#]include.*Soln[.]hpp/) { $result .= "// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility.\n". - "#include \"yask_compiler_utility_api.hpp\"\n". + "#include \"yask_compiler_api.hpp\"\n". "using namespace std;\n". "using namespace yask;\n"; } From c4f4122f0c46724144a0b67941d73cb721c0b3a4 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 16 May 2019 13:35:25 -0700 Subject: [PATCH 34/62] Enable yask_exception::what() to return description. Helps when static ctors throw exceptions. --- include/yask_common_api.hpp | 30 ++++++++++++++++-------------- src/common/common_utils.cpp | 4 ++-- src/kernel/Makefile | 1 + 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index 933b4b33..0189dd11 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -85,32 +85,34 @@ namespace yask { /** Objects of this exception contain additional message from yask framework */ class yask_exception: public std::exception { private: - /// Additional message container + /// Description of exception. std::string _msg; public: /// Construct a YASK exception with no message. - yask_exception() {}; + yask_exception() : + _msg("YASK exception") { }; /// Construct a YASK exception with `message`. yask_exception(const std::string& message) : - _msg(message) {}; + _msg(message) { }; - virtual ~yask_exception() {}; + virtual ~yask_exception() { }; - /// Get default message. - /** Returns a C-style character string describing the general cause of the current error. - @returns default message of the exception. */ - virtual const char* what() noexcept; + /// Get description. + /** Returns a C-style character string describing the cause of the current error. + @returns description of the exception. */ + virtual const char* what() const noexcept; - /// Add additional message to this exception. - void add_message(const std::string& message - /**< [in] Additional message as string. */ ); + /// Append `message` to description of this exception. + virtual void add_message(const std::string& message + /**< [in] Additional message as string. */ ); - /// Get additional message. - /** @returns additional message as string */ - const char* get_message() const; + /// Get description. + /** Same as what(). + @returns description of the exception. */ + virtual const char* get_message() const; }; /// Factory to create output objects. diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 1d2281f6..0e1e2b50 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -148,8 +148,8 @@ namespace yask { int yask_num_threads[yask_max_levels] = { 0 }; // See yask_common_api.hpp for documentation. - const char* yask_exception::what() noexcept { - return "yask::yask_exception\n"; + const char* yask_exception::what() const noexcept { + return _msg.c_str(); } void yask_exception::add_message(const string& arg_msg) { diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 321c8e40..590db76b 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -633,6 +633,7 @@ $(YK_GEN_DIR)/yask_var_code.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(YK_CODE_FILE): $(YC_EXEC) $(MKDIR) $(dir $@) + @- rm -f $@ $(RUN_PREFIX) $< $(YC_FLAGS) $(EXTRA_YC_FLAGS) -p $(YC_TARGET) $@ | tee $(YC_REPORT_FILE) 2>&1 @ grep -q -E 'End of .* code' $@ @- gindent -fca $@ || \ From 16145434bea4fe89ab09f18cfcca00ef73083a97 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 17 May 2019 15:40:11 -0700 Subject: [PATCH 35/62] Remove linker error caused by repeated class names. --- include/aux/Soln.hpp | 2 +- include/aux/yc_solution_api.hpp | 7 +- include/yask_common_api.hpp | 2 + src/common/common.mk | 5 +- src/compiler/lib/Cpp.hpp | 2 +- src/compiler/lib/Solution.cpp | 20 +- src/kernel/Makefile | 2 +- src/stencils/AwpElasticStencil.cpp | 713 ++--- src/stencils/AwpStencil.cpp | 677 +++-- src/stencils/FSGElastic2Stencil.cpp | 2 + src/stencils/Iso3dfdStencil.cpp | 340 ++- src/stencils/SimpleStencils.cpp | 429 +-- src/stencils/TTIStencil.cpp | 4371 ++++++++++++--------------- src/stencils/TestStencils.cpp | 1249 ++++---- utils/bin/convert_v2_stencil.pl | 5 +- 15 files changed, 3663 insertions(+), 4163 deletions(-) diff --git a/include/aux/Soln.hpp b/include/aux/Soln.hpp index 82cec1c1..72e59410 100644 --- a/include/aux/Soln.hpp +++ b/include/aux/Soln.hpp @@ -102,7 +102,7 @@ namespace yask { /** The derived class must implement a constructor that takes only a \ref StencilList reference. */ #define REGISTER_STENCIL(class_name) \ - static class_name class_name ## _instance(stub_stencils) + static class_name class_name ## _v2instance(stub_stencils) // Convenience macros for declaring dims in a class derived from \ref StencilBase. // The 'd' arg is the new var name and the dim name. diff --git a/include/aux/yc_solution_api.hpp b/include/aux/yc_solution_api.hpp index ee8aa1fe..1d2cdad6 100644 --- a/include/aux/yc_solution_api.hpp +++ b/include/aux/yc_solution_api.hpp @@ -71,9 +71,6 @@ namespace yask { /// Factory to create new nodes. yc_node_factory _node_factory; - /// A common registry shared among all yc_solution_base objects. - static soln_map _soln_registry; - public: /// Constructor. @@ -99,9 +96,7 @@ namespace yask { /** @returns Reference to the registry. */ - static const soln_map& get_registry() { - return _soln_registry; - } + static soln_map& get_registry(); /// Define all functionality of this solution. /** diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index 0189dd11..64f10775 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -33,9 +33,11 @@ IN THE SOFTWARE. #include #include +#include #include #include #include +#include namespace yask { diff --git a/src/common/common.mk b/src/common/common.mk index b41446c4..4bacd955 100644 --- a/src/common/common.mk +++ b/src/common/common.mk @@ -59,8 +59,9 @@ COMM_SRC_NAMES := output common_utils tuple combo fd_coeff fd_coeff2 COEFF_DIR := $(SRC_DIR)/contrib/coefficients # Globs and flags. -INC_GLOB := $(wildcard $(addsuffix /*.hpp,$(INC_DIR))) -INC_CXXFLAGS := $(addprefix -I,$(INC_DIR) $(INC_DIR)/aux) +INC_DIRS := $(INC_DIR) $(INC_DIR)/aux +INC_GLOB := $(wildcard $(addsuffix /*.hpp,$(INC_DIRS))) +INC_CXXFLAGS := $(addprefix -I,$(INC_DIRS)) # YASK stencil compiler. # This is here because both the compiler and kernel diff --git a/src/compiler/lib/Cpp.hpp b/src/compiler/lib/Cpp.hpp index 2df7a34f..c9a2be02 100644 --- a/src/compiler/lib/Cpp.hpp +++ b/src/compiler/lib/Cpp.hpp @@ -257,7 +257,7 @@ namespace yask { protected: EqBundlePacks& _eqBundlePacks; // packs of bundles w/o inter-dependencies. EqBundles& _clusterEqBundles; // eq-bundles for scalar and vector. - string _context, _context_base; + string _context, _context_base; // class names; // Print an expression as a one-line C++ comment. void addComment(ostream& os, EqBundle& eq); diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index e625729f..d8318c99 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -32,9 +32,6 @@ using namespace std; namespace yask { - // Static registry. - yc_solution_base::soln_map yc_solution_base::_soln_registry; - // Stencil-solution APIs. yc_var_ptr StencilSolution::newVar(const std::string& name, bool isScratch, @@ -66,17 +63,28 @@ namespace yask { auto& cluster = _settings._clusterOptions; cluster.addDimBack(dim->get_name(), mult); } + yc_solution_base::soln_map& yc_solution_base::get_registry() { + static yc_solution_base::soln_map* rp = 0; + if (!rp) + + // Creates a global singleton. + // Small memory leak because it's never deleted, but not important. + rp = new yc_solution_base::soln_map; + assert(rp); + return *rp; + } yc_solution_base::yc_solution_base(const std::string& name) { - if (_soln_registry.count(name)) { + auto& reg = yc_solution_base::get_registry(); + if (reg.count(name)) { yask_exception e("Error: solution '" + name + "' is already defined"); throw e; } _soln = _yc_factory.new_solution(name); assert(_soln.get()); - + // Add this new 'yc_solution_base' to the map. - _soln_registry[name] = this; + reg[name] = this; } yc_solution_base::yc_solution_base(yc_solution_base& base) { _soln = base.get_soln(); diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 590db76b..342c4375 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -298,7 +298,7 @@ YK_GEN_HEADERS := $(addprefix $(YK_GEN_DIR)/, \ yask_layouts.hpp \ yask_var_code.hpp) \ $(YK_CODE_FILE) -YK_INC_DIRS := $(INC_DIR) $(YK_LIB_SRC_DIR) $(COMM_DIR) $(COEFF_DIR) +YK_INC_DIRS := $(INC_DIRS) $(YK_LIB_SRC_DIR) $(COMM_DIR) $(COEFF_DIR) YK_INC_GLOB := $(addsuffix /*.hpp,$(YK_INC_DIRS)) YK_API_TEST_EXEC := $(BIN_OUT_DIR)/$(YK_BASE)_api_test.exe YK_VAR_TEST_EXEC := $(BIN_OUT_DIR)/$(YK_BASE)_var_test.exe diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp index 47c93f19..677b1b63 100644 --- a/src/stencils/AwpElasticStencil.cpp +++ b/src/stencils/AwpElasticStencil.cpp @@ -49,59 +49,62 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -class AwpElasticStencil : public yc_solution_base { - -protected: - - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - - // Time-varying 3D-spatial velocity vars. - yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); - yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); - yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); - - // Time-varying 3D-spatial Stress vars. - yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); - yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); - - // 3D-spatial Lame' coefficients. - yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); - yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); - yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); - - // Sponge coefficients. - // (Most of these will be 1.0.) +// Create an anonymous namespace to ensure that types are local. +namespace { + + class AwpElasticStencil : public yc_solution_base { + + protected: + + // Indices & dimensions. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + + // Time-varying 3D-spatial velocity vars. + yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); + yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); + yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); + + // Time-varying 3D-spatial Stress vars. + yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); + + // 3D-spatial Lame' coefficients. + yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); + yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); + yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); + + // Sponge coefficients. + // (Most of these will be 1.0.) #ifdef FULL_SPONGE_VAR - yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); + yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); #else - yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); - yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); - yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); + yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); + yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); + yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); #endif - // Spatial FD coefficients. - const double c1 = 9.0/8.0; - const double c2 = -1.0/24.0; + // Spatial FD coefficients. + const double c1 = 9.0/8.0; + const double c2 = -1.0/24.0; - // Physical dimensions in time and space. - yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); - yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); + // Physical dimensions in time and space. + yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); + yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); - // For the surface stress conditions, we need to write into 2 points - // above the surface. Since we can only write into the "domain", we - // will define the surface index to be 2 points before the last domain - // index. Thus, there will be two layers in the domain above the surface. + // For the surface stress conditions, we need to write into 2 points + // above the surface. Since we can only write into the "domain", we + // will define the surface index to be 2 points before the last domain + // index. Thus, there will be two layers in the domain above the surface. #define SURFACE_IDX (last_domain_index(z) - 2) - // Define some sub-domains related to the surface. + // Define some sub-domains related to the surface. #define IF_BELOW_SURFACE IF_DOMAIN (z < SURFACE_IDX) #define IF_AT_SURFACE IF_DOMAIN (z == SURFACE_IDX) #define IF_AT_OR_BELOW_SURFACE IF_DOMAIN (z <= SURFACE_IDX) @@ -114,354 +117,356 @@ class AwpElasticStencil : public yc_solution_base { yc_var_proxy tmp_vel_z = yc_var_proxy("tmp_vel_z", get_soln(), { x, y, z }, true); #endif -public: + public: - AwpElasticStencil() : - yc_solution_base("awp_elastic") { } + AwpElasticStencil() : + yc_solution_base("awp_elastic") { } - // Adjustment for sponge layer. - void adjust_for_sponge(yc_number_node_ptr& val) { + // Adjustment for sponge layer. + void adjust_for_sponge(yc_number_node_ptr& val) { #ifdef FULL_SPONGE_VAR - val *= sponge(x, y, z); + val *= sponge(x, y, z); #else - val *= cr_x(x) * cr_y(y) * cr_z(z); + val *= cr_x(x) * cr_y(y) * cr_z(z); #endif - } - - // Velocity-var define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress vars at t. Note that the t, - // x, y, z parameters are integer var indices, not actual offsets in - // time or space, so half-steps due to staggered vars are adjusted - // appropriately. - - yc_number_node_ptr get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto rho_val = (rho(x, y, z ) + - rho(x, y-1, z ) + - rho(x, y, z-1) + - rho(x, y-1, z-1)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + - c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + - c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + - c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + - c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + - c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_x); - - // Return the value at t+1. - return next_vel_x; - } - yc_number_node_ptr get_next_vel_y(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto rho_val = (rho(x, y, z ) + - rho(x+1, y, z ) + - rho(x, y, z-1) + - rho(x+1, y, z-1)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + - c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + - c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + - c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + - c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + - c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_y); - - // Return the value at t+1. - return next_vel_y; - } - yc_number_node_ptr get_next_vel_z(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto rho_val = (rho(x, y, z) + - rho(x+1, y, z) + - rho(x, y-1, z) + - rho(x+1, y-1, z)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + - c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + - c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + - c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + - c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + - c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_z); - - // Return the value at t+1. - return next_vel_z; - } - - // Free-surface boundary equations for velocity. - void define_free_surface_vel() { - - // Since we're defining points when z == surface + 1, - // the surface itself will be at z - 1; - auto surf = z - 1; + } + + // Velocity-var define functions. For each D in x, y, z, define vel_D + // at t+1 based on vel_x at t and stress vars at t. Note that the t, + // x, y, z parameters are integer var indices, not actual offsets in + // time or space, so half-steps due to staggered vars are adjusted + // appropriately. + + yc_number_node_ptr get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + auto rho_val = (rho(x, y, z ) + + rho(x, y-1, z ) + + rho(x, y, z-1) + + rho(x, y-1, z-1)) * (1.0 / 4.0); + auto d_val = + c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + + c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + + c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + + c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + + c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + + c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); + auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + adjust_for_sponge(next_vel_x); + + // Return the value at t+1. + return next_vel_x; + } + yc_number_node_ptr get_next_vel_y(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + auto rho_val = (rho(x, y, z ) + + rho(x+1, y, z ) + + rho(x, y, z-1) + + rho(x+1, y, z-1)) * (1.0 / 4.0); + auto d_val = + c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + + c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + + c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + + c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + + c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); + auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + adjust_for_sponge(next_vel_y); + + // Return the value at t+1. + return next_vel_y; + } + yc_number_node_ptr get_next_vel_z(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + auto rho_val = (rho(x, y, z) + + rho(x+1, y, z) + + rho(x, y-1, z) + + rho(x+1, y-1, z)) * (1.0 / 4.0); + auto d_val = + c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + + c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + + c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + + c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + + c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); + auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + adjust_for_sponge(next_vel_z); + + // Return the value at t+1. + return next_vel_z; + } + + // Free-surface boundary equations for velocity. + void define_free_surface_vel() { + + // Since we're defining points when z == surface + 1, + // the surface itself will be at z - 1; + auto surf = z - 1; #ifdef USE_SCRATCH_VARS - // The values for velocity at t+1 will be needed - // in multiple free-surface calculations. - // Thus, it will reduce the number of FP ops - // required if we pre-compute them and store them - // in scratch vars. + // The values for velocity at t+1 will be needed + // in multiple free-surface calculations. + // Thus, it will reduce the number of FP ops + // required if we pre-compute them and store them + // in scratch vars. #define VEL_X tmp_vel_x #define VEL_Y tmp_vel_y #define VEL_Z tmp_vel_z - VEL_X(x, y, z) EQUALS get_next_vel_x(x, y, z); - VEL_Y(x, y, z) EQUALS get_next_vel_y(x, y, z); - VEL_Z(x, y, z) EQUALS get_next_vel_z(x, y, z); + VEL_X(x, y, z) EQUALS get_next_vel_x(x, y, z); + VEL_Y(x, y, z) EQUALS get_next_vel_y(x, y, z); + VEL_Z(x, y, z) EQUALS get_next_vel_z(x, y, z); #else - // If not using scratch vars, just call the - // functions to calculate each value of velocity - // at t+1 every time it's needed. + // If not using scratch vars, just call the + // functions to calculate each value of velocity + // at t+1 every time it's needed. #define VEL_X get_next_vel_x #define VEL_Y get_next_vel_y #define VEL_Z get_next_vel_z #endif - // A couple of intermediate values. - auto d_x_val = VEL_X(x+1, y, surf) - - (VEL_Z(x+1, y, surf) - VEL_Z(x, y, surf)); - auto d_y_val = VEL_Y(x, y-1, surf) - - (VEL_Z(x, y, surf) - VEL_Z(x, y-1, surf)); - - // Following values are valid one layer above the free surface. - auto plus1_vel_x = VEL_X(x, y, surf) - - (VEL_Z(x, y, surf) - VEL_Z(x-1, y, surf)); - auto plus1_vel_y = VEL_Y(x, y, surf) - - (VEL_Z(x, y+1, surf) - VEL_Z(x, y, surf)); - auto plus1_vel_z = VEL_Z(x, y, surf) - - ((d_x_val - plus1_vel_x) + - (VEL_X(x+1, y, surf) - VEL_X(x, y, surf)) + - (plus1_vel_y - d_y_val) + - (VEL_Y(x, y, surf) - VEL_Y(x, y-1, surf))) / - ((mu(x, y, surf) * - (2.0 / mu(x, y, surf) + 1.0 / lambda(x, y, surf)))); + // A couple of intermediate values. + auto d_x_val = VEL_X(x+1, y, surf) - + (VEL_Z(x+1, y, surf) - VEL_Z(x, y, surf)); + auto d_y_val = VEL_Y(x, y-1, surf) - + (VEL_Z(x, y, surf) - VEL_Z(x, y-1, surf)); + + // Following values are valid one layer above the free surface. + auto plus1_vel_x = VEL_X(x, y, surf) - + (VEL_Z(x, y, surf) - VEL_Z(x-1, y, surf)); + auto plus1_vel_y = VEL_Y(x, y, surf) - + (VEL_Z(x, y+1, surf) - VEL_Z(x, y, surf)); + auto plus1_vel_z = VEL_Z(x, y, surf) - + ((d_x_val - plus1_vel_x) + + (VEL_X(x+1, y, surf) - VEL_X(x, y, surf)) + + (plus1_vel_y - d_y_val) + + (VEL_Y(x, y, surf) - VEL_Y(x, y-1, surf))) / + ((mu(x, y, surf) * + (2.0 / mu(x, y, surf) + 1.0 / lambda(x, y, surf)))); #undef VEL_X #undef VEL_Y #undef VEL_Z - // Define layer at one point above surface. - vel_x(t+1, x, y, z) EQUALS plus1_vel_x IF_ONE_ABOVE_SURFACE; - vel_y(t+1, x, y, z) EQUALS plus1_vel_y IF_ONE_ABOVE_SURFACE; - vel_z(t+1, x, y, z) EQUALS plus1_vel_z IF_ONE_ABOVE_SURFACE; + // Define layer at one point above surface. + vel_x(t+1, x, y, z) EQUALS plus1_vel_x IF_ONE_ABOVE_SURFACE; + vel_y(t+1, x, y, z) EQUALS plus1_vel_y IF_ONE_ABOVE_SURFACE; + vel_z(t+1, x, y, z) EQUALS plus1_vel_z IF_ONE_ABOVE_SURFACE; #ifdef SET_ALL_POINTS - // Define layer two points above surface for completeness, even - // though these aren't input to any stencils. - vel_x(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - vel_y(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - vel_z(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + // Define layer two points above surface for completeness, even + // though these aren't input to any stencils. + vel_x(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + vel_y(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + vel_z(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; #endif - } - - // Compute average of 8 neighbors. - yc_number_node_ptr ave8(yc_var_proxy& g, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - return 8.0 / - (g(x, y, z ) + g(x+1, y, z ) + - g(x, y-1, z ) + g(x+1, y-1, z ) + - g(x, y, z-1) + g(x+1, y, z-1) + - g(x, y-1, z-1) + g(x+1, y-1, z-1)); - } - - // Some common velocity calculations. - yc_number_node_ptr d_x_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - return - c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); - } - yc_number_node_ptr d_y_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - return - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + - c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); - } - yc_number_node_ptr d_z_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - return - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + - c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); - } - - // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel vars at t+1. - // This implies that the velocity-var define functions must be called - // before these for a given value of t. Note that the t, x, y, z - // parameters are integer var indices, not actual offsets in time or - // space, so half-steps due to staggered vars are adjusted - // appropriately. - - yc_number_node_ptr get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - auto next_stress_xx = stress_xx(t, x, y, z) + - ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_x_val(x, y, z)) + - (ave8(lambda, x, y, z) * - (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); - adjust_for_sponge(next_stress_xx); - - // Return the value at t+1. - return next_stress_xx; - } - yc_number_node_ptr get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - auto next_stress_yy = stress_yy(t, x, y, z) + - ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_y_val(x, y, z)) + - (ave8(lambda, x, y, z) * - (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); - adjust_for_sponge(next_stress_yy); - - // Return the value at t+1. - return next_stress_yy; - } - yc_number_node_ptr get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - auto next_stress_zz = stress_zz(t, x, y, z) + - ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_z_val(x, y, z)) + - (ave8(lambda, x, y, z) * - (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); - adjust_for_sponge(next_stress_zz); - - // return the value at t+1. - return next_stress_zz; - } - yc_number_node_ptr get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - // Compute average of 2 neighbors. - auto mu2 = 2.0 / - (mu(x, y, z ) + mu(x, y, z-1)); - - // Note that we are using the velocity values at t+1. - auto d_xy_val = - c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - auto d_yx_val = - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + - c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - - auto next_stress_xy = stress_xy(t, x, y, z) + - ((mu2 * delta_t / h) * (d_xy_val + d_yx_val)); - adjust_for_sponge(next_stress_xy); - - // return the value at t+1. - return next_stress_xy; - } - yc_number_node_ptr get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - // Compute average of 2 neighbors. - auto mu2 = 2.0 / - (mu(x, y, z ) + mu(x, y-1, z )); - - // Note that we are using the velocity values at t+1. - auto d_xz_val = - c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - auto d_zx_val = - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + - c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - - auto next_stress_xz = stress_xz(t, x, y, z) + - ((mu2 * delta_t / h) * (d_xz_val + d_zx_val)); - adjust_for_sponge(next_stress_xz); - - // return the value at t+1. - return next_stress_xz; - } - yc_number_node_ptr get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - // Compute average of 2 neighbors. - auto mu2 = 2.0 / - (mu(x, y, z ) + mu(x+1, y, z )); - - // Note that we are using the velocity values at t+1. - auto d_yz_val = - c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + - c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - auto d_zy_val = - c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + - c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - - auto next_stress_yz = stress_yz(t, x, y, z) + - ((mu2 * delta_t / h) * (d_yz_val + d_zy_val)); - adjust_for_sponge(next_stress_yz); - - // return the value at t+1. - return next_stress_yz; - } - - // Free-surface boundary equations for stress. - void define_free_surface_stress() { - - // When z == surface + 1, the surface will be at z - 1; - auto surf = z - 1; - - stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf) IF_ONE_ABOVE_SURFACE; - stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; - stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; + } + + // Compute average of 8 neighbors. + yc_number_node_ptr ave8(yc_var_proxy& g, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + return 8.0 / + (g(x, y, z ) + g(x+1, y, z ) + + g(x, y-1, z ) + g(x+1, y-1, z ) + + g(x, y, z-1) + g(x+1, y, z-1) + + g(x, y-1, z-1) + g(x+1, y-1, z-1)); + } + + // Some common velocity calculations. + yc_number_node_ptr d_x_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); + } + yc_number_node_ptr d_y_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + + c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); + } + yc_number_node_ptr d_z_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + + c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); + } + + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called + // before these for a given value of t. Note that the t, x, y, z + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted + // appropriately. + + yc_number_node_ptr get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + auto next_stress_xx = stress_xx(t, x, y, z) + + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_x_val(x, y, z)) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); + adjust_for_sponge(next_stress_xx); + + // Return the value at t+1. + return next_stress_xx; + } + yc_number_node_ptr get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + auto next_stress_yy = stress_yy(t, x, y, z) + + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_y_val(x, y, z)) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); + adjust_for_sponge(next_stress_yy); + + // Return the value at t+1. + return next_stress_yy; + } + yc_number_node_ptr get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + auto next_stress_zz = stress_zz(t, x, y, z) + + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_z_val(x, y, z)) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); + adjust_for_sponge(next_stress_zz); + + // return the value at t+1. + return next_stress_zz; + } + yc_number_node_ptr get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + // Compute average of 2 neighbors. + auto mu2 = 2.0 / + (mu(x, y, z ) + mu(x, y, z-1)); + + // Note that we are using the velocity values at t+1. + auto d_xy_val = + c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); + auto d_yx_val = + c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); + + auto next_stress_xy = stress_xy(t, x, y, z) + + ((mu2 * delta_t / h) * (d_xy_val + d_yx_val)); + adjust_for_sponge(next_stress_xy); + + // return the value at t+1. + return next_stress_xy; + } + yc_number_node_ptr get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + // Compute average of 2 neighbors. + auto mu2 = 2.0 / + (mu(x, y, z ) + mu(x, y-1, z )); + + // Note that we are using the velocity values at t+1. + auto d_xz_val = + c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); + auto d_zx_val = + c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); + + auto next_stress_xz = stress_xz(t, x, y, z) + + ((mu2 * delta_t / h) * (d_xz_val + d_zx_val)); + adjust_for_sponge(next_stress_xz); + + // return the value at t+1. + return next_stress_xz; + } + yc_number_node_ptr get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + // Compute average of 2 neighbors. + auto mu2 = 2.0 / + (mu(x, y, z ) + mu(x+1, y, z )); + + // Note that we are using the velocity values at t+1. + auto d_yz_val = + c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); + auto d_zy_val = + c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); + + auto next_stress_yz = stress_yz(t, x, y, z) + + ((mu2 * delta_t / h) * (d_yz_val + d_zy_val)); + adjust_for_sponge(next_stress_yz); + + // return the value at t+1. + return next_stress_yz; + } + + // Free-surface boundary equations for stress. + void define_free_surface_stress() { + + // When z == surface + 1, the surface will be at z - 1; + auto surf = z - 1; + + stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf) IF_ONE_ABOVE_SURFACE; + stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; + stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; #ifdef SET_ALL_POINTS - // Define other 3 stress values for completeness, even - // though these aren't input to any stencils. - stress_xx(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; - stress_yy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; - stress_xy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; + // Define other 3 stress values for completeness, even + // though these aren't input to any stencils. + stress_xx(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; + stress_yy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; + stress_xy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; #endif - // When z == surface + 2, the surface will be at z - 2; - surf = z - 2; + // When z == surface + 2, the surface will be at z - 2; + surf = z - 2; - stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf-1) IF_TWO_ABOVE_SURFACE; - stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; - stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; + stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf-1) IF_TWO_ABOVE_SURFACE; + stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; + stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; #ifdef SET_ALL_POINTS - // Define other 3 stress values for completeness, even - // though these aren't input to any stencils. - stress_xx(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - stress_yy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - stress_xy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + // Define other 3 stress values for completeness, even + // though these aren't input to any stencils. + stress_xx(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + stress_yy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + stress_xy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; #endif - } - - // Define the t+1 values for all velocity and stress vars. - virtual void define() { - - // Define velocity components. - vel_x(t+1, x, y, z) EQUALS get_next_vel_x(x, y, z) IF_AT_OR_BELOW_SURFACE; - vel_y(t+1, x, y, z) EQUALS get_next_vel_y(x, y, z) IF_AT_OR_BELOW_SURFACE; - vel_z(t+1, x, y, z) EQUALS get_next_vel_z(x, y, z) IF_AT_OR_BELOW_SURFACE; - - // Define stress components. Use non-overlapping sub-domains only, - // i.e. AT and BELOW but not AT_OR_BELOW, even though there are some - // repeated stencils. This allows the YASK compiler to bundle all - // the stress equations together. - stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_BELOW_SURFACE; - stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_BELOW_SURFACE; - stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_BELOW_SURFACE; - stress_xz(t+1, x, y, z) EQUALS get_next_stress_xz(x, y, z) IF_BELOW_SURFACE; - stress_yz(t+1, x, y, z) EQUALS get_next_stress_yz(x, y, z) IF_BELOW_SURFACE; - stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_BELOW_SURFACE; - - stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_AT_SURFACE; - stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_AT_SURFACE; - stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_AT_SURFACE; - stress_xz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; - stress_yz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; - stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_AT_SURFACE; - - // Boundary conditions. + } + + // Define the t+1 values for all velocity and stress vars. + virtual void define() { + + // Define velocity components. + vel_x(t+1, x, y, z) EQUALS get_next_vel_x(x, y, z) IF_AT_OR_BELOW_SURFACE; + vel_y(t+1, x, y, z) EQUALS get_next_vel_y(x, y, z) IF_AT_OR_BELOW_SURFACE; + vel_z(t+1, x, y, z) EQUALS get_next_vel_z(x, y, z) IF_AT_OR_BELOW_SURFACE; + + // Define stress components. Use non-overlapping sub-domains only, + // i.e. AT and BELOW but not AT_OR_BELOW, even though there are some + // repeated stencils. This allows the YASK compiler to bundle all + // the stress equations together. + stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_BELOW_SURFACE; + stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_BELOW_SURFACE; + stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_BELOW_SURFACE; + stress_xz(t+1, x, y, z) EQUALS get_next_stress_xz(x, y, z) IF_BELOW_SURFACE; + stress_yz(t+1, x, y, z) EQUALS get_next_stress_yz(x, y, z) IF_BELOW_SURFACE; + stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_BELOW_SURFACE; + + stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_AT_SURFACE; + stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_AT_SURFACE; + stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_AT_SURFACE; + stress_xz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; + stress_yz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; + stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_AT_SURFACE; + + // Boundary conditions. #ifdef DO_ABOVE_SURFACE - define_free_surface_vel(); - define_free_surface_stress(); + define_free_surface_vel(); + define_free_surface_stress(); #endif - } -}; + } + }; -// Create an object of type 'AwpElasticStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static AwpElasticStencil AwpElasticStencil_instance; + // Create an object of type 'AwpElasticStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static AwpElasticStencil AwpElasticStencil_instance; #undef DO_SURFACE #undef FULL_SPONGE_VAR #undef USE_SCRATCH_VARS + +} // namespace. diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index 6e66eb70..8ab73c50 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -35,351 +35,356 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -class AwpStencil : public yc_solution_base { - -protected: - - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - - // Time-varying 3D-spatial velocity vars. - yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); - yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); - yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); - - // Time-varying 3D-spatial Stress vars. - yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); - yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); - - // Time-varying attenuation memory vars. - yc_var_proxy stress_mem_xx = yc_var_proxy("stress_mem_xx", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_yy = yc_var_proxy("stress_mem_yy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_zz = yc_var_proxy("stress_mem_zz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_xy = yc_var_proxy("stress_mem_xy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_xz = yc_var_proxy("stress_mem_xz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_yz = yc_var_proxy("stress_mem_yz", get_soln(), { t, x, y, z }); - - // 3D vars used for anelastic attenuation - yc_var_proxy weight = yc_var_proxy("weight", get_soln(), { x, y, z }); - yc_var_proxy tau2 = yc_var_proxy("tau2", get_soln(), { x, y, z }); - yc_var_proxy anelastic_ap = yc_var_proxy("anelastic_ap", get_soln(), { x, y, z }); - yc_var_proxy anelastic_as_diag = yc_var_proxy("anelastic_as_diag", get_soln(), { x, y, z }); - yc_var_proxy anelastic_xy = yc_var_proxy("anelastic_xy", get_soln(), { x, y, z }); - yc_var_proxy anelastic_xz = yc_var_proxy("anelastic_xz", get_soln(), { x, y, z }); - yc_var_proxy anelastic_yz = yc_var_proxy("anelastic_yz", get_soln(), { x, y, z }); - - // 3D-spatial Lame' coefficients. - yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); - yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); - yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); - - // Sponge coefficients. - // (Most of these will be 1.0.) +// Create an anonymous namespace to ensure that types are local. +namespace { + + class AwpStencil : public yc_solution_base { + + protected: + + // Indices & dimensions. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + + // Time-varying 3D-spatial velocity vars. + yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); + yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); + yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); + + // Time-varying 3D-spatial Stress vars. + yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); + + // Time-varying attenuation memory vars. + yc_var_proxy stress_mem_xx = yc_var_proxy("stress_mem_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_yy = yc_var_proxy("stress_mem_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_zz = yc_var_proxy("stress_mem_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_xy = yc_var_proxy("stress_mem_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_xz = yc_var_proxy("stress_mem_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_yz = yc_var_proxy("stress_mem_yz", get_soln(), { t, x, y, z }); + + // 3D vars used for anelastic attenuation + yc_var_proxy weight = yc_var_proxy("weight", get_soln(), { x, y, z }); + yc_var_proxy tau2 = yc_var_proxy("tau2", get_soln(), { x, y, z }); + yc_var_proxy anelastic_ap = yc_var_proxy("anelastic_ap", get_soln(), { x, y, z }); + yc_var_proxy anelastic_as_diag = yc_var_proxy("anelastic_as_diag", get_soln(), { x, y, z }); + yc_var_proxy anelastic_xy = yc_var_proxy("anelastic_xy", get_soln(), { x, y, z }); + yc_var_proxy anelastic_xz = yc_var_proxy("anelastic_xz", get_soln(), { x, y, z }); + yc_var_proxy anelastic_yz = yc_var_proxy("anelastic_yz", get_soln(), { x, y, z }); + + // 3D-spatial Lame' coefficients. + yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); + yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); + yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); + + // Sponge coefficients. + // (Most of these will be 1.0.) #ifdef FULL_SPONGE_VAR - yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); + yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); #else - yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); - yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); - yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); + yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); + yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); + yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); #endif - // Spatial FD coefficients. - const double c1 = 9.0/8.0; - const double c2 = -1.0/24.0; + // Spatial FD coefficients. + const double c1 = 9.0/8.0; + const double c2 = -1.0/24.0; - // Physical dimensions in time and space. - yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); - yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); + // Physical dimensions in time and space. + yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); + yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); -public: + public: - AwpStencil() : - yc_solution_base("awp") { } + AwpStencil() : + yc_solution_base("awp") { } - // Adjustment for sponge layer. - void adjust_for_sponge(yc_number_node_ptr& val) { + // Adjustment for sponge layer. + void adjust_for_sponge(yc_number_node_ptr& val) { #ifdef FULL_SPONGE_VAR - val *= sponge(x, y, z); + val *= sponge(x, y, z); #else - val *= cr_x(x) * cr_y(y) * cr_z(z); + val *= cr_x(x) * cr_y(y) * cr_z(z); #endif - } - - // Velocity-var define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress vars at t. Note that the t, - // x, y, z parameters are integer var indices, not actual offsets in - // time or space, so half-steps due to staggered vars are adjusted - // appropriately. - - void define_vel_x() { - auto rho_val = (rho(x, y, z ) + - rho(x, y-1, z ) + - rho(x, y, z-1) + - rho(x, y-1, z-1)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + - c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + - c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + - c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + - c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + - c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_x); - - // define the value at t+1. - vel_x(t+1, x, y, z) EQUALS next_vel_x; - } - void define_vel_y() { - auto rho_val = (rho(x, y, z ) + - rho(x+1, y, z ) + - rho(x, y, z-1) + - rho(x+1, y, z-1)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + - c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + - c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + - c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + - c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + - c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_y); - - // define the value at t+1. - vel_y(t+1, x, y, z) EQUALS next_vel_y; - } - void define_vel_z() { - auto rho_val = (rho(x, y, z) + - rho(x+1, y, z) + - rho(x, y-1, z) + - rho(x+1, y-1, z)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + - c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + - c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + - c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + - c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + - c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_z); - - // define the value at t+1. - vel_z(t+1, x, y, z) EQUALS next_vel_z; - } - - // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel vars at t+1. - // This implies that the velocity-var define functions must be called - // before these for a given value of t. Note that the t, x, y, z - // parameters are integer var indices, not actual offsets in time or - // space, so half-steps due to staggered vars are adjusted - // appropriately. - - void define_stress_xx(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, - yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, - yc_number_node_ptr tau1) { - - auto stress_mem_xx_old = stress_mem_xx(t, x, y, z); - - auto next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + - (1.0 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_as_diag(x, y, z) * (d_y_val + d_z_val) - - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - - auto next_stress_xx = stress_xx(t, x, y, z) + - ((delta_t / h) * ((2. * mu_val * d_x_val) + - (lambda_val * (d_x_val + d_y_val + d_z_val)))) + - delta_t * (next_stress_mem_xx + stress_mem_xx_old); - - adjust_for_sponge(next_stress_xx); - - // define the value at t+1. - stress_mem_xx(t+1, x, y, z) EQUALS next_stress_mem_xx; - stress_xx(t+1, x, y, z) EQUALS next_stress_xx; - } - void define_stress_yy(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, - yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, - yc_number_node_ptr tau1) { - - auto stress_mem_yy_old = stress_mem_yy(t, x, y, z); - - auto next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + - (1 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_z_val) - - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - - auto next_stress_yy = stress_yy(t, x, y, z) + - ((delta_t / h) * ((2. * mu_val * d_y_val) + - (lambda_val * (d_x_val + d_y_val + d_z_val)))) + - delta_t * (next_stress_mem_yy + stress_mem_yy_old); - - adjust_for_sponge(next_stress_yy); - - // define the value at t+1. - stress_mem_yy(t+1, x, y, z) EQUALS next_stress_mem_yy; - stress_yy(t+1, x, y, z) EQUALS next_stress_yy; - } - void define_stress_zz(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, - yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, - yc_number_node_ptr tau1) { - - auto stress_mem_zz_old = stress_mem_zz(t, x, y, z); - - auto next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + - (1 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_y_val) - - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); - - auto next_stress_zz = stress_zz(t, x, y, z) + - ((delta_t / h) * ((2. * mu_val * d_z_val) + - (lambda_val * (d_x_val + d_y_val + d_z_val)))) + - delta_t * (next_stress_mem_zz + stress_mem_zz_old); - - adjust_for_sponge(next_stress_zz); - - // define the value at t+1. - stress_mem_zz(t+1, x, y, z) EQUALS next_stress_mem_zz; - stress_zz(t+1, x, y, z) EQUALS next_stress_zz; - } - void define_stress_xy(yc_number_node_ptr tau1) { - - auto mu_val = 2.0 / - (mu(x, y, z ) + mu(x, y, z-1)); - - // Note that we are using the velocity values at t+1. - auto d_xy_val = - c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - auto d_yx_val = - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + - c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - - auto stress_mem_xy_old = stress_mem_xy(t, x, y, z); - - auto next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - - (0.5 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_xy(x, y, z) * (d_xy_val + d_yx_val)); - - auto next_stress_xy = stress_xy(t, x, y, z) + - ((mu_val * delta_t / h) * (d_xy_val + d_yx_val)) + - delta_t * (next_stress_mem_xy + stress_mem_xy_old); - - adjust_for_sponge(next_stress_xy); - - // define the value at t+1. - stress_mem_xy(t+1, x, y, z) EQUALS next_stress_mem_xy; - stress_xy(t+1, x, y, z) EQUALS next_stress_xy; - } - void define_stress_xz(yc_number_node_ptr tau1) { - - auto mu_val = 2.0 / - (mu(x, y, z ) + mu(x, y-1, z )); - - // Note that we are using the velocity values at t+1. - auto d_xz_val = - c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - auto d_zx_val = - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + - c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - - auto stress_mem_xz_old = stress_mem_xz(t, x, y, z); - - auto next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - - (0.5 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_xz(x, y, z) * (d_xz_val + d_zx_val)); - - auto next_stress_xz = stress_xz(t, x, y, z) + - ((mu_val * delta_t / h) * (d_xz_val + d_zx_val)) + - delta_t * (next_stress_mem_xz + stress_mem_xz_old); - - adjust_for_sponge(next_stress_xz); - - // define the value at t+1. - stress_mem_xz(t+1, x, y, z) EQUALS next_stress_mem_xz; - stress_xz(t+1, x, y, z) EQUALS next_stress_xz; - } - void define_stress_yz(yc_number_node_ptr tau1) { - - auto mu_val = 2.0 / - (mu(x, y, z ) + mu(x+1, y, z )); - - // Note that we are using the velocity values at t+1. - auto d_yz_val = - c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + - c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - auto d_zy_val = - c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + - c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - - auto stress_mem_yz_old = stress_mem_yz(t, x, y, z); - - auto next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - - (0.5 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_yz(x, y, z) * (d_yz_val + d_zy_val)); - - auto next_stress_yz = stress_yz(t, x, y, z) + - ((mu_val * delta_t / h) * (d_yz_val + d_zy_val)) + - delta_t * (next_stress_mem_yz + stress_mem_yz_old); - - adjust_for_sponge(next_stress_yz); - - // define the value at t+1. - stress_mem_yz(t+1, x, y, z) EQUALS next_stress_mem_yz; - stress_yz(t+1, x, y, z) EQUALS next_stress_yz; - } - - // Call all the define_* functions. - virtual void define() { - - // Define velocity components. - define_vel_x(); - define_vel_y(); - define_vel_z(); - - // Define some values common to the diagonal stress equations. - auto lambda_val = 8.0 / - (lambda(x, y, z ) + lambda(x+1, y, z ) + - lambda(x, y-1, z ) + lambda(x+1, y-1, z ) + - lambda(x, y, z-1) + lambda(x+1, y, z-1) + - lambda(x, y-1, z-1) + lambda(x+1, y-1, z-1)); - auto mu_val = 8.0 / - (mu(x, y, z ) + mu(x+1, y, z ) + - mu(x, y-1, z ) + mu(x+1, y-1, z ) + - mu(x, y, z-1) + mu(x+1, y, z-1) + - mu(x, y-1, z-1) + mu(x+1, y-1, z-1)); - - // Note that we are using the velocity values at t+1. - auto d_x_val = - c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); - auto d_y_val = - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + - c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); - auto d_z_val = - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + - c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); - - auto tau1 = 1.0 - tau2(x, y, z); - - // Define stress components. - define_stress_xx(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); - define_stress_yy(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); - define_stress_zz(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); - define_stress_xy(tau1); - define_stress_xz(tau1); - define_stress_yz(tau1); - } -}; - -// Create an object of type 'AwpStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static AwpStencil AwpStencil_instance; + } + + // Velocity-var define functions. For each D in x, y, z, define vel_D + // at t+1 based on vel_x at t and stress vars at t. Note that the t, + // x, y, z parameters are integer var indices, not actual offsets in + // time or space, so half-steps due to staggered vars are adjusted + // appropriately. + + void define_vel_x() { + auto rho_val = (rho(x, y, z ) + + rho(x, y-1, z ) + + rho(x, y, z-1) + + rho(x, y-1, z-1)) * (1.0 / 4.0); + auto d_val = + c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + + c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + + c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + + c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + + c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + + c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); + auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + adjust_for_sponge(next_vel_x); + + // define the value at t+1. + vel_x(t+1, x, y, z) EQUALS next_vel_x; + } + void define_vel_y() { + auto rho_val = (rho(x, y, z ) + + rho(x+1, y, z ) + + rho(x, y, z-1) + + rho(x+1, y, z-1)) * (1.0 / 4.0); + auto d_val = + c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + + c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + + c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + + c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + + c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); + auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + adjust_for_sponge(next_vel_y); + + // define the value at t+1. + vel_y(t+1, x, y, z) EQUALS next_vel_y; + } + void define_vel_z() { + auto rho_val = (rho(x, y, z) + + rho(x+1, y, z) + + rho(x, y-1, z) + + rho(x+1, y-1, z)) * (1.0 / 4.0); + auto d_val = + c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + + c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + + c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + + c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + + c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + + c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); + auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; + adjust_for_sponge(next_vel_z); + + // define the value at t+1. + vel_z(t+1, x, y, z) EQUALS next_vel_z; + } + + // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // define stress_D at t+1 based on stress_D at t and vel vars at t+1. + // This implies that the velocity-var define functions must be called + // before these for a given value of t. Note that the t, x, y, z + // parameters are integer var indices, not actual offsets in time or + // space, so half-steps due to staggered vars are adjusted + // appropriately. + + void define_stress_xx(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, + yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, + yc_number_node_ptr tau1) { + + auto stress_mem_xx_old = stress_mem_xx(t, x, y, z); + + auto next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + + (1.0 / h) * tau1 * weight(x, y, z) * + (mu_val * anelastic_as_diag(x, y, z) * (d_y_val + d_z_val) - + (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); + + auto next_stress_xx = stress_xx(t, x, y, z) + + ((delta_t / h) * ((2. * mu_val * d_x_val) + + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + + delta_t * (next_stress_mem_xx + stress_mem_xx_old); + + adjust_for_sponge(next_stress_xx); + + // define the value at t+1. + stress_mem_xx(t+1, x, y, z) EQUALS next_stress_mem_xx; + stress_xx(t+1, x, y, z) EQUALS next_stress_xx; + } + void define_stress_yy(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, + yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, + yc_number_node_ptr tau1) { + + auto stress_mem_yy_old = stress_mem_yy(t, x, y, z); + + auto next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + + (1 / h) * tau1 * weight(x, y, z) * + (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_z_val) - + (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); + + auto next_stress_yy = stress_yy(t, x, y, z) + + ((delta_t / h) * ((2. * mu_val * d_y_val) + + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + + delta_t * (next_stress_mem_yy + stress_mem_yy_old); + + adjust_for_sponge(next_stress_yy); + + // define the value at t+1. + stress_mem_yy(t+1, x, y, z) EQUALS next_stress_mem_yy; + stress_yy(t+1, x, y, z) EQUALS next_stress_yy; + } + void define_stress_zz(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, + yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, + yc_number_node_ptr tau1) { + + auto stress_mem_zz_old = stress_mem_zz(t, x, y, z); + + auto next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + + (1 / h) * tau1 * weight(x, y, z) * + (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_y_val) - + (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); + + auto next_stress_zz = stress_zz(t, x, y, z) + + ((delta_t / h) * ((2. * mu_val * d_z_val) + + (lambda_val * (d_x_val + d_y_val + d_z_val)))) + + delta_t * (next_stress_mem_zz + stress_mem_zz_old); + + adjust_for_sponge(next_stress_zz); + + // define the value at t+1. + stress_mem_zz(t+1, x, y, z) EQUALS next_stress_mem_zz; + stress_zz(t+1, x, y, z) EQUALS next_stress_zz; + } + void define_stress_xy(yc_number_node_ptr tau1) { + + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x, y, z-1)); + + // Note that we are using the velocity values at t+1. + auto d_xy_val = + c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); + auto d_yx_val = + c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); + + auto stress_mem_xy_old = stress_mem_xy(t, x, y, z); + + auto next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - + (0.5 / h) * tau1 * weight(x, y, z) * + (mu_val * anelastic_xy(x, y, z) * (d_xy_val + d_yx_val)); + + auto next_stress_xy = stress_xy(t, x, y, z) + + ((mu_val * delta_t / h) * (d_xy_val + d_yx_val)) + + delta_t * (next_stress_mem_xy + stress_mem_xy_old); + + adjust_for_sponge(next_stress_xy); + + // define the value at t+1. + stress_mem_xy(t+1, x, y, z) EQUALS next_stress_mem_xy; + stress_xy(t+1, x, y, z) EQUALS next_stress_xy; + } + void define_stress_xz(yc_number_node_ptr tau1) { + + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x, y-1, z )); + + // Note that we are using the velocity values at t+1. + auto d_xz_val = + c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); + auto d_zx_val = + c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); + + auto stress_mem_xz_old = stress_mem_xz(t, x, y, z); + + auto next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - + (0.5 / h) * tau1 * weight(x, y, z) * + (mu_val * anelastic_xz(x, y, z) * (d_xz_val + d_zx_val)); + + auto next_stress_xz = stress_xz(t, x, y, z) + + ((mu_val * delta_t / h) * (d_xz_val + d_zx_val)) + + delta_t * (next_stress_mem_xz + stress_mem_xz_old); + + adjust_for_sponge(next_stress_xz); + + // define the value at t+1. + stress_mem_xz(t+1, x, y, z) EQUALS next_stress_mem_xz; + stress_xz(t+1, x, y, z) EQUALS next_stress_xz; + } + void define_stress_yz(yc_number_node_ptr tau1) { + + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x+1, y, z )); + + // Note that we are using the velocity values at t+1. + auto d_yz_val = + c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); + auto d_zy_val = + c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); + + auto stress_mem_yz_old = stress_mem_yz(t, x, y, z); + + auto next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - + (0.5 / h) * tau1 * weight(x, y, z) * + (mu_val * anelastic_yz(x, y, z) * (d_yz_val + d_zy_val)); + + auto next_stress_yz = stress_yz(t, x, y, z) + + ((mu_val * delta_t / h) * (d_yz_val + d_zy_val)) + + delta_t * (next_stress_mem_yz + stress_mem_yz_old); + + adjust_for_sponge(next_stress_yz); + + // define the value at t+1. + stress_mem_yz(t+1, x, y, z) EQUALS next_stress_mem_yz; + stress_yz(t+1, x, y, z) EQUALS next_stress_yz; + } + + // Call all the define_* functions. + virtual void define() { + + // Define velocity components. + define_vel_x(); + define_vel_y(); + define_vel_z(); + + // Define some values common to the diagonal stress equations. + auto lambda_val = 8.0 / + (lambda(x, y, z ) + lambda(x+1, y, z ) + + lambda(x, y-1, z ) + lambda(x+1, y-1, z ) + + lambda(x, y, z-1) + lambda(x+1, y, z-1) + + lambda(x, y-1, z-1) + lambda(x+1, y-1, z-1)); + auto mu_val = 8.0 / + (mu(x, y, z ) + mu(x+1, y, z ) + + mu(x, y-1, z ) + mu(x+1, y-1, z ) + + mu(x, y, z-1) + mu(x+1, y, z-1) + + mu(x, y-1, z-1) + mu(x+1, y-1, z-1)); + + // Note that we are using the velocity values at t+1. + auto d_x_val = + c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); + auto d_y_val = + c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + + c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); + auto d_z_val = + c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + + c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); + + auto tau1 = 1.0 - tau2(x, y, z); + + // Define stress components. + define_stress_xx(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); + define_stress_yy(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); + define_stress_zz(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); + define_stress_xy(tau1); + define_stress_xz(tau1); + define_stress_yz(tau1); + } + }; + + // Create an object of type 'AwpStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static AwpStencil AwpStencil_instance; + +} // namespace. diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index d6ab5b17..8f1c1a8b 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -32,6 +32,7 @@ IN THE SOFTWARE. #include "yask_compiler_api.hpp" using namespace std; using namespace yask; + #include "ElasticStencil/Elastic2Stencil.hpp" namespace fsg { @@ -503,3 +504,4 @@ namespace fsg { static FSG2ABCElasticStencil FSG2ABCElasticStencil_instance; } + diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index f2635806..72f9e37c 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -32,191 +32,195 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -class Iso3dfdStencil : public yc_solution_with_radius_base { - -protected: - - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - - // Vars. - yc_var_proxy p = - yc_var_proxy("p", get_soln(), { t, x, y, z }); // time-varying 3D var. - yc_var_proxy v = - yc_var_proxy("v", get_soln(), { x, y, z }); // constant 3D var = (c(x,y,z)^2 * delta_t^2). - -public: - - // For this stencil, the 'radius' is the number of FD coefficients on - // either side of center in each spatial dimension. For example, - // radius=8 implements a 16th-order accurate FD stencil. - // The accuracy in time is fixed at 2nd order. - Iso3dfdStencil(string suffix="", int radius=8) : - yc_solution_with_radius_base("iso3dfd" + suffix, radius) { } - virtual ~Iso3dfdStencil() { } - - // Define RHS expression for p at t+1 based on values from v and p at t. - virtual yc_number_node_ptr get_next_p() { - - // yc_var_proxy spacing. - // In this implementation, it's a constant. - // Could make this a YASK variable to allow setting at run-time. - double delta_xyz = 50.0; - double d2 = delta_xyz * delta_xyz; +// Create an anonymous namespace to ensure that types are local. +namespace { + + class Iso3dfdStencil : public yc_solution_with_radius_base { + + protected: + + // Indices & dimensions. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + + // Vars. + yc_var_proxy p = + yc_var_proxy("p", get_soln(), { t, x, y, z }); // time-varying 3D var. + yc_var_proxy v = + yc_var_proxy("v", get_soln(), { x, y, z }); // constant 3D var = (c(x,y,z)^2 * delta_t^2). + + public: + + // For this stencil, the 'radius' is the number of FD coefficients on + // either side of center in each spatial dimension. For example, + // radius=8 implements a 16th-order accurate FD stencil. + // The accuracy in time is fixed at 2nd order. + Iso3dfdStencil(string suffix="", int radius=8) : + yc_solution_with_radius_base("iso3dfd" + suffix, radius) { } + virtual ~Iso3dfdStencil() { } + + // Define RHS expression for p at t+1 based on values from v and p at t. + virtual yc_number_node_ptr get_next_p() { + + // yc_var_proxy spacing. + // In this implementation, it's a constant. + // Could make this a YASK variable to allow setting at run-time. + double delta_xyz = 50.0; + double d2 = delta_xyz * delta_xyz; - // Spatial FD coefficients for 2nd derivative. - auto coeff = get_center_fd_coefficients(2, get_radius()); - size_t c0i = get_radius(); // index of center sample. + // Spatial FD coefficients for 2nd derivative. + auto coeff = get_center_fd_coefficients(2, get_radius()); + size_t c0i = get_radius(); // index of center sample. - for (size_t i = 0; i < coeff.size(); i++) { + for (size_t i = 0; i < coeff.size(); i++) { - // Need 3 copies of center sample for x, y, and z FDs. - if (i == c0i) - coeff[i] *= 3.0; + // Need 3 copies of center sample for x, y, and z FDs. + if (i == c0i) + coeff[i] *= 3.0; - // Divide each by delta_xyz^2. - coeff[i] /= d2; - } + // Divide each by delta_xyz^2. + coeff[i] /= d2; + } - // Calculate FDx + FDy + FDz. - // Start with center value multiplied by coeff 0. - auto fd_sum = p(t, x, y, z) * coeff[c0i]; + // Calculate FDx + FDy + FDz. + // Start with center value multiplied by coeff 0. + auto fd_sum = p(t, x, y, z) * coeff[c0i]; - // Add values from x, y, and z axes multiplied by the - // coeff for the given radius. - for (int r = 1; r <= get_radius(); r++) { + // Add values from x, y, and z axes multiplied by the + // coeff for the given radius. + for (int r = 1; r <= get_radius(); r++) { - // Add values from axes at radius r. - fd_sum += ( - // x-axis. - p(t, x-r, y, z) + - p(t, x+r, y, z) + + // Add values from axes at radius r. + fd_sum += ( + // x-axis. + p(t, x-r, y, z) + + p(t, x+r, y, z) + - // y-axis. - p(t, x, y-r, z) + - p(t, x, y+r, z) + + // y-axis. + p(t, x, y-r, z) + + p(t, x, y+r, z) + - // z-axis. - p(t, x, y, z-r) + - p(t, x, y, z+r) + // z-axis. + p(t, x, y, z-r) + + p(t, x, y, z+r) - ) * coeff[c0i + r]; // R & L coeffs are identical. - } + ) * coeff[c0i + r]; // R & L coeffs are identical. + } - // Wave equation is: - // 2nd_time_derivative(p) = c^2 * laplacian(p). - // See https://en.wikipedia.org/wiki/Wave_equation. + // Wave equation is: + // 2nd_time_derivative(p) = c^2 * laplacian(p). + // See https://en.wikipedia.org/wiki/Wave_equation. - // For this implementation, we are fixing the accuracy-order in time - // to 2 and using the known FD coefficients (1, -2, 1) to solve the - // equation manually. But we could parameterize by accuracy-order - // in time as well, starting with a call to - // 'get_forward_fd_coefficients(2, time_order)' for the temporal FD - // coefficients. - - // So, wave equation with FD approximations is: - // (p(t+1) - 2 * p(t) + p(t-1)) / delta_t^2 = c^2 * fd_sum. - - // Solve for p(t+1): - // p(t+1) = 2 * p(t) - p(t-1) + c^2 * fd_sum * delta_t^2. - - // Let v = c^2 * delta_t^2 for each var point. - auto next_p = (2.0 * p(t, x, y, z)) - - p(t-1, x, y, z) + (fd_sum * v(x, y, z)); - - return next_p; - } - - // Add some code to the kernel to set default options. - virtual void add_kernel_code() { - auto soln = get_soln(); - - // These best-known settings were found - // by automated and manual tuning. They are only applied - // for certain target configs. - - // Only valid for SP FP and radius 8. - if (soln->get_element_bytes() == 4 && - get_radius() == 8) { - - // Change the settings immediately after the kernel solution - // is created. - soln->INSERT_YASK_KERNEL_CODE - (yc_solution::after_new_solution, - if (get_target_isa() == "avx512") { - set_block_size("x", 108); - set_block_size("y", 28); - set_block_size("z", 132); - } - else { - set_block_size("x", 48); - set_block_size("y", 64); - set_block_size("z", 112); - } - ); + // For this implementation, we are fixing the accuracy-order in time + // to 2 and using the known FD coefficients (1, -2, 1) to solve the + // equation manually. But we could parameterize by accuracy-order + // in time as well, starting with a call to + // 'get_forward_fd_coefficients(2, time_order)' for the temporal FD + // coefficients. + + // So, wave equation with FD approximations is: + // (p(t+1) - 2 * p(t) + p(t-1)) / delta_t^2 = c^2 * fd_sum. + + // Solve for p(t+1): + // p(t+1) = 2 * p(t) - p(t-1) + c^2 * fd_sum * delta_t^2. + + // Let v = c^2 * delta_t^2 for each var point. + auto next_p = (2.0 * p(t, x, y, z)) - + p(t-1, x, y, z) + (fd_sum * v(x, y, z)); + + return next_p; } + + // Add some code to the kernel to set default options. + virtual void add_kernel_code() { + auto soln = get_soln(); + + // These best-known settings were found + // by automated and manual tuning. They are only applied + // for certain target configs. + + // Settings are tested only for SP FP and radius 8. + if (soln->get_element_bytes() == 4 && + get_radius() == 8) { + + // Change the settings immediately after the kernel solution + // is created. + soln->INSERT_YASK_KERNEL_CODE + (if (get_target_isa() == "avx512") { + set_block_size("x", 108); + set_block_size("y", 28); + set_block_size("z", 132); + } + else { + set_block_size("x", 48); + set_block_size("y", 64); + set_block_size("z", 112); + } + ); + } - } + } - // Define equation for p at t+1 based on values from v and p at t. - virtual void define() { - - // Get equation for RHS. - auto next_p = get_next_p(); - - // Define the value at t+1 to be equal to next_p. - // Since this implements the finite-difference method, this - // is actually an approximation. - p(t+1, x, y, z) EQUALS next_p; - - // Insert custom kernel code. - add_kernel_code(); - } -}; - -// Create an object of type 'Iso3dfdStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static Iso3dfdStencil Iso3dfdStencil_instance; - -// Add a sponge absorption factor. -class Iso3dfdSpongeStencil : public Iso3dfdStencil { -protected: - -public: - Iso3dfdSpongeStencil(int radius=8) : - Iso3dfdStencil("_sponge", radius) { } - virtual ~Iso3dfdSpongeStencil() { } - - // Define equation for p at t+1 based on values from v and p at t. - virtual void define() { - - // Sponge coefficients. - // In practice, the interior values would be set to 1.0, - // and values nearer the boundary would be set to values - // increasingly approaching 0.0. - yc_var_proxy cr_x("cr_x", get_soln(), { x }); - yc_var_proxy cr_y("cr_y", get_soln(), { y }); - yc_var_proxy cr_z("cr_z", get_soln(), { z }); + // Define equation for p at t+1 based on values from v and p at t. + virtual void define() { + + // Get equation for RHS. + auto next_p = get_next_p(); + + // Define the value at t+1 to be equal to next_p. + // Since this implements the finite-difference method, this + // is actually an approximation. + p(t+1, x, y, z) EQUALS next_p; + + // Insert custom kernel code. + add_kernel_code(); + } + }; + + // Create an object of type 'Iso3dfdStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static Iso3dfdStencil Iso3dfdStencil_instance; + + // Add a sponge absorption factor. + class Iso3dfdSpongeStencil : public Iso3dfdStencil { + protected: + + public: + Iso3dfdSpongeStencil(int radius=8) : + Iso3dfdStencil("_sponge", radius) { } + virtual ~Iso3dfdSpongeStencil() { } + + // Define equation for p at t+1 based on values from v and p at t. + virtual void define() { + + // Sponge coefficients. + // In practice, the interior values would be set to 1.0, + // and values nearer the boundary would be set to values + // increasingly approaching 0.0. + yc_var_proxy cr_x("cr_x", get_soln(), { x }); + yc_var_proxy cr_y("cr_y", get_soln(), { y }); + yc_var_proxy cr_z("cr_z", get_soln(), { z }); - // Get equation for RHS. - auto next_p = get_next_p(); + // Get equation for RHS. + auto next_p = get_next_p(); + + // Apply sponge absorption. + next_p *= cr_x(x) * cr_y(y) * cr_z(z); - // Apply sponge absorption. - next_p *= cr_x(x) * cr_y(y) * cr_z(z); + // Define the value at t+1 to be equal to next_p. + p(t+1, x, y, z) EQUALS next_p; - // Define the value at t+1 to be equal to next_p. - p(t+1, x, y, z) EQUALS next_p; + // Insert custom kernel code. + add_kernel_code(); + } + }; - // Insert custom kernel code. - add_kernel_code(); - } -}; + // Create an object of type 'Iso3dfdSpongeStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static Iso3dfdSpongeStencil Iso3dfdSpongeStencil_instance; -// Create an object of type 'Iso3dfdSpongeStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static Iso3dfdSpongeStencil Iso3dfdSpongeStencil_instance; +} // namespace. diff --git a/src/stencils/SimpleStencils.cpp b/src/stencils/SimpleStencils.cpp index 5d3501c9..76fab546 100644 --- a/src/stencils/SimpleStencils.cpp +++ b/src/stencils/SimpleStencils.cpp @@ -33,232 +33,237 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -class AvePtsStencil : public yc_solution_with_radius_base { +// Create an anonymous namespace to ensure that types are local. +namespace { -protected: + class AvePtsStencil : public yc_solution_with_radius_base { - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying 3D var. + // Indices & dimensions. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // Add additional points to expression v. - // Returns number of points added. - virtual int addPoints(yc_number_node_ptr& v) =0; + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying 3D var. -public: - AvePtsStencil(const string& name, int radius) : - yc_solution_with_radius_base(name, radius) { } + // Add additional points to expression v. + // Returns number of points added. + virtual int addPoints(yc_number_node_ptr& v) =0; - // Define equation at t+1 based on values at t. - virtual void define() { + public: + AvePtsStencil(const string& name, int radius) : + yc_solution_with_radius_base(name, radius) { } - // start with center point. - yc_number_node_ptr v = A(t, x, y, z); + // Define equation at t+1 based on values at t. + virtual void define() { - // Add additional points from derived class. - int pts = 1 + addPoints(v); + // start with center point. + yc_number_node_ptr v = A(t, x, y, z); - // Average. - if (pts > 1) - v *= 1.0 / pts; + // Add additional points from derived class. + int pts = 1 + addPoints(v); + + // Average. + if (pts > 1) + v *= 1.0 / pts; - // Define the value at t+1 to be equivalent to v. - A(t+1, x, y, z) EQUALS v; - } -}; - -// Add points from x, y, and z axes. -class AxisStencil : public AvePtsStencil { -protected: - - // Add additional points to expression v. - virtual int addPoints(yc_number_node_ptr& v) - { - int pts = 0; - for (int r = 1; r <= get_radius(); r++) { - - v += - // x-axis. - A(t, x-r, y, z) + - A(t, x+r, y, z) + - - // y-axis. - A(t, x, y-r, z) + - A(t, x, y+r, z) + - - // z-axis. - A(t, x, y, z-r) + - A(t, x, y, z+r); - pts += 3 * 2; + // Define the value at t+1 to be equivalent to v. + A(t+1, x, y, z) EQUALS v; } - return pts; - } - -public: - AxisStencil(int radius=4) : - AvePtsStencil("3axis", radius) { } - AxisStencil(const string& name, int radius=4) : - AvePtsStencil(name, radius) { } -}; - -// Create an object of type 'AxisStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static AxisStencil AxisStencil_instance; - -// Add points from x-y, x-z, and y-z diagonals. -class DiagStencil : public AxisStencil { -protected: - - // Add additional points to v. - virtual int addPoints(yc_number_node_ptr& v) - { - // Get points from axes. - int pts = AxisStencil::addPoints(v); - - // Add points from diagonals. - for (int r = 1; r <= get_radius(); r++) { - - v += - // x-y diagonal. - A(t, x-r, y-r, z) + - A(t, x+r, y-r, z) + - A(t, x-r, y+r, z) + - A(t, x+r, y+r, z) + - - // x-z diagonal. - A(t, x-r, y, z-r) + - A(t, x+r, y, z+r) + - A(t, x-r, y, z+r) + - A(t, x+r, y, z-r) + - - // y-z diagonal. - A(t, x, y-r, z-r) + - A(t, x, y+r, z+r) + - A(t, x, y-r, z+r) + - A(t, x, y+r, z-r); - pts += 3 * 4; + }; + + // Add points from x, y, and z axes. + class AxisStencil : public AvePtsStencil { + protected: + + // Add additional points to expression v. + virtual int addPoints(yc_number_node_ptr& v) + { + int pts = 0; + for (int r = 1; r <= get_radius(); r++) { + + v += + // x-axis. + A(t, x-r, y, z) + + A(t, x+r, y, z) + + + // y-axis. + A(t, x, y-r, z) + + A(t, x, y+r, z) + + + // z-axis. + A(t, x, y, z-r) + + A(t, x, y, z+r); + pts += 3 * 2; + } + return pts; } - return pts; - } - -public: - DiagStencil(int radius=4) : - AxisStencil("3axis_with_diags", radius) { } - DiagStencil(const string& name, int radius=4) : - AxisStencil(name, radius) { } -}; - -// Create an object of type 'DiagStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static DiagStencil DiagStencil_instance; - -// Add points from x-y, x-z, and y-z planes not covered by axes or diagonals. -class PlaneStencil : public DiagStencil { -protected: - - // Add additional points to v. - virtual int addPoints(yc_number_node_ptr& v) - { - // Get points from axes and diagonals. - int pts = DiagStencil::addPoints(v); - - // Add remaining points on planes. - for (int r = 1; r <= get_radius(); r++) { - for (int m = r+1; m <= get_radius(); m++) { + + public: + AxisStencil(int radius=4) : + AvePtsStencil("3axis", radius) { } + AxisStencil(const string& name, int radius=4) : + AvePtsStencil(name, radius) { } + }; + + // Create an object of type 'AxisStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static AxisStencil AxisStencil_instance; + + // Add points from x-y, x-z, and y-z diagonals. + class DiagStencil : public AxisStencil { + protected: + + // Add additional points to v. + virtual int addPoints(yc_number_node_ptr& v) + { + // Get points from axes. + int pts = AxisStencil::addPoints(v); + + // Add points from diagonals. + for (int r = 1; r <= get_radius(); r++) { v += - // x-y plane. - A(t, x-r, y-m, z) + - A(t, x-m, y-r, z) + - A(t, x+r, y+m, z) + - A(t, x+m, y+r, z) + - A(t, x-r, y+m, z) + - A(t, x-m, y+r, z) + - A(t, x+r, y-m, z) + - A(t, x+m, y-r, z) + - - // x-z plane. - A(t, x-r, y, z-m) + - A(t, x-m, y, z-r) + - A(t, x+r, y, z+m) + - A(t, x+m, y, z+r) + - A(t, x-r, y, z+m) + - A(t, x-m, y, z+r) + - A(t, x+r, y, z-m) + - A(t, x+m, y, z-r) + - - // y-z plane. - A(t, x, y-r, z-m) + - A(t, x, y-m, z-r) + - A(t, x, y+r, z+m) + - A(t, x, y+m, z+r) + - A(t, x, y-r, z+m) + - A(t, x, y-m, z+r) + - A(t, x, y+r, z-m) + - A(t, x, y+m, z-r); - pts += 3 * 8; + // x-y diagonal. + A(t, x-r, y-r, z) + + A(t, x+r, y-r, z) + + A(t, x-r, y+r, z) + + A(t, x+r, y+r, z) + + + // x-z diagonal. + A(t, x-r, y, z-r) + + A(t, x+r, y, z+r) + + A(t, x-r, y, z+r) + + A(t, x+r, y, z-r) + + + // y-z diagonal. + A(t, x, y-r, z-r) + + A(t, x, y+r, z+r) + + A(t, x, y-r, z+r) + + A(t, x, y+r, z-r); + pts += 3 * 4; } + return pts; } - return pts; - } - -public: - PlaneStencil(int radius=3) : - DiagStencil("3plane", radius) { } - PlaneStencil(const string& name, int radius=3) : - DiagStencil(name, radius) { } -}; - -// Create an object of type 'PlaneStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static PlaneStencil PlaneStencil_instance; - -// Add points from rest of cube. -class CubeStencil : public PlaneStencil { -protected: - - // Add additional points to v. - virtual int addPoints(yc_number_node_ptr& v) - { - // Get points from planes. - int pts = PlaneStencil::addPoints(v); - - // Add points from rest of cube. - for (int rx = 1; rx <= get_radius(); rx++) - for (int ry = 1; ry <= get_radius(); ry++) - for (int rz = 1; rz <= get_radius(); rz++) { - - v += - // Each quadrant. - A(t, x+rx, y+ry, z+rz) + - A(t, x+rx, y-ry, z-rz) + - A(t, x+rx, y+ry, z-rz) + - A(t, x+rx, y-ry, z+rz) + - A(t, x-rx, y+ry, z+rz) + - A(t, x-rx, y-ry, z-rz) + - A(t, x-rx, y+ry, z-rz) + - A(t, x-rx, y-ry, z+rz); - pts += 8; + + public: + DiagStencil(int radius=4) : + AxisStencil("3axis_with_diags", radius) { } + DiagStencil(const string& name, int radius=4) : + AxisStencil(name, radius) { } + }; + + // Create an object of type 'DiagStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static DiagStencil DiagStencil_instance; + + // Add points from x-y, x-z, and y-z planes not covered by axes or diagonals. + class PlaneStencil : public DiagStencil { + protected: + + // Add additional points to v. + virtual int addPoints(yc_number_node_ptr& v) + { + // Get points from axes and diagonals. + int pts = DiagStencil::addPoints(v); + + // Add remaining points on planes. + for (int r = 1; r <= get_radius(); r++) { + for (int m = r+1; m <= get_radius(); m++) { + + v += + // x-y plane. + A(t, x-r, y-m, z) + + A(t, x-m, y-r, z) + + A(t, x+r, y+m, z) + + A(t, x+m, y+r, z) + + A(t, x-r, y+m, z) + + A(t, x-m, y+r, z) + + A(t, x+r, y-m, z) + + A(t, x+m, y-r, z) + + + // x-z plane. + A(t, x-r, y, z-m) + + A(t, x-m, y, z-r) + + A(t, x+r, y, z+m) + + A(t, x+m, y, z+r) + + A(t, x-r, y, z+m) + + A(t, x-m, y, z+r) + + A(t, x+r, y, z-m) + + A(t, x+m, y, z-r) + + + // y-z plane. + A(t, x, y-r, z-m) + + A(t, x, y-m, z-r) + + A(t, x, y+r, z+m) + + A(t, x, y+m, z+r) + + A(t, x, y-r, z+m) + + A(t, x, y-m, z+r) + + A(t, x, y+r, z-m) + + A(t, x, y+m, z-r); + pts += 3 * 8; } - return pts; - } - -public: - CubeStencil(int radius=2) : - PlaneStencil("cube", radius) { } - CubeStencil(const string& name, int radius=2) : - PlaneStencil(name, radius) { } -}; - -// Create an object of type 'CubeStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static CubeStencil CubeStencil_instance; + } + return pts; + } + + public: + PlaneStencil(int radius=3) : + DiagStencil("3plane", radius) { } + PlaneStencil(const string& name, int radius=3) : + DiagStencil(name, radius) { } + }; + + // Create an object of type 'PlaneStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static PlaneStencil PlaneStencil_instance; + + // Add points from rest of cube. + class CubeStencil : public PlaneStencil { + protected: + + // Add additional points to v. + virtual int addPoints(yc_number_node_ptr& v) + { + // Get points from planes. + int pts = PlaneStencil::addPoints(v); + + // Add points from rest of cube. + for (int rx = 1; rx <= get_radius(); rx++) + for (int ry = 1; ry <= get_radius(); ry++) + for (int rz = 1; rz <= get_radius(); rz++) { + + v += + // Each quadrant. + A(t, x+rx, y+ry, z+rz) + + A(t, x+rx, y-ry, z-rz) + + A(t, x+rx, y+ry, z-rz) + + A(t, x+rx, y-ry, z+rz) + + A(t, x-rx, y+ry, z+rz) + + A(t, x-rx, y-ry, z-rz) + + A(t, x-rx, y+ry, z-rz) + + A(t, x-rx, y-ry, z+rz); + pts += 8; + } + return pts; + } + + public: + CubeStencil(int radius=2) : + PlaneStencil("cube", radius) { } + CubeStencil(const string& name, int radius=2) : + PlaneStencil(name, radius) { } + }; + + // Create an object of type 'CubeStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static CubeStencil CubeStencil_instance; + +} // namespace. diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index f5a834ab..845f3a09 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -31,2479 +31,1944 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -class TTIStencil:public yc_solution_with_radius_base +// Create an anonymous namespace to ensure that types are local. +namespace { -protected: + class TTIStencil:public yc_solution_with_radius_base + { - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + protected: - // Vars. - yc_var_proxy u = yc_var_proxy("u", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield var. - yc_var_proxy v = yc_var_proxy("v", get_soln(), { t, x, y, z }); // Time-varying 3D wavefield var. - yc_var_proxy m = yc_var_proxy("m", get_soln(), { x, y, z }); // Square slowness of the model. - yc_var_proxy damp = yc_var_proxy("damp", get_soln(), { x, y, z }); // Boundary damping. - yc_var_proxy phi = yc_var_proxy("phi", get_soln(), { x, y, z }); - yc_var_proxy theta = yc_var_proxy("theta", get_soln(), { x, y, z }); - yc_var_proxy delta = yc_var_proxy("delta", get_soln(), { x, y, z }); - yc_var_proxy epsilon = yc_var_proxy("epsilon", get_soln(), { x, y, z }); + // Indices & dimensions. + yc_index_node_ptr t = new_step_index ("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index ("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index ("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index ("z"); // spatial dim. - // Hoisted misc time-invariant data. - yc_var_proxy ti0 = yc_var_proxy("ti0", get_soln(), { x, y, z }); - yc_var_proxy ti1 = yc_var_proxy("ti1", get_soln(), { x, y, z }); - yc_var_proxy ti2 = yc_var_proxy("ti2", get_soln(), { x, y, z }); - yc_var_proxy ti3 = yc_var_proxy("ti3", get_soln(), { x, y, z }); + // Vars. + yc_var_proxy u = yc_var_proxy ("u", get_soln (), { t, x, y, z } + ); // Time-varying 3D wavefield var. + yc_var_proxy v = yc_var_proxy ("v", get_soln (), { t, x, y, z } + ); // Time-varying 3D wavefield var. + yc_var_proxy m = yc_var_proxy ("m", get_soln (), { x, y, z } + ); // Square slowness of the model. + yc_var_proxy damp = yc_var_proxy ("damp", get_soln (), { x, y, z } + ); // Boundary damping. + yc_var_proxy phi = yc_var_proxy ("phi", get_soln (), { x, y, z } + ); + yc_var_proxy theta = yc_var_proxy ("theta", get_soln (), { x, y, z } + ); + yc_var_proxy delta = yc_var_proxy ("delta", get_soln (), { x, y, z } + ); + yc_var_proxy epsilon = yc_var_proxy ("epsilon", get_soln (), { x, y, z } + ); -public: + // Hoisted misc time-invariant data. + yc_var_proxy ti0 = yc_var_proxy ("ti0", get_soln (), { x, y, z } + ); + yc_var_proxy ti1 = yc_var_proxy ("ti1", get_soln (), { x, y, z } + ); + yc_var_proxy ti2 = yc_var_proxy ("ti2", get_soln (), { x, y, z } + ); + yc_var_proxy ti3 = yc_var_proxy ("ti3", get_soln (), { x, y, z } + ); - // For this stencil, the 'radius' is the number of FD coefficients on - // either side of center in each spatial dimension. -TTIStencil (int radius = 2): - yc_solution_with_radius_base ("tti", radius) - { - } + public: - // The following statements were auto-generated by the Devito symbolic finite-difference package. + // For this stencil, the 'radius' is the number of FD coefficients on + // either side of center in each spatial dimension. + TTIStencil (int radius = 2): + yc_solution_with_radius_base ("tti", radius) + { + } - // Define equation for 'u' and 'v' at t+1 based on values at t - // for spatial order = 4. - virtual void define_so4 () - { + // The following statements were auto-generated by the Devito symbolic finite-difference package. - auto temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); - auto temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, - z) - - 2.5e-2 * u (t, x, y + 2, - z); - auto temp192 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 1, - z) - - 2.5e-2 * u (t, x, y + 1, - z); - auto temp183 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x - 2, y, - z) + - 1.0e-1 * u (t, x - 1, y, - z); - auto temp168 = - -7.5e-2 * u (t, x, y + 1, z) + 1.0e-1 * u (t, x + 1, y + 1, - z) - 2.5e-2 * u (t, x + 2, - y + 1, - z); - auto temp197 = - 3.75e-2 * (temp161 * ti1 (x, y, z) * ti2 (x, y, z) + - temp163 * ti2 (x, y, z) * ti3 (x, y, - z) - (-7.5e-2 * u (t, x, y, - z) + - 1.0e-1 * u (t, x, y, - z + 1) - - 2.5e-2 * u (t, x, y, - z + - 2)) * - ti0 (x, y, z)); - auto temp171 = - -7.5e-2 * u (t, x + 1, y, z) + 1.0e-1 * u (t, x + 1, y + 1, - z) - 2.5e-2 * u (t, x + 1, - y + 2, - z); - auto temp178 = 2.5e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)); - auto temp182 = - 2.5e-2 * (-u (t, x - 2, y - 1, z) + u (t, x - 2, y + 1, z)); - auto temp190 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x - 1, y, - z) - - 2.5e-2 * u (t, x + 1, y, - z); - auto temp173 = 2.5e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)); - auto temp188 = - 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x - 1, y + 1, z)); - auto temp154 = 2.5e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); - auto temp186 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 2, - z) + - 1.0e-1 * u (t, x, y - 1, - z); - auto temp158 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x + 1, y, - z) - - 2.5e-2 * u (t, x + 2, y, - z); - auto temp191 = - 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x + 1, y - 1, z)); - auto temp184 = - 2.5e-2 * (-u (t, x - 1, y - 2, z) + u (t, x + 1, y - 2, z)); - auto temp181 = - -7.5e-2 * u (t, x - 1, y, z) + 1.0e-1 * u (t, x - 1, y + 1, - z) - 2.5e-2 * u (t, x - 1, - y + 2, - z); - auto temp176 = - -7.5e-2 * u (t, x, y - 1, z) + 1.0e-1 * u (t, x + 1, y - 1, - z) - 2.5e-2 * u (t, x + 2, - y - 1, - z); - auto temp123 = - (2.5e-2 * - ((v (t, x, y, z) - v (t, x, y - 2, z)) * ti0 (x, y - 1, z) * ti3 (x, - y - 1, - z) + - (-v (t, x, y - 1, z - 1) + v (t, x, y - 1, z + 1)) * ti2 (x, y - 1, - z)) + - (-7.5e-2 * v (t, x, y - 1, z) + 1.0e-1 * v (t, x + 1, y - 1, z) - - 2.5e-2 * v (t, x + 2, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, - z)) * - ti0 (x, y - 1, z) * ti3 (x, y - 1, z); - auto temp102 = - (2.5e-2 * - ((-v (t, x - 1, y, z - 1) + v (t, x - 1, y, z + 1)) * ti2 (x - 1, y, - z) + (-v (t, - x - - 1, - y - - 1, - z) + - v (t, - x - - 1, - y + - 1, - z)) * - ti0 (x - 1, y, z) * ti3 (x - 1, y, z)) + (1.0e-1 * v (t, x, y, - z) - - 7.5e-2 * v (t, x - 1, y, - z) - - 2.5e-2 * v (t, x + 1, y, - z)) * ti0 (x - 1, - y, - z) * - ti1 (x - 1, y, z)) * ti0 (x - 1, y, - z) * ti1 (x - 1, y, z); - auto temp131 = - (2.5e-2 * (-v (t, x - 1, y, z - 2) + v (t, x + 1, y, z - 2)) * - ti0 (x, y, z - 2) * ti1 (x, y, - z - 2) + (-2.5e-2 * v (t, x, y, - z) - 7.5e-2 * v (t, - x, - y, - z - - 2) + - 1.0e-1 * v (t, x, y, - z - 1)) * ti2 (x, y, - z - 2) + - (-7.5e-2 * v (t, x, y, z - 2) + 1.0e-1 * v (t, x, y + 1, z - 2) - - 2.5e-2 * v (t, x, y + 2, z - 2)) * ti0 (x, y, z - 2) * ti3 (x, y, - z - - 2)) * - ti2 (x, y, z - 2); - auto temp87 = - (2.5e-2 * - ((-v (t, x - 2, y, z - 1) + v (t, x - 2, y, z + 1)) * ti2 (x - 2, y, - z) + (-v (t, - x - - 2, - y - - 1, - z) + - v (t, - x - - 2, - y + - 1, - z)) * - ti0 (x - 2, y, z) * ti3 (x - 2, y, z)) + (-2.5e-2 * v (t, x, y, - z) - - 7.5e-2 * v (t, x - 2, y, - z) + - 1.0e-1 * v (t, x - 1, y, - z)) * ti0 (x - 2, - y, - z) * - ti1 (x - 2, y, z)) * ti0 (x - 2, y, - z) * ti1 (x - 2, y, z); - auto temp47 = - 2.5e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z)) * ti0 (x, y, - z) * ti1 (x, - y, - z) - + (-7.5e-2 * v (t, x, y, z) + 1.0e-1 * v (t, x, y, z + 1) - - 2.5e-2 * v (t, x, y, z + 2)) * ti2 (x, y, z) + (-7.5e-2 * v (t, x, - y, - z) + - 1.0e-1 * v (t, x, - y + 1, - z) - - 2.5e-2 * v (t, x, - y + 2, - z)) * - ti0 (x, y, z) * ti3 (x, y, z); - auto temp110 = - (2.5e-2 * - ((-v (t, x, y, z) + v (t, x, y + 2, z)) * ti0 (x, y + 1, z) * ti3 (x, - y + 1, - z) + - (-v (t, x, y + 1, z - 1) + v (t, x, y + 1, z + 1)) * ti2 (x, y + 1, - z)) + - (-7.5e-2 * v (t, x, y + 1, z) + 1.0e-1 * v (t, x + 1, y + 1, z) - - 2.5e-2 * v (t, x + 2, y + 1, z)) * ti0 (x, y + 1, z) * ti1 (x, y + 1, - z)) * - ti0 (x, y + 1, z) * ti3 (x, y + 1, z); - auto temp140 = - (2.5e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) * ti0 (x + 1, y, z) * - ti1 (x + 1, y, - z) + (-7.5e-2 * v (t, x + 1, y, z) + 1.0e-1 * v (t, x + 1, y, - z + 1) - - 2.5e-2 * v (t, x + 1, y, - z + 2)) * ti2 (x + 1, y, - z) + - (-7.5e-2 * v (t, x + 1, y, z) + 1.0e-1 * v (t, x + 1, y + 1, z) - - 2.5e-2 * v (t, x + 1, y + 2, z)) * ti0 (x + 1, y, z) * ti3 (x + 1, y, - z)) * - ti0 (x + 1, y, - z) * ti1 (x + 1, y, - z); - auto temp149 = - (2.5e-2 * (-v (t, x - 1, y - 2, z) + v (t, x + 1, y - 2, z)) * - ti0 (x, y - 2, z) * ti1 (x, y - 2, - z) + (-2.5e-2 * v (t, x, y, - z) - 7.5e-2 * v (t, x, - y - 2, - z) + - 1.0e-1 * v (t, x, y - 1, z)) * ti0 (x, - y - - 2, - z) * - ti3 (x, y - 2, - z) + (-7.5e-2 * v (t, x, y - 2, z) + 1.0e-1 * v (t, x, y - 2, - z + 1) - - 2.5e-2 * v (t, x, y - 2, z + 2)) * ti2 (x, y - 2, - z)) * ti0 (x, - y - 2, - z) * - ti3 (x, y - 2, z); - auto temp39 = - (2.5e-2 * ((-v (t, x, y, z - 1) + v (t, x, y, z + 1)) * ti2 (x, y, - z) + - (-v (t, x, - y - 1, - z) + v (t, - x, - y + 1, - z)) - * ti0 (x, y, z) * ti3 (x, y, z)) + (-7.5e-2 * v (t, x, y, - z) + - 1.0e-1 * v (t, - x + 1, - y, - z) - - 2.5e-2 * v (t, x + 2, - y, - z)) * - ti0 (x, y, - z) * ti1 (x, y, z)) * ti0 (x, y, z) * ti1 (x, y, z); - auto temp132 = - (2.5e-2 * (-v (t, x - 1, y, z - 1) + v (t, x + 1, y, z - 1)) * - ti0 (x, y, z - 1) * ti1 (x, y, - z - 1) + (1.0e-1 * v (t, x, y, - z) - 7.5e-2 * v (t, x, - y, - z - - 1) - - 2.5e-2 * v (t, x, y, - z + 1)) * ti2 (x, y, - z - 1) + - (-7.5e-2 * v (t, x, y, z - 1) + 1.0e-1 * v (t, x, y + 1, z - 1) - - 2.5e-2 * v (t, x, y + 2, z - 1)) * ti0 (x, y, z - 1) * ti3 (x, y, - z - - 1)) * - ti2 (x, y, z - 1); - auto temp6 = - 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); - auto temp141 = - (2.5e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) * ti0 (x - 1, y, z) * - ti1 (x - 1, y, - z) + (-7.5e-2 * v (t, x - 1, y, z) + 1.0e-1 * v (t, x - 1, y, - z + 1) - - 2.5e-2 * v (t, x - 1, y, - z + 2)) * ti2 (x - 1, y, - z) + - (-7.5e-2 * v (t, x - 1, y, z) + 1.0e-1 * v (t, x - 1, y + 1, z) - - 2.5e-2 * v (t, x - 1, y + 2, z)) * ti0 (x - 1, y, z) * ti3 (x - 1, y, - z)) * - ti0 (x - 1, y, - z) * ti1 (x - 1, y, - z); - auto temp10 = - 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); - auto temp215 = - 3.75e-2 * (-temp154 * ti1 (x, y, z) + temp158 * ti3 (x, y, z)) * ti3 (x, - y, - z) - + (temp197 * ti3 (x, y, - z) + (3.75e-2 * (temp154 * ti3 (x, y, - z) + temp158 * ti1 (x, - y, - z)) - * ti2 (x, y, - z) - 9.375e-4 * (-u (t, x, y, z - 1) + - u (t, x, y, - z + 1)) * ti0 (x, - y, - z)) * - ti1 (x, y, - z)) * ti2 (x, - y, - z) + - (1.25e-2 * (temp182 * ti3 (x - 2, y, z) + temp183 * ti1 (x - 2, y, z)) * - ti2 (x - 2, - y, - z) - - 3.125e-4 * (-u (t, x - 2, y, z - 1) + u (t, x - 2, y, z + 1)) * ti0 (x - - 2, - y, - z)) - * ti1 (x - 2, - y, - z) * ti2 (x - 2, y, - z) + - 5.0e-2 * ((temp191 * ti3 (x, y - 1, z) - temp192 * ti1 (x, y - 1, z)) * - ti1 (x, y - 1, - z) + - (2.5e-2 * (-u (t, x - 1, y, z - 1) + u (t, x + 1, y, z - 1)) * - ti1 (x, y, - z - 1) * ti2 (x, - y, - z - - 1) - - (1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y, z - 1) - - 2.5e-2 * u (t, x, - y, - z + 1)) * ti0 (x, y, - z - 1) + (-7.5e-2 * u (t, x, y, - z - 1) + - 1.0e-1 * u (t, x, - y + 1, - z - 1) - - 2.5e-2 * u (t, x, - y + 2, - z - - 1)) * - ti2 (x, y, - z - 1) * ti3 (x, y, z - 1)) * ti0 (x, y, - z - 1)) + - (1.25e-2 * temp168 * ti1 (x, y + 1, z) * ti2 (x, y + 1, z) + - 3.125e-4 * ((-u (t, x, y, z) + u (t, x, y + 2, z)) * ti2 (x, y + 1, z) * - ti3 (x, y + 1, - z) - (-u (t, x, y + 1, - z - 1) + u (t, x, - y + 1, - z + - 1)) * - ti0 (x, y + 1, z))) * ti2 (x, y + 1, z) * ti3 (x, y + 1, - z) + - (1.25e-2 * - (temp171 * ti2 (x + 1, y, z) * ti3 (x + 1, y, z) - - (-7.5e-2 * u (t, x + 1, y, z) + 1.0e-1 * u (t, x + 1, y, z + 1) - - 2.5e-2 * u (t, x + 1, y, z + 2)) * ti0 (x + 1, y, - z)) + 3.125e-4 * (-u (t, x, - y, - z) + - u (t, - x + 2, - y, - z)) * - ti1 (x + 1, y, z) * ti2 (x + 1, y, z)) * ti1 (x + 1, y, - z) * ti2 (x + 1, y, - z) + - 1.25e-2 * - ((-temp171 * ti1 (x + 1, y, z) + - 2.5e-2 * (-u (t, x, y, z) + u (t, x + 2, y, z)) * ti3 (x + 1, y, - z)) * ti3 (x + - 1, - y, - z) - + (-temp173 * ti1 (x, y - 1, z) + temp176 * ti3 (x, y - 1, z)) * ti1 (x, - y - - 1, - z) - + (-temp182 * ti1 (x - 2, y, - z) + temp183 * ti3 (x - 2, y, - z)) * ti3 (x - 2, y, - z) + - ((temp184 * ti1 (x, y - 2, z) + temp186 * ti3 (x, y - 2, z)) * ti2 (x, - y - - 2, - z) - - (-7.5e-2 * u (t, - x, - y - 2, - z) + 1.0e-1 * u (t, - x, - y - 2, - z + 1) - 2.5e-2 * u (t, - x, - y - 2, - z - + - 2)) - * ti0 (x, y - 2, z)) * ti2 (x, y - 2, z) * ti3 (x, y - 2, - z) + - (2.5e-2 * - (-(u (t, x, y, z) - u (t, x, y, z - 2)) * ti0 (x, y, z - 1) + - (-u (t, x, y - 1, z - 1) + u (t, x, y + 1, z - 1)) * ti2 (x, y, - z - - 1) * - ti3 (x, y, z - 1)) + (-7.5e-2 * u (t, x, y, z - 1) + 1.0e-1 * u (t, - x + - 1, - y, - z - - - 1) - - 2.5e-2 * u (t, x + 2, y, z - 1)) * ti1 (x, - y, - z - - 1) * - ti2 (x, y, z - 1)) * ti0 (x, y, z - 1)) - (temp197 * ti0 (x, y, - z) + - 3.75e-2 * (temp161 * - ti3 (x, y, - z) - - temp163 * ti1 (x, - y, - z)) - * ti1 (x, y, - z) + - 1.25e-2 * (temp168 * - ti3 (x, y + 1, - z) - - 2.5e-2 * - (-u (t, x, y, - z) + u (t, - x, - y + - 2, - z)) - * ti1 (x, y + 1, - z)) * - ti1 (x, y + 1, - z) + - 1.25e-2 * (temp178 * - ti3 (x - 1, y, - z) - - temp181 * - ti1 (x - 1, y, - z)) * - ti3 (x - 1, y, - z) + - 1.25e-2 * (temp184 * - ti3 (x, y - 2, - z) - - temp186 * ti1 (x, - y - - - 2, - z)) - * ti1 (x, y - 2, - z) + - 5.0e-2 * (-temp188 * - ti1 (x - 1, y, - z) + - temp190 * ti3 (x - - 1, - y, - z)) - * ti3 (x - 1, y, - z) + - (1.25e-2 * - (temp173 * ti3 (x, y - 1, - z) + - temp176 * ti1 (x, y - 1, - z)) * - ti2 (x, y - 1, - z) - - 3.125e-4 * - (-u (t, x, y - 1, z - 1) + - u (t, x, y - 1, - z + 1)) * ti0 (x, - y - 1, - z)) - * ti2 (x, y - 1, z) * ti3 (x, - y - - - 1, - z) - + - 1.25e-2 * - ((temp178 * ti1 (x - 1, y, - z) + - temp181 * ti3 (x - 1, y, - z)) * - ti2 (x - 1, y, - z) - - (-7.5e-2 * u (t, x - 1, y, - z) + - 1.0e-1 * u (t, - x - 1, - y, - z + - 1) - - 2.5e-2 * u (t, x - 1, y, - z + - 2)) * ti0 (x - - 1, - y, - z)) - * ti1 (x - 1, - y, - z) * ti2 (x - 1, y, - z) + - (5.0e-2 * - (temp188 * ti3 (x - 1, y, - z) + - temp190 * ti1 (x - 1, y, - z)) * - ti2 (x - 1, y, - z) - - 1.25e-3 * - (-u (t, x - 1, y, z - 1) + - u (t, x - 1, y, - z + 1)) * ti0 (x - 1, - y, - z)) * - ti1 (x - 1, y, - z) * ti2 (x - 1, y, - z) + - 5.0e-2 * - ((temp191 * ti1 (x, y - 1, - z) + - temp192 * ti3 (x, y - 1, - z)) * - ti2 (x, y - 1, - z) - - (-7.5e-2 * u (t, x, y - 1, - z) + - 1.0e-1 * u (t, - x, - y - 1, - z + - 1) - - 2.5e-2 * u (t, x, y - 1, - z + - 2)) * - ti0 (x, y - 1, - z)) * ti2 (x, y - 1, - z) * - ti3 (x, y - 1, - z) + - 1.25e-2 * (2.5e-2 * - (-(-u (t, x, y, - z) + u (t, - x, - y, - z - + - 2)) - * ti0 (x, y, - z + 1) + - (-u - (t, x, y - 1, - z + 1) + u (t, - x, - y - + - 1, - z - + - 1)) - * ti2 (x, y, - z + - 1) * - ti3 (x, y, - z + 1)) + - (-7.5e-2 * - u (t, x, y, - z + 1) + - 1.0e-1 * u (t, - x + - 1, - y, - z + - 1) - - - 2.5e-2 * u (t, - x + - 2, - y, - z + - 1)) - * ti1 (x, y, - z + - 1) * - ti2 (x, y, - z + - 1)) * - ti0 (x, y, - z + 1) + - 1.25e-2 * (2.5e-2 * - (-u (t, x - 1, y, - z - 2) + - u (t, x + 1, - y, - z - - 2)) * ti1 (x, - y, - z - - - 2) - * ti2 (x, y, - z - 2) - - (-2.5e-2 * - u (t, x, y, - z) - - 7.5e-2 * u (t, - x, - y, - z - - 2) - + - 1.0e-1 * u (t, - x, - y, - z - - 1)) - * ti0 (x, y, - z - 2) + - (-7.5e-2 * - u (t, x, y, - z - 2) + - 1.0e-1 * u (t, - x, - y + - 1, - z - - 2) - - - 2.5e-2 * u (t, - x, - y + - 2, - z - - 2)) - * ti2 (x, y, - z - - 2) * - ti3 (x, y, - z - - 2)) * - ti0 (x, y, z - 2)); - auto temp77 = - (2.5e-2 * ((v (t, x, y, z) - v (t, x, y, z - 2)) * ti2 (x, y, - z - 1) + (-v (t, - x, - y - - 1, - z - - 1) - + v (t, - x, - y - + - 1, - z - - - 1)) - * ti0 (x, y, z - 1) * ti3 (x, y, z - 1)) + (-7.5e-2 * v (t, - x, - y, - z - - 1) + - 1.0e-1 * v (t, - x + - 1, y, - z - - 1) - - 2.5e-2 * v (t, - x + - 2, y, - z - - 1)) * - ti0 (x, - y, - z - 1) * ti1 (x, y, z - 1)) * ti2 (x, y, z - 1); - auto temp61 = - (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y, z + 2)) * ti2 (x, y, - z + 1) + (-v (t, - x, - y - - - 1, - z - + - 1) - + - v (t, - x, - y + - 1, - z + - 1)) - * ti0 (x, y, z + 1) * ti3 (x, y, z + 1)) + (-7.5e-2 * v (t, - x, - y, - z + - 1) + - 1.0e-1 * v (t, - x + - 1, y, - z + - 1) - - 2.5e-2 * v (t, - x + - 2, y, - z + - 1)) * - ti0 (x, - y, - z + 1) * ti1 (x, y, z + 1)) * ti2 (x, y, z + 1); - auto temp150 = - (2.5e-2 * (-v (t, x - 1, y - 1, z) + v (t, x + 1, y - 1, z)) * - ti0 (x, y - 1, z) * ti1 (x, y - 1, - z) + (1.0e-1 * v (t, x, y, - z) - 7.5e-2 * v (t, x, - y - 1, - z) - - 2.5e-2 * v (t, x, y + 1, z)) * ti0 (x, - y - - 1, - z) * - ti3 (x, y - 1, - z) + (-7.5e-2 * v (t, x, y - 1, z) + 1.0e-1 * v (t, x, y - 1, - z + 1) - - 2.5e-2 * v (t, x, y - 1, z + 2)) * ti2 (x, y - 1, - z)) * ti0 (x, - y - 1, - z) * - ti3 (x, y - 1, z); + // Define equation for 'u' and 'v' at t+1 based on values at t + // for spatial order = 4. + virtual void define_so4 () + { - // Next time-step values. - u (t + 1, x, y, - z) EQUALS temp6 *(temp10 * u (t - 1, x, y, - z) + - 1.5695652173913 * (temp215 * epsilon (x, y, z) + - (3.75e-2 * - (temp39 + - temp47 * (ti0 (x, y, z) * - ti3 (x, y, - z) + ti2 (x, y, - z))) - - 5.0e-2 * (temp102 + temp132 + - temp150) + - 1.25e-2 * (temp110 - temp123 + - temp131 + temp140 - - temp141 + temp149 + - temp61 - temp77 + - temp87)) * delta (x, - y, - z)) - + 4.0 * m (x, y, z) * u (t, x, y, z)); - v (t + 1, x, y, - z) EQUALS temp6 *(temp10 * v (t - 1, x, y, - z) + 1.5695652173913 * temp215 * delta (x, - y, - z) - + 5.88586956521739e-2 * (temp39 + - temp47 * (ti0 (x, y, z) * - ti3 (x, y, - z) + ti2 (x, - y, - z))) - - 7.84782608695652e-2 * (temp102 + temp132 + - temp150) + - 1.96195652173913e-2 * (temp110 - temp123 + temp131 + - temp140 - temp141 + temp149 + - temp61 - temp77 + temp87) + - 4.0 * m (x, y, z) * v (t, x, y, z)); + auto temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); + auto temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, + z) - 2.5e-2 * u (t, x, y + 2, + z); + auto temp192 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 1, + z) - 2.5e-2 * u (t, x, y + 1, + z); + auto temp183 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x - 2, y, + z) + 1.0e-1 * u (t, x - 1, y, + z); + auto temp168 = -7.5e-2 * u (t, x, y + 1, z) + 1.0e-1 * u (t, x + 1, y + 1, + z) - 2.5e-2 * u (t, x + 2, + y + 1, + z); + auto temp197 = 3.75e-2 * (temp161 * ti1 (x, y, z) * ti2 (x, y, z) + temp163 * ti2 (x, y, z) * ti3 (x, y, + z) - (-7.5e-2 * u (t, x, y, + z) + 1.0e-1 * u (t, x, y, + z + 1) - 2.5e-2 * u (t, x, y, + z + 2)) * ti0 (x, y, z)); + auto temp171 = -7.5e-2 * u (t, x + 1, y, z) + 1.0e-1 * u (t, x + 1, y + 1, + z) - 2.5e-2 * u (t, x + 1, + y + 2, + z); + auto temp178 = 2.5e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)); + auto temp182 = 2.5e-2 * (-u (t, x - 2, y - 1, z) + u (t, x - 2, y + 1, z)); + auto temp190 = 1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x - 1, y, + z) - 2.5e-2 * u (t, x + 1, y, + z); + auto temp173 = 2.5e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)); + auto temp188 = 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x - 1, y + 1, z)); + auto temp154 = 2.5e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); + auto temp186 = -2.5e-2 * u (t, x, y, z) - 7.5e-2 * u (t, x, y - 2, + z) + 1.0e-1 * u (t, x, y - 1, + z); + auto temp158 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x + 1, y, + z) - 2.5e-2 * u (t, x + 2, y, + z); + auto temp191 = 2.5e-2 * (-u (t, x - 1, y - 1, z) + u (t, x + 1, y - 1, z)); + auto temp184 = 2.5e-2 * (-u (t, x - 1, y - 2, z) + u (t, x + 1, y - 2, z)); + auto temp181 = -7.5e-2 * u (t, x - 1, y, z) + 1.0e-1 * u (t, x - 1, y + 1, + z) - 2.5e-2 * u (t, x - 1, + y + 2, + z); + auto temp176 = -7.5e-2 * u (t, x, y - 1, z) + 1.0e-1 * u (t, x + 1, y - 1, + z) - 2.5e-2 * u (t, x + 2, + y - 1, + z); + auto temp123 = (2.5e-2 * ((v (t, x, y, z) - v (t, x, y - 2, z)) * ti0 (x, y - 1, z) * ti3 (x, + y - 1, + z) + (-v (t, x, y - 1, z - 1) + v (t, x, y - 1, z + 1)) * ti2 (x, y - 1, + z)) + + (-7.5e-2 * v (t, x, y - 1, z) + 1.0e-1 * v (t, x + 1, y - 1, z) - 2.5e-2 * v (t, x + 2, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, + z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); + auto temp102 = (2.5e-2 * ((-v (t, x - 1, y, z - 1) + v (t, x - 1, y, z + 1)) * ti2 (x - 1, y, + z) + (-v (t, + x - 1, + y - 1, + z) + v (t, + x - 1, + y + 1, + z)) * ti0 (x - 1, y, z) * ti3 (x - 1, y, z)) + (1.0e-1 * v (t, x, y, + z) - 7.5e-2 * v (t, x - 1, y, + z) - 2.5e-2 * v (t, x + 1, y, + z)) * ti0 (x - 1, + y, + z) * ti1 (x - 1, y, z)) * ti0 (x - 1, y, + z) * + ti1 (x - 1, y, z); + auto temp131 = (2.5e-2 * (-v (t, x - 1, y, z - 2) + v (t, x + 1, y, z - 2)) * ti0 (x, y, z - 2) * ti1 (x, y, + z - 2) + (-2.5e-2 * v (t, x, y, + z) - 7.5e-2 * v (t, + x, + y, + z - 2) + 1.0e-1 * v (t, x, y, + z - 1)) * ti2 (x, y, + z - 2) + + (-7.5e-2 * v (t, x, y, z - 2) + 1.0e-1 * v (t, x, y + 1, z - 2) - 2.5e-2 * v (t, x, y + 2, z - 2)) * ti0 (x, y, z - 2) * ti3 (x, y, + z - 2)) * ti2 (x, y, z - 2); + auto temp87 = (2.5e-2 * ((-v (t, x - 2, y, z - 1) + v (t, x - 2, y, z + 1)) * ti2 (x - 2, y, + z) + (-v (t, + x - 2, + y - 1, + z) + v (t, + x - 2, + y + 1, + z)) * ti0 (x - 2, y, z) * ti3 (x - 2, y, z)) + (-2.5e-2 * v (t, x, y, + z) - 7.5e-2 * v (t, x - 2, y, + z) + 1.0e-1 * v (t, x - 1, y, + z)) * ti0 (x - 2, + y, + z) * ti1 (x - 2, y, z)) * ti0 (x - 2, y, + z) * + ti1 (x - 2, y, z); + auto temp47 = 2.5e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z)) * ti0 (x, y, + z) * ti1 (x, + y, + z) + (-7.5e-2 * v (t, x, y, z) + 1.0e-1 * v (t, x, y, z + 1) - 2.5e-2 * v (t, x, y, z + 2)) * ti2 (x, y, z) + (-7.5e-2 * v (t, x, + y, + z) + 1.0e-1 * v (t, x, + y + 1, + z) - 2.5e-2 * v (t, x, + y + 2, + z)) * + ti0 (x, y, z) * ti3 (x, y, z); + auto temp110 = (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y + 2, z)) * ti0 (x, y + 1, z) * ti3 (x, + y + 1, + z) + (-v (t, x, y + 1, z - 1) + v (t, x, y + 1, z + 1)) * ti2 (x, y + 1, + z)) + + (-7.5e-2 * v (t, x, y + 1, z) + 1.0e-1 * v (t, x + 1, y + 1, z) - 2.5e-2 * v (t, x + 2, y + 1, z)) * ti0 (x, y + 1, z) * ti1 (x, y + 1, + z)) * ti0 (x, y + 1, z) * ti3 (x, y + 1, z); + auto temp140 = (2.5e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) * ti0 (x + 1, y, z) * ti1 (x + 1, y, + z) + (-7.5e-2 * v (t, x + 1, y, z) + 1.0e-1 * v (t, x + 1, y, + z + 1) - 2.5e-2 * v (t, x + 1, y, + z + 2)) * ti2 (x + 1, y, + z) + + (-7.5e-2 * v (t, x + 1, y, z) + 1.0e-1 * v (t, x + 1, y + 1, z) - 2.5e-2 * v (t, x + 1, y + 2, z)) * ti0 (x + 1, y, z) * ti3 (x + 1, y, + z)) * ti0 (x + 1, y, + z) * ti1 (x + 1, y, + z); + auto temp149 = (2.5e-2 * (-v (t, x - 1, y - 2, z) + v (t, x + 1, y - 2, z)) * ti0 (x, y - 2, z) * ti1 (x, y - 2, + z) + (-2.5e-2 * v (t, x, y, + z) - 7.5e-2 * v (t, x, + y - 2, + z) + 1.0e-1 * v (t, x, y - 1, z)) * ti0 (x, + y - 2, + z) * ti3 (x, y - 2, + z) + + (-7.5e-2 * v (t, x, y - 2, z) + 1.0e-1 * v (t, x, y - 2, + z + 1) - 2.5e-2 * v (t, x, y - 2, z + 2)) * ti2 (x, y - 2, + z)) * ti0 (x, + y - 2, + z) * ti3 (x, y - 2, z); + auto temp39 = (2.5e-2 * ((-v (t, x, y, z - 1) + v (t, x, y, z + 1)) * ti2 (x, y, + z) + (-v (t, x, + y - 1, + z) + v (t, + x, + y + 1, + z)) * ti0 (x, y, z) * ti3 (x, y, z)) + (-7.5e-2 * v (t, x, y, + z) + 1.0e-1 * v (t, + x + 1, + y, + z) - 2.5e-2 * v (t, x + 2, + y, + z)) * ti0 (x, y, + z) * ti1 (x, y, z)) * ti0 (x, y, z) * ti1 (x, y, z); + auto temp132 = (2.5e-2 * (-v (t, x - 1, y, z - 1) + v (t, x + 1, y, z - 1)) * ti0 (x, y, z - 1) * ti1 (x, y, + z - 1) + (1.0e-1 * v (t, x, y, + z) - 7.5e-2 * v (t, x, + y, + z - 1) - 2.5e-2 * v (t, x, y, + z + 1)) * ti2 (x, y, + z - 1) + + (-7.5e-2 * v (t, x, y, z - 1) + 1.0e-1 * v (t, x, y + 1, z - 1) - 2.5e-2 * v (t, x, y + 2, z - 1)) * ti0 (x, y, z - 1) * ti3 (x, y, + z - 1)) * ti2 (x, y, z - 1); + auto temp6 = 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); + auto temp141 = (2.5e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) * ti0 (x - 1, y, z) * ti1 (x - 1, y, + z) + (-7.5e-2 * v (t, x - 1, y, z) + 1.0e-1 * v (t, x - 1, y, + z + 1) - 2.5e-2 * v (t, x - 1, y, + z + 2)) * ti2 (x - 1, + y, + z) + + (-7.5e-2 * v (t, x - 1, y, z) + 1.0e-1 * v (t, x - 1, y + 1, z) - 2.5e-2 * v (t, x - 1, y + 2, z)) * ti0 (x - 1, y, z) * ti3 (x - 1, y, + z)) * ti0 (x - 1, y, + z) * ti1 (x - 1, y, + z); + auto temp10 = 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); + auto temp215 = 3.75e-2 * (-temp154 * ti1 (x, y, z) + temp158 * ti3 (x, y, z)) * ti3 (x, + y, + z) + (temp197 * ti3 (x, y, + z) + (3.75e-2 * (temp154 * ti3 (x, y, + z) + temp158 * ti1 (x, + y, + z)) * ti2 (x, y, + z) - 9.375e-4 * (-u (t, x, y, z - 1) + u (t, x, y, + z + 1)) * ti0 (x, + y, + z)) * ti1 (x, y, + z)) * ti2 (x, + y, + z) + + (1.25e-2 * (temp182 * ti3 (x - 2, y, z) + temp183 * ti1 (x - 2, y, z)) * ti2 (x - 2, + y, + z) - 3.125e-4 * (-u (t, x - 2, y, z - 1) + u (t, x - 2, y, z + 1)) * ti0 (x - 2, + y, + z)) * ti1 (x - 2, + y, + z) * ti2 (x - 2, y, + z) + + 5.0e-2 * ((temp191 * ti3 (x, y - 1, z) - temp192 * ti1 (x, y - 1, z)) * ti1 (x, y - 1, + z) + (2.5e-2 * (-u (t, x - 1, y, z - 1) + u (t, x + 1, y, z - 1)) * ti1 (x, y, + z - 1) * ti2 (x, + y, + z - 1) - (1.0e-1 * u (t, x, y, z) - 7.5e-2 * u (t, x, y, z - 1) - 2.5e-2 * u (t, x, + y, + z + + 1)) * + ti0 (x, y, + z - 1) + (-7.5e-2 * u (t, x, + y, + z - 1) + 1.0e-1 * u (t, x, + y + 1, + z - 1) - 2.5e-2 * u (t, x, + y + 2, + z - 1)) * ti2 (x, y, + z - 1) * ti3 (x, y, z - 1)) * ti0 (x, y, + z - 1)) + + (1.25e-2 * temp168 * ti1 (x, y + 1, z) * ti2 (x, y + 1, z) + 3.125e-4 * ((-u (t, x, y, z) + u (t, x, y + 2, z)) * ti2 (x, y + 1, z) * ti3 (x, y + 1, + z) - (-u (t, x, y + 1, + z - 1) + u (t, x, + y + 1, + z + 1)) * ti0 (x, y + 1, z))) * ti2 (x, y + 1, z) * ti3 (x, y + 1, + z) + + (1.25e-2 * (temp171 * ti2 (x + 1, y, z) * ti3 (x + 1, y, z) - (-7.5e-2 * u (t, x + 1, y, z) + 1.0e-1 * u (t, x + 1, y, z + 1) - 2.5e-2 * u (t, x + 1, y, z + 2)) * ti0 (x + 1, y, + z)) + 3.125e-4 * (-u (t, x, + y, + z) + u (t, + x + 2, + y, + z)) * ti1 (x + 1, y, z) * ti2 (x + 1, y, + z)) * ti1 (x + 1, + y, + z) * + ti2 (x + 1, y, + z) + 1.25e-2 * ((-temp171 * ti1 (x + 1, y, z) + 2.5e-2 * (-u (t, x, y, z) + u (t, x + 2, y, z)) * ti3 (x + 1, y, + z)) * ti3 (x + 1, + y, + z) + (-temp173 * ti1 (x, y - 1, z) + temp176 * ti3 (x, y - 1, z)) * ti1 (x, + y - 1, + z) + (-temp182 * ti1 (x - 2, y, + z) + temp183 * ti3 (x - 2, y, + z)) * ti3 (x - + 2, + y, + z) + + ((temp184 * ti1 (x, y - 2, z) + temp186 * ti3 (x, y - 2, z)) * ti2 (x, + y - 2, + z) - (-7.5e-2 * u (t, + x, + y - 2, + z) + 1.0e-1 * u (t, + x, + y - 2, + z + 1) - 2.5e-2 * u (t, + x, + y - 2, + z + 2)) * ti0 (x, y - 2, z)) * ti2 (x, y - 2, z) * ti3 (x, y - 2, + z) + + (2.5e-2 * (-(u (t, x, y, z) - u (t, x, y, z - 2)) * ti0 (x, y, z - 1) + (-u (t, x, y - 1, z - 1) + u (t, x, y + 1, z - 1)) * ti2 (x, y, + z - 1) * ti3 (x, y, z - 1)) + (-7.5e-2 * u (t, x, y, z - 1) + 1.0e-1 * u (t, + x + 1, + y, + z + - + 1) + - 2.5e-2 * u (t, x + 2, y, z - 1)) * ti1 (x, + y, + z - + 1) * + ti2 (x, y, z - 1)) * ti0 (x, y, z - 1)) - (temp197 * ti0 (x, y, + z) + 3.75e-2 * (temp161 * ti3 (x, y, + z) - temp163 * ti1 (x, + y, + z)) * ti1 (x, y, + z) + 1.25e-2 * (temp168 * ti3 (x, y + 1, + z) - 2.5e-2 * (-u (t, x, y, + z) + u (t, + x, + y + 2, + z)) * ti1 (x, y + 1, + z)) * ti1 (x, y + 1, + z) + + 1.25e-2 * (temp178 * ti3 (x - 1, y, + z) - temp181 * ti1 (x - 1, y, + z)) * ti3 (x - 1, y, + z) + 1.25e-2 * (temp184 * ti3 (x, y - 2, + z) - temp186 * ti1 (x, + y - 2, + z)) * ti1 (x, y - 2, + z) + 5.0e-2 * (-temp188 * ti1 (x - 1, y, + z) + temp190 * ti3 (x - 1, + y, + z)) * + ti3 (x - 1, y, + z) + (1.25e-2 * (temp173 * ti3 (x, y - 1, + z) + temp176 * ti1 (x, y - 1, + z)) * ti2 (x, y - 1, + z) - 3.125e-4 * (-u (t, x, y - 1, z - 1) + u (t, x, y - 1, + z + 1)) * ti0 (x, + y - 1, + z)) * ti2 (x, y - 1, z) * ti3 (x, + y - 1, + z) + + 1.25e-2 * ((temp178 * ti1 (x - 1, y, + z) + temp181 * ti3 (x - 1, y, + z)) * ti2 (x - 1, y, + z) - (-7.5e-2 * u (t, x - 1, y, + z) + 1.0e-1 * u (t, + x - 1, + y, + z + 1) - 2.5e-2 * u (t, x - 1, y, + z + 2)) * ti0 (x - 1, + y, + z)) * ti1 (x - 1, + y, + z) * ti2 (x - 1, y, + z) + + (5.0e-2 * (temp188 * ti3 (x - 1, y, + z) + temp190 * ti1 (x - 1, y, + z)) * ti2 (x - 1, y, + z) - 1.25e-3 * (-u (t, x - 1, y, z - 1) + u (t, x - 1, y, + z + 1)) * ti0 (x - 1, + y, + z)) * ti1 (x - 1, y, + z) * ti2 (x - 1, y, + z) + 5.0e-2 * ((temp191 * ti1 (x, y - 1, + z) + + temp192 * ti3 (x, y - 1, + z)) * ti2 (x, + y - + 1, + z) + - (-7.5e-2 * u (t, x, y - 1, + z) + + 1.0e-1 * u (t, + x, + y - 1, + z + + 1) - + 2.5e-2 * u (t, x, y - 1, + z + + 2)) * ti0 (x, + y - + 1, + z)) + * ti2 (x, y - 1, + z) * ti3 (x, y - 1, + z) + 1.25e-2 * (2.5e-2 * (-(-u (t, x, y, + z) + u (t, + x, + y, + z + 2)) * ti0 (x, y, + z + 1) + (-u (t, x, y - 1, + z + 1) + u (t, + x, + y + 1, + z + 1)) * ti2 (x, y, + z + 1) * ti3 (x, y, + z + 1)) + (-7.5e-2 * u (t, x, y, + z + 1) + 1.0e-1 * u (t, + x + 1, + y, + z + + 1) + - 2.5e-2 * u (t, + x + 2, + y, + z + 1)) * ti1 (x, y, + z + + 1) * ti2 (x, y, + z + + 1)) * + ti0 (x, y, + z + 1) + 1.25e-2 * (2.5e-2 * (-u (t, x - 1, y, + z - 2) + u (t, x + 1, + y, + z - 2)) * ti1 (x, + y, + z - 2) * ti2 (x, y, + z - 2) - (-2.5e-2 * u (t, x, y, + z) - 7.5e-2 * u (t, + x, + y, + z - 2) + 1.0e-1 * u (t, + x, + y, + z - 1)) * ti0 (x, y, + z - 2) + (-7.5e-2 * u (t, + x, + y, + z - + 2) + + 1.0e-1 * u (t, + x, + y + + 1, + z - + 2) - + 2.5e-2 * u (t, + x, + y + + 2, + z - + 2)) * + ti2 (x, y, + z - 2) * ti3 (x, y, + z - 2)) * ti0 (x, y, z - 2)); + auto temp77 = (2.5e-2 * ((v (t, x, y, z) - v (t, x, y, z - 2)) * ti2 (x, y, + z - 1) + (-v (t, + x, + y - 1, + z - 1) + v (t, + x, + y + 1, + z - 1)) * ti0 (x, y, z - 1) * ti3 (x, y, z - 1)) + (-7.5e-2 * v (t, + x, + y, + z - 1) + 1.0e-1 * v (t, + x + 1, y, + z - 1) - 2.5e-2 * v (t, + x + 2, + y, + z - 1)) * ti0 (x, + y, + z - 1) * ti1 (x, y, + z - 1)) * ti2 (x, + y, + z - + 1); + auto temp61 = (2.5e-2 * ((-v (t, x, y, z) + v (t, x, y, z + 2)) * ti2 (x, y, + z + 1) + (-v (t, + x, + y - 1, + z + 1) + v (t, + x, + y + 1, + z + 1)) * ti0 (x, y, z + 1) * ti3 (x, y, z + 1)) + (-7.5e-2 * v (t, + x, + y, + z + 1) + 1.0e-1 * v (t, + x + 1, y, + z + 1) - 2.5e-2 * v (t, + x + 2, + y, + z + 1)) * ti0 (x, + y, + z + 1) * ti1 (x, y, + z + 1)) * ti2 (x, + y, + z + + + 1); + auto temp150 = (2.5e-2 * (-v (t, x - 1, y - 1, z) + v (t, x + 1, y - 1, z)) * ti0 (x, y - 1, z) * ti1 (x, y - 1, + z) + (1.0e-1 * v (t, x, y, + z) - 7.5e-2 * v (t, x, + y - 1, + z) - 2.5e-2 * v (t, x, y + 1, z)) * ti0 (x, + y - 1, + z) * ti3 (x, y - 1, + z) + (-7.5e-2 * v (t, x, y - 1, z) + 1.0e-1 * v (t, x, y - 1, + z + 1) - + 2.5e-2 * v (t, x, y - 1, z + 2)) * ti2 (x, y - 1, + z)) * ti0 (x, + y - + 1, + z) * + ti3 (x, y - 1, z); - } + // Next time-step values. + u (t + 1, x, y, + z) EQUALS temp6 *(temp10 * u (t - 1, x, y, + z) + + 1.5695652173913 * (temp215 * epsilon (x, y, z) + + (3.75e-2 * + (temp39 + + temp47 * (ti0 (x, y, z) * + ti3 (x, y, + z) + ti2 (x, y, + z))) - + 5.0e-2 * (temp102 + temp132 + temp150) + 1.25e-2 * (temp110 - temp123 + temp131 + temp140 - temp141 + temp149 + temp61 - temp77 + temp87)) * delta (x, y, z)) + 4.0 * m (x, y, z) * u (t, x, y, z)); + v (t + 1, x, y, + z) EQUALS temp6 *(temp10 * v (t - 1, x, y, + z) + 1.5695652173913 * temp215 * delta (x, + y, + z) + + 5.88586956521739e-2 * (temp39 + + temp47 * (ti0 (x, y, z) * + ti3 (x, y, + z) + ti2 (x, + y, + z))) + - 7.84782608695652e-2 * (temp102 + temp132 + temp150) + 1.96195652173913e-2 * (temp110 - temp123 + temp131 + temp140 - temp141 + temp149 + temp61 - temp77 + temp87) + 4.0 * m (x, y, z) * v (t, x, y, z)); - // Define equation for 'u' and 'v' at t+1 based on values at t - // for spatial order = 8. - virtual void define_so8 () - { + } - auto temp330 = - 4.16666666666667e-3 * (u (t, x - 2, y, z) - u (t, x + 2, y, z)) + - 3.33333333333333e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); - auto temp333 = - -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 1, - z) + - 7.5e-2 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, - z) + - 4.16666666666667e-3 * u (t, x, y + 3, z); - auto temp336 = - 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x, y + 2, z)) + - 4.16666666666667e-3 * (u (t, x, y - 1, z) - u (t, x, y + 3, z)); - auto temp395 = - 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x + 2, y - 2, - z)) + - 3.33333333333333e-2 * (-u (t, x - 1, - y - 2, - z) + u (t, - x + 1, - y - 2, - z)); - auto temp365 = - -4.16666666666667e-2 * u (t, x - 2, y, z) - 1.25e-2 * u (t, x - 2, - y - 1, - z) + - 7.5e-2 * u (t, x - 2, y + 1, z) - 2.5e-2 * u (t, x - 2, y + 2, - z) + - 4.16666666666667e-3 * u (t, x - 2, y + 3, z); - auto temp375 = - -4.16666666666667e-2 * u (t, x + 2, y, z) - 1.25e-2 * u (t, x + 2, - y - 1, - z) + - 7.5e-2 * u (t, x + 2, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 2, - z) + - 4.16666666666667e-3 * u (t, x + 2, y + 3, z); - auto temp394 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 3, y, - z) - - 4.16666666666667e-2 * u (t, x - 2, y, z) + 7.5e-2 * u (t, x - 1, y, - z) + - 4.16666666666667e-3 * u (t, x + 1, y, z); - auto temp407 = - 4.16666666666667e-3 * (u (t, x - 1, y - 2, z) - u (t, x - 1, y + 2, - z)) + - 3.33333333333333e-2 * (-u (t, x - 1, - y - 1, - z) + u (t, - x - 1, - y + 1, - z)); - auto temp352 = - 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x, y - 4, z)) + - 3.33333333333333e-2 * (-u (t, x, y - 3, z) + u (t, x, y - 1, z)); - auto temp347 = - -4.16666666666667e-2 * u (t, x + 1, y, z) - 1.25e-2 * u (t, x + 1, - y - 1, - z) + - 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 1, y + 2, - z) + - 4.16666666666667e-3 * u (t, x + 1, y + 3, z); - auto temp409 = - 4.16666666666667e-3 * (u (t, x + 1, y - 2, z) - u (t, x + 1, y + 2, - z)) + - 3.33333333333333e-2 * (-u (t, x + 1, - y - 1, - z) + u (t, - x + 1, - y + 1, - z)); - auto temp318 = - 4.16666666666667e-3 * (u (t, x, y - 2, z) - u (t, x, y + 2, z)) + - 3.33333333333333e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); - auto temp381 = - -4.16666666666667e-2 * u (t, x, y - 1, z) - 1.25e-2 * u (t, x - 1, - y - 1, - z) + - 7.5e-2 * u (t, x + 1, y - 1, z) - 2.5e-2 * u (t, x + 2, y - 1, - z) + - 4.16666666666667e-3 * u (t, x + 3, y - 1, z); - auto temp408 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 2, y, - z) - - 4.16666666666667e-2 * u (t, x - 1, y, z) - 2.5e-2 * u (t, x + 1, y, - z) + - 4.16666666666667e-3 * u (t, x + 2, y, z); - auto temp390 = - 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 4, - z) - - 4.16666666666667e-2 * u (t, x, y - 3, z) + 7.5e-2 * u (t, x, y - 2, - z) - - 2.5e-2 * u (t, x, y - 1, z); - auto temp360 = - 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x - 4, y, z)) + - 3.33333333333333e-2 * (-u (t, x - 3, y, z) + u (t, x - 1, y, z)); - auto temp370 = - -4.16666666666667e-2 * u (t, x, y + 2, z) - 1.25e-2 * u (t, x - 1, - y + 2, - z) + - 7.5e-2 * u (t, x + 1, y + 2, z) - 2.5e-2 * u (t, x + 2, y + 2, - z) + - 4.16666666666667e-3 * u (t, x + 3, y + 2, z); - auto temp357 = - -4.16666666666667e-2 * u (t, x, y - 2, z) - 1.25e-2 * u (t, x - 1, - y - 2, - z) + - 7.5e-2 * u (t, x + 1, y - 2, z) - 2.5e-2 * u (t, x + 2, y - 2, - z) + - 4.16666666666667e-3 * u (t, x + 3, y - 2, z); - auto temp385 = - -4.16666666666667e-2 * u (t, x - 1, y, z) - 1.25e-2 * u (t, x - 1, + // Define equation for 'u' and 'v' at t+1 based on values at t + // for spatial order = 8. + virtual void define_so8 () + { + + auto temp330 = 4.16666666666667e-3 * (u (t, x - 2, y, z) - u (t, x + 2, y, z)) + 3.33333333333333e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); + auto temp333 = -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 1, + z) + 7.5e-2 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, + z) + 4.16666666666667e-3 * u (t, x, y + 3, z); + auto temp336 = 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x, y + 2, z)) + 4.16666666666667e-3 * (u (t, x, y - 1, z) - u (t, x, y + 3, z)); + auto temp395 = 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x + 2, y - 2, + z)) + 3.33333333333333e-2 * (-u (t, x - 1, + y - 2, + z) + u (t, + x + 1, + y - 2, + z)); + auto temp365 = -4.16666666666667e-2 * u (t, x - 2, y, z) - 1.25e-2 * u (t, x - 2, + y - 1, + z) + 7.5e-2 * u (t, x - 2, y + 1, z) - 2.5e-2 * u (t, x - 2, y + 2, + z) + 4.16666666666667e-3 * u (t, x - 2, y + 3, z); + auto temp375 = -4.16666666666667e-2 * u (t, x + 2, y, z) - 1.25e-2 * u (t, x + 2, + y - 1, + z) + 7.5e-2 * u (t, x + 2, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 2, + z) + 4.16666666666667e-3 * u (t, x + 2, y + 3, z); + auto temp394 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 3, y, + z) - 4.16666666666667e-2 * u (t, x - 2, y, z) + 7.5e-2 * u (t, x - 1, y, + z) + 4.16666666666667e-3 * u (t, x + 1, y, z); + auto temp407 = 4.16666666666667e-3 * (u (t, x - 1, y - 2, z) - u (t, x - 1, y + 2, + z)) + 3.33333333333333e-2 * (-u (t, x - 1, + y - 1, + z) + u (t, + x - 1, + y + 1, + z)); + auto temp352 = 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x, y - 4, z)) + 3.33333333333333e-2 * (-u (t, x, y - 3, z) + u (t, x, y - 1, z)); + auto temp347 = -4.16666666666667e-2 * u (t, x + 1, y, z) - 1.25e-2 * u (t, x + 1, + y - 1, + z) + 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 1, y + 2, + z) + 4.16666666666667e-3 * u (t, x + 1, y + 3, z); + auto temp409 = 4.16666666666667e-3 * (u (t, x + 1, y - 2, z) - u (t, x + 1, y + 2, + z)) + 3.33333333333333e-2 * (-u (t, x + 1, + y - 1, + z) + u (t, + x + 1, + y + 1, + z)); + auto temp318 = 4.16666666666667e-3 * (u (t, x, y - 2, z) - u (t, x, y + 2, z)) + 3.33333333333333e-2 * (-u (t, x, y - 1, z) + u (t, x, y + 1, z)); + auto temp381 = -4.16666666666667e-2 * u (t, x, y - 1, z) - 1.25e-2 * u (t, x - 1, + y - 1, + z) + 7.5e-2 * u (t, x + 1, y - 1, z) - 2.5e-2 * u (t, x + 2, y - 1, + z) + 4.16666666666667e-3 * u (t, x + 3, y - 1, z); + auto temp408 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 2, y, + z) - 4.16666666666667e-2 * u (t, x - 1, y, z) - 2.5e-2 * u (t, x + 1, y, + z) + 4.16666666666667e-3 * u (t, x + 2, y, z); + auto temp390 = 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 4, + z) - 4.16666666666667e-2 * u (t, x, y - 3, z) + 7.5e-2 * u (t, x, y - 2, + z) - 2.5e-2 * u (t, x, y - 1, z); + auto temp360 = 4.16666666666667e-3 * (-u (t, x, y, z) + u (t, x - 4, y, z)) + 3.33333333333333e-2 * (-u (t, x - 3, y, z) + u (t, x - 1, y, z)); + auto temp370 = -4.16666666666667e-2 * u (t, x, y + 2, z) - 1.25e-2 * u (t, x - 1, + y + 2, + z) + 7.5e-2 * u (t, x + 1, y + 2, z) - 2.5e-2 * u (t, x + 2, y + 2, + z) + 4.16666666666667e-3 * u (t, x + 3, y + 2, z); + auto temp357 = -4.16666666666667e-2 * u (t, x, y - 2, z) - 1.25e-2 * u (t, x - 1, + y - 2, + z) + 7.5e-2 * u (t, x + 1, y - 2, z) - 2.5e-2 * u (t, x + 2, y - 2, + z) + 4.16666666666667e-3 * u (t, x + 3, y - 2, z); + auto temp385 = -4.16666666666667e-2 * u (t, x - 1, y, z) - 1.25e-2 * u (t, x - 1, + y - 1, + z) + 7.5e-2 * u (t, x - 1, y + 1, z) - 2.5e-2 * u (t, x - 1, y + 2, + z) + 4.16666666666667e-3 * u (t, x - 1, y + 3, z); + auto temp377 = 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)) + 4.16666666666667e-3 * (u (t, x, y - 3, z) - u (t, x, y + 1, z)); + auto temp343 = 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x + 2, y, z)) + 4.16666666666667e-3 * (u (t, x - 1, y, z) - u (t, x + 3, y, z)); + auto temp388 = 4.16666666666667e-3 * (u (t, x - 2, y - 3, z) - u (t, x + 2, y - 3, + z)) + 3.33333333333333e-2 * (-u (t, x - 1, + y - 3, + z) + u (t, + x + 1, + y - 3, + z)); + auto temp406 = -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x, y + 1, + z) + 7.5e-2 * u (t, x, y + 2, z) - 2.5e-2 * u (t, x, y + 3, + z) + 4.16666666666667e-3 * u (t, x, y + 4, z); + auto temp404 = 4.16666666666667e-3 * (u (t, x - 2, y + 1, z) - u (t, x + 2, y + 1, + z)) + 3.33333333333333e-2 * (-u (t, x - 1, + y + 1, + z) + u (t, + x + 1, + y + 1, + z)); + auto temp342 = -4.16666666666667e-2 * u (t, x, y + 1, z) - 1.25e-2 * u (t, x - 1, + y + 1, + z) + 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 1, + z) + 4.16666666666667e-3 * u (t, x + 3, y + 1, z); + auto temp410 = -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x + 1, y, + z) + 7.5e-2 * u (t, x + 2, y, z) - 2.5e-2 * u (t, x + 3, y, + z) + 4.16666666666667e-3 * u (t, x + 4, y, z); + auto temp367 = 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x, y + 4, z)) + 3.33333333333333e-2 * (-u (t, x, y + 1, z) + u (t, x, y + 3, z)); + auto temp399 = 4.16666666666667e-3 * (u (t, x - 2, y - 1, z) - u (t, x + 2, y - 1, + z)) + 3.33333333333333e-2 * (-u (t, x - 1, + y - 1, + z) + u (t, + x + 1, + y - 1, + z)); + auto temp325 = -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 1, y, + z) + 7.5e-2 * u (t, x + 1, y, z) - 2.5e-2 * u (t, x + 2, y, + z) + 4.16666666666667e-3 * u (t, x + 3, y, z); + auto temp386 = 4.16666666666667e-3 * (u (t, x - 3, y - 2, z) - u (t, x - 3, y + 2, + z)) + 3.33333333333333e-2 * (-u (t, x - 3, + y - 1, + z) + u (t, + x - 3, + y + 1, + z)); + auto temp396 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 3, + z) - 4.16666666666667e-2 * u (t, x, y - 2, z) + 7.5e-2 * u (t, x, y - 1, + z) + 4.16666666666667e-3 * u (t, x, y + 1, z); + auto temp401 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 2, + z) - 4.16666666666667e-2 * u (t, x, y - 1, z) - 2.5e-2 * u (t, x, y + 1, + z) + 4.16666666666667e-3 * u (t, x, y + 2, z); + auto temp372 = 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x + 4, y, z)) + 3.33333333333333e-2 * (-u (t, x + 1, y, z) + u (t, x + 3, y, z)); + auto temp420 = 2.08333333333333e-2 * ((temp330 * ti1 (x, y, z) + temp333 * ti3 (x, y, z)) * ti2 (x, y, + z) - (-4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y, z - 1) + 7.5e-2 * u (t, x, y, + z + 1) - 2.5e-2 * u (t, + x, + y, + z + + 2) + + 4.16666666666667e-3 * u (t, x, y, z + 3)) * ti0 (x, y, z)); + auto temp387 = 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x - 4, y, + z) - 4.16666666666667e-2 * u (t, x - 3, y, z) + 7.5e-2 * u (t, x - 2, y, + z) - 2.5e-2 * u (t, x - 1, y, z); + auto temp383 = 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)) + 4.16666666666667e-3 * (u (t, x - 3, y, z) - u (t, x + 1, y, z)); + auto temp392 = 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x - 2, y + 2, + z)) + 3.33333333333333e-2 * (-u (t, x - 2, + y - 1, + z) + u (t, + x - 2, + y + 1, + z)); + auto temp284 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 2) - v (t, x + 2, y, z - 2)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 2) + v (t, x + 1, y, z - 2))) * ti1 (x, y, + z - 2) + + (-4.16666666666667e-2 * v (t, x, y, z - 2) - 1.25e-2 * v (t, x, y - 1, z - 2) + 7.5e-2 * v (t, x, y + 1, + z - 2) - 2.5e-2 * v (t, x, y + 2, z - 2) + 4.16666666666667e-3 * v (t, x, + y + 3, + z - 2)) * ti3 (x, y, z - 2)) * ti0 (x, y, z - 2) + (-2.5e-2 * v (t, x, y, + z) - + 1.25e-2 * v (t, x, y, + z - 3) - + 4.16666666666667e-2 * + v (t, + x, + y, + z + - + 2) + + 7.5e-2 * v (t, x, + y, + z - + 1) + + 4.16666666666667e-3 * + v (t, + x, + y, + z + + + 1)) + * ti2 (x, y, z - 2)) * ti2 (x, y, z - 2); + auto temp308 = (((4.16666666666667e-3 * (v (t, x - 2, y - 2, z) - v (t, x + 2, y - 2, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 2, z) + v (t, x + 1, y - 2, z))) * ti1 (x, y - 2, + z) + + (-2.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 3, z) - 4.16666666666667e-2 * v (t, x, y - 2, z) + 7.5e-2 * v (t, x, y - 1, + z) + 4.16666666666667e-3 * v (t, x, y + 1, z)) * ti3 (x, y - 2, + z)) * ti0 (x, + y - 2, + z) + (-4.16666666666667e-2 * v (t, x, y - 2, z) - + 1.25e-2 * v (t, x, y - 2, + z - 1) + 7.5e-2 * v (t, x, y - 2, + z + 1) - + 2.5e-2 * v (t, x, y - 2, + z + 2) + 4.16666666666667e-3 * v (t, + x, + y + - + 2, + z + + + 3)) + * ti2 (x, y - 2, z)) * ti0 (x, y - 2, z) * ti3 (x, y - 2, z); + auto temp92 = (((4.16666666666667e-3 * (v (t, x, y - 2, z + 1) - v (t, x, y + 2, z + 1)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z + 1) + v (t, x, y + 1, z + 1))) * ti3 (x, y, + z + 1) + + (-4.16666666666667e-2 * v (t, x, y, z + 1) - 1.25e-2 * v (t, x - 1, y, z + 1) + 7.5e-2 * v (t, x + 1, y, + z + 1) - 2.5e-2 * v (t, x + 2, y, z + 1) + 4.16666666666667e-3 * v (t, + x + 3, + y, + z + 1)) * ti1 (x, y, z + 1)) * ti0 (x, y, + z + 1) + + (3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x, y, z + 2)) + 4.16666666666667e-3 * (v (t, x, y, z - 1) - v (t, x, y, z + 3))) * ti2 (x, y, + z + 1)) * ti2 (x, + y, + z + 1); + auto temp185 = (((4.16666666666667e-3 * (v (t, x - 2, y - 2, z) - v (t, x - 2, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 2, y - 1, z) + v (t, x - 2, y + 1, z))) * ti3 (x - 2, y, + z) + + (-2.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x - 3, y, z) - 4.16666666666667e-2 * v (t, x - 2, y, z) + 7.5e-2 * v (t, x - 1, y, + z) + 4.16666666666667e-3 * v (t, x + 1, y, z)) * ti1 (x - 2, y, + z)) * ti0 (x - 2, + y, + z) + + (4.16666666666667e-3 * (v (t, x - 2, y, z - 2) - v (t, x - 2, y, z + 2)) + 3.33333333333333e-2 * (-v (t, x - 2, y, z - 1) + v (t, x - 2, y, z + 1))) * ti2 (x - 2, y, + z)) * ti0 (x - 2, + y, + z) * ti1 (x - 2, y, z); + auto temp283 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 3) - v (t, x + 2, y, z - 3)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 3) + v (t, x + 1, y, z - 3))) * ti1 (x, y, + z - 3) + + (-4.16666666666667e-2 * v (t, x, y, z - 3) - 1.25e-2 * v (t, x, y - 1, z - 3) + 7.5e-2 * v (t, x, y + 1, + z - 3) - 2.5e-2 * v (t, x, y + 2, z - 3) + 4.16666666666667e-3 * v (t, x, + y + 3, + z - + 3)) * + ti3 (x, y, z - 3)) * ti0 (x, y, z - 3) + (4.16666666666667e-3 * v (t, + x, + y, + z) - 1.25e-2 * v (t, x, y, + z - 4) - 4.16666666666667e-2 * v (t, + x, + y, + z - 3) + 7.5e-2 * v (t, x, y, + z - 2) - 2.5e-2 * v (t, x, y, + z - 1)) * ti2 (x, + y, + z - 3)) * ti2 (x, y, z - 3); + auto temp309 = (((4.16666666666667e-3 * (v (t, x - 2, y - 1, z) - v (t, x + 2, y - 1, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + v (t, x + 1, y - 1, z))) * ti1 (x, y - 1, + z) + + (7.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 2, z) - 4.16666666666667e-2 * v (t, x, y - 1, z) - 2.5e-2 * v (t, x, y + 1, + z) + 4.16666666666667e-3 * v (t, x, y + 2, z)) * ti3 (x, y - 1, + z)) * ti0 (x, + y - 1, + z) + (-4.16666666666667e-2 * v (t, x, y - 1, z) - + 1.25e-2 * v (t, x, y - 1, z - 1) + 7.5e-2 * v (t, + x, + y + - + 1, + z + + + 1) + - 2.5e-2 * v (t, x, y - 1, + z + 2) + + 4.16666666666667e-3 * v (t, x, + y - 1, + z + + 3)) * + ti2 (x, y - 1, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); + auto temp310 = (((4.16666666666667e-3 * (v (t, x - 2, y + 1, z) - v (t, x + 2, y + 1, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y + 1, z) + v (t, x + 1, y + 1, z))) * ti1 (x, y + 1, + z) + + (-1.25e-2 * v (t, x, y, z) - 4.16666666666667e-2 * v (t, x, y + 1, z) + 7.5e-2 * v (t, x, y + 2, + z) - 2.5e-2 * v (t, x, y + 3, z) + 4.16666666666667e-3 * v (t, x, y + 4, + z)) * ti3 (x, + y + 1, + z)) * ti0 (x, y + 1, + z) + (-4.16666666666667e-2 * v (t, x, + y + 1, + z) - 1.25e-2 * v (t, x, y + 1, + z - 1) + + 7.5e-2 * v (t, + x, + y + 1, + z + 1) - 2.5e-2 * v (t, x, y + 1, + z + 2) + + 4.16666666666667e-3 * v (t, x, y + 1, + z + 3)) * ti2 (x, + y + 1, + z)) * ti0 (x, + y + 1, + z) * + ti3 (x, y + 1, z); + auto temp307 = (((4.16666666666667e-3 * (v (t, x - 2, y - 3, z) - v (t, x + 2, y - 3, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 3, z) + v (t, x + 1, y - 3, z))) * ti1 (x, y - 3, + z) + + (4.16666666666667e-3 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 4, z) - 4.16666666666667e-2 * v (t, x, + y - 3, + z) + 7.5e-2 * v (t, x, y - 2, z) - 2.5e-2 * v (t, x, y - 1, + z)) * ti3 (x, y - 3, + z)) * ti0 (x, + y - 3, + z) + + (-4.16666666666667e-2 * v (t, x, y - 3, z) - 1.25e-2 * v (t, x, y - 3, z - 1) + 7.5e-2 * v (t, x, y - 3, + z + 1) - 2.5e-2 * v (t, x, y - 3, z + 2) + 4.16666666666667e-3 * v (t, x, + y - 3, + z + 3)) * ti2 (x, y - 3, z)) * ti0 (x, y - 3, z) * ti3 (x, y - 3, z); + auto temp298 = (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x + 4, y, z)) + 3.33333333333333e-2 * (-v (t, x + 1, y, z) + v (t, x + 3, y, z))) * ti1 (x + 2, y, + z) + + (-4.16666666666667e-2 * v (t, x + 2, y, z) - 1.25e-2 * v (t, x + 2, y - 1, z) + 7.5e-2 * v (t, x + 2, y + 1, + z) - 2.5e-2 * v (t, + x + 2, + y + 2, + z) + 4.16666666666667e-3 * v (t, x + 2, y + 3, z)) * ti3 (x + 2, y, + z)) * ti0 (x + 2, + y, + z) + (-4.16666666666667e-2 * v (t, x + 2, y, + z) - 1.25e-2 * v (t, + x + + 2, + y, + z - + 1) + + 7.5e-2 * v (t, x + 2, y, z + 1) - 2.5e-2 * v (t, + x + + 2, + y, + z + + 2) + + 4.16666666666667e-3 * v (t, x + 2, y, + z + 3)) * ti2 (x + 2, + y, + z)) * + ti0 (x + 2, + y, + z) * ti1 (x + 2, y, z); + auto temp165 = (((4.16666666666667e-3 * (v (t, x - 3, y - 2, z) - v (t, x - 3, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 3, y - 1, z) + v (t, x - 3, y + 1, z))) * ti3 (x - 3, y, + z) + + (4.16666666666667e-3 * v (t, x, y, z) - 1.25e-2 * v (t, x - 4, y, z) - 4.16666666666667e-2 * v (t, x - 3, + y, + z) + 7.5e-2 * v (t, x - 2, y, z) - 2.5e-2 * v (t, x - 1, y, + z)) * ti1 (x - 3, y, + z)) * ti0 (x - 3, + y, + z) + + (4.16666666666667e-3 * (v (t, x - 3, y, z - 2) - v (t, x - 3, y, z + 2)) + 3.33333333333333e-2 * (-v (t, x - 3, y, z - 1) + v (t, x - 3, y, z + 1))) * ti2 (x - 3, y, + z)) * ti0 (x - 3, + y, + z) * ti1 (x - 3, y, z); + auto temp154 = (((4.16666666666667e-3 * (v (t, x, y - 2, z - 1) - v (t, x, y + 2, z - 1)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 1) + v (t, x, y + 1, z - 1))) * ti3 (x, y, + z - 1) + + (-4.16666666666667e-2 * v (t, x, y, z - 1) - 1.25e-2 * v (t, x - 1, y, z - 1) + 7.5e-2 * v (t, x + 1, y, + z - 1) - 2.5e-2 * v (t, x + 2, y, z - 1) + 4.16666666666667e-3 * v (t, + x + 3, + y, + z - 1)) * ti1 (x, y, z - 1)) * ti0 (x, y, + z - 1) + + (3.33333333333333e-2 * (v (t, x, y, z) - v (t, x, y, z - 2)) + 4.16666666666667e-3 * (v (t, x, y, z - 3) - v (t, x, y, z + 1))) * ti2 (x, y, + z - 1)) * ti2 (x, + y, + z - 1); + auto temp299 = (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) + 4.16666666666667e-3 * (v (t, x - 3, y, z) - v (t, x + 1, y, z))) * ti1 (x - 1, y, + z) + + (-4.16666666666667e-2 * v (t, x - 1, y, z) - 1.25e-2 * v (t, x - 1, y - 1, z) + 7.5e-2 * v (t, x - 1, y + 1, + z) - 2.5e-2 * v (t, + x - 1, + y + 2, + z) + 4.16666666666667e-3 * v (t, x - 1, y + 3, z)) * ti3 (x - 1, y, + z)) * ti0 (x - 1, + y, + z) + (-4.16666666666667e-2 * v (t, x - 1, y, + z) - 1.25e-2 * v (t, + x - + 1, + y, + z - + 1) + + 7.5e-2 * v (t, x - 1, y, z + 1) - 2.5e-2 * v (t, + x - + 1, + y, + z + + 2) + + 4.16666666666667e-3 * v (t, x - 1, y, + z + 3)) * ti2 (x - 1, + y, + z)) * + ti0 (x - 1, + y, + z) * ti1 (x - 1, y, z); + auto temp289 = (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) + 4.16666666666667e-3 * (v (t, x - 1, y, z) - v (t, x + 3, y, z))) * ti1 (x + 1, y, + z) + + (-4.16666666666667e-2 * v (t, x + 1, y, z) - 1.25e-2 * v (t, x + 1, y - 1, z) + 7.5e-2 * v (t, x + 1, y + 1, + z) - 2.5e-2 * v (t, + x + 1, + y + 2, + z) + 4.16666666666667e-3 * v (t, x + 1, y + 3, z)) * ti3 (x + 1, y, + z)) * ti0 (x + 1, + y, + z) + (-4.16666666666667e-2 * v (t, x + 1, y, + z) - 1.25e-2 * v (t, + x + + 1, + y, + z - + 1) + + 7.5e-2 * v (t, x + 1, y, z + 1) - 2.5e-2 * v (t, + x + + 1, + y, + z + + 2) + + 4.16666666666667e-3 * v (t, x + 1, y, + z + 3)) * ti2 (x + 1, + y, + z)) * + ti0 (x + 1, + y, + z) * ti1 (x + 1, y, z); + auto temp116 = (((4.16666666666667e-3 * (v (t, x, y - 2, z - 2) - v (t, x, y + 2, z - 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 2) + v (t, x, y + 1, z - 2))) * ti3 (x, y, + z - 2) + + (-4.16666666666667e-2 * v (t, x, y, z - 2) - 1.25e-2 * v (t, x - 1, y, z - 2) + 7.5e-2 * v (t, x + 1, y, + z - 2) - 2.5e-2 * v (t, x + 2, y, z - 2) + 4.16666666666667e-3 * v (t, + x + 3, + y, + z - 2)) * ti1 (x, y, z - 2)) * ti0 (x, y, + z - 2) + + (4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x, y, z - 4)) + 3.33333333333333e-2 * (-v (t, x, y, z - 3) + v (t, x, y, z - 1))) * ti2 (x, y, + z - 2)) * ti2 (x, + y, + z - 2); + auto temp56 = (((4.16666666666667e-3 * (v (t, x, y - 2, z) - v (t, x, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z) + v (t, x, y + 1, z))) * ti3 (x, y, + z) + + (-4.16666666666667e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x - 1, y, z) + 7.5e-2 * v (t, x + 1, y, + z) - 2.5e-2 * v (t, + x + 2, + y, + z) + 4.16666666666667e-3 * v (t, x + 3, y, z)) * ti1 (x, y, z)) * ti0 (x, + y, + z) + + (4.16666666666667e-3 * (v (t, x, y, z - 2) - v (t, x, y, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y, z - 1) + v (t, x, y, z + 1))) * ti2 (x, y, + z)) * ti0 (x, y, + z) * ti1 (x, y, z); + auto temp204 = (((4.16666666666667e-3 * (v (t, x - 1, y - 2, z) - v (t, x - 1, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + v (t, x - 1, y + 1, z))) * ti3 (x - 1, y, + z) + + (7.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x - 2, y, z) - 4.16666666666667e-2 * v (t, x - 1, y, z) - 2.5e-2 * v (t, x + 1, y, + z) + 4.16666666666667e-3 * v (t, x + 2, y, z)) * ti1 (x - 1, y, + z)) * ti0 (x - 1, + y, + z) + + (4.16666666666667e-3 * (v (t, x - 1, y, z - 2) - v (t, x - 1, y, z + 2)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 1) + v (t, x - 1, y, z + 1))) * ti2 (x - 1, y, + z)) * ti0 (x - 1, + y, + z) * ti1 (x - 1, y, z); + auto temp288 = (((4.16666666666667e-3 * (v (t, x - 2, y, z + 1) - v (t, x + 2, y, z + 1)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z + 1) + v (t, x + 1, y, z + 1))) * ti1 (x, y, + z + 1) + + (-4.16666666666667e-2 * v (t, x, y, z + 1) - 1.25e-2 * v (t, x, y - 1, z + 1) + 7.5e-2 * v (t, x, y + 1, + z + 1) - 2.5e-2 * v (t, x, y + 2, z + 1) + 4.16666666666667e-3 * v (t, x, + y + 3, + z + + 1)) * ti3 (x, y, z + 1)) * ti0 (x, y, z + 1) + (-1.25e-2 * v (t, x, y, + z) - + 4.16666666666667e-2 * + v (t, + x, + y, + z + 1) + + 7.5e-2 * v (t, x, y, + z + 2) - + 2.5e-2 * v (t, x, y, + z + 3) + + 4.16666666666667e-3 * + v (t, + x, + y, + z + + + 4)) + * ti2 (x, y, z + 1)) * ti2 (x, y, z + 1); + auto temp10 = 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); + auto temp133 = (((4.16666666666667e-3 * (v (t, x, y - 2, z + 2) - v (t, x, y + 2, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z + 2) + v (t, x, y + 1, z + 2))) * ti3 (x, y, + z + 2) + + (-4.16666666666667e-2 * v (t, x, y, z + 2) - 1.25e-2 * v (t, x - 1, y, z + 2) + 7.5e-2 * v (t, x + 1, y, + z + 2) - 2.5e-2 * v (t, x + 2, y, z + 2) + 4.16666666666667e-3 * v (t, + x + 3, + y, + z + 2)) * ti1 (x, y, z + 2)) * ti0 (x, y, + z + 2) + + (4.16666666666667e-3 * (v (t, x, y, z) - v (t, x, y, z + 4)) + 3.33333333333333e-2 * (-v (t, x, y, z + 1) + v (t, x, y, z + 3))) * ti2 (x, y, + z + 2)) * ti2 (x, + y, + z + 2); + auto temp286 = (((4.16666666666667e-3 * (v (t, x - 2, y, z - 1) - v (t, x + 2, y, z - 1)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z - 1) + v (t, x + 1, y, z - 1))) * ti1 (x, y, + z - 1) + + (-4.16666666666667e-2 * v (t, x, y, z - 1) - 1.25e-2 * v (t, x, y - 1, z - 1) + 7.5e-2 * v (t, x, y + 1, + z - 1) - 2.5e-2 * v (t, x, y + 2, z - 1) + 4.16666666666667e-3 * v (t, x, + y + 3, + z - 1)) * ti3 (x, y, z - 1)) * ti0 (x, y, z - 1) + (7.5e-2 * v (t, x, y, + z) - + 1.25e-2 * v (t, x, y, + z - 2) - + 4.16666666666667e-2 * + v (t, + x, + y, + z + - + 1) + - 2.5e-2 * v (t, x, + y, + z + + 1) + + 4.16666666666667e-3 * + v (t, + x, + y, + z + + + 2)) + * ti2 (x, y, z - 1)) * ti2 (x, y, z - 1); + auto temp252 = (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x, y - 4, z)) + 3.33333333333333e-2 * (-v (t, x, y - 3, z) + v (t, x, y - 1, z))) * ti3 (x, y - 2, + z) + + (-4.16666666666667e-2 * v (t, x, y - 2, z) - 1.25e-2 * v (t, x - 1, y - 2, z) + 7.5e-2 * v (t, x + 1, y - 2, + z) - 2.5e-2 * v (t, + x + 2, + y - 2, + z) + 4.16666666666667e-3 * v (t, x + 3, y - 2, z)) * ti1 (x, y - 2, + z)) * ti0 (x, + y - 2, + z) + + (4.16666666666667e-3 * (v (t, x, y - 2, z - 2) - v (t, x, y - 2, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y - 2, z - 1) + v (t, x, y - 2, z + 1))) * ti2 (x, y - 2, + z)) * ti0 (x, + y - 2, + z) * ti3 (x, y - 2, z); + auto temp487 = temp420 * ti2 (x, y, z) * ti3 (x, y, + z) + 2.08333333333333e-2 * ((-temp318 * ti1 (x, y, z) + temp325 * ti3 (x, y, z)) * ti3 (x, y, + z) + ((temp318 * ti3 (x, y, z) + temp325 * ti1 (x, y, z)) * ti2 (x, y, + z) - + (4.16666666666667e-3 * (u (t, x, y, z - 2) - u (t, x, y, z + 2)) + + 3.33333333333333e-2 * (-u (t, x, y, z - 1) + u (t, x, y, z + 1))) * ti0 (x, y, + z)) * ti1 (x, + y, + z) * ti2 (x, y, + z)) + + 3.75e-2 * ((temp399 * ti3 (x, y - 1, z) - temp401 * ti1 (x, y - 1, - z) + - 7.5e-2 * u (t, x - 1, y + 1, z) - 2.5e-2 * u (t, x - 1, y + 2, - z) + - 4.16666666666667e-3 * u (t, x - 1, y + 3, z); - auto temp377 = - 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x, y - 2, z)) + - 4.16666666666667e-3 * (u (t, x, y - 3, z) - u (t, x, y + 1, z)); - auto temp343 = - 3.33333333333333e-2 * (-u (t, x, y, z) + u (t, x + 2, y, z)) + - 4.16666666666667e-3 * (u (t, x - 1, y, z) - u (t, x + 3, y, z)); - auto temp388 = - 4.16666666666667e-3 * (u (t, x - 2, y - 3, z) - u (t, x + 2, y - 3, - z)) + - 3.33333333333333e-2 * (-u (t, x - 1, - y - 3, - z) + u (t, - x + 1, - y - 3, - z)); - auto temp406 = - -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x, y + 1, - z) + - 7.5e-2 * u (t, x, y + 2, z) - 2.5e-2 * u (t, x, y + 3, - z) + - 4.16666666666667e-3 * u (t, x, y + 4, z); - auto temp404 = - 4.16666666666667e-3 * (u (t, x - 2, y + 1, z) - u (t, x + 2, y + 1, - z)) + - 3.33333333333333e-2 * (-u (t, x - 1, - y + 1, - z) + u (t, - x + 1, - y + 1, - z)); - auto temp342 = - -4.16666666666667e-2 * u (t, x, y + 1, z) - 1.25e-2 * u (t, x - 1, - y + 1, - z) + - 7.5e-2 * u (t, x + 1, y + 1, z) - 2.5e-2 * u (t, x + 2, y + 1, - z) + - 4.16666666666667e-3 * u (t, x + 3, y + 1, z); - auto temp410 = - -1.25e-2 * u (t, x, y, z) - 4.16666666666667e-2 * u (t, x + 1, y, - z) + - 7.5e-2 * u (t, x + 2, y, z) - 2.5e-2 * u (t, x + 3, y, - z) + - 4.16666666666667e-3 * u (t, x + 4, y, z); - auto temp367 = - 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x, y + 4, z)) + - 3.33333333333333e-2 * (-u (t, x, y + 1, z) + u (t, x, y + 3, z)); - auto temp399 = - 4.16666666666667e-3 * (u (t, x - 2, y - 1, z) - u (t, x + 2, y - 1, - z)) + - 3.33333333333333e-2 * (-u (t, x - 1, - y - 1, - z) + u (t, - x + 1, - y - 1, - z)); - auto temp325 = - -4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x - 1, y, - z) + - 7.5e-2 * u (t, x + 1, y, z) - 2.5e-2 * u (t, x + 2, y, - z) + - 4.16666666666667e-3 * u (t, x + 3, y, z); - auto temp386 = - 4.16666666666667e-3 * (u (t, x - 3, y - 2, z) - u (t, x - 3, y + 2, - z)) + - 3.33333333333333e-2 * (-u (t, x - 3, - y - 1, - z) + u (t, - x - 3, - y + 1, - z)); - auto temp396 = -2.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 3, - z) - - 4.16666666666667e-2 * u (t, x, y - 2, z) + 7.5e-2 * u (t, x, y - 1, - z) + - 4.16666666666667e-3 * u (t, x, y + 1, z); - auto temp401 = 7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y - 2, - z) - - 4.16666666666667e-2 * u (t, x, y - 1, z) - 2.5e-2 * u (t, x, y + 1, - z) + - 4.16666666666667e-3 * u (t, x, y + 2, z); - auto temp372 = - 4.16666666666667e-3 * (u (t, x, y, z) - u (t, x + 4, y, z)) + - 3.33333333333333e-2 * (-u (t, x + 1, y, z) + u (t, x + 3, y, z)); - auto temp420 = - 2.08333333333333e-2 * - ((temp330 * ti1 (x, y, z) + temp333 * ti3 (x, y, z)) * ti2 (x, y, - z) - - (-4.16666666666667e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y, z - 1) + - 7.5e-2 * u (t, x, y, - z + 1) - 2.5e-2 * u (t, - x, - y, - z + - 2) - + 4.16666666666667e-3 * u (t, x, y, z + 3)) * ti0 (x, y, z)); - auto temp387 = - 4.16666666666667e-3 * u (t, x, y, z) - 1.25e-2 * u (t, x - 4, y, - z) - - 4.16666666666667e-2 * u (t, x - 3, y, z) + 7.5e-2 * u (t, x - 2, y, - z) - - 2.5e-2 * u (t, x - 1, y, z); - auto temp383 = - 3.33333333333333e-2 * (u (t, x, y, z) - u (t, x - 2, y, z)) + - 4.16666666666667e-3 * (u (t, x - 3, y, z) - u (t, x + 1, y, z)); - auto temp392 = - 4.16666666666667e-3 * (u (t, x - 2, y - 2, z) - u (t, x - 2, y + 2, - z)) + - 3.33333333333333e-2 * (-u (t, x - 2, - y - 1, - z) + u (t, - x - 2, - y + 1, - z)); - auto temp284 = - (((4.16666666666667e-3 * - (v (t, x - 2, y, z - 2) - v (t, x + 2, y, z - 2)) + - 3.33333333333333e-2 * (-v (t, x - 1, y, z - 2) + - v (t, x + 1, y, z - 2))) * ti1 (x, y, - z - 2) + - (-4.16666666666667e-2 * v (t, x, y, z - 2) - - 1.25e-2 * v (t, x, y - 1, z - 2) + 7.5e-2 * v (t, x, y + 1, - z - 2) - - 2.5e-2 * v (t, x, y + 2, z - 2) + 4.16666666666667e-3 * v (t, x, - y + 3, - z - - 2)) * - ti3 (x, y, z - 2)) * ti0 (x, y, z - 2) + (-2.5e-2 * v (t, x, y, - z) - - 1.25e-2 * v (t, x, y, - z - 3) - - 4.16666666666667e-2 * v (t, - x, - y, - z - - - 2) - + 7.5e-2 * v (t, x, y, - z - 1) + - 4.16666666666667e-3 * v (t, - x, - y, - z - + - 1)) - * ti2 (x, y, z - 2)) * ti2 (x, y, z - 2); - auto temp308 = - (((4.16666666666667e-3 * - (v (t, x - 2, y - 2, z) - v (t, x + 2, y - 2, z)) + - 3.33333333333333e-2 * (-v (t, x - 1, y - 2, z) + - v (t, x + 1, y - 2, z))) * ti1 (x, y - 2, - z) + - (-2.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 3, z) - - 4.16666666666667e-2 * v (t, x, y - 2, z) + 7.5e-2 * v (t, x, y - 1, - z) + - 4.16666666666667e-3 * v (t, x, y + 1, z)) * ti3 (x, y - 2, - z)) * ti0 (x, - y - 2, - z) + - (-4.16666666666667e-2 * v (t, x, y - 2, z) - - 1.25e-2 * v (t, x, y - 2, z - 1) + 7.5e-2 * v (t, x, y - 2, - z + 1) - - 2.5e-2 * v (t, x, y - 2, z + 2) + 4.16666666666667e-3 * v (t, x, - y - 2, - z + - 3)) * - ti2 (x, y - 2, z)) * ti0 (x, y - 2, z) * ti3 (x, y - 2, z); - auto temp92 = - (((4.16666666666667e-3 * - (v (t, x, y - 2, z + 1) - v (t, x, y + 2, z + 1)) + - 3.33333333333333e-2 * (-v (t, x, y - 1, z + 1) + - v (t, x, y + 1, z + 1))) * ti3 (x, y, - z + 1) + - (-4.16666666666667e-2 * v (t, x, y, z + 1) - - 1.25e-2 * v (t, x - 1, y, z + 1) + 7.5e-2 * v (t, x + 1, y, - z + 1) - - 2.5e-2 * v (t, x + 2, y, z + 1) + 4.16666666666667e-3 * v (t, - x + 3, - y, - z + - 1)) * - ti1 (x, y, z + 1)) * ti0 (x, y, - z + 1) + - (3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x, y, z + 2)) + - 4.16666666666667e-3 * (v (t, x, y, z - 1) - - v (t, x, y, z + 3))) * ti2 (x, y, - z + 1)) * ti2 (x, - y, - z + - 1); - auto temp185 = - (((4.16666666666667e-3 * - (v (t, x - 2, y - 2, z) - v (t, x - 2, y + 2, z)) + - 3.33333333333333e-2 * (-v (t, x - 2, y - 1, z) + - v (t, x - 2, y + 1, z))) * ti3 (x - 2, y, - z) + - (-2.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x - 3, y, z) - - 4.16666666666667e-2 * v (t, x - 2, y, z) + 7.5e-2 * v (t, x - 1, y, - z) + - 4.16666666666667e-3 * v (t, x + 1, y, z)) * ti1 (x - 2, y, - z)) * ti0 (x - 2, - y, - z) + - (4.16666666666667e-3 * - (v (t, x - 2, y, z - 2) - v (t, x - 2, y, z + 2)) + - 3.33333333333333e-2 * (-v (t, x - 2, y, z - 1) + - v (t, x - 2, y, z + 1))) * ti2 (x - 2, y, - z)) * ti0 (x - - 2, - y, - z) - * ti1 (x - 2, y, z); - auto temp283 = - (((4.16666666666667e-3 * - (v (t, x - 2, y, z - 3) - v (t, x + 2, y, z - 3)) + - 3.33333333333333e-2 * (-v (t, x - 1, y, z - 3) + - v (t, x + 1, y, z - 3))) * ti1 (x, y, - z - 3) + - (-4.16666666666667e-2 * v (t, x, y, z - 3) - - 1.25e-2 * v (t, x, y - 1, z - 3) + 7.5e-2 * v (t, x, y + 1, - z - 3) - - 2.5e-2 * v (t, x, y + 2, z - 3) + 4.16666666666667e-3 * v (t, x, - y + 3, - z - - 3)) * - ti3 (x, y, z - 3)) * ti0 (x, y, z - 3) + (4.16666666666667e-3 * v (t, - x, - y, - z) - - 1.25e-2 * v (t, x, y, - z - 4) - - 4.16666666666667e-2 * v (t, - x, - y, - z - - 3) + - 7.5e-2 * v (t, x, y, - z - 2) - - 2.5e-2 * v (t, x, y, - z - 1)) * ti2 (x, - y, - z - - - 3)) - * ti2 (x, y, z - 3); - auto temp309 = - (((4.16666666666667e-3 * - (v (t, x - 2, y - 1, z) - v (t, x + 2, y - 1, z)) + - 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + - v (t, x + 1, y - 1, z))) * ti1 (x, y - 1, - z) + - (7.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 2, z) - - 4.16666666666667e-2 * v (t, x, y - 1, z) - 2.5e-2 * v (t, x, y + 1, - z) + - 4.16666666666667e-3 * v (t, x, y + 2, z)) * ti3 (x, y - 1, - z)) * ti0 (x, - y - 1, - z) + - (-4.16666666666667e-2 * v (t, x, y - 1, z) - - 1.25e-2 * v (t, x, y - 1, z - 1) + 7.5e-2 * v (t, x, y - 1, - z + 1) - - 2.5e-2 * v (t, x, y - 1, z + 2) + 4.16666666666667e-3 * v (t, x, - y - 1, - z + - 3)) * - ti2 (x, y - 1, z)) * ti0 (x, y - 1, z) * ti3 (x, y - 1, z); - auto temp310 = - (((4.16666666666667e-3 * - (v (t, x - 2, y + 1, z) - v (t, x + 2, y + 1, z)) + - 3.33333333333333e-2 * (-v (t, x - 1, y + 1, z) + - v (t, x + 1, y + 1, z))) * ti1 (x, y + 1, - z) + - (-1.25e-2 * v (t, x, y, z) - - 4.16666666666667e-2 * v (t, x, y + 1, z) + 7.5e-2 * v (t, x, y + 2, - z) - - 2.5e-2 * v (t, x, y + 3, z) + 4.16666666666667e-3 * v (t, x, y + 4, - z)) * ti3 (x, - y + - 1, - z)) - * ti0 (x, y + 1, - z) + (-4.16666666666667e-2 * v (t, x, - y + 1, - z) - 1.25e-2 * v (t, x, y + 1, - z - 1) + - 7.5e-2 * v (t, - x, - y + 1, - z + 1) - 2.5e-2 * v (t, x, y + 1, - z + 2) + - 4.16666666666667e-3 * v (t, x, y + 1, - z + 3)) * ti2 (x, y + 1, - z)) * ti0 (x, - y + 1, - z) * - ti3 (x, y + 1, z); - auto temp307 = - (((4.16666666666667e-3 * - (v (t, x - 2, y - 3, z) - v (t, x + 2, y - 3, z)) + - 3.33333333333333e-2 * (-v (t, x - 1, y - 3, z) + - v (t, x + 1, y - 3, z))) * ti1 (x, y - 3, - z) + - (4.16666666666667e-3 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 4, z) - - 4.16666666666667e-2 * v (t, x, - y - 3, - z) + - 7.5e-2 * v (t, x, y - 2, z) - 2.5e-2 * v (t, x, y - 1, - z)) * ti3 (x, y - 3, - z)) * ti0 (x, - y - - 3, - z) + - (-4.16666666666667e-2 * v (t, x, y - 3, z) - - 1.25e-2 * v (t, x, y - 3, z - 1) + 7.5e-2 * v (t, x, y - 3, - z + 1) - - 2.5e-2 * v (t, x, y - 3, z + 2) + 4.16666666666667e-3 * v (t, x, - y - 3, - z + - 3)) * - ti2 (x, y - 3, z)) * ti0 (x, y - 3, z) * ti3 (x, y - 3, z); - auto temp298 = - (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x + 4, y, z)) + - 3.33333333333333e-2 * (-v (t, x + 1, y, z) + - v (t, x + 3, y, z))) * ti1 (x + 2, y, - z) + - (-4.16666666666667e-2 * v (t, x + 2, y, z) - - 1.25e-2 * v (t, x + 2, y - 1, z) + 7.5e-2 * v (t, x + 2, y + 1, - z) - 2.5e-2 * v (t, - x + - 2, - y + - 2, - z) + - 4.16666666666667e-3 * v (t, x + 2, y + 3, z)) * ti3 (x + 2, y, - z)) * ti0 (x + 2, - y, - z) + - (-4.16666666666667e-2 * v (t, x + 2, y, - z) - 1.25e-2 * v (t, x + 2, y, - z - 1) + - 7.5e-2 * v (t, x + 2, y, z + 1) - 2.5e-2 * v (t, x + 2, y, - z + 2) + - 4.16666666666667e-3 * v (t, x + 2, y, z + 3)) * ti2 (x + 2, - y, - z)) * ti0 (x + 2, - y, - z) * - ti1 (x + 2, y, z); - auto temp165 = - (((4.16666666666667e-3 * - (v (t, x - 3, y - 2, z) - v (t, x - 3, y + 2, z)) + - 3.33333333333333e-2 * (-v (t, x - 3, y - 1, z) + - v (t, x - 3, y + 1, z))) * ti3 (x - 3, y, - z) + - (4.16666666666667e-3 * v (t, x, y, z) - 1.25e-2 * v (t, x - 4, y, z) - - 4.16666666666667e-2 * v (t, x - 3, - y, - z) + - 7.5e-2 * v (t, x - 2, y, z) - 2.5e-2 * v (t, x - 1, y, - z)) * ti1 (x - 3, y, - z)) * ti0 (x - - 3, - y, - z) - + - (4.16666666666667e-3 * - (v (t, x - 3, y, z - 2) - v (t, x - 3, y, z + 2)) + - 3.33333333333333e-2 * (-v (t, x - 3, y, z - 1) + - v (t, x - 3, y, z + 1))) * ti2 (x - 3, y, - z)) * ti0 (x - - 3, - y, - z) - * ti1 (x - 3, y, z); - auto temp154 = - (((4.16666666666667e-3 * - (v (t, x, y - 2, z - 1) - v (t, x, y + 2, z - 1)) + - 3.33333333333333e-2 * (-v (t, x, y - 1, z - 1) + - v (t, x, y + 1, z - 1))) * ti3 (x, y, - z - 1) + - (-4.16666666666667e-2 * v (t, x, y, z - 1) - - 1.25e-2 * v (t, x - 1, y, z - 1) + 7.5e-2 * v (t, x + 1, y, - z - 1) - - 2.5e-2 * v (t, x + 2, y, z - 1) + 4.16666666666667e-3 * v (t, - x + 3, - y, - z - - 1)) * - ti1 (x, y, z - 1)) * ti0 (x, y, - z - 1) + - (3.33333333333333e-2 * (v (t, x, y, z) - v (t, x, y, z - 2)) + - 4.16666666666667e-3 * (v (t, x, y, z - 3) - - v (t, x, y, z + 1))) * ti2 (x, y, - z - 1)) * ti2 (x, - y, - z - - 1); - auto temp299 = - (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x - 2, y, z)) + - 4.16666666666667e-3 * (v (t, x - 3, y, z) - - v (t, x + 1, y, z))) * ti1 (x - 1, y, - z) + - (-4.16666666666667e-2 * v (t, x - 1, y, z) - - 1.25e-2 * v (t, x - 1, y - 1, z) + 7.5e-2 * v (t, x - 1, y + 1, - z) - 2.5e-2 * v (t, - x - - 1, - y + - 2, - z) + - 4.16666666666667e-3 * v (t, x - 1, y + 3, z)) * ti3 (x - 1, y, - z)) * ti0 (x - 1, - y, - z) + - (-4.16666666666667e-2 * v (t, x - 1, y, - z) - 1.25e-2 * v (t, x - 1, y, - z - 1) + - 7.5e-2 * v (t, x - 1, y, z + 1) - 2.5e-2 * v (t, x - 1, y, - z + 2) + - 4.16666666666667e-3 * v (t, x - 1, y, z + 3)) * ti2 (x - 1, - y, - z)) * ti0 (x - 1, - y, - z) * - ti1 (x - 1, y, z); - auto temp289 = - (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x + 2, y, z)) + - 4.16666666666667e-3 * (v (t, x - 1, y, z) - - v (t, x + 3, y, z))) * ti1 (x + 1, y, - z) + - (-4.16666666666667e-2 * v (t, x + 1, y, z) - - 1.25e-2 * v (t, x + 1, y - 1, z) + 7.5e-2 * v (t, x + 1, y + 1, - z) - 2.5e-2 * v (t, - x + - 1, - y + - 2, - z) + - 4.16666666666667e-3 * v (t, x + 1, y + 3, z)) * ti3 (x + 1, y, - z)) * ti0 (x + 1, - y, - z) + - (-4.16666666666667e-2 * v (t, x + 1, y, - z) - 1.25e-2 * v (t, x + 1, y, - z - 1) + - 7.5e-2 * v (t, x + 1, y, z + 1) - 2.5e-2 * v (t, x + 1, y, - z + 2) + - 4.16666666666667e-3 * v (t, x + 1, y, z + 3)) * ti2 (x + 1, - y, - z)) * ti0 (x + 1, - y, - z) * - ti1 (x + 1, y, z); - auto temp116 = - (((4.16666666666667e-3 * - (v (t, x, y - 2, z - 2) - v (t, x, y + 2, z - 2)) + - 3.33333333333333e-2 * (-v (t, x, y - 1, z - 2) + - v (t, x, y + 1, z - 2))) * ti3 (x, y, - z - 2) + - (-4.16666666666667e-2 * v (t, x, y, z - 2) - - 1.25e-2 * v (t, x - 1, y, z - 2) + 7.5e-2 * v (t, x + 1, y, - z - 2) - - 2.5e-2 * v (t, x + 2, y, z - 2) + 4.16666666666667e-3 * v (t, - x + 3, - y, - z - - 2)) * - ti1 (x, y, z - 2)) * ti0 (x, y, - z - 2) + - (4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x, y, z - 4)) + - 3.33333333333333e-2 * (-v (t, x, y, z - 3) + - v (t, x, y, z - 1))) * ti2 (x, y, - z - 2)) * ti2 (x, - y, - z - - 2); - auto temp56 = - (((4.16666666666667e-3 * (v (t, x, y - 2, z) - v (t, x, y + 2, z)) + - 3.33333333333333e-2 * (-v (t, x, y - 1, z) + - v (t, x, y + 1, z))) * ti3 (x, y, - z) + - (-4.16666666666667e-2 * v (t, x, y, z) - - 1.25e-2 * v (t, x - 1, y, z) + 7.5e-2 * v (t, x + 1, y, - z) - 2.5e-2 * v (t, - x + 2, - y, - z) + - 4.16666666666667e-3 * v (t, x + 3, y, z)) * ti1 (x, y, z)) * ti0 (x, - y, - z) - + (4.16666666666667e-3 * (v (t, x, y, z - 2) - v (t, x, y, z + 2)) + - 3.33333333333333e-2 * (-v (t, x, y, z - 1) + - v (t, x, y, z + 1))) * ti2 (x, y, - z)) * ti0 (x, y, - z) * - ti1 (x, y, z); - auto temp204 = - (((4.16666666666667e-3 * - (v (t, x - 1, y - 2, z) - v (t, x - 1, y + 2, z)) + - 3.33333333333333e-2 * (-v (t, x - 1, y - 1, z) + - v (t, x - 1, y + 1, z))) * ti3 (x - 1, y, - z) + - (7.5e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x - 2, y, z) - - 4.16666666666667e-2 * v (t, x - 1, y, z) - 2.5e-2 * v (t, x + 1, y, - z) + - 4.16666666666667e-3 * v (t, x + 2, y, z)) * ti1 (x - 1, y, - z)) * ti0 (x - 1, - y, - z) + - (4.16666666666667e-3 * - (v (t, x - 1, y, z - 2) - v (t, x - 1, y, z + 2)) + - 3.33333333333333e-2 * (-v (t, x - 1, y, z - 1) + - v (t, x - 1, y, z + 1))) * ti2 (x - 1, y, - z)) * ti0 (x - - 1, - y, - z) - * ti1 (x - 1, y, z); - auto temp288 = - (((4.16666666666667e-3 * - (v (t, x - 2, y, z + 1) - v (t, x + 2, y, z + 1)) + - 3.33333333333333e-2 * (-v (t, x - 1, y, z + 1) + - v (t, x + 1, y, z + 1))) * ti1 (x, y, - z + 1) + - (-4.16666666666667e-2 * v (t, x, y, z + 1) - - 1.25e-2 * v (t, x, y - 1, z + 1) + 7.5e-2 * v (t, x, y + 1, - z + 1) - - 2.5e-2 * v (t, x, y + 2, z + 1) + 4.16666666666667e-3 * v (t, x, - y + 3, - z + - 1)) * - ti3 (x, y, z + 1)) * ti0 (x, y, z + 1) + (-1.25e-2 * v (t, x, y, - z) - - 4.16666666666667e-2 * v (t, - x, - y, - z - + - 1) - + 7.5e-2 * v (t, x, y, - z + 2) - - 2.5e-2 * v (t, x, y, - z + 3) + - 4.16666666666667e-3 * v (t, - x, - y, - z - + - 4)) - * ti2 (x, y, z + 1)) * ti2 (x, y, z + 1); - auto temp10 = - 8.85879567828298e-1 * damp (x, y, z) - 2.0 * m (x, y, z); - auto temp133 = - (((4.16666666666667e-3 * - (v (t, x, y - 2, z + 2) - v (t, x, y + 2, z + 2)) + - 3.33333333333333e-2 * (-v (t, x, y - 1, z + 2) + - v (t, x, y + 1, z + 2))) * ti3 (x, y, - z + 2) + - (-4.16666666666667e-2 * v (t, x, y, z + 2) - - 1.25e-2 * v (t, x - 1, y, z + 2) + 7.5e-2 * v (t, x + 1, y, - z + 2) - - 2.5e-2 * v (t, x + 2, y, z + 2) + 4.16666666666667e-3 * v (t, - x + 3, - y, - z + - 2)) * - ti1 (x, y, z + 2)) * ti0 (x, y, - z + 2) + - (4.16666666666667e-3 * (v (t, x, y, z) - v (t, x, y, z + 4)) + - 3.33333333333333e-2 * (-v (t, x, y, z + 1) + - v (t, x, y, z + 3))) * ti2 (x, y, - z + 2)) * ti2 (x, - y, - z + - 2); - auto temp286 = - (((4.16666666666667e-3 * - (v (t, x - 2, y, z - 1) - v (t, x + 2, y, z - 1)) + - 3.33333333333333e-2 * (-v (t, x - 1, y, z - 1) + - v (t, x + 1, y, z - 1))) * ti1 (x, y, - z - 1) + - (-4.16666666666667e-2 * v (t, x, y, z - 1) - - 1.25e-2 * v (t, x, y - 1, z - 1) + 7.5e-2 * v (t, x, y + 1, - z - 1) - - 2.5e-2 * v (t, x, y + 2, z - 1) + 4.16666666666667e-3 * v (t, x, - y + 3, - z - - 1)) * - ti3 (x, y, z - 1)) * ti0 (x, y, z - 1) + (7.5e-2 * v (t, x, y, - z) - - 1.25e-2 * v (t, x, y, - z - 2) - - 4.16666666666667e-2 * v (t, - x, - y, - z - - - 1) - - 2.5e-2 * v (t, x, y, - z + 1) + - 4.16666666666667e-3 * v (t, - x, - y, - z - + - 2)) - * ti2 (x, y, z - 1)) * ti2 (x, y, z - 1); - auto temp252 = - (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x, y - 4, z)) + - 3.33333333333333e-2 * (-v (t, x, y - 3, z) + - v (t, x, y - 1, z))) * ti3 (x, y - 2, - z) + - (-4.16666666666667e-2 * v (t, x, y - 2, z) - - 1.25e-2 * v (t, x - 1, y - 2, z) + 7.5e-2 * v (t, x + 1, y - 2, - z) - 2.5e-2 * v (t, - x + - 2, - y - - 2, - z) + - 4.16666666666667e-3 * v (t, x + 3, y - 2, z)) * ti1 (x, y - 2, - z)) * ti0 (x, - y - 2, - z) - + - (4.16666666666667e-3 * - (v (t, x, y - 2, z - 2) - v (t, x, y - 2, z + 2)) + - 3.33333333333333e-2 * (-v (t, x, y - 2, z - 1) + - v (t, x, y - 2, z + 1))) * ti2 (x, y - 2, - z)) * ti0 (x, - y - - 2, - z) * - ti3 (x, y - 2, z); - auto temp487 = temp420 * ti2 (x, y, z) * ti3 (x, y, - z) + - 2.08333333333333e-2 * - ((-temp318 * ti1 (x, y, z) + temp325 * ti3 (x, y, z)) * ti3 (x, y, - z) + - ((temp318 * ti3 (x, y, z) + temp325 * ti1 (x, y, z)) * ti2 (x, y, - z) - - (4.16666666666667e-3 * (u (t, x, y, z - 2) - u (t, x, y, z + 2)) + - 3.33333333333333e-2 * (-u (t, x, y, z - 1) + - u (t, x, y, z + 1))) * ti0 (x, y, - z)) * ti1 (x, - y, - z) - * ti2 (x, y, - z)) + 3.75e-2 * ((temp399 * ti3 (x, y - 1, z) - temp401 * ti1 (x, - y - - - 1, - z)) - * ti1 (x, y - 1, - z) + - (((4.16666666666667e-3 * - (u (t, x - 2, y, z - 1) - u (t, x + 2, y, - z - 1)) + - 3.33333333333333e-2 * (-u (t, - x - 1, - y, - z - 1) + u (t, - x + - 1, - y, - z - - 1))) - * ti1 (x, y, - z - 1) + (-4.16666666666667e-2 * u (t, - x, - y, - z - - - 1) - - 1.25e-2 * u (t, x, y - 1, - z - 1) + - 7.5e-2 * u (t, x, y + 1, - z - 1) - - 2.5e-2 * u (t, x, y + 2, - z - 1) + - 4.16666666666667e-3 * u (t, - x, - y + - 3, - z - - 1)) - * ti3 (x, y, z - 1)) * ti2 (x, y, - z - 1) - - (7.5e-2 * u (t, x, y, z) - - 1.25e-2 * u (t, x, y, - z - 2) - - 4.16666666666667e-2 * u (t, x, y, - z - 1) - - 2.5e-2 * u (t, x, y, - z + 1) + - 4.16666666666667e-3 * u (t, x, y, - z + 2)) * ti0 (x, y, - z - - 1)) * - ti0 (x, y, - z - 1)) + 1.25e-2 * ((-temp392 * ti1 (x - - 2, - y, - z) + - temp394 * ti3 (x - - 2, y, - z)) * - ti3 (x - 2, y, - z) + - ((temp392 * - ti3 (x - 2, y, - z) + - temp394 * ti1 (x - - 2, - y, - z)) - * ti2 (x - 2, y, - z) - - (4.16666666666667e-3 - * (u (t, x - 2, y, - z - 2) - - u (t, - x - 2, y, - z + - 2)) + - 3.33333333333333e-2 - * (-u (t, x - 2, y, - z - 1) + - u (t, - x - 2, y, - z + - 1))) - * ti0 (x - 2, y, - z)) * - ti1 (x - 2, y, - z) * ti2 (x - 2, - y, - z) + - ((temp395 * - ti1 (x, y - 2, - z) + - temp396 * ti3 (x, - y - - 2, - z)) - * ti2 (x, y - 2, - z) - - (-4.16666666666667e-2 - * u (t, x, y - 2, - z) - - 1.25e-2 * u (t, x, - y - - 2, - z - - 1) + - 7.5e-2 * u (t, x, - y - 2, - z + - 1) - - 2.5e-2 * u (t, x, - y - 2, - z + - 2) + - 4.16666666666667e-3 - * u (t, x, y - 2, - z + - 3)) * ti0 (x, - y - - 2, - z)) - * ti2 (x, y - 2, - z) * ti3 (x, - y - - 2, - z)) - + - 6.25e-3 * ((-temp409 * ti1 (x + 1, y, z) + temp410 * ti3 (x + 1, y, z)) * - ti3 (x + 1, - y, - z) - + - ((temp404 * ti1 (x, y + 1, z) + - temp406 * ti3 (x, y + 1, z)) * ti2 (x, - y + 1, - z) - - (-4.16666666666667e-2 * u (t, x, y + 1, z) - - 1.25e-2 * u (t, x, y + 1, z - 1) + 7.5e-2 * u (t, x, - y + 1, - z + 1) - - 2.5e-2 * u (t, x, y + 1, - z + 2) + 4.16666666666667e-3 * u (t, x, - y + 1, - z + - 3)) * - ti0 (x, y + 1, z)) * ti2 (x, y + 1, z) * ti3 (x, y + 1, - z) + - ((temp409 * ti3 (x + 1, y, z) + - temp410 * ti1 (x + 1, y, z)) * ti2 (x + 1, - y, - z) - - - (4.16666666666667e-3 * - (u (t, x + 1, y, z - 2) - u (t, x + 1, y, z + 2)) + - 3.33333333333333e-2 * (-u (t, x + 1, y, z - 1) + - u (t, x + 1, y, - z + 1))) * ti0 (x + 1, y, - z)) * ti1 (x + 1, - y, - z) * - ti2 (x + 1, y, - z)) + - 1.66666666666667e-2 * - ((temp343 * ti3 (x + 1, y, z) - temp347 * ti1 (x + 1, y, z)) * ti3 (x + 1, - y, - z) + - (-temp377 * ti1 (x, y - 1, z) + temp381 * ti3 (x, y - 1, z)) * ti1 (x, - y - - 1, - z) + - ((temp336 * ti3 (x, y + 1, z) + temp342 * ti1 (x, y + 1, z)) * ti2 (x, - y + - 1, - z) - - (4.16666666666667e-3 * - (u (t, x, y + 1, z - 2) - u (t, x, y + 1, z + 2)) + - 3.33333333333333e-2 * (-u (t, x, y + 1, z - 1) + - u (t, x, y + 1, z + 1))) * ti0 (x, y + 1, - z)) * ti2 (x, - y + - 1, - z) * - ti3 (x, y + 1, - z) + - ((temp343 * ti1 (x + 1, y, z) + temp347 * ti3 (x + 1, y, z)) * ti2 (x + - 1, y, - z) - - (-4.16666666666667e-2 * u (t, x + 1, y, z) - - 1.25e-2 * u (t, x + 1, y, z - 1) + 7.5e-2 * u (t, - x + 1, - y, - z + 1) - - 2.5e-2 * u (t, x + 1, y, - z + 2) + 4.16666666666667e-3 * u (t, x + 1, - y, - z + - 3)) * - ti0 (x + 1, y, z)) * ti1 (x + 1, y, z) * ti2 (x + 1, y, - z) + - (((4.16666666666667e-3 * - (u (t, x, y - 2, z - 1) - u (t, x, y + 2, z - 1)) + - 3.33333333333333e-2 * (-u (t, x, y - 1, z - 1) + - u (t, x, y + 1, z - 1))) * ti3 (x, y, - z - 1) + - (-4.16666666666667e-2 * u (t, x, y, z - 1) - - 1.25e-2 * u (t, x - 1, y, z - 1) + 7.5e-2 * u (t, x + 1, y, - z - 1) - - 2.5e-2 * u (t, x + 2, y, z - 1) + 4.16666666666667e-3 * u (t, - x + 3, - y, - z - - 1)) - * ti1 (x, y, z - 1)) * ti2 (x, y, - z - 1) - - (3.33333333333333e-2 * (u (t, x, y, z) - u (t, x, y, - z - 2)) + - 4.16666666666667e-3 * (u (t, x, y, z - 3) - u (t, x, y, - z + 1))) * ti0 (x, y, - z - - 1)) * - ti0 (x, - y, - z - - - 1)) - + - 2.08333333333333e-3 * - ((temp360 * ti3 (x - 2, y, z) - temp365 * ti1 (x - 2, y, z)) * ti3 (x - 2, - y, - z) + - (-temp367 * ti1 (x, y + 2, z) + temp370 * ti3 (x, y + 2, z)) * ti1 (x, - y + - 2, - z) + - (temp388 * ti3 (x, y - 3, z) - temp390 * ti1 (x, y - 3, z)) * ti1 (x, - y - 3, - z) - + ((temp352 * ti3 (x, y - 2, z) + temp357 * ti1 (x, y - 2, z)) * ti2 (x, - y - - 2, - z) - - - (4.16666666666667e-3 * - (u (t, x, y - 2, z - 2) - u (t, x, y - 2, z + 2)) + - 3.33333333333333e-2 * (-u (t, x, y - 2, z - 1) + - u (t, x, y - 2, z + 1))) * ti0 (x, y - 2, - z)) * ti2 (x, - y - - - 2, - z) - * ti3 (x, y - 2, - z) + - ((temp360 * ti1 (x - 2, y, z) + temp365 * ti3 (x - 2, y, z)) * ti2 (x - - 2, y, - z) - - (-4.16666666666667e-2 * u (t, x - 2, y, z) - - 1.25e-2 * u (t, x - 2, y, z - 1) + 7.5e-2 * u (t, - x - 2, - y, - z + 1) - - 2.5e-2 * u (t, x - 2, y, - z + 2) + 4.16666666666667e-3 * u (t, x - 2, - y, - z + - 3)) * - ti0 (x - 2, y, z)) * ti1 (x - 2, y, z) * ti2 (x - 2, y, - z) + - (((4.16666666666667e-3 * - (u (t, x, y - 2, z + 2) - u (t, x, y + 2, z + 2)) + - 3.33333333333333e-2 * (-u (t, x, y - 1, z + 2) + - u (t, x, y + 1, z + 2))) * ti3 (x, y, - z + 2) + - (-4.16666666666667e-2 * u (t, x, y, z + 2) - - 1.25e-2 * u (t, x - 1, y, z + 2) + 7.5e-2 * u (t, x + 1, y, - z + 2) - - 2.5e-2 * u (t, x + 2, y, z + 2) + 4.16666666666667e-3 * u (t, - x + 3, - y, - z + - 2)) * - ti1 (x, y, z + 2)) * ti2 (x, y, - z + 2) - - (4.16666666666667e-3 * (u (t, x, y, z) - u (t, x, y, z + 4)) + - 3.33333333333333e-2 * (-u (t, x, y, z + 1) + - u (t, x, y, z + 3))) * ti0 (x, y, - z + 2)) * ti0 (x, - y, - z - + - 2) - + - (((4.16666666666667e-3 * - (u (t, x - 2, y, z - 3) - u (t, x + 2, y, z - 3)) + - 3.33333333333333e-2 * (-u (t, x - 1, y, z - 3) + - u (t, x + 1, y, z - 3))) * ti1 (x, y, - z - 3) + - (-4.16666666666667e-2 * u (t, x, y, z - 3) - - 1.25e-2 * u (t, x, y - 1, z - 3) + 7.5e-2 * u (t, x, y + 1, - z - 3) - - 2.5e-2 * u (t, x, y + 2, z - 3) + 4.16666666666667e-3 * u (t, x, - y + 3, - z - - 3)) * - ti3 (x, y, z - 3)) * ti2 (x, y, - z - 3) - (4.16666666666667e-3 * u (t, x, - y, - z) - - 1.25e-2 * u (t, x, y, - z - 4) - - 4.16666666666667e-2 * u (t, x, - y, - z - - 3) + - 7.5e-2 * u (t, x, y, - z - 2) - - 2.5e-2 * u (t, x, y, - z - 1)) * ti0 (x, - y, - z - - 3)) - * ti0 (x, y, z - 3)) - (temp420 * ti0 (x, y, - z) + - 2.08333333333333e-2 * (temp330 * ti3 (x, y, z) - - temp333 * ti1 (x, y, - z)) * - ti1 (x, y, - z) + - 1.66666666666667e-2 * (-temp336 * ti1 (x, y + 1, - z) + - temp342 * ti3 (x, y + 1, - z)) * - ti1 (x, y + 1, - z) + - 2.08333333333333e-3 * (-temp352 * ti1 (x, y - 2, - z) + - temp357 * ti3 (x, y - 2, - z)) * - ti1 (x, y - 2, - z) + - 2.08333333333333e-3 * (temp372 * ti3 (x + 2, y, - z) - - temp375 * ti1 (x + 2, y, - z)) * - ti3 (x + 2, y, - z) + - 1.66666666666667e-2 * (temp383 * ti3 (x - 1, y, - z) - - temp385 * ti1 (x - 1, y, - z)) * - ti3 (x - 1, y, - z) + - 2.08333333333333e-3 * (-temp386 * ti1 (x - 3, y, - z) + - temp387 * ti3 (x - 3, y, - z)) * - ti3 (x - 3, y, - z) + 1.25e-2 * (temp395 * ti3 (x, y - 2, - z) - - temp396 * ti1 (x, y - 2, - z)) * - ti1 (x, y - 2, - z) + 6.25e-3 * (temp404 * ti3 (x, y + 1, - z) - - temp406 * ti1 (x, y + 1, - z)) * - ti1 (x, y + 1, - z) + 3.75e-2 * (-temp407 * ti1 (x - 1, y, - z) + - temp408 * ti3 (x - 1, y, - z)) * - ti3 (x - 1, y, - z) + - 2.08333333333333e-3 * - ((temp367 * ti3 (x, y + 2, z) + - temp370 * ti1 (x, y + 2, z)) * ti2 (x, y + 2, - z) - - (4.16666666666667e-3 * - (u (t, x, y + 2, z - 2) - u (t, x, y + 2, - z + 2)) + - 3.33333333333333e-2 * (-u (t, x, - y + 2, - z - 1) + u (t, x, - y + 2, - z + - 1))) * - ti0 (x, y + 2, z)) * ti2 (x, y + 2, z) * ti3 (x, - y - + - 2, - z) - + - 2.08333333333333e-3 * - ((temp372 * ti1 (x + 2, y, z) + - temp375 * ti3 (x + 2, y, z)) * ti2 (x + 2, y, - z) - - (-4.16666666666667e-2 * u (t, x + 2, y, z) - - 1.25e-2 * u (t, x + 2, y, - z - 1) + 7.5e-2 * u (t, x + 2, - y, - z + 1) - - 2.5e-2 * u (t, x + 2, y, - z + 2) + - 4.16666666666667e-3 * u (t, x + 2, y, - z + 3)) * ti0 (x + 2, - y, - z)) - * ti1 (x + 2, y, z) * ti2 (x + 2, y, - z) + - 1.66666666666667e-2 * - ((temp377 * ti3 (x, y - 1, z) + - temp381 * ti1 (x, y - 1, z)) * ti2 (x, y - 1, - z) - - (4.16666666666667e-3 * - (u (t, x, y - 1, z - 2) - u (t, x, y - 1, - z + 2)) + - 3.33333333333333e-2 * (-u (t, x, - y - 1, - z - 1) + u (t, x, - y - 1, - z + - 1))) * - ti0 (x, y - 1, z)) * ti2 (x, y - 1, z) * ti3 (x, - y - - - 1, - z) - + - 1.66666666666667e-2 * - ((temp383 * ti1 (x - 1, y, z) + - temp385 * ti3 (x - 1, y, z)) * ti2 (x - 1, y, - z) - - (-4.16666666666667e-2 * u (t, x - 1, y, z) - - 1.25e-2 * u (t, x - 1, y, - z - 1) + 7.5e-2 * u (t, x - 1, - y, - z + 1) - - 2.5e-2 * u (t, x - 1, y, - z + 2) + - 4.16666666666667e-3 * u (t, x - 1, y, - z + 3)) * ti0 (x - 1, - y, - z)) - * ti1 (x - 1, y, z) * ti2 (x - 1, y, - z) + - 2.08333333333333e-3 * - ((temp386 * ti3 (x - 3, y, z) + - temp387 * ti1 (x - 3, y, z)) * ti2 (x - 3, y, - z) - - (4.16666666666667e-3 * - (u (t, x - 3, y, z - 2) - u (t, x - 3, y, - z + 2)) + - 3.33333333333333e-2 * (-u (t, - x - 3, y, - z - 1) + u (t, - x - 3, - y, - z + - 1))) * - ti0 (x - 3, y, z)) * ti1 (x - 3, y, - z) * ti2 (x - 3, y, - z) + - 2.08333333333333e-3 * - ((temp388 * ti1 (x, y - 3, z) + - temp390 * ti3 (x, y - 3, z)) * ti2 (x, y - 3, - z) - - (-4.16666666666667e-2 * u (t, x, y - 3, z) - - 1.25e-2 * u (t, x, y - 3, - z - 1) + 7.5e-2 * u (t, x, - y - 3, - z + 1) - - 2.5e-2 * u (t, x, y - 3, - z + 2) + - 4.16666666666667e-3 * u (t, x, y - 3, - z + 3)) * ti0 (x, - y - 3, - z)) - * ti2 (x, y - 3, z) * ti3 (x, y - 3, - z) + - 3.75e-2 * - ((temp399 * ti1 (x, y - 1, z) + - temp401 * ti3 (x, y - 1, z)) * ti2 (x, y - 1, - z) - - (-4.16666666666667e-2 * u (t, x, y - 1, z) - - 1.25e-2 * u (t, x, y - 1, - z - 1) + 7.5e-2 * u (t, x, - y - 1, - z + 1) - - 2.5e-2 * u (t, x, y - 1, - z + 2) + - 4.16666666666667e-3 * u (t, x, y - 1, - z + 3)) * ti0 (x, - y - 1, - z)) - * ti2 (x, y - 1, z) * ti3 (x, y - 1, - z) + - 3.75e-2 * - ((temp407 * ti3 (x - 1, y, z) + - temp408 * ti1 (x - 1, y, z)) * ti2 (x - 1, y, - z) - - (4.16666666666667e-3 * - (u (t, x - 1, y, z - 2) - u (t, x - 1, y, - z + 2)) + - 3.33333333333333e-2 * (-u (t, - x - 1, y, - z - 1) + u (t, - x - 1, - y, - z + - 1))) * - ti0 (x - 1, y, z)) * ti1 (x - 1, y, - z) * ti2 (x - 1, y, - z) + - 2.08333333333333e-3 * - (((4.16666666666667e-3 * - (u (t, x, y - 2, z - 2) - u (t, x, y + 2, - z - 2)) + - 3.33333333333333e-2 * (-u (t, - x, - y - 1, - z - 2) + u (t, x, - y + 1, - z - - 2))) * - ti3 (x, y, - z - 2) + (-4.16666666666667e-2 * u (t, - x, - y, - z - - 2) - - 1.25e-2 * u (t, x - 1, y, - z - 2) + - 7.5e-2 * u (t, x + 1, y, - z - 2) - - 2.5e-2 * u (t, x + 2, y, - z - 2) + - 4.16666666666667e-3 * u (t, - x + 3, - y, - z - - 2)) - * ti1 (x, y, z - 2)) * ti2 (x, y, - z - 2) - - (4.16666666666667e-3 * - (-u (t, x, y, z) + u (t, x, y, z - 4)) + - 3.33333333333333e-2 * (-u (t, x, y, z - 3) + - u (t, x, y, - z - 1))) * ti0 (x, - y, - z - - 2)) - * ti0 (x, y, - z - 2) + - 1.66666666666667e-2 * - (((4.16666666666667e-3 * - (u (t, x, y - 2, z + 1) - u (t, x, y + 2, - z + 1)) + - 3.33333333333333e-2 * (-u (t, - x, - y - 1, - z + 1) + u (t, x, - y + 1, - z + - 1))) * - ti3 (x, y, - z + 1) + (-4.16666666666667e-2 * u (t, - x, - y, - z + - 1) - - 1.25e-2 * u (t, x - 1, y, - z + 1) + - 7.5e-2 * u (t, x + 1, y, - z + 1) - - 2.5e-2 * u (t, x + 2, y, - z + 1) + - 4.16666666666667e-3 * u (t, - x + 3, - y, - z + - 1)) - * ti1 (x, y, z + 1)) * ti2 (x, y, - z + 1) - - (3.33333333333333e-2 * - (-u (t, x, y, z) + u (t, x, y, z + 2)) + - 4.16666666666667e-3 * (u (t, x, y, z - 1) - - u (t, x, y, - z + 3))) * ti0 (x, - y, - z - + - 1)) - * ti0 (x, y, - z + 1) + - 1.25e-2 * - (((4.16666666666667e-3 * - (u (t, x - 2, y, z - 2) - u (t, x + 2, y, - z - 2)) + - 3.33333333333333e-2 * (-u (t, - x - 1, - y, - z - 2) + u (t, - x + 1, - y, - z - - 2))) * - ti1 (x, y, - z - 2) + (-4.16666666666667e-2 * u (t, - x, - y, - z - - 2) - - 1.25e-2 * u (t, x, y - 1, - z - 2) + - 7.5e-2 * u (t, x, y + 1, - z - 2) - - 2.5e-2 * u (t, x, y + 2, - z - 2) + - 4.16666666666667e-3 * u (t, - x, - y + 3, - z - - 2)) - * ti3 (x, y, z - 2)) * ti2 (x, y, - z - 2) - - (-2.5e-2 * u (t, x, y, z) - - 1.25e-2 * u (t, x, y, - z - 3) - - 4.16666666666667e-2 * u (t, x, y, - z - 2) + - 7.5e-2 * u (t, x, y, - z - 1) + - 4.16666666666667e-3 * u (t, x, y, - z + 1)) * ti0 (x, y, - z - - 2)) * - ti0 (x, y, - z - 2) + - 6.25e-3 * - (((4.16666666666667e-3 * - (u (t, x - 2, y, z + 1) - u (t, x + 2, y, - z + 1)) + - 3.33333333333333e-2 * (-u (t, - x - 1, + z)) * ti1 (x, y - 1, + z) + (((4.16666666666667e-3 * (u (t, x - 2, y, z - 1) - u (t, x + 2, y, + z - 1)) + 3.33333333333333e-2 * (-u (t, + x - 1, + y, + z - 1) + u (t, + x + 1, + y, + z - 1))) * ti1 (x, y, + z - 1) + (-4.16666666666667e-2 * u (t, + x, + y, + z - 1) - + 1.25e-2 * u (t, x, y - 1, + z - 1) + 7.5e-2 * u (t, x, y + 1, + z - 1) - + 2.5e-2 * u (t, x, y + 2, + z - 1) + + 4.16666666666667e-3 * u (t, + x, + y + 3, + z - 1)) * ti3 (x, y, + z - + 1)) * + ti2 (x, y, + z - 1) - (7.5e-2 * u (t, x, y, z) - 1.25e-2 * u (t, x, y, + z - 2) - 4.16666666666667e-2 * u (t, x, y, + z - 1) - 2.5e-2 * u (t, x, y, + z + 1) + 4.16666666666667e-3 * u (t, x, y, + z + 2)) * ti0 (x, y, + z - + 1)) * ti0 (x, y, + z - + 1)) + + 1.25e-2 * ((-temp392 * ti1 (x - 2, + y, + z) + temp394 * ti3 (x - 2, y, + z)) * ti3 (x - 2, y, + z) + ((temp392 * ti3 (x - 2, y, + z) + temp394 * ti1 (x - 2, + y, + z)) * ti2 (x - 2, y, + z) - (4.16666666666667e-3 * (u (t, x - 2, y, + z - 2) - u (t, + x - 2, y, + z + 2)) + 3.33333333333333e-2 * (-u (t, x - 2, y, + z - 1) + u (t, + x - 2, y, + z + 1))) * ti0 (x - 2, y, + z)) * ti1 (x - 2, y, + z) * ti2 (x - 2, + y, + z) + + ((temp395 * ti1 (x, y - 2, + z) + temp396 * ti3 (x, + y - 2, + z)) * ti2 (x, y - 2, + z) - (-4.16666666666667e-2 * u (t, x, y - 2, + z) - 1.25e-2 * u (t, x, + y - 2, + z - 1) + 7.5e-2 * u (t, x, + y - 2, + z + 1) - 2.5e-2 * u (t, x, + y - 2, + z + 2) + 4.16666666666667e-3 * u (t, x, y - 2, + z + 3)) * ti0 (x, + y - 2, + z)) * ti2 (x, y - 2, + z) * ti3 (x, + y - 2, + z)) + + 6.25e-3 * ((-temp409 * ti1 (x + 1, y, z) + temp410 * ti3 (x + 1, y, z)) * ti3 (x + 1, + y, + z) + ((temp404 * ti1 (x, y + 1, z) + temp406 * ti3 (x, y + 1, z)) * ti2 (x, + y + 1, + z) + - (-4.16666666666667e-2 * u (t, x, y + 1, z) - 1.25e-2 * u (t, x, y + 1, z - 1) + 7.5e-2 * u (t, x, + y + 1, + z + 1) - 2.5e-2 * u (t, x, y + 1, + z + 2) + 4.16666666666667e-3 * u (t, x, + y + 1, + z + + 3)) * + ti0 (x, y + 1, z)) * ti2 (x, y + 1, z) * ti3 (x, y + 1, + z) + ((temp409 * ti3 (x + 1, y, z) + temp410 * ti1 (x + 1, y, z)) * ti2 (x + 1, + y, + z) + - + (4.16666666666667e-3 * + (u (t, x + 1, y, z - 2) - u (t, x + 1, y, z + 2)) + + 3.33333333333333e-2 * (-u (t, x + 1, y, z - 1) + u (t, x + 1, y, + z + 1))) * ti0 (x + 1, y, + z)) * ti1 (x + 1, + y, + z) * ti2 (x + 1, y, + z)) + + 1.66666666666667e-2 * ((temp343 * ti3 (x + 1, y, z) - temp347 * ti1 (x + 1, y, z)) * ti3 (x + 1, + y, + z) + (-temp377 * ti1 (x, y - 1, z) + temp381 * ti3 (x, y - 1, z)) * ti1 (x, + y - 1, + z) + ((temp336 * ti3 (x, y + 1, z) + temp342 * ti1 (x, y + 1, z)) * ti2 (x, + y + 1, + z) - + (4.16666666666667e-3 * + (u (t, x, y + 1, z - 2) - u (t, x, y + 1, z + 2)) + + 3.33333333333333e-2 * (-u (t, x, y + 1, z - 1) + + u (t, x, y + 1, z + 1))) * ti0 (x, y + 1, + z)) * ti2 (x, + y + 1, + z) * + ti3 (x, y + 1, + z) + ((temp343 * ti1 (x + 1, y, z) + temp347 * ti3 (x + 1, y, z)) * ti2 (x + 1, y, + z) - (-4.16666666666667e-2 * u (t, x + 1, y, z) - 1.25e-2 * u (t, x + 1, y, z - 1) + 7.5e-2 * u (t, + x + 1, + y, + z + 1) - 2.5e-2 * u (t, x + 1, y, + z + 2) + + 4.16666666666667e-3 * u (t, x + 1, + y, + z + 3)) * ti0 (x + 1, y, z)) * ti1 (x + 1, y, z) * ti2 (x + 1, y, + z) + + (((4.16666666666667e-3 * (u (t, x, y - 2, z - 1) - u (t, x, y + 2, z - 1)) + 3.33333333333333e-2 * (-u (t, x, y - 1, z - 1) + u (t, x, y + 1, z - 1))) * ti3 (x, y, + z - 1) + + (-4.16666666666667e-2 * u (t, x, y, z - 1) - 1.25e-2 * u (t, x - 1, y, z - 1) + 7.5e-2 * u (t, x + 1, y, + z - 1) - 2.5e-2 * u (t, x + 2, y, z - 1) + 4.16666666666667e-3 * u (t, + x + 3, + y, + z - 1)) * ti1 (x, y, z - 1)) * ti2 (x, y, + z - + 1) - + (3.33333333333333e-2 * (u (t, x, y, z) - u (t, x, y, + z - 2)) + 4.16666666666667e-3 * (u (t, x, y, + z - 3) - u (t, x, y, + z + 1))) * ti0 (x, y, + z - 1)) * ti0 (x, + y, + z + - + 1)) + + 2.08333333333333e-3 * ((temp360 * ti3 (x - 2, y, z) - temp365 * ti1 (x - 2, y, z)) * ti3 (x - 2, + y, + z) + (-temp367 * ti1 (x, y + 2, z) + temp370 * ti3 (x, y + 2, z)) * ti1 (x, + y + 2, + z) + (temp388 * ti3 (x, y - 3, z) - temp390 * ti1 (x, y - 3, z)) * ti1 (x, + y - 3, + z) + + ((temp352 * ti3 (x, y - 2, z) + temp357 * ti1 (x, y - 2, z)) * ti2 (x, + y - 2, + z) + - (4.16666666666667e-3 * (u (t, x, y - 2, z - 2) - u (t, x, y - 2, z + 2)) + 3.33333333333333e-2 * (-u (t, x, y - 2, z - 1) + u (t, x, y - 2, z + 1))) * ti0 (x, y - 2, + z)) * ti2 (x, + y - 2, + z) * ti3 (x, y - 2, + z) + + ((temp360 * ti1 (x - 2, y, z) + temp365 * ti3 (x - 2, y, z)) * ti2 (x - 2, y, + z) - (-4.16666666666667e-2 * u (t, x - 2, y, z) - 1.25e-2 * u (t, x - 2, y, z - 1) + 7.5e-2 * u (t, + x - 2, + y, + z + 1) - 2.5e-2 * u (t, x - 2, y, + z + 2) + + 4.16666666666667e-3 * u (t, x - 2, + y, + z + 3)) * ti0 (x - 2, y, z)) * ti1 (x - 2, y, z) * ti2 (x - 2, y, + z) + + (((4.16666666666667e-3 * (u (t, x, y - 2, z + 2) - u (t, x, y + 2, z + 2)) + 3.33333333333333e-2 * (-u (t, x, y - 1, z + 2) + u (t, x, y + 1, z + 2))) * ti3 (x, y, + z + 2) + + (-4.16666666666667e-2 * u (t, x, y, z + 2) - 1.25e-2 * u (t, x - 1, y, z + 2) + 7.5e-2 * u (t, x + 1, y, + z + 2) - 2.5e-2 * u (t, x + 2, y, z + 2) + 4.16666666666667e-3 * u (t, + x + 3, + y, + z + 2)) * ti1 (x, y, z + 2)) * ti2 (x, y, + z + + 2) - + (4.16666666666667e-3 * (u (t, x, y, z) - u (t, x, y, z + 4)) + 3.33333333333333e-2 * (-u (t, x, y, z + 1) + u (t, x, y, z + 3))) * ti0 (x, y, + z + 2)) * ti0 (x, + y, + z + + + 2) + + (((4.16666666666667e-3 * (u (t, x - 2, y, z - 3) - u (t, x + 2, y, z - 3)) + 3.33333333333333e-2 * (-u (t, x - 1, y, z - 3) + u (t, x + 1, y, z - 3))) * ti1 (x, y, + z - 3) + + (-4.16666666666667e-2 * u (t, x, y, z - 3) - 1.25e-2 * u (t, x, y - 1, z - 3) + 7.5e-2 * u (t, x, y + 1, + z - 3) - 2.5e-2 * u (t, x, y + 2, z - 3) + 4.16666666666667e-3 * u (t, x, + y + 3, + z - 3)) * ti3 (x, y, z - 3)) * ti2 (x, y, + z - + 3) - + (4.16666666666667e-3 * u (t, x, y, - z + 1) + u (t, - x + 1, - y, - z + - 1))) * - ti1 (x, y, - z + 1) + (-4.16666666666667e-2 * u (t, - x, - y, - z + - 1) - - 1.25e-2 * u (t, x, y - 1, - z + 1) + - 7.5e-2 * u (t, x, y + 1, - z + 1) - - 2.5e-2 * u (t, x, y + 2, - z + 1) + - 4.16666666666667e-3 * u (t, - x, - y + 3, - z + - 1)) - * ti3 (x, y, z + 1)) * ti2 (x, y, - z + 1) - - (-1.25e-2 * u (t, x, y, z) - - 4.16666666666667e-2 * u (t, x, y, - z + 1) + - 7.5e-2 * u (t, x, y, z + 2) - 2.5e-2 * u (t, - x, - y, - z + - 3) - + 4.16666666666667e-3 * u (t, x, y, - z + 4)) * ti0 (x, - y, - z + - 1)) - * ti0 (x, y, z + 1)); - auto temp290 = - (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x - 4, y, z)) + - 3.33333333333333e-2 * (-v (t, x - 3, y, z) + - v (t, x - 1, y, z))) * ti1 (x - 2, y, - z) + - (-4.16666666666667e-2 * v (t, x - 2, y, z) - - 1.25e-2 * v (t, x - 2, y - 1, z) + 7.5e-2 * v (t, x - 2, y + 1, - z) - 2.5e-2 * v (t, - x - - 2, - y + - 2, - z) + - 4.16666666666667e-3 * v (t, x - 2, y + 3, z)) * ti3 (x - 2, y, - z)) * ti0 (x - 2, - y, - z) + - (-4.16666666666667e-2 * v (t, x - 2, y, - z) - 1.25e-2 * v (t, x - 2, y, - z - 1) + - 7.5e-2 * v (t, x - 2, y, z + 1) - 2.5e-2 * v (t, x - 2, y, - z + 2) + - 4.16666666666667e-3 * v (t, x - 2, y, z + 3)) * ti2 (x - 2, - y, - z)) * ti0 (x - 2, - y, - z) * - ti1 (x - 2, y, z); - auto temp275 = - (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x, y - 2, z)) + - 4.16666666666667e-3 * (v (t, x, y - 3, z) - - v (t, x, y + 1, z))) * ti3 (x, y - 1, - z) + - (-4.16666666666667e-2 * v (t, x, y - 1, z) - - 1.25e-2 * v (t, x - 1, y - 1, z) + 7.5e-2 * v (t, x + 1, y - 1, - z) - 2.5e-2 * v (t, - x + - 2, - y - - 1, - z) + - 4.16666666666667e-3 * v (t, x + 3, y - 1, z)) * ti1 (x, y - 1, - z)) * ti0 (x, - y - 1, - z) - + - (4.16666666666667e-3 * - (v (t, x, y - 1, z - 2) - v (t, x, y - 1, z + 2)) + - 3.33333333333333e-2 * (-v (t, x, y - 1, z - 1) + - v (t, x, y - 1, z + 1))) * ti2 (x, y - 1, - z)) * ti0 (x, - y - - 1, - z) * - ti3 (x, y - 1, z); - auto temp237 = - (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x, y + 2, z)) + - 4.16666666666667e-3 * (v (t, x, y - 1, z) - - v (t, x, y + 3, z))) * ti3 (x, y + 1, - z) + - (-4.16666666666667e-2 * v (t, x, y + 1, z) - - 1.25e-2 * v (t, x - 1, y + 1, z) + 7.5e-2 * v (t, x + 1, y + 1, - z) - 2.5e-2 * v (t, - x + - 2, - y + - 1, - z) + - 4.16666666666667e-3 * v (t, x + 3, y + 1, z)) * ti1 (x, y + 1, - z)) * ti0 (x, - y + 1, - z) - + - (4.16666666666667e-3 * - (v (t, x, y + 1, z - 2) - v (t, x, y + 1, z + 2)) + - 3.33333333333333e-2 * (-v (t, x, y + 1, z - 1) + - v (t, x, y + 1, z + 1))) * ti2 (x, y + 1, - z)) * ti0 (x, - y + - 1, - z) * - ti3 (x, y + 1, z); - auto temp262 = - (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x, y + 4, z)) + - 3.33333333333333e-2 * (-v (t, x, y + 1, z) + - v (t, x, y + 3, z))) * ti3 (x, y + 2, - z) + - (-4.16666666666667e-2 * v (t, x, y + 2, z) - - 1.25e-2 * v (t, x - 1, y + 2, z) + 7.5e-2 * v (t, x + 1, y + 2, - z) - 2.5e-2 * v (t, - x + - 2, - y + - 2, - z) + - 4.16666666666667e-3 * v (t, x + 3, y + 2, z)) * ti1 (x, y + 2, - z)) * ti0 (x, - y + 2, - z) - + - (4.16666666666667e-3 * - (v (t, x, y + 2, z - 2) - v (t, x, y + 2, z + 2)) + - 3.33333333333333e-2 * (-v (t, x, y + 2, z - 1) + - v (t, x, y + 2, z + 1))) * ti2 (x, y + 2, - z)) * ti0 (x, - y + - 2, - z) * - ti3 (x, y + 2, z); - auto temp68 = - ((4.16666666666667e-3 * (v (t, x - 2, y, z) - v (t, x + 2, y, z)) + - 3.33333333333333e-2 * (-v (t, x - 1, y, z) + - v (t, x + 1, y, z))) * ti1 (x, y, - z) + - (-4.16666666666667e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 1, z) + - 7.5e-2 * v (t, x, y + 1, - z) - 2.5e-2 * v (t, x, - y + 2, - z) + - 4.16666666666667e-3 * v (t, x, y + 3, z)) * ti3 (x, y, z)) * ti0 (x, - y, - z) - + (-4.16666666666667e-2 * v (t, x, y, z) - - 1.25e-2 * v (t, x, y, z - 1) + 7.5e-2 * v (t, x, y, - z + 1) - 2.5e-2 * v (t, - x, - y, - z - + - 2) - + 4.16666666666667e-3 * v (t, x, y, z + 3)) * ti2 (x, y, z); - auto temp6 = - 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); - auto temp225 = - (((4.16666666666667e-3 * - (v (t, x + 1, y - 2, z) - v (t, x + 1, y + 2, z)) + - 3.33333333333333e-2 * (-v (t, x + 1, y - 1, z) + - v (t, x + 1, y + 1, z))) * ti3 (x + 1, y, - z) + - (-1.25e-2 * v (t, x, y, z) - - 4.16666666666667e-2 * v (t, x + 1, y, z) + 7.5e-2 * v (t, x + 2, y, - z) - - 2.5e-2 * v (t, x + 3, y, z) + 4.16666666666667e-3 * v (t, x + 4, y, - z)) * ti1 (x + - 1, - y, - z)) - * ti0 (x + 1, y, - z) + - (4.16666666666667e-3 * - (v (t, x + 1, y, z - 2) - v (t, x + 1, y, z + 2)) + - 3.33333333333333e-2 * (-v (t, x + 1, y, z - 1) + - v (t, x + 1, y, z + 1))) * ti2 (x + 1, y, - z)) * ti0 (x + - 1, - y, - z) - * ti1 (x + 1, y, z); + z) - 1.25e-2 * u (t, x, y, + z - 4) - 4.16666666666667e-2 * u (t, x, + y, + z - 3) + 7.5e-2 * u (t, x, y, + z - 2) - 2.5e-2 * u (t, x, y, + z - 1)) * ti0 (x, + y, + z - 3)) * ti0 (x, y, z - 3)) - (temp420 * ti0 (x, y, + z) + + 2.08333333333333e-2 * (temp330 * ti3 (x, y, + z) - + temp333 * ti1 (x, y, + z)) * + ti1 (x, y, + z) + + 1.66666666666667e-2 * (-temp336 * ti1 (x, y + 1, + z) + + temp342 * ti3 (x, + y + 1, + z)) * + ti1 (x, y + 1, + z) + + 2.08333333333333e-3 * (-temp352 * ti1 (x, y - 2, + z) + + temp357 * ti3 (x, + y - 2, + z)) * + ti1 (x, y - 2, + z) + + 2.08333333333333e-3 * (temp372 * ti3 (x + 2, y, + z) - + temp375 * ti1 (x + 2, y, + z)) * + ti3 (x + 2, y, + z) + + 1.66666666666667e-2 * (temp383 * ti3 (x - 1, y, + z) - + temp385 * ti1 (x - 1, y, + z)) * + ti3 (x - 1, y, + z) + + 2.08333333333333e-3 * (-temp386 * ti1 (x - 3, y, + z) + + temp387 * ti3 (x - 3, y, + z)) * + ti3 (x - 3, y, + z) + 1.25e-2 * (temp395 * ti3 (x, + y - 2, + z) - + temp396 * ti1 (x, + y - 2, + z)) * + ti1 (x, y - 2, + z) + 6.25e-3 * (temp404 * ti3 (x, + y + 1, + z) - + temp406 * ti1 (x, + y + 1, + z)) * + ti1 (x, y + 1, + z) + 3.75e-2 * (-temp407 * ti1 (x - 1, y, + z) + + temp408 * ti3 (x - 1, y, + z)) * + ti3 (x - 1, y, + z) + + 2.08333333333333e-3 * ((temp367 * ti3 (x, y + 2, + z) + + temp370 * ti1 (x, + y + 2, + z)) + * ti2 (x, y + 2, + z) - + (4.16666666666667e-3 + * (u (t, x, y + 2, + z - 2) - u (t, x, + y + 2, + z + + 2)) + + 3.33333333333333e-2 + * (-u (t, x, + y + 2, + z - 1) + u (t, x, + y + 2, + z + + 1))) * + ti0 (x, y + 2, + z)) * ti2 (x, + y + 2, + z) * ti3 (x, + y + + 2, + z) + + 2.08333333333333e-3 * ((temp372 * ti1 (x + 2, y, + z) + + temp375 * ti3 (x + 2, + y, + z)) + * ti2 (x + 2, y, + z) - + (-4.16666666666667e-2 + * u (t, x + 2, y, + z) - 1.25e-2 * u (t, + x + 2, + y, + z - + 1) + + 7.5e-2 * u (t, + x + 2, + y, + z + + 1) - + 2.5e-2 * u (t, + x + 2, + y, + z + + 2) + + 4.16666666666667e-3 + * u (t, x + 2, y, + z + 3)) * ti0 (x + 2, + y, + z)) + * ti1 (x + 2, y, + z) * ti2 (x + 2, + y, + z) + + 1.66666666666667e-2 * ((temp377 * ti3 (x, y - 1, + z) + + temp381 * ti1 (x, + y - 1, + z)) + * ti2 (x, y - 1, + z) - + (4.16666666666667e-3 + * (u (t, x, y - 1, + z - 2) - u (t, x, + y - 1, + z + + 2)) + + 3.33333333333333e-2 + * (-u (t, x, + y - 1, + z - 1) + u (t, x, + y - 1, + z + + 1))) * + ti0 (x, y - 1, + z)) * ti2 (x, + y - 1, + z) * ti3 (x, + y - + 1, + z) + + 1.66666666666667e-2 * ((temp383 * ti1 (x - 1, y, + z) + + temp385 * ti3 (x - 1, + y, + z)) + * ti2 (x - 1, y, + z) - + (-4.16666666666667e-2 + * u (t, x - 1, y, + z) - 1.25e-2 * u (t, + x - 1, + y, + z - + 1) + + 7.5e-2 * u (t, + x - 1, + y, + z + + 1) - + 2.5e-2 * u (t, + x - 1, + y, + z + + 2) + + 4.16666666666667e-3 + * u (t, x - 1, y, + z + 3)) * ti0 (x - 1, + y, + z)) + * ti1 (x - 1, y, + z) * ti2 (x - 1, + y, + z) + + 2.08333333333333e-3 * ((temp386 * ti3 (x - 3, y, + z) + + temp387 * ti1 (x - 3, + y, + z)) + * ti2 (x - 3, y, + z) - + (4.16666666666667e-3 + * (u (t, x - 3, y, + z - 2) - u (t, + x - 3, y, + z + + 2)) + + 3.33333333333333e-2 * (-u (t, + x + - + 3, + y, + z + - + 1) + + + u (t, + x - + 3, + y, + z + + 1))) + * ti0 (x - 3, y, + z)) * ti1 (x - 3, + y, + z) * + ti2 (x - 3, y, + z) + + 2.08333333333333e-3 * ((temp388 * ti1 (x, y - 3, + z) + + temp390 * ti3 (x, + y - 3, + z)) + * ti2 (x, y - 3, + z) - + (-4.16666666666667e-2 + * u (t, x, y - 3, + z) - 1.25e-2 * u (t, x, + y - 3, + z - + 1) + + 7.5e-2 * u (t, x, + y - 3, + z + + 1) - + 2.5e-2 * u (t, x, + y - 3, + z + + 2) + + 4.16666666666667e-3 + * u (t, x, y - 3, + z + 3)) * ti0 (x, + y - 3, + z)) + * ti2 (x, y - 3, + z) * ti3 (x, + y - 3, + z) + + 3.75e-2 * ((temp399 * ti1 (x, y - 1, + z) + temp401 * ti3 (x, + y - 1, + z)) + * ti2 (x, y - 1, + z) - + (-4.16666666666667e-2 * u (t, x, y - 1, + z) - + 1.25e-2 * u (t, x, + y - 1, + z - 1) + 7.5e-2 * u (t, x, + y - 1, + z + + 1) - + 2.5e-2 * u (t, x, + y - 1, + z + + 2) + + 4.16666666666667e-3 * u (t, x, y - 1, + z + + 3)) * ti0 (x, + y - + 1, + z)) + * ti2 (x, y - 1, + z) * ti3 (x, + y - 1, + z) + + 3.75e-2 * ((temp407 * ti3 (x - 1, y, + z) + temp408 * ti1 (x - 1, + y, + z)) + * ti2 (x - 1, y, + z) - + (4.16666666666667e-3 * (u (t, x - 1, y, + z - 2) - u (t, + x - + 1, + y, + z + + 2)) + + 3.33333333333333e-2 * (-u (t, + x - 1, y, + z - 1) + + u (t, + x - 1, + y, + z + + 1))) * + ti0 (x - 1, y, + z)) * ti1 (x - 1, + y, + z) * ti2 (x - 1, y, + z) + + 2.08333333333333e-3 * + (((4.16666666666667e-3 * + (u (t, x, y - 2, z - 2) - u (t, x, y + 2, + z - 2)) + + 3.33333333333333e-2 * (-u (t, + x, + y - 1, + z - 2) + u (t, x, + y + 1, + z - + 2))) * + ti3 (x, y, + z - 2) + (-4.16666666666667e-2 * u (t, + x, + y, + z - + 2) - + 1.25e-2 * u (t, + x - 1, y, + z - 2) + 7.5e-2 * u (t, + x + + + 1, + y, + z + - + 2) + - 2.5e-2 * u (t, + x + 2, + y, + z - + 2) + + 4.16666666666667e-3 * u (t, + x + 3, + y, + z - + 2)) + * ti1 (x, y, + z - 2)) * ti2 (x, y, + z - 2) - + (4.16666666666667e-3 + * (-u (t, x, y, z) + u (t, x, y, + z - 4)) + + 3.33333333333333e-2 * (-u (t, x, y, + z - 3) + u (t, x, + y, + z - + 1))) + * ti0 (x, + y, + z - 2)) * ti0 (x, y, + z - 2) + + 1.66666666666667e-2 * + (((4.16666666666667e-3 * + (u (t, x, y - 2, z + 1) - u (t, x, y + 2, + z + 1)) + + 3.33333333333333e-2 * (-u (t, + x, + y - 1, + z + 1) + u (t, x, + y + 1, + z + + 1))) * + ti3 (x, y, + z + 1) + (-4.16666666666667e-2 * u (t, + x, + y, + z + + 1) - + 1.25e-2 * u (t, + x - 1, y, + z + 1) + 7.5e-2 * u (t, + x + + + 1, + y, + z + + + 1) + - 2.5e-2 * u (t, + x + 2, + y, + z + + 1) + + 4.16666666666667e-3 * u (t, + x + 3, + y, + z + + 1)) + * ti1 (x, y, + z + 1)) * ti2 (x, y, + z + 1) - + (3.33333333333333e-2 + * (-u (t, x, y, z) + u (t, x, y, + z + 2)) + + 4.16666666666667e-3 + * (u (t, x, y, z - 1) - u (t, x, y, + z + 3))) * ti0 (x, + y, + z + + + 1)) + * ti0 (x, y, + z + 1) + + 1.25e-2 * + (((4.16666666666667e-3 * + (u (t, x - 2, y, z - 2) - u (t, x + 2, y, + z - 2)) + + 3.33333333333333e-2 * (-u (t, + x - 1, + y, + z - 2) + u (t, + x + 1, + y, + z - + 2))) * + ti1 (x, y, + z - 2) + (-4.16666666666667e-2 * u (t, + x, + y, + z - + 2) - + 1.25e-2 * u (t, x, + y - 1, + z - + 2) + 7.5e-2 * u (t, x, + y + 1, + z - + 2) - + 2.5e-2 * u (t, x, + y + 2, + z - + 2) + + 4.16666666666667e-3 * u (t, + x, + y + 3, + z - + 2)) + * ti3 (x, y, + z - 2)) * ti2 (x, y, + z - 2) - + (-2.5e-2 * u (t, x, y, + z) - 1.25e-2 * u (t, x, + y, + z - + 3) - + 4.16666666666667e-2 * u (t, x, y, + z - 2) + 7.5e-2 * u (t, x, + y, + z - + 1) + + 4.16666666666667e-3 * u (t, x, y, + z + 1)) * ti0 (x, + y, + z - + 2)) + * ti0 (x, y, + z - 2) + + 6.25e-3 * + (((4.16666666666667e-3 * + (u (t, x - 2, y, z + 1) - u (t, x + 2, y, + z + 1)) + + 3.33333333333333e-2 * (-u (t, + x - 1, + y, + z + 1) + u (t, + x + 1, + y, + z + + 1))) * + ti1 (x, y, + z + 1) + (-4.16666666666667e-2 * u (t, + x, + y, + z + + 1) - + 1.25e-2 * u (t, x, + y - 1, + z + + 1) + 7.5e-2 * u (t, x, + y + 1, + z + + 1) - + 2.5e-2 * u (t, x, + y + 2, + z + + 1) + + 4.16666666666667e-3 * u (t, + x, + y + 3, + z + + 1)) + * ti3 (x, y, + z + 1)) * ti2 (x, y, + z + 1) - + (-1.25e-2 * u (t, x, y, + z) - + 4.16666666666667e-2 * u (t, x, y, + z + 1) + 7.5e-2 * u (t, x, + y, + z + + 2) - + 2.5e-2 * u (t, + x, + y, + z + + 3) + 4.16666666666667e-3 * u (t, x, y, + z + + 4)) * + ti0 (x, + y, + z + 1)) * ti0 (x, y, z + 1)); + auto temp290 = (((4.16666666666667e-3 * (-v (t, x, y, z) + v (t, x - 4, y, z)) + 3.33333333333333e-2 * (-v (t, x - 3, y, z) + v (t, x - 1, y, z))) * ti1 (x - 2, y, + z) + + (-4.16666666666667e-2 * v (t, x - 2, y, z) - 1.25e-2 * v (t, x - 2, y - 1, z) + 7.5e-2 * v (t, x - 2, y + 1, + z) - 2.5e-2 * v (t, + x - 2, + y + 2, + z) + 4.16666666666667e-3 * v (t, x - 2, y + 3, z)) * ti3 (x - 2, y, + z)) * ti0 (x - 2, + y, + z) + (-4.16666666666667e-2 * v (t, x - 2, y, + z) - 1.25e-2 * v (t, + x - + 2, + y, + z - + 1) + + 7.5e-2 * v (t, x - 2, y, z + 1) - 2.5e-2 * v (t, + x - + 2, + y, + z + + 2) + + 4.16666666666667e-3 * v (t, x - 2, y, + z + 3)) * ti2 (x - 2, + y, + z)) * + ti0 (x - 2, + y, + z) * ti1 (x - 2, y, z); + auto temp275 = (((3.33333333333333e-2 * (v (t, x, y, z) - v (t, x, y - 2, z)) + 4.16666666666667e-3 * (v (t, x, y - 3, z) - v (t, x, y + 1, z))) * ti3 (x, y - 1, + z) + + (-4.16666666666667e-2 * v (t, x, y - 1, z) - 1.25e-2 * v (t, x - 1, y - 1, z) + 7.5e-2 * v (t, x + 1, y - 1, + z) - 2.5e-2 * v (t, + x + 2, + y - 1, + z) + 4.16666666666667e-3 * v (t, x + 3, y - 1, z)) * ti1 (x, y - 1, + z)) * ti0 (x, + y - 1, + z) + + (4.16666666666667e-3 * (v (t, x, y - 1, z - 2) - v (t, x, y - 1, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y - 1, z - 1) + v (t, x, y - 1, z + 1))) * ti2 (x, y - 1, + z)) * ti0 (x, + y - 1, + z) * ti3 (x, y - 1, z); + auto temp237 = (((3.33333333333333e-2 * (-v (t, x, y, z) + v (t, x, y + 2, z)) + 4.16666666666667e-3 * (v (t, x, y - 1, z) - v (t, x, y + 3, z))) * ti3 (x, y + 1, + z) + + (-4.16666666666667e-2 * v (t, x, y + 1, z) - 1.25e-2 * v (t, x - 1, y + 1, z) + 7.5e-2 * v (t, x + 1, y + 1, + z) - 2.5e-2 * v (t, + x + 2, + y + 1, + z) + 4.16666666666667e-3 * v (t, x + 3, y + 1, z)) * ti1 (x, y + 1, + z)) * ti0 (x, + y + 1, + z) + + (4.16666666666667e-3 * (v (t, x, y + 1, z - 2) - v (t, x, y + 1, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y + 1, z - 1) + v (t, x, y + 1, z + 1))) * ti2 (x, y + 1, + z)) * ti0 (x, + y + 1, + z) * ti3 (x, y + 1, z); + auto temp262 = (((4.16666666666667e-3 * (v (t, x, y, z) - v (t, x, y + 4, z)) + 3.33333333333333e-2 * (-v (t, x, y + 1, z) + v (t, x, y + 3, z))) * ti3 (x, y + 2, + z) + + (-4.16666666666667e-2 * v (t, x, y + 2, z) - 1.25e-2 * v (t, x - 1, y + 2, z) + 7.5e-2 * v (t, x + 1, y + 2, + z) - 2.5e-2 * v (t, + x + 2, + y + 2, + z) + 4.16666666666667e-3 * v (t, x + 3, y + 2, z)) * ti1 (x, y + 2, + z)) * ti0 (x, + y + 2, + z) + + (4.16666666666667e-3 * (v (t, x, y + 2, z - 2) - v (t, x, y + 2, z + 2)) + 3.33333333333333e-2 * (-v (t, x, y + 2, z - 1) + v (t, x, y + 2, z + 1))) * ti2 (x, y + 2, + z)) * ti0 (x, + y + 2, + z) * ti3 (x, y + 2, z); + auto temp68 = ((4.16666666666667e-3 * (v (t, x - 2, y, z) - v (t, x + 2, y, z)) + 3.33333333333333e-2 * (-v (t, x - 1, y, z) + v (t, x + 1, y, z))) * ti1 (x, y, + z) + + (-4.16666666666667e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y - 1, z) + 7.5e-2 * v (t, x, y + 1, + z) - 2.5e-2 * v (t, x, + y + 2, + z) + 4.16666666666667e-3 * v (t, x, y + 3, z)) * ti3 (x, y, z)) * ti0 (x, + y, + z) + + (-4.16666666666667e-2 * v (t, x, y, z) - 1.25e-2 * v (t, x, y, z - 1) + 7.5e-2 * v (t, x, y, + z + 1) - 2.5e-2 * v (t, + x, + y, + z + 2) + 4.16666666666667e-3 * v (t, x, y, z + 3)) * ti2 (x, y, z); + auto temp6 = 1.0 / (8.85879567828298e-1 * damp (x, y, z) + 2.0 * m (x, y, z)); + auto temp225 = (((4.16666666666667e-3 * (v (t, x + 1, y - 2, z) - v (t, x + 1, y + 2, z)) + 3.33333333333333e-2 * (-v (t, x + 1, y - 1, z) + v (t, x + 1, y + 1, z))) * ti3 (x + 1, y, + z) + + (-1.25e-2 * v (t, x, y, z) - 4.16666666666667e-2 * v (t, x + 1, y, z) + 7.5e-2 * v (t, x + 2, y, + z) - 2.5e-2 * v (t, x + 3, y, z) + 4.16666666666667e-3 * v (t, x + 4, y, + z)) * ti1 (x + 1, + y, + z)) * ti0 (x + 1, y, + z) + + (4.16666666666667e-3 * (v (t, x + 1, y, z - 2) - v (t, x + 1, y, z + 2)) + 3.33333333333333e-2 * (-v (t, x + 1, y, z - 1) + v (t, x + 1, y, z + 1))) * ti2 (x + 1, y, + z)) * ti0 (x + 1, + y, + z) * ti1 (x + 1, y, z); - // Next time-step values. - u (t + 1, x, y, - z) EQUALS temp6 *(temp10 * u (t - 1, x, y, - z) + - 1.5695652173913 * (temp487 * epsilon (x, y, z) + - (2.08333333333333e-2 * - (temp56 + - temp68 * (ti0 (x, y, z) * - ti3 (x, y, - z) + ti2 (x, y, - z))) + - 1.25e-2 * (temp185 + temp284 + + // Next time-step values. + u (t + 1, x, y, + z) EQUALS temp6 *(temp10 * u (t - 1, x, y, + z) + + 1.5695652173913 * (temp487 * epsilon (x, y, z) + + (2.08333333333333e-2 * + (temp56 + + temp68 * (ti0 (x, y, z) * + ti3 (x, y, + z) + ti2 (x, y, + z))) + + 1.25e-2 * (temp185 + temp284 + temp308) - - 3.75e-2 * (temp204 + temp286 + + 3.75e-2 * (temp204 + temp286 + temp309) + - 6.25e-3 * (temp225 + temp288 + + 6.25e-3 * (temp225 + temp288 + temp310) + - 1.66666666666667e-2 * - (-temp154 + temp237 - temp275 + - temp289 - temp299 + temp92) + - 2.08333333333333e-3 * - (temp116 - temp133 - temp165 + - temp252 - temp262 - temp283 + - temp290 - temp298 - - temp307)) * delta (x, y, - z)) + - 4.0 * m (x, y, z) * u (t, x, y, z)); - v (t + 1, x, y, - z) EQUALS temp6 *(temp10 * v (t - 1, x, y, - z) + 1.5695652173913 * temp487 * delta (x, - y, - z) - + 3.26992753623188e-2 * (temp56 + - temp68 * (ti0 (x, y, z) * - ti3 (x, y, - z) + ti2 (x, - y, - z))) - + 1.96195652173913e-2 * (temp185 + temp284 + - temp308) - - 5.88586956521739e-2 * (temp204 + temp286 + temp309) + - 9.80978260869565e-3 * (temp225 + temp288 + temp310) + - 2.61594202898551e-2 * (-temp154 + temp237 - temp275 + - temp289 - temp299 + temp92) + - 3.26992753623188e-3 * (temp116 - temp133 - temp165 + - temp252 - temp262 - temp283 + - temp290 - temp298 - temp307) + - 4.0 * m (x, y, z) * v (t, x, y, z)); + 1.66666666666667e-2 * + (-temp154 + temp237 - temp275 + + temp289 - temp299 + temp92) + 2.08333333333333e-3 * (temp116 - temp133 - temp165 + temp252 - temp262 - temp283 + temp290 - temp298 - temp307)) * delta (x, y, z)) + 4.0 * m (x, y, z) * u (t, x, y, z)); + v (t + 1, x, y, + z) EQUALS temp6 *(temp10 * v (t - 1, x, y, + z) + 1.5695652173913 * temp487 * delta (x, + y, + z) + + 3.26992753623188e-2 * (temp56 + + temp68 * (ti0 (x, y, z) * + ti3 (x, y, + z) + ti2 (x, + y, + z))) + + 1.96195652173913e-2 * (temp185 + temp284 + + temp308) - + 5.88586956521739e-2 * (temp204 + temp286 + temp309) + + 9.80978260869565e-3 * (temp225 + temp288 + temp310) + + 2.61594202898551e-2 * (-temp154 + temp237 - temp275 + + temp289 - temp299 + temp92) + 3.26992753623188e-3 * (temp116 - temp133 - temp165 + temp252 - temp262 - temp283 + temp290 - temp298 - temp307) + 4.0 * m (x, y, z) * v (t, x, y, z)); - } + } - // Required stencil-definition method. - virtual void define () - { - switch (get_radius()) - { - case 2: - define_so4 (); - break; - case 4: - define_so8 (); - break; - default: { - yask_exception e("Error: only radius values of 2 and 4 are currently supported for the TTI stencil example"); - throw e; - } - } - } -}; + // Required stencil-definition method. + virtual void define () + { + switch (get_radius ()) + { + case 2: + define_so4 (); + break; + case 4: + define_so8 (); + break; + default: + { + yask_exception e ("Error: only radius values of 2 and 4 are currently supported for the TTI stencil example"); + throw e; + } + } + } + }; + + // Create an object of type 'TTIStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TTIStencil TTIStencil_instance; -// Create an object of type 'TTIStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TTIStencil TTIStencil_instance; +} // namespace. diff --git a/src/stencils/TestStencils.cpp b/src/stencils/TestStencils.cpp index e6525eac..609ce104 100644 --- a/src/stencils/TestStencils.cpp +++ b/src/stencils/TestStencils.cpp @@ -30,823 +30,828 @@ IN THE SOFTWARE. using namespace std; using namespace yask; -// A base class for stencil tests. -class TestBase : public yc_solution_with_radius_base { +// Create an anonymous namespace to ensure that types are local. +namespace { + + // A base class for stencil tests. + class TestBase : public yc_solution_with_radius_base { -protected: - - // Indices & dimensions. - // Not all these will be used in all tests. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr w = new_domain_index("w"); // spatial dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - - // Define some stencils in different dimensions. - // These will be asymmetrical if any of the '*_ext' params are not 0; + protected: + + // Indices & dimensions. + // Not all these will be used in all tests. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr w = new_domain_index("w"); // spatial dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + + // Define some stencils in different dimensions. + // These will be asymmetrical if any of the '*_ext' params are not 0; - // Define simple stencil from var 'V' at 't0' centered around 'x0'. - // Extend given radius left and/or right w/'*_ext'. - virtual yc_number_node_ptr def_1d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, - int left_ext, int right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int i = -get_radius() - left_ext; i <= get_radius() + right_ext; i++, n++) - v += V(t0, x0+i); - return v / n; - } - - // Define simple stencil from scratch or read-only var 'V' centered - // around 'x0'. Similar to 'def_1d()', but doesn't use step var. - virtual yc_number_node_ptr def_no_t_1d(yc_var_proxy& V, const yc_number_node_ptr& x0, - int left_ext, int right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int i = -get_radius() - left_ext; i <= get_radius() + right_ext; i++, n++) - v += V(x0+i); - return v / n; - } - - // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0'. - // Extend given radius left and/or right w/'*_ext'. - // Use some points from the entire rectangle, not just on the axes. - virtual yc_number_node_ptr def_2d(yc_var_proxy& V, const yc_number_node_ptr& t0, - const yc_number_node_ptr& x0, - int x_left_ext, int x_right_ext, - const yc_number_node_ptr& y0, - int y_left_ext, int y_right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) - for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) { - v += V(t0, x0+i, y0+j); - n++; - } - return v / n; - } - - // Define simple stencil from scratch or read-only var 'V' at 't0' - // centered around 'x0', 'y0'. Extend given radius left and/or right - // w/'*_ext'. - virtual yc_number_node_ptr def_no_t_2d(yc_var_proxy& V, - const yc_number_node_ptr& x0, - int x_left_ext, int x_right_ext, - const yc_number_node_ptr& y0, - int y_left_ext, int y_right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) - for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) { - v += V(x0+i, y0+j); - n++; - } - return v / n; - } - - // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0', 'z0'. - // Extend given radius left and/or right w/'*_ext'. - // Use some points from the entire rectangular polytope, not just on the axes. - virtual yc_number_node_ptr def_3d(yc_var_proxy& V, const yc_number_node_ptr& t0, - const yc_number_node_ptr& x0, - int x_left_ext, int x_right_ext, - const yc_number_node_ptr& y0, - int y_left_ext, int y_right_ext, - const yc_number_node_ptr& z0, - int z_left_ext, int z_right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) - for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) - for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { - v += V(t0, x0+i, y0+j, z0+k); + // Define simple stencil from var 'V' at 't0' centered around 'x0'. + // Extend given radius left and/or right w/'*_ext'. + virtual yc_number_node_ptr def_1d(yc_var_proxy& V, const yc_number_node_ptr& t0, const yc_number_node_ptr& x0, + int left_ext, int right_ext) { + yc_number_node_ptr v; + int n = 0; + for (int i = -get_radius() - left_ext; i <= get_radius() + right_ext; i++, n++) + v += V(t0, x0+i); + return v / n; + } + + // Define simple stencil from scratch or read-only var 'V' centered + // around 'x0'. Similar to 'def_1d()', but doesn't use step var. + virtual yc_number_node_ptr def_no_t_1d(yc_var_proxy& V, const yc_number_node_ptr& x0, + int left_ext, int right_ext) { + yc_number_node_ptr v; + int n = 0; + for (int i = -get_radius() - left_ext; i <= get_radius() + right_ext; i++, n++) + v += V(x0+i); + return v / n; + } + + // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0'. + // Extend given radius left and/or right w/'*_ext'. + // Use some points from the entire rectangle, not just on the axes. + virtual yc_number_node_ptr def_2d(yc_var_proxy& V, const yc_number_node_ptr& t0, + const yc_number_node_ptr& x0, + int x_left_ext, int x_right_ext, + const yc_number_node_ptr& y0, + int y_left_ext, int y_right_ext) { + yc_number_node_ptr v; + int n = 0; + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) { + v += V(t0, x0+i, y0+j); n++; } - return v / n; - } - - // Define simple stencil from scratch or read-only var 'V' centered - // around 'x0', 'y0', 'z0'. Extend given radius left and/or right - // w/'*_ext'. - virtual yc_number_node_ptr def_no_t_3d(yc_var_proxy& V, - const yc_number_node_ptr& x0, - int x_left_ext, int x_right_ext, - const yc_number_node_ptr& y0, - int y_left_ext, int y_right_ext, - const yc_number_node_ptr& z0, - int z_left_ext, int z_right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) - for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) - for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { - v += V(x0+i, y0+j, z0+k); + return v / n; + } + + // Define simple stencil from scratch or read-only var 'V' at 't0' + // centered around 'x0', 'y0'. Extend given radius left and/or right + // w/'*_ext'. + virtual yc_number_node_ptr def_no_t_2d(yc_var_proxy& V, + const yc_number_node_ptr& x0, + int x_left_ext, int x_right_ext, + const yc_number_node_ptr& y0, + int y_left_ext, int y_right_ext) { + yc_number_node_ptr v; + int n = 0; + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) { + v += V(x0+i, y0+j); n++; } - return v / n; - } - - // Define simple stencil from var 'V' at 't0' centered around 'w0', 'x0', 'y0', 'z0'. - // Extend given radius left and/or right w/'*_ext'. - // Use some points from the entire rectangular polytope, not just on the axes. - virtual yc_number_node_ptr def_4d(yc_var_proxy& V, const yc_number_node_ptr& t0, - const yc_number_node_ptr& w0, - int w_left_ext, int w_right_ext, - const yc_number_node_ptr& x0, - int x_left_ext, int x_right_ext, - const yc_number_node_ptr& y0, - int y_left_ext, int y_right_ext, - const yc_number_node_ptr& z0, - int z_left_ext, int z_right_ext) { - yc_number_node_ptr v; - int n = 0; - for (int h : { -get_radius() - w_left_ext, 0, get_radius() + w_right_ext }) + return v / n; + } + + // Define simple stencil from var 'V' at 't0' centered around 'x0', 'y0', 'z0'. + // Extend given radius left and/or right w/'*_ext'. + // Use some points from the entire rectangular polytope, not just on the axes. + virtual yc_number_node_ptr def_3d(yc_var_proxy& V, const yc_number_node_ptr& t0, + const yc_number_node_ptr& x0, + int x_left_ext, int x_right_ext, + const yc_number_node_ptr& y0, + int y_left_ext, int y_right_ext, + const yc_number_node_ptr& z0, + int z_left_ext, int z_right_ext) { + yc_number_node_ptr v; + int n = 0; for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { - v += V(t0, w0+h, x0+i, y0+j, z0+k); + v += V(t0, x0+i, y0+j, z0+k); n++; } - return v / n; - } - -public: - - TestBase(const string& name, int radius) : - yc_solution_with_radius_base(name, radius) { } -}; - -// Simple 1D test. -class Test1dStencil : public TestBase { - -protected: - - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. - -public: - - Test1dStencil(int radius=2) : - TestBase("test_1d", radius) { } - - // Define equation to apply to all points in 'A' var. - virtual void define() { + return v / n; + } + + // Define simple stencil from scratch or read-only var 'V' centered + // around 'x0', 'y0', 'z0'. Extend given radius left and/or right + // w/'*_ext'. + virtual yc_number_node_ptr def_no_t_3d(yc_var_proxy& V, + const yc_number_node_ptr& x0, + int x_left_ext, int x_right_ext, + const yc_number_node_ptr& y0, + int y_left_ext, int y_right_ext, + const yc_number_node_ptr& z0, + int z_left_ext, int z_right_ext) { + yc_number_node_ptr v; + int n = 0; + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) + for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { + v += V(x0+i, y0+j, z0+k); + n++; + } + return v / n; + } - // define the value at t+1 using asymmetric stencil. - A(t+1, x) EQUALS def_1d(A, t, x, 0, 2); - } -}; + // Define simple stencil from var 'V' at 't0' centered around 'w0', 'x0', 'y0', 'z0'. + // Extend given radius left and/or right w/'*_ext'. + // Use some points from the entire rectangular polytope, not just on the axes. + virtual yc_number_node_ptr def_4d(yc_var_proxy& V, const yc_number_node_ptr& t0, + const yc_number_node_ptr& w0, + int w_left_ext, int w_right_ext, + const yc_number_node_ptr& x0, + int x_left_ext, int x_right_ext, + const yc_number_node_ptr& y0, + int y_left_ext, int y_right_ext, + const yc_number_node_ptr& z0, + int z_left_ext, int z_right_ext) { + yc_number_node_ptr v; + int n = 0; + for (int h : { -get_radius() - w_left_ext, 0, get_radius() + w_right_ext }) + for (int i : { -get_radius() - x_left_ext, 0, get_radius() + x_right_ext }) + for (int j : { -get_radius() - y_left_ext, 0, get_radius() + y_right_ext }) + for (int k : { -get_radius() - z_left_ext, 0, get_radius() + z_right_ext }) { + v += V(t0, w0+h, x0+i, y0+j, z0+k); + n++; + } + return v / n; + } -// Create an object of type 'Test1dStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static Test1dStencil Test1dStencil_instance; + public: -// Simple 2D test. -class Test2dStencil : public TestBase { + TestBase(const string& name, int radius) : + yc_solution_with_radius_base(name, radius) { } + }; -protected: + // Simple 1D test. + class Test1dStencil : public TestBase { - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. + protected: -public: + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. - Test2dStencil(int radius=2) : - TestBase("test_2d", radius) { } + public: - // Define equation to apply to all points in 'A' var. - virtual void define() { + Test1dStencil(int radius=2) : + TestBase("test_1d", radius) { } - // define the value at t+1 using asymmetric stencil. - A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 4, 3); - } -}; + // Define equation to apply to all points in 'A' var. + virtual void define() { -// Create an object of type 'Test2dStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static Test2dStencil Test2dStencil_instance; + // define the value at t+1 using asymmetric stencil. + A(t+1, x) EQUALS def_1d(A, t, x, 0, 2); + } + }; -// Simple 3D test. -class Test3dStencil : public TestBase { + // Create an object of type 'Test1dStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static Test1dStencil Test1dStencil_instance; -protected: + // Simple 2D test. + class Test2dStencil : public TestBase { - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + protected: -public: + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. - Test3dStencil(int radius=2) : - TestBase("test_3d", radius) { } + public: - // Define equation to apply to all points in 'A' var. - virtual void define() { + Test2dStencil(int radius=2) : + TestBase("test_2d", radius) { } + + // Define equation to apply to all points in 'A' var. + virtual void define() { - // define the value at t+1 using asymmetric stencil. - A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 4, 3, z, 2, 1); - } -}; + // define the value at t+1 using asymmetric stencil. + A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 4, 3); + } + }; + + // Create an object of type 'Test2dStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static Test2dStencil Test2dStencil_instance; -// Create an object of type 'Test3dStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static Test3dStencil Test3dStencil_instance; + // Simple 3D test. + class Test3dStencil : public TestBase { + + protected: + + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + + public: + + Test3dStencil(int radius=2) : + TestBase("test_3d", radius) { } + + // Define equation to apply to all points in 'A' var. + virtual void define() { + + // define the value at t+1 using asymmetric stencil. + A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 4, 3, z, 2, 1); + } + }; + + // Create an object of type 'Test3dStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static Test3dStencil Test3dStencil_instance; -// Simple 4D test. -class Test4dStencil : public TestBase { + // Simple 4D test. + class Test4dStencil : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, w, x, y, z }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, w, x, y, z }); // time-varying var. -public: + public: - Test4dStencil(int radius=1) : - TestBase("test_4d", radius) { } + Test4dStencil(int radius=1) : + TestBase("test_4d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // define the value at t+1 using asymmetric stencil. - A(t+1, w, x, y, z) EQUALS def_4d(A, t, w, 1, 2, x, 0, 2, y, 2, 1, z, 1, 0); - } -}; + // define the value at t+1 using asymmetric stencil. + A(t+1, w, x, y, z) EQUALS def_4d(A, t, w, 1, 2, x, 0, 2, y, 2, 1, z, 1, 0); + } + }; -// Create an object of type 'Test4dStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static Test4dStencil Test4dStencil_instance; + // Create an object of type 'Test4dStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static Test4dStencil Test4dStencil_instance; -// Test vars that don't cover all domain dims. -class TestPartialStencil3 : public TestBase { + // Test vars that don't cover all domain dims. + class TestPartialStencil3 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }); - yc_var_proxy C = yc_var_proxy("C", get_soln(), { y }); - yc_var_proxy D = yc_var_proxy("D", get_soln(), { z }); - yc_var_proxy E = yc_var_proxy("E", get_soln(), { x, y }); - yc_var_proxy F = yc_var_proxy("F", get_soln(), { y, z }); - yc_var_proxy G = yc_var_proxy("G", get_soln(), { z, y }); - yc_var_proxy H = yc_var_proxy("H", get_soln(), { y, z, x }); // different order. - yc_var_proxy I = yc_var_proxy("I", get_soln(), { }); + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }); + yc_var_proxy C = yc_var_proxy("C", get_soln(), { y }); + yc_var_proxy D = yc_var_proxy("D", get_soln(), { z }); + yc_var_proxy E = yc_var_proxy("E", get_soln(), { x, y }); + yc_var_proxy F = yc_var_proxy("F", get_soln(), { y, z }); + yc_var_proxy G = yc_var_proxy("G", get_soln(), { z, y }); + yc_var_proxy H = yc_var_proxy("H", get_soln(), { y, z, x }); // different order. + yc_var_proxy I = yc_var_proxy("I", get_soln(), { }); -public: + public: - TestPartialStencil3(int radius=2) : - TestBase("test_partial_3d", radius) { } + TestPartialStencil3(int radius=2) : + TestBase("test_partial_3d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // define the value at t+1 using asymmetric stencil. - A(t+1, x, y, z) EQUALS - def_3d(A, t, x, 0, 2, y, 4, 3, z, 2, 1) + - def_no_t_1d(B, x, 0, 1) + - def_no_t_1d(C, y, 1, 0) + - def_no_t_1d(D, z, 0, 0) + - def_no_t_2d(E, x, 0, 0, y, 1, 0) + - def_no_t_2d(F, y, 0, 1, z, 0, 0) + - def_no_t_2d(G, z, 1, 0, y, 0, 1) + - def_no_t_3d(H, y, 1, 0, z, 0, 1, x, 1, 0) + I; - } -}; + // define the value at t+1 using asymmetric stencil. + A(t+1, x, y, z) EQUALS + def_3d(A, t, x, 0, 2, y, 4, 3, z, 2, 1) + + def_no_t_1d(B, x, 0, 1) + + def_no_t_1d(C, y, 1, 0) + + def_no_t_1d(D, z, 0, 0) + + def_no_t_2d(E, x, 0, 0, y, 1, 0) + + def_no_t_2d(F, y, 0, 1, z, 0, 0) + + def_no_t_2d(G, z, 1, 0, y, 0, 1) + + def_no_t_3d(H, y, 1, 0, z, 0, 1, x, 1, 0) + I; + } + }; -// Create an object of type 'TestPartialStencil3', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestPartialStencil3 TestPartialStencil3_instance; + // Create an object of type 'TestPartialStencil3', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestPartialStencil3 TestPartialStencil3_instance; -// Test misc indices. -class TestMisc2dStencil : public yc_solution_with_radius_base { + // Test misc indices. + class TestMisc2dStencil : public yc_solution_with_radius_base { -protected: + protected: - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr a = new_misc_index("a"); - yc_index_node_ptr b = new_misc_index("b"); - yc_index_node_ptr c = new_misc_index("c"); + // Indices & dimensions. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr a = new_misc_index("a"); + yc_index_node_ptr b = new_misc_index("b"); + yc_index_node_ptr c = new_misc_index("c"); - // Time-varying var. Intermix last domain dim with misc dims to make - // sure compiler creates correct layout. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, a, y, b, c }); + // Time-varying var. Intermix last domain dim with misc dims to make + // sure compiler creates correct layout. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, a, y, b, c }); -public: + public: - TestMisc2dStencil(int radius=2) : - yc_solution_with_radius_base("test_misc_2d", radius) { } + TestMisc2dStencil(int radius=2) : + yc_solution_with_radius_base("test_misc_2d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Define the value at t+1 using asymmetric stencil - // with various pos & neg indices in misc dims. - yc_number_node_ptr v = A(t, x, 0, y, -1, 2) + 1.0; - for (int r = 1; r <= get_radius(); r++) - v += A(t, x + r, 3, y, 0, 1); - for (int r = 1; r <= get_radius() + 1; r++) - v += A(t, x - r, 4, y, 2, 1); - for (int r = 1; r <= get_radius() + 2; r++) - v += A(t, x, -2, y + r, 2, 0); - for (int r = 1; r <= get_radius() + 3; r++) - v += A(t, x, 0, y - r, 0, -1); - A(t+1, x, 1, y, 2, 3) EQUALS v; - } -}; + // Define the value at t+1 using asymmetric stencil + // with various pos & neg indices in misc dims. + yc_number_node_ptr v = A(t, x, 0, y, -1, 2) + 1.0; + for (int r = 1; r <= get_radius(); r++) + v += A(t, x + r, 3, y, 0, 1); + for (int r = 1; r <= get_radius() + 1; r++) + v += A(t, x - r, 4, y, 2, 1); + for (int r = 1; r <= get_radius() + 2; r++) + v += A(t, x, -2, y + r, 2, 0); + for (int r = 1; r <= get_radius() + 3; r++) + v += A(t, x, 0, y - r, 0, -1); + A(t+1, x, 1, y, 2, 3) EQUALS v; + } + }; -// Create an object of type 'TestMisc2dStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestMisc2dStencil TestMisc2dStencil_instance; + // Create an object of type 'TestMisc2dStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestMisc2dStencil TestMisc2dStencil_instance; -// A "stream-like" stencil that just reads and writes -// with no spatial offsets. -// The radius controls how many reads are done in the time domain. -// Running with radius=2 should give performance comparable to -// (but not identical to) the stream 'triad' benchmark. + // A "stream-like" stencil that just reads and writes + // with no spatial offsets. + // The radius controls how many reads are done in the time domain. + // Running with radius=2 should give performance comparable to + // (but not identical to) the stream 'triad' benchmark. -class StreamStencil : public yc_solution_with_radius_base { + class StreamStencil : public yc_solution_with_radius_base { -protected: + protected: - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. + // Indices & dimensions. + yc_index_node_ptr t = new_step_index("t"); // step in time dim. + yc_index_node_ptr x = new_domain_index("x"); // spatial dim. + yc_index_node_ptr y = new_domain_index("y"); // spatial dim. + yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying 3D var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying 3D var. -public: + public: - StreamStencil(int radius=2) : - yc_solution_with_radius_base("test_stream_3d", radius) { } - virtual ~StreamStencil() { } + StreamStencil(int radius=2) : + yc_solution_with_radius_base("test_stream_3d", radius) { } + virtual ~StreamStencil() { } - // Define equation to read 'get_radius()' values and write one. - virtual void define() { + // Define equation to read 'get_radius()' values and write one. + virtual void define() { - yc_number_node_ptr v; + yc_number_node_ptr v; - // Add 'get_radius()' values from past time-steps. - for (int r = 0; r < get_radius(); r++) - v += A(t-r, x, y, z); + // Add 'get_radius()' values from past time-steps. + for (int r = 0; r < get_radius(); r++) + v += A(t-r, x, y, z); - // define the value at t+1 to be equivalent to v + 1. - A(t+1, x, y, z) EQUALS v + 1; - } -}; + // define the value at t+1 to be equivalent to v + 1. + A(t+1, x, y, z) EQUALS v + 1; + } + }; -// Create an object of type 'StreamStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static StreamStencil StreamStencil_instance; + // Create an object of type 'StreamStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static StreamStencil StreamStencil_instance; -// Reverse-time stencil. -// In this test, A(t-1) depends on A(t). + // Reverse-time stencil. + // In this test, A(t-1) depends on A(t). -class TestReverseStencil : public TestBase { + class TestReverseStencil : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); -public: + public: - TestReverseStencil(int radius=2) : - TestBase("test_reverse_2d", radius) { } + TestReverseStencil(int radius=2) : + TestBase("test_reverse_2d", radius) { } - // Define equation to do simple test. - virtual void define() { + // Define equation to do simple test. + virtual void define() { - // Like the previous 2D test, but defines value at 't-1'. - A(t-1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 4, 3); - } -}; + // Like the previous 2D test, but defines value at 't-1'. + A(t-1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 4, 3); + } + }; -// Create an object of type 'TestReverseStencil', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestReverseStencil TestReverseStencil_instance; + // Create an object of type 'TestReverseStencil', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestReverseStencil TestReverseStencil_instance; -// Test dependent equations. -// These will create 2 stencil packs that will be applied in sequence -// for each time-step. -class TestDepStencil1 : public TestBase { + // Test dependent equations. + // These will create 2 stencil packs that will be applied in sequence + // for each time-step. + class TestDepStencil1 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x }); // time-varying var. -public: + public: - TestDepStencil1(int radius=2) : - TestBase("test_dep_1d", radius) { } + TestDepStencil1(int radius=2) : + TestBase("test_dep_1d", radius) { } - // Define equation to apply to all points in 'A' and 'B' vars. - virtual void define() { + // Define equation to apply to all points in 'A' and 'B' vars. + virtual void define() { - // Define A(t+1) from A(t) & stencil at B(t). - A(t+1, x) EQUALS A(t, x) - def_1d(B, t, x, 0, 1); + // Define A(t+1) from A(t) & stencil at B(t). + A(t+1, x) EQUALS A(t, x) - def_1d(B, t, x, 0, 1); - // Define B(t+1) from B(t) & stencil at A(t+1). - B(t+1, x) EQUALS B(t, x) - def_1d(A, t+1, x, 3, 2); - } -}; + // Define B(t+1) from B(t) & stencil at A(t+1). + B(t+1, x) EQUALS B(t, x) - def_1d(A, t+1, x, 3, 2); + } + }; -// Create an object of type 'TestDepStencil1', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestDepStencil1 TestDepStencil1_instance; + // Create an object of type 'TestDepStencil1', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestDepStencil1 TestDepStencil1_instance; -class TestDepStencil2 : public TestBase { + class TestDepStencil2 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x, y }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x, y }); // time-varying var. -public: + public: - TestDepStencil2(int radius=2) : - TestBase("test_dep_2d", radius) { } + TestDepStencil2(int radius=2) : + TestBase("test_dep_2d", radius) { } - // Define equation to apply to all points in 'A' and 'B' vars. - virtual void define() { + // Define equation to apply to all points in 'A' and 'B' vars. + virtual void define() { - // Define A(t+1) from A(t) & stencil at B(t). - A(t+1, x, y) EQUALS A(t, x, y) - def_2d(B, t, x, 0, 1, y, 2, 1); + // Define A(t+1) from A(t) & stencil at B(t). + A(t+1, x, y) EQUALS A(t, x, y) - def_2d(B, t, x, 0, 1, y, 2, 1); - // Define B(t+1) from B(t) & stencil at A(t+1). - B(t+1, x, y) EQUALS B(t, x, y) - def_2d(A, t+1, x, 3, 2, y, 0, 1); - } -}; + // Define B(t+1) from B(t) & stencil at A(t+1). + B(t+1, x, y) EQUALS B(t, x, y) - def_2d(A, t+1, x, 3, 2, y, 0, 1); + } + }; -// Create an object of type 'TestDepStencil2', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestDepStencil2 TestDepStencil2_instance; + // Create an object of type 'TestDepStencil2', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestDepStencil2 TestDepStencil2_instance; -class TestDepStencil3 : public TestBase { + class TestDepStencil3 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x, y, z }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x, y, z }); // time-varying var. -public: + public: - TestDepStencil3(int radius=2) : - TestBase("test_dep_3d", radius) { } + TestDepStencil3(int radius=2) : + TestBase("test_dep_3d", radius) { } - // Define equation to apply to all points in 'A' and 'B' vars. - virtual void define() { + // Define equation to apply to all points in 'A' and 'B' vars. + virtual void define() { - // Define A(t+1) from A(t) & stencil at B(t). - A(t+1, x, y, z) EQUALS A(t, x, y, z) - - def_3d(B, t, x, 0, 1, y, 2, 1, z, 1, 0); + // Define A(t+1) from A(t) & stencil at B(t). + A(t+1, x, y, z) EQUALS A(t, x, y, z) - + def_3d(B, t, x, 0, 1, y, 2, 1, z, 1, 0); - // Define B(t+1) from B(t) & stencil at A(t+1). - B(t+1, x, y, z) EQUALS B(t, x, y, z) - - def_3d(A, t+1, x, 1, 0, y, 0, 1, z, 2, 1); - } -}; + // Define B(t+1) from B(t) & stencil at A(t+1). + B(t+1, x, y, z) EQUALS B(t, x, y, z) - + def_3d(A, t+1, x, 1, 0, y, 0, 1, z, 2, 1); + } + }; -// Create an object of type 'TestDepStencil3', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestDepStencil3 TestDepStencil3_instance; + // Create an object of type 'TestDepStencil3', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestDepStencil3 TestDepStencil3_instance; -// Test the use of scratch-pad vars. + // Test the use of scratch-pad vars. -class TestScratchStencil1 : public TestBase { + class TestScratchStencil1 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. - // Temporary storage. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }, true); + // Temporary storage. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }, true); -public: + public: - TestScratchStencil1(int radius=2) : - TestBase("test_scratch_1d", radius) { } + TestScratchStencil1(int radius=2) : + TestBase("test_scratch_1d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Define values in scratch var 'B'. - B(x) EQUALS def_1d(A, t, x, 1, 0); + // Define values in scratch var 'B'. + B(x) EQUALS def_1d(A, t, x, 1, 0); - // Set 'A' from scratch var values. - A(t+1, x) EQUALS def_no_t_1d(B, x-4, 2, 3) + def_no_t_1d(B, x+6, 0, 1); - } -}; + // Set 'A' from scratch var values. + A(t+1, x) EQUALS def_no_t_1d(B, x-4, 2, 3) + def_no_t_1d(B, x+6, 0, 1); + } + }; -// Create an object of type 'TestScratchStencil1', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestScratchStencil1 TestScratchStencil1_instance; + // Create an object of type 'TestScratchStencil1', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestScratchStencil1 TestScratchStencil1_instance; -class TestScratchStencil3 : public TestBase { + class TestScratchStencil3 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. - // Temporary storage. - yc_var_proxy t1 = yc_var_proxy("t1", get_soln(), { x, y, z }, true); - yc_var_proxy t2 = yc_var_proxy("t2", get_soln(), { x, y, z }, true); - yc_var_proxy t3 = yc_var_proxy("t3", get_soln(), { x, y, z }, true); + // Temporary storage. + yc_var_proxy t1 = yc_var_proxy("t1", get_soln(), { x, y, z }, true); + yc_var_proxy t2 = yc_var_proxy("t2", get_soln(), { x, y, z }, true); + yc_var_proxy t3 = yc_var_proxy("t3", get_soln(), { x, y, z }, true); -public: + public: - TestScratchStencil3(int radius=2) : - TestBase("test_scratch_3d", radius) { } + TestScratchStencil3(int radius=2) : + TestBase("test_scratch_3d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Set scratch vars. - t1(x, y, z) EQUALS def_3d(A, t, x, 0, 1, y, 2, 1, z, 1, 0); - t2(x, y, z) EQUALS def_3d(A, t, x, 1, 0, y, 0, 2, z, 0, 1); + // Set scratch vars. + t1(x, y, z) EQUALS def_3d(A, t, x, 0, 1, y, 2, 1, z, 1, 0); + t2(x, y, z) EQUALS def_3d(A, t, x, 1, 0, y, 0, 2, z, 0, 1); - // Set a scratch var from other scratch vars. - t3(x, y, z) EQUALS t1(x-1, y+1, z) + t2(x, y, z-1); + // Set a scratch var from other scratch vars. + t3(x, y, z) EQUALS t1(x-1, y+1, z) + t2(x, y, z-1); - // Update A from scratch vars. - A(t+1, x, y, z) EQUALS A(t, x, y, z) + - def_no_t_3d(t1, x, 2, 0, y, 0, 1, z, 1, 0) + - def_no_t_3d(t3, x, 1, 0, y, 0, 1, z, 0, 2); - } -}; + // Update A from scratch vars. + A(t+1, x, y, z) EQUALS A(t, x, y, z) + + def_no_t_3d(t1, x, 2, 0, y, 0, 1, z, 1, 0) + + def_no_t_3d(t3, x, 1, 0, y, 0, 1, z, 0, 2); + } + }; -// Create an object of type 'TestScratchStencil3', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestScratchStencil3 TestScratchStencil3_instance; + // Create an object of type 'TestScratchStencil3', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestScratchStencil3 TestScratchStencil3_instance; -// Test the use of boundary code in sub-domains. -class TestBoundaryStencil1 : public TestBase { + // Test the use of boundary code in sub-domains. + class TestBoundaryStencil1 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. -public: + public: - TestBoundaryStencil1(int radius=2) : - TestBase("test_boundary_1d", radius) { } + TestBoundaryStencil1(int radius=2) : + TestBase("test_boundary_1d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Define interior sub-domain. - auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); + // Define interior sub-domain. + auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); - // Define interior points. - auto u = def_1d(A, t, x, 0, 1); - A(t+1, x) EQUALS u IF_DOMAIN sd0; + // Define interior points. + auto u = def_1d(A, t, x, 0, 1); + A(t+1, x) EQUALS u IF_DOMAIN sd0; - // Define exterior points. - A(t+1, x) EQUALS -u IF_DOMAIN !sd0; - } -}; + // Define exterior points. + A(t+1, x) EQUALS -u IF_DOMAIN !sd0; + } + }; -// Create an object of type 'TestBoundaryStencil1', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestBoundaryStencil1 TestBoundaryStencil1_instance; + // Create an object of type 'TestBoundaryStencil1', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestBoundaryStencil1 TestBoundaryStencil1_instance; -class TestBoundaryStencil2 : public TestBase { + class TestBoundaryStencil2 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. -public: + public: - TestBoundaryStencil2(int radius=2) : - TestBase("test_boundary_2d", radius) { } + TestBoundaryStencil2(int radius=2) : + TestBase("test_boundary_2d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Sub-domain is rectangle interior. - auto sd0 = - (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && - (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6); + // Sub-domain is rectangle interior. + auto sd0 = + (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && + (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6); - // Set A w/different stencils depending on condition. - A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 1, 0) IF_DOMAIN sd0; - A(t+1, x, y) EQUALS def_2d(A, t, x, 1, 0, y, 0, 2) IF_DOMAIN !sd0; - } -}; + // Set A w/different stencils depending on condition. + A(t+1, x, y) EQUALS def_2d(A, t, x, 0, 2, y, 1, 0) IF_DOMAIN sd0; + A(t+1, x, y) EQUALS def_2d(A, t, x, 1, 0, y, 0, 2) IF_DOMAIN !sd0; + } + }; -// Create an object of type 'TestBoundaryStencil2', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestBoundaryStencil2 TestBoundaryStencil2_instance; + // Create an object of type 'TestBoundaryStencil2', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestBoundaryStencil2 TestBoundaryStencil2_instance; -class TestBoundaryStencil3 : public TestBase { + class TestBoundaryStencil3 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y, z }); // time-varying var. -public: + public: - TestBoundaryStencil3(int radius=2) : - TestBase("test_boundary_3d", radius) { } + TestBoundaryStencil3(int radius=2) : + TestBase("test_boundary_3d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Sub-domain is rectangle interior. - auto sd0 = - (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && - (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6) && - (z >= first_domain_index(z) + 6) && (z <= last_domain_index(z) - 4); + // Sub-domain is rectangle interior. + auto sd0 = + (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3) && + (y >= first_domain_index(y) + 4) && (y <= last_domain_index(y) - 6) && + (z >= first_domain_index(z) + 6) && (z <= last_domain_index(z) - 4); - // Set A w/different stencils depending on condition. - A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 1, 0, z, 0, 1) IF_DOMAIN sd0; - A(t+1, x, y, z) EQUALS def_3d(A, t, x, 1, 0, y, 0, 2, z, 1, 0) IF_DOMAIN !sd0; - } -}; + // Set A w/different stencils depending on condition. + A(t+1, x, y, z) EQUALS def_3d(A, t, x, 0, 2, y, 1, 0, z, 0, 1) IF_DOMAIN sd0; + A(t+1, x, y, z) EQUALS def_3d(A, t, x, 1, 0, y, 0, 2, z, 1, 0) IF_DOMAIN !sd0; + } + }; -// Create an object of type 'TestBoundaryStencil3', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestBoundaryStencil3 TestBoundaryStencil3_instance; + // Create an object of type 'TestBoundaryStencil3', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestBoundaryStencil3 TestBoundaryStencil3_instance; -// Test step condition. -class TestStepCondStencil1 : public TestBase { + // Test step condition. + class TestStepCondStencil1 : public TestBase { -protected: + protected: - // Indices. - yc_index_node_ptr b = new_misc_index("b"); + // Indices. + yc_index_node_ptr b = new_misc_index("b"); - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { b }); + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { b }); -public: + public: - TestStepCondStencil1(int radius=2) : - TestBase("test_step_cond_1d", radius) { } + TestStepCondStencil1(int radius=2) : + TestBase("test_step_cond_1d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Time condition. - auto tc0 = (t % 2 == 0); + // Time condition. + auto tc0 = (t % 2 == 0); - // Var condition. - auto vc0 = (B(0) > B(1)); + // Var condition. + auto vc0 = (B(0) > B(1)); - // Set A w/different stencils depending on the conditions. It is - // the programmer's responsibility to ensure that the conditions are - // exclusive when necessary. It is not checked at compile or - // run-time. + // Set A w/different stencils depending on the conditions. It is + // the programmer's responsibility to ensure that the conditions are + // exclusive when necessary. It is not checked at compile or + // run-time. - // Use this equation when t is even. - A(t+1, x) EQUALS def_1d(A, t, x, 0, 0) IF_STEP tc0; + // Use this equation when t is even. + A(t+1, x) EQUALS def_1d(A, t, x, 0, 0) IF_STEP tc0; - // Use this equation when t is odd and B(0) > B(1). - A(t+1, x) EQUALS def_1d(A, t, x, 1, 2) IF_STEP !tc0 && vc0; + // Use this equation when t is odd and B(0) > B(1). + A(t+1, x) EQUALS def_1d(A, t, x, 1, 2) IF_STEP !tc0 && vc0; - // Use this equation when t is even and B(0) <= B(1). - A(t+1, x) EQUALS def_1d(A, t, x, 2, 0) IF_STEP !tc0 && !vc0; - } -}; + // Use this equation when t is even and B(0) <= B(1). + A(t+1, x) EQUALS def_1d(A, t, x, 2, 0) IF_STEP !tc0 && !vc0; + } + }; -// Create an object of type 'TestStepCondStencil1', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestStepCondStencil1 TestStepCondStencil1_instance; + // Create an object of type 'TestStepCondStencil1', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestStepCondStencil1 TestStepCondStencil1_instance; -// Test the use of conditional updates with scratch-pad vars. -class TestScratchBoundaryStencil1 : public TestBase { + // Test the use of conditional updates with scratch-pad vars. + class TestScratchBoundaryStencil1 : public TestBase { -protected: + protected: - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); // time-varying var. - // Temporary storage. - yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }, true); + // Temporary storage. + yc_var_proxy B = yc_var_proxy("B", get_soln(), { x }, true); -public: + public: - TestScratchBoundaryStencil1(int radius=2) : - TestBase("test_scratch_boundary_1d", radius) { } + TestScratchBoundaryStencil1(int radius=2) : + TestBase("test_scratch_boundary_1d", radius) { } - // Define equation to apply to all points in 'A' var. - virtual void define() { + // Define equation to apply to all points in 'A' var. + virtual void define() { - // Define values in scratch var 'B' using current values from 'A'. - B(x) EQUALS def_1d(A, t, x, 1, 0); + // Define values in scratch var 'B' using current values from 'A'. + B(x) EQUALS def_1d(A, t, x, 1, 0); - // Define sub-domain. - auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); + // Define sub-domain. + auto sd0 = (x >= first_domain_index(x) + 5) && (x <= last_domain_index(x) - 3); - // Define next values for 'A' from scratch var values. - auto v = def_no_t_1d(B, x-6, 2, 3) - def_no_t_1d(B, x+7, 0, 2); - A(t+1, x) EQUALS v IF_DOMAIN sd0; - A(t+1, x) EQUALS -v IF_DOMAIN !sd0; - } -}; + // Define next values for 'A' from scratch var values. + auto v = def_no_t_1d(B, x-6, 2, 3) - def_no_t_1d(B, x+7, 0, 2); + A(t+1, x) EQUALS v IF_DOMAIN sd0; + A(t+1, x) EQUALS -v IF_DOMAIN !sd0; + } + }; + + // Create an object of type 'TestScratchBoundaryStencil1', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestScratchBoundaryStencil1 TestScratchBoundaryStencil1_instance; -// Create an object of type 'TestScratchBoundaryStencil1', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestScratchBoundaryStencil1 TestScratchBoundaryStencil1_instance; + // A stencil that uses svml math functions. + class TestFuncStencil1 : public TestBase { -// A stencil that uses svml math functions. -class TestFuncStencil1 : public TestBase { + protected: -protected: + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); + yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x }); + yc_var_proxy C = yc_var_proxy("C", get_soln(), { t, x }); - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x }); - yc_var_proxy B = yc_var_proxy("B", get_soln(), { t, x }); - yc_var_proxy C = yc_var_proxy("C", get_soln(), { t, x }); + public: -public: + TestFuncStencil1(int radius=1) : + TestBase("test_func_1d", radius) { } - TestFuncStencil1(int radius=1) : - TestBase("test_func_1d", radius) { } + virtual void define() { + A(t+1, x) EQUALS cos(A(t, x)) - 2 * sin(A(t, x)); + B(t+1, x) EQUALS pow(def_1d(B, t, x, 0, 1), 1.0/2.5); + C(t+1, x) EQUALS atan(def_1d(A, t+1, x, 1, 0) + cbrt(C(t, x+1))); + } + }; - virtual void define() { - A(t+1, x) EQUALS cos(A(t, x)) - 2 * sin(A(t, x)); - B(t+1, x) EQUALS pow(def_1d(B, t, x, 0, 1), 1.0/2.5); - C(t+1, x) EQUALS atan(def_1d(A, t+1, x, 1, 0) + cbrt(C(t, x+1))); - } -}; + // Create an object of type 'TestFuncStencil1', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestFuncStencil1 TestFuncStencil1_instance; -// Create an object of type 'TestFuncStencil1', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestFuncStencil1 TestFuncStencil1_instance; + // A stencil that has vars but no stencil equation. + class TestEmptyStencil2 : public TestBase { -// A stencil that has vars but no stencil equation. -class TestEmptyStencil2 : public TestBase { + protected: -protected: + // Vars. + yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. - // Vars. - yc_var_proxy A = yc_var_proxy("A", get_soln(), { t, x, y }); // time-varying var. + public: -public: + TestEmptyStencil2(int radius=1) : + TestBase("test_empty_2d", radius) { } - TestEmptyStencil2(int radius=1) : - TestBase("test_empty_2d", radius) { } + virtual void define() { } + }; - virtual void define() { } -}; + // Create an object of type 'TestEmptyStencil2', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestEmptyStencil2 TestEmptyStencil2_instance; -// Create an object of type 'TestEmptyStencil2', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestEmptyStencil2 TestEmptyStencil2_instance; + // A stencil that no vars and no stencil equation. + // Kernel must be built with domain_dims and step_dim options. + class TestEmptyStencil0: public TestBase { -// A stencil that no vars and no stencil equation. -// Kernel must be built with domain_dims and step_dim options. -class TestEmptyStencil0: public TestBase { + protected: -protected: + public: -public: + TestEmptyStencil0(int radius=1) : + TestBase("test_empty", radius) { } - TestEmptyStencil0(int radius=1) : - TestBase("test_empty", radius) { } + virtual void define() { } + }; - virtual void define() { } -}; + // Create an object of type 'TestEmptyStencil0', + // making it available in the YASK compiler utility via the + // '-stencil' commmand-line option or the 'stencil=' build option. + static TestEmptyStencil0 TestEmptyStencil0_instance; -// Create an object of type 'TestEmptyStencil0', -// making it available in the YASK compiler utility via the -// '-stencil' commmand-line option or the 'stencil=' build option. -static TestEmptyStencil0 TestEmptyStencil0_instance; +} // namespace. diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index d6555054..a71743a8 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -86,7 +86,9 @@ ($) $result .= "// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility.\n". "#include \"yask_compiler_api.hpp\"\n". "using namespace std;\n". - "using namespace yask;\n"; + "using namespace yask;\n". + "\n// Create an anonymous namespace to ensure that types are local.\n". + "namespace {\n"; } # For other code, make substitutions and append changes. @@ -148,6 +150,7 @@ ($) } } close INF; + $result .= "\n} // anonymous namespace.\n"; if ($OPT{in_place}) { From 58f258971209615a2f31fddafba88ea68b02c703 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 7 Jun 2019 15:48:44 -0700 Subject: [PATCH 36/62] Add ability to add various call-backs. --- include/aux/yk_solution_api.hpp | 70 +++++- include/yask_compiler_api.hpp | 102 +++------ src/compiler/lib/Cpp.hpp | 3 +- src/compiler/lib/Solution.hpp | 23 +- src/compiler/lib/YaskKernel.cpp | 45 ++-- src/compiler/tests/yask_compiler_api_test.cpp | 9 + src/kernel/lib/context.cpp | 6 +- src/kernel/lib/context.hpp | 39 +++- src/kernel/lib/soln_apis.cpp | 25 +- .../tests/yask_kernel_api_exception_test.py | 213 +----------------- src/kernel/tests/yask_kernel_api_test.py | 2 +- src/stencils/Iso3dfdStencil.cpp | 43 ++-- src/stencils/SSGElasticStencil.cpp | 1 - 13 files changed, 218 insertions(+), 363 deletions(-) diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index 853d5646..249a9247 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -879,6 +879,72 @@ namespace yask { virtual int get_default_numa_preferred() const =0; +#ifndef SWIG + /// **[Advanced]** Callback hook with \ref yk_solution parameter. + typedef std::function hook_fn_t; + + /// **[Advanced]** Callback hook with \ref yk_solution and step-index parameters. + typedef std::function hook_fn_2idx_t; + + /// **[Advanced]** Register a hook function to be called at the beginning of yk_solution::prepare_solution(). + /** + A reference to the \ref yk_solution is passed to the `hook_fn`. + + If this method is called more than once, the hook functions will be + called in the order registered. + + @note Not available in the Python API. + */ + virtual void + call_before_prepare_solution(hook_fn_t hook_fn + /**< [in] callback function */) =0; + + /// **[Advanced]** Register a hook function to be called at the end of yk_solution::prepare_solution(). + /** + A reference to the \ref yk_solution is passed to the `hook_fn`. + + If this method is called more than once, the hook functions will be + called in the order registered. + + @note Not available in the Python API. + */ + virtual void + call_after_prepare_solution(hook_fn_t hook_fn + /**< [in] callback function */) =0; + + /// **[Advanced]** Register a hook function to be called at the beginning of yk_solution::run_solution(). + /** + A reference to the \ref yk_solution + and the `first_step_index` and `last_step_index` passed to run_solution() + are passed to the `hook_fn`. + + If this method is called more than once, the hook functions will be + called in the order registered. + + @note Not available in the Python API. + */ + virtual void + call_before_run_solution(hook_fn_2idx_t hook_fn + /**< [in] callback function */) =0; + + /// **[Advanced]** Register a hook function to be called at the end of yk_solution::run_solution(). + /** + A reference to the \ref yk_solution + and the `first_step_index` and `last_step_index` passed to run_solution() + are passed to the `hook_fn`. + + If this method is called more than once, the hook functions will be + called in the order registered. + + @note Not available in the Python API. + */ + virtual void + call_after_run_solution(hook_fn_2idx_t hook_fn + /**< [in] callback function */) =0; +#endif + /// **[Advanced]** Merge YASK variables with another solution. /** Calls yk_var::fuse_vars() for each pair of vars that have the same name @@ -958,7 +1024,7 @@ namespace yask { fuse_grids(yk_solution_ptr source) { fuse_vars(source); } - }; + }; // yk_solution. /// Statistics from calls to run_solution(). /** @@ -1013,7 +1079,7 @@ namespace yask { */ virtual double get_elapsed_secs() =0; - }; + }; // yk_stats. /** @}*/ } // namespace yask. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 2d484df6..8e72f382 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -217,7 +217,7 @@ namespace yask { /** C++ initializer-list version with same semantics as the vector version of new_var(). - @note This version is not available (or needed) in the Python API. + @note Not available in the Python API. Use the vector version. @returns Pointer to the new \ref yc_var object. */ virtual yc_var_ptr @@ -258,7 +258,7 @@ namespace yask { /** C++ initializer-list version with same semantics as the vector version of new_scratch_var(). - @note This version is not available (or needed) in the Python API. + @note Not available in the Python API. Use the vector version. @returns Pointer to the new \ref yc_var object. */ virtual yc_var_ptr @@ -364,7 +364,8 @@ namespace yask { @note "avx512f" is allowed as an alias for "avx512". @warning *Side effect:* Applies optimizations to the equation(s), so some pointers to nodes in the original equations may refer to modified nodes or nodes - that have been optimized away after calling format(). + that have been optimized away after calling format(). In general, do not use + pointers to nodes across calls to format(). */ virtual void format(const std::string& format_type @@ -373,73 +374,40 @@ namespace yask { /**< [out] Pointer to object to receive formatted output. See \ref yask_output_factory. */) =0; - /// Keys for calling insert_kernel_code(). - enum kernel_code_key - { - /// Code to be called at the end of constructing a \ref yk_solution via - /// yk_factory::new_solution(). - after_new_solution, - - /// Code to be called at the beginning of yk_solution::prepare_solution(). - before_prepare_solution, - - /// Code to be called at the end of yk_solution::prepare_solution(). - after_prepare_solution, - - /// Code to be called at the beginning of each call to yk_solution::run_solution(). - /** The `idx_t`-type variables `first_step_index` and `last_step_index` are - available to the inserted code with the values passed to - yk_solution::run_solution(). - - @note yk_solution::run_solution() may be called several times - by the `bin/yask.sh` utility or any custom application. - */ - before_run_solution, - - /// Code to be called at the end of each call to yk_solution::prepare_solution(). - /** The `idx_t`-type variables `first_step_index` and `last_step_index` are - available to the inserted code with the values passed to - yk_solution::run_solution(). - */ - after_run_solution - - }; - - /// **[Advanced]** Add block of code to be run in the kernel at the specified time. - /** - This is a mechanism to insert any valid code into the kernel library - that will be built from the file(s) generated by the YASK compiler. - The code will be run when indicated by the `key` argument. - If this API is called more than once with the same key, the code will - be appended. - Be sure that your code is well-formed, including a closing semicolon - if applicable. - If there are any syntax errors or other issues, they will not be visible until - the kernel is compiled. - - Code is inserted as methods in the created solution. Thus, the "`this`" pointer - refers to the current \ref yk_solution object, and \ref yk_solution - methods may be called directly. - - Of course, equivalent code can be added directly to any custom application using - the kernel library. - However, the method provided by insert_kernel_code() is useful when using the - provided YASK kernel-performance utility launched via `bin/yask.sh`. - It also provides a method to provide consistent kernel code when the + /// **[Advanced]** Add block of custom C++ code to the kernel solution. + /** + This block of code will be executed immediately after the stencil solution + is constructed in the kernel, i.e., at the end of a call to + yk_factory::new_solution(). + + Common uses of this facility include setting default run-time settings + such as block sizes and registering call-back routines, e.g., via + yk_solution::call_before_prepare_solution(); + + Unlike yk_solution::call_before_prepare_solution() and similar functions + which have `std::function` parameters, + the parameter to this function is a string because the code is not compiled + until the kernel library is built. + + Alternatively , equivalent code can be added directly to any + custom application using the kernel library APIs. However, this + function is useful when using the provided YASK + kernel-performance utility launched via `bin/yask.sh`. It also + provides a method to provide consistent kernel code when the kernel library is used in multiple applications. */ virtual void - insert_kernel_code(kernel_code_key key - /**< [in] See \ref kernel_code_key. */, - std::string code - /**< [in] Code to be inserted. */) =0; + call_after_new_solution(const std::string& code + /**< [in] Code to be inserted, using + `kernel_soln` of type \ref yk_solution + to access the kernel solution. */) =0; - /// A convenience macro for calling yask::yc_solution::insert_kernel_code(). + /// **[Advanced]** A convenience macro for calling yask::yc_solution::call_after_new_solution(). /** - Allows inserting code without the surrounding quotes, making it easier - to format in many editors and IDEs. + Allows writing the code without the surrounding quotes, making it easier + to format in many editors and IDEs (and perhaps look somewhat like a lambda function). */ -#define INSERT_YASK_KERNEL_CODE(key, ...) insert_kernel_code(key, #__VA_ARGS__) +#define CALL_AFTER_NEW_SOLUTION(...) call_after_new_solution(#__VA_ARGS__) /// **[Advanced]** Explicitly define and order the domain dimensions used in the solution. /** @@ -460,7 +428,7 @@ namespace yask { /** C++ initializer-list version with same semantics as the vector version of new_var(). - @note This version is not available (or needed) in the Python API. + @note Not available in the Python API. Use the vector version. */ virtual void set_domain_dims(const std::initializer_list& dims @@ -687,7 +655,7 @@ namespace yask { See example code shown in yc_solution::new_var(). - @note This version is not available (or needed) in the Python API. + @note Not available in the Python API. Use the vector version. @returns Pointer to AST node used to read or write from point in var. */ virtual yc_var_point_node_ptr @@ -719,7 +687,7 @@ namespace yask { /** C++ initializer-list version with same semantics as the vector version of new_relative_var_point(). - @note This version is not available (or needed) in the Python API. + @note Not available in the Python API. Use the vector version. @returns Pointer to AST node used to read or write from point in var. */ virtual yc_var_point_node_ptr new_relative_var_point(const std::initializer_list& dim_offsets) = 0; diff --git a/src/compiler/lib/Cpp.hpp b/src/compiler/lib/Cpp.hpp index c9a2be02..db705c67 100644 --- a/src/compiler/lib/Cpp.hpp +++ b/src/compiler/lib/Cpp.hpp @@ -257,7 +257,7 @@ namespace yask { protected: EqBundlePacks& _eqBundlePacks; // packs of bundles w/o inter-dependencies. EqBundles& _clusterEqBundles; // eq-bundles for scalar and vector. - string _context, _context_base; // class names; + string _context, _context_base, _context_hook; // class names; // Print an expression as a one-line C++ comment. void addComment(ostream& os, EqBundle& eq); @@ -293,6 +293,7 @@ namespace yask { // name of C++ struct. _context = "StencilContext_" + _stencil.getName(); _context_base = _context + "_data"; + _context_hook = _context + "_hook"; } virtual ~YASKCppPrinter() { } diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 205d010e..1964ed05 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -62,11 +62,8 @@ namespace yask { // Settings for the solution. CompilerSettings _settings; - // Code extensions that overload default functions from YASK in the - // generated code for this solution. - typedef vector CodeList; - typedef map ExtensionsList; - ExtensionsList _extensions; + // Code extensions. + vector _kernel_code; private: @@ -103,16 +100,7 @@ namespace yask { _settings = settings; } virtual const Dimensions& getDims() { return _dims; } - - // Get user-provided code for the given section. - CodeList * getExtensionCode(kernel_code_key section) - { - auto elem = _extensions.find(section); - if ( elem != _extensions.end() ) { - return &elem->second; - } - return NULL; - } + virtual const vector& getKernelCode() { return _kernel_code; } // Get the messsage output stream. virtual std::ostream& get_ostr() const { @@ -191,9 +179,8 @@ namespace yask { return ev; } virtual void - insert_kernel_code(kernel_code_key key, - string code) { - _extensions[key].push_back(code); + call_after_new_solution(const string& code) { + _kernel_code.push_back(code); } virtual void add_flow_dependency(yc_equation_node_ptr from, yc_equation_node_ptr to) { diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index e9e5c433..7b4046ff 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -484,7 +484,7 @@ namespace yask { os << "\n // Make a new var iff its dims match any in the stencil.\n" " // Returns pointer to the new var or nullptr if no match.\n" " virtual VarBasePtr newStencilVar(const std::string& name," - " const VarDimNames& dims) {\n" + " const VarDimNames& dims) override {\n" " VarBasePtr gp;\n" << newVarCode << " return gp;\n" @@ -492,7 +492,7 @@ namespace yask { // Scratch-vars method. os << "\n // Make new scratch vars.\n" - " virtual void makeScratchVars(int num_threads) {\n" << + " virtual void makeScratchVars(int num_threads) override {\n" << scratchCode << " } // newScratchVars\n"; @@ -804,7 +804,16 @@ namespace yask { // Print final YASK context. void YASKCppPrinter::printContext(ostream& os) { - os << endl << " ////// Overall stencil-specific context //////" << endl << + os << "\n ////// User-provided code //////" << endl << + "struct " << _context_hook << " {\n" + " static void call_after_new_solution(yk_solution& kernel_soln) {\n" + " // Code provided by user.\n"; + for (auto& code : _stencil.getKernelCode()) + os << " " << code << "\n"; + os << " }\n" + "};\n"; + + os << "\n ////// Overall stencil-specific context //////" << endl << "struct " << _context << " : public " << _context_base << " {" << endl; // Stencil eqBundle objects. @@ -877,8 +886,10 @@ namespace yask { os << " stPacks.push_back(" << bpName << ");\n"; } - os << "\n after_new_solution_hook();\n" - " } // Ctor.\n"; + os << "\n // Call code provided by user.\n" << + _context_hook << "::call_after_new_solution(*this);\n"; + + os << " } // Ctor.\n"; // Dims creator. os << "\n // Create Dims object.\n" @@ -931,30 +942,6 @@ namespace yask { os << " return p;\n" " }\n"; - os << "\n // Code provided by user.\n"; - map protos - { { yc_solution::after_new_solution, "after_new_solution_hook()" }, - { yc_solution::before_prepare_solution, "before_prepare_solution_hook()" }, - { yc_solution::after_prepare_solution, "after_prepare_solution_hook()" }, - { yc_solution::before_run_solution, - "before_run_solution_hook(idx_t first_step_index, idx_t last_step_index)" }, - { yc_solution::after_run_solution, - "after_run_solution_hook(idx_t first_step_index, idx_t last_step_index)" } }; - for (auto& i : protos) { - auto key = i.first; - auto& proto = i.second; - os << " virtual void " << proto << " override {\n" - " STATE_VARS(this);\n" - " TRACE_MSG(\"" << proto << "...\");\n"; - auto *extraCode = _stencil.getExtensionCode(key); - if (extraCode) { - for ( auto code : *extraCode ) - os << " " << code << ";\n"; - } - os << " TRACE_MSG(\"" << proto << " done\");\n" - " }\n"; - } - os << "}; // " << _context << endl; } diff --git a/src/compiler/tests/yask_compiler_api_test.cpp b/src/compiler/tests/yask_compiler_api_test.cpp index 785de22c..4d96cb51 100644 --- a/src/compiler/tests/yask_compiler_api_test.cpp +++ b/src/compiler/tests/yask_compiler_api_test.cpp @@ -104,6 +104,15 @@ int main() { auto n_eq1 = fac.new_equation_node(n_lhs, -n8, !sd0); cout << n_eq1->format_simple() << endl; + // Insert code that will register a run-time hook. + soln->CALL_AFTER_NEW_SOLUTION + ( + kernel_soln.call_after_prepare_solution + ([](yk_solution& ksoln) { + auto vars = ksoln.get_vars(); + }); + ); + cout << "Solution '" << soln->get_name() << "' contains " << soln->get_num_vars() << " var(s), and " << soln->get_num_equations() << " equation(s)." << endl; diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index b1a7aab5..fae2623b 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -186,7 +186,8 @@ namespace yask { STATE_VARS(this); // User-provided code. - before_run_solution_hook(first_step_index, last_step_index); + call_2idx_hooks(_before_run_solution_hooks, + first_step_index, last_step_index); // Start timer. run_time.start(); @@ -561,7 +562,8 @@ namespace yask { run_time.stop(); // User-provided code. - after_run_solution_hook(first_step_index, last_step_index); + call_2idx_hooks(_after_run_solution_hooks, + first_step_index, last_step_index); } // run_solution(). diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index a6fe3b66..a9fc8c09 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -136,7 +136,7 @@ namespace yask { get_elapsed_secs() { return run_time; } }; - // Collections of things in a context. + // Things in a context. class StencilBundleBase; class BundlePack; typedef std::vector StencilBundleList; @@ -167,6 +167,14 @@ namespace yask { std::map >& _data_buf, const std::string& type); + // Callbacks. + typedef std::vector hook_fn_vec; + hook_fn_vec _before_prepare_solution_hooks; + hook_fn_vec _after_prepare_solution_hooks; + typedef std::vector hook_fn_2idx_vec; + hook_fn_2idx_vec _before_run_solution_hooks; + hook_fn_2idx_vec _after_run_solution_hooks; + public: // Name. @@ -494,14 +502,11 @@ namespace yask { const VarDimNames& dims, const VarDimSizes* sizes); - // Stubs for user-inserted code. - virtual void after_new_solution_hook() { } - virtual void before_prepare_solution_hook() { } - virtual void after_prepare_solution_hook() { } - virtual void before_run_solution_hook(idx_t first_step_index, - idx_t last_step_index) { } - virtual void after_run_solution_hook(idx_t first_step_index, - idx_t last_step_index) { } + // Call user-inserted code. + virtual void call_hooks(hook_fn_vec& hook_fns); + virtual void call_2idx_hooks(hook_fn_2idx_vec& hook_fns, + idx_t first_step_index, + idx_t last_step_index); // APIs. // See yask_kernel_api.hpp. @@ -636,6 +641,22 @@ namespace yask { STATE_VARS_CONST(this); return opts->_numa_pref; } + virtual void + call_before_prepare_solution(hook_fn_t hook_fn) { + _before_prepare_solution_hooks.push_back(hook_fn); + } + virtual void + call_after_prepare_solution(hook_fn_t hook_fn) { + _after_prepare_solution_hooks.push_back(hook_fn); + } + virtual void + call_before_run_solution(hook_fn_2idx_t hook_fn) { + _before_run_solution_hooks.push_back(hook_fn); + } + virtual void + call_after_run_solution(hook_fn_2idx_t hook_fn) { + _after_run_solution_hooks.push_back(hook_fn); + } // Auto-tuner methods. virtual void eval_auto_tuner(idx_t num_steps); diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 08702a37..8d039750 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -77,13 +77,34 @@ namespace yask { SET_SOLN_API(set_min_pad_size, opts->_min_pad_sizes[dim] = n, false, true, false, false) #undef SET_SOLN_API + // Callbacks. + void StencilContext::call_hooks(hook_fn_vec& hook_fns) { + STATE_VARS(this); + int n=0; + for (auto& cb : hook_fns) { + TRACE_MSG("Calling hook " << (++n) << "..."); + cb(*this); + } + } + void StencilContext::call_2idx_hooks(hook_fn_2idx_vec& hook_fns, + idx_t first_step_index, + idx_t last_step_index) { + STATE_VARS(this); + int n=0; + for (auto& cb : hook_fns) { + TRACE_MSG("Calling hook " << (++n) << "..."); + cb(*this, first_step_index, last_step_index); + } + } + // Allocate vars and MPI bufs. // Initialize some data structures. void StencilContext::prepare_solution() { STATE_VARS(this); + TRACE_MSG("Calling prepare_solution()..."); // User-provided code. - before_prepare_solution_hook(); + call_hooks(_before_prepare_solution_hooks); // Don't continue until all ranks are this far. env->global_barrier(); @@ -168,7 +189,7 @@ namespace yask { init_stats(); // User-provided code. - after_prepare_solution_hook(); + call_hooks(_after_prepare_solution_hooks); } // prepare_solution(). diff --git a/src/kernel/tests/yask_kernel_api_exception_test.py b/src/kernel/tests/yask_kernel_api_exception_test.py index 79a8b444..d5e33de5 100755 --- a/src/kernel/tests/yask_kernel_api_exception_test.py +++ b/src/kernel/tests/yask_kernel_api_exception_test.py @@ -30,128 +30,6 @@ import argparse import yask_kernel -# Read data from var using NumPy ndarray. -def read_var(var, timestep) : - - # Ignore with fixed-sized vars. - if var.is_fixed_size(): - return - - print("Reading var '" + var.get_name() + "' at time " + repr(timestep) + "...") - - # Create indices for YASK and shape for NumPy. - first_indices = [] - last_indices = [] - shape = [] - nelems = 1 - for dname in var.get_dim_names() : - - if dname == soln.get_step_dim_name() : - - # Read one timestep only. - # So, we don't need to add a time axis in 'shape'. - first_indices += [timestep] - last_indices += [timestep] - - # Domain dim? - elif dname in soln.get_domain_dim_names() : - - # Full domain in this rank. - first_idx = soln.get_first_rank_domain_index(dname) - last_idx = soln.get_last_rank_domain_index(dname) - - # Read one point in the halo, too. - first_idx -= 1 - last_idx += 1 - - first_indices += [first_idx] - last_indices += [last_idx] - shape += [last_idx - first_idx + 1] - nelems *= last_idx - first_idx + 1 - - # Misc dim? - else : - - # Read first index only. - first_indices += [var.get_first_misc_index(dname)] - last_indices += [var.get_first_misc_index(dname)] - - # Create a NumPy ndarray to hold the extracted data. - ndarray1 = np.empty(shape, dtype, 'C'); - - print("Reading " + repr(nelems) + " element(s)...") - nread = var.get_elements_in_slice(ndarray1.data, first_indices, last_indices) - print(ndarray1) - - # Raw access to this var. - if soln.get_element_bytes() == 4 : - ptype = ct.POINTER(ct.c_float) - else : - ptype = ct.POINTER(ct.c_double) - raw_ptr = var.get_raw_storage_buffer() - fp_ptr = ct.cast(int(raw_ptr), ptype) - num_elems = var.get_num_storage_elements() - print("Raw data: " + repr(fp_ptr[0]) + ", ..., " + repr(fp_ptr[num_elems-1])) - #ndarray2 = np.fromiter(fp_ptr, dtype, num_elems); print(ndarray2) - -# Init var using NumPy ndarray. -def init_var(var, timestep) : - print("Initializing var '" + var.get_name() + "' at time " + repr(timestep) + "...") - - # Create indices for YASK, shape & point for NumPy. - first_indices = [] - last_indices = [] - shape = [] - point = () - nelems = 1 - for dname in var.get_dim_names() : - - if dname == soln.get_step_dim_name() : - - # Write one timestep only. - # So, we don't need to add a time axis in 'shape'. - first_indices += [timestep] - last_indices += [timestep] - - # Domain dim? - elif dname in soln.get_domain_dim_names() : - - # Full domain in this rank. - first_idx = soln.get_first_rank_domain_index(dname) - last_idx = soln.get_last_rank_domain_index(dname) - - # Write one point in the halo, too. - first_idx -= 1 - last_idx += 1 - - first_indices += [first_idx] - last_indices += [last_idx] - shape += [last_idx - first_idx + 1] - nelems *= last_idx - first_idx + 1 - - # Since the array covers one layer of points in the halo - # starting at 0,..,0, 1,..,1 is the first point in the - # computable domain. - point += (1,) - - # Misc dim? - else : - - # Write first index only. - first_indices += [var.get_first_misc_index(dname)] - last_indices += [var.get_first_misc_index(dname)] - - # Create a NumPy ndarray to hold the data. - ndarray = np.zeros(shape, dtype, 'C'); - - # Set one point to a non-zero value. - ndarray[point] = 21.0; - print(ndarray) - - print("Writing " + repr(nelems) + " element(s)...") - nset = var.set_elements_in_slice(ndarray.data, first_indices, last_indices) - print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) - # Main script. if __name__ == "__main__": @@ -189,15 +67,6 @@ def init_var(var, timestep) : # Set domain size in each dim. soln.set_overall_domain_size(dim_name, 128) - # Set block size. - soln.set_block_size(dim_name, 32) - - # Make a test fixed-size var. - fvar_sizes = () - for dim_name in soln_dims : - fvar_sizes += (5,) - fvar = soln.new_fixed_size_var("fvar", soln_dims, fvar_sizes) - # Exception test print("Exception Test: Call 'run_solution' without calling prepare_solution().") try: @@ -243,93 +112,13 @@ def init_var(var, timestep) : for var in soln.get_vars() : # Init all values including padding. - var.set_all_elements_same(-9.0) - - # Done with fixed-sized vars. - if var.is_fixed_size(): - continue - - # Init timestep 0 using NumPy. - # This will set one point in each rank. - init_var(var, 0) - read_var(var, 0) - - # Simple one-index example. - # Note that index relative to overall problem domain, - # so it will only appear in one rank. - one_index = 100 - one_indices = [] - - # Create indices to bound a subset of domain: - # Index 0 in time, and a small cube in center - # of overall problem. - # Note that indices are relative to overall problem domain, - # so the cube may be in one rank or it may be spread over - # more than one. - cube_radius = 20 - first_indices = [] - last_indices = [] - - for dname in var.get_dim_names() : - - # Step dim? - if dname == soln.get_step_dim_name() : - - # Add index for timestep zero (0) only. - one_indices += [0] - first_indices += [0] - last_indices += [0] - - # Domain dim? - elif dname in soln.get_domain_dim_names() : - - # Simple index for one point. - one_indices += [one_index] - - # Midpoint of overall problem in this dim. - midpt = soln.get_overall_domain_size(dname) // 2; - - # Create indices a small amount before and after the midpoint. - first_indices += [midpt - cube_radius] - last_indices += [midpt + cube_radius] - - # Misc dim? - else : - - # Add indices to set all allowed values. - # (This isn't really meaningful; it's just illustrative.) - one_indices += [var.get_first_misc_index(dname)] - first_indices += [var.get_first_misc_index(dname)] - last_indices += [var.get_last_misc_index(dname)] - - # Init value at one point. - nset = var.set_element(15.0, one_indices) - print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) - - # Init the values within the small cube. - nset = var.set_elements_in_slice_same(0.5, first_indices, last_indices) - print("Set " + repr(nset) + " element(s) in rank " + repr(env.get_rank_index())) - - # Print the initial contents of the var at timesteps 0 and 1. - read_var(var, 0) - read_var(var, 1) + var.set_all_elements_same(1.0) # Apply the stencil solution to the data. env.global_barrier() print("Running the solution for 1 step...") soln.run_solution(0) - # Print result at timestep 1. - for var in soln.get_vars() : - read_var(var, 1) - - print("Running the solution for 10 more steps...") - soln.run_solution(1, 10) - - # Print final result at timestep 11, assuming update was to t+1. - for var in soln.get_vars() : - read_var(var, 11) - print("Debug output captured:\n" + debug_output.get_string()) if num_exception != 2: diff --git a/src/kernel/tests/yask_kernel_api_test.py b/src/kernel/tests/yask_kernel_api_test.py index efc7a7ff..4e20add8 100755 --- a/src/kernel/tests/yask_kernel_api_test.py +++ b/src/kernel/tests/yask_kernel_api_test.py @@ -30,7 +30,7 @@ import argparse import yask_kernel as yk -# Prepare an NymPy ndarray to hold a slice of 'var'. +# Prepare a NumPy ndarray to hold a slice of 'var'. def make_ndarray(var, timestep) : # Create indices for YASK and shape for NumPy. diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 72f9e37c..2f542297 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -133,34 +133,39 @@ namespace { return next_p; } - // Add some code to the kernel to set default options. + // Add some code to the kernel to set default run-time options. virtual void add_kernel_code() { - auto soln = get_soln(); + auto soln = get_soln(); // pointer to compile-time soln. - // These best-known settings were found - // by automated and manual tuning. They are only applied - // for certain target configs. + // These best-known settings were found by automated and manual + // tuning. They are only applied for certain target configs. - // Settings are tested only for SP FP and radius 8. + // Settings are only for SP FP and radius 8, which + // can be checked by the YASK compiler. if (soln->get_element_bytes() == 4 && get_radius() == 8) { // Change the settings immediately after the kernel solution // is created. - soln->INSERT_YASK_KERNEL_CODE - (if (get_target_isa() == "avx512") { - set_block_size("x", 108); - set_block_size("y", 28); - set_block_size("z", 132); - } - else { - set_block_size("x", 48); - set_block_size("y", 64); - set_block_size("z", 112); - } - ); + soln->CALL_AFTER_NEW_SOLUTION + ( + // Add extra padding in all dimensions. + kernel_soln.apply_command_line_options("-ep 1"); + + // Check target ISA at kernel run-time for block-size. + auto isa = kernel_soln.get_target_isa(); + if (isa == "avx512") { + kernel_soln.set_block_size("x", 108); + kernel_soln.set_block_size("y", 28); + kernel_soln.set_block_size("z", 132); + } + else { + kernel_soln.set_block_size("x", 48); + kernel_soln.set_block_size("y", 64); + kernel_soln.set_block_size("z", 112); + } + ); } - } // Define equation for p at t+1 based on values from v and p at t. diff --git a/src/stencils/SSGElasticStencil.cpp b/src/stencils/SSGElasticStencil.cpp index ea217ab8..1f907b15 100644 --- a/src/stencils/SSGElasticStencil.cpp +++ b/src/stencils/SSGElasticStencil.cpp @@ -87,7 +87,6 @@ class SSGElasticStencil : public ElasticStencilBase { return interp_mu( x, y, z, N() ); } - // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, // define stress_D at t+1 based on stress_D at t and vel vars at t+1. // This implies that the velocity-var define functions must be called From 79381c3412eebece7115f7f37e162e47839b2d15 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 7 Jun 2019 16:16:17 -0700 Subject: [PATCH 37/62] Standardize arch names between compiler and kernel; #205. --- include/aux/Soln.hpp | 2 +- include/yask_compiler_api.hpp | 8 +++++--- src/compiler/lib/Solution.cpp | 29 ++++++++++++++++++----------- src/compiler/lib/Solution.hpp | 1 + src/kernel/Makefile | 4 ++-- src/stencils/Iso3dfdStencil.cpp | 17 ++++++++--------- 6 files changed, 35 insertions(+), 26 deletions(-) diff --git a/include/aux/Soln.hpp b/include/aux/Soln.hpp index 72e59410..4ee004c7 100644 --- a/include/aux/Soln.hpp +++ b/include/aux/Soln.hpp @@ -28,7 +28,7 @@ IN THE SOFTWARE. // It is to be used only for backward compatibility for old-style // stencil DSL code in YASK version 2. // Newer DSL code using the provided YASK compiler utility should include -// "yask_compiler_utility_api.hpp" and use only published APIs. +// "yask_compiler_api.hpp" directly and use only published APIs. #pragma once diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 8e72f382..7a4cf5d9 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -349,10 +349,11 @@ namespace yask { /** Currently supported format types: Type | Output --------|-------- - cpp | YASK stencil classes for generic C++. + intel64 | YASK stencil classes for generic 64-bit C++. avx | YASK stencil classes for CORE AVX ISA. avx2 | YASK stencil classes for CORE AVX2 ISA. - avx512 | YASK stencil classes for CORE AVX-512 & MIC AVX-512 ISAs. + avx512 | YASK stencil classes for CORE AVX-512 ISA. + knl | YASK stencil classes for MIC AVX-512 ISA. knc | YASK stencil classes for Knights Corner ISA. dot | DOT-language description. dot-lite| DOT-language description of var accesses only. @@ -361,7 +362,8 @@ namespace yask { Progress text will be written to the output stream set via set_debug_output(). - @note "avx512f" is allowed as an alias for "avx512". + Deprecated alias "avx512f" is allowed for "avx512" and "cpp" for "intel64". + @warning *Side effect:* Applies optimizations to the equation(s), so some pointers to nodes in the original equations may refer to modified nodes or nodes that have been optimized away after calling format(). In general, do not use diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index d8318c99..de16374d 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -156,28 +156,35 @@ namespace yask { // Format in given format-type. void StencilSolution::format(const string& format_type, yask_output_ptr output) { - + _format_name = format_type; + + // Aliases. + if (_format_name == "cpp") + _format_name = "intel64"; + else if (_format_name == "avx512f") + _format_name = "avx512"; + // Look for format match. // Most args to the printers just set references to data. // Data itself will be created in analyze_solution(). PrinterBase* printer = 0; - if (format_type == "cpp") + if (_format_name == "intel64") printer = new YASKCppPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (format_type == "knc") + else if (_format_name == "knc") printer = new YASKKncPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (format_type == "avx" || format_type == "avx2") + else if (_format_name == "avx" || _format_name == "avx2") printer = new YASKAvx256Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (format_type == "avx512" || format_type == "avx512f") + else if (_format_name == "avx512" || _format_name == "knl") printer = new YASKAvx512Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (format_type == "dot") + else if (_format_name == "dot") printer = new DOTPrinter(*this, _clusterEqBundles, false); - else if (format_type == "dot-lite") + else if (_format_name == "dot-lite") printer = new DOTPrinter(*this, _clusterEqBundles, true); - else if (format_type == "pseudo") + else if (_format_name == "pseudo") printer = new PseudoPrinter(*this, _clusterEqBundles, false); - else if (format_type == "pseudo-long") + else if (_format_name == "pseudo-long") printer = new PseudoPrinter(*this, _clusterEqBundles, true); - else if (format_type == "pov-ray") // undocumented. + else if (_format_name == "pov-ray") // undocumented. printer = new POVRayPrinter(*this, _clusterEqBundles); else { THROW_YASK_EXCEPTION("Error: format-type '" + format_type + @@ -191,7 +198,7 @@ namespace yask { analyze_solution(vlen, is_folding_efficient); // Create the output. - *_dos << "\nGenerating '" << format_type << "' output...\n"; + *_dos << "\nGenerating '" << _format_name << "' output...\n"; printer->print(output->get_ostream()); delete printer; } diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 1964ed05..51672cd9 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -68,6 +68,7 @@ namespace yask { private: // Intermediate data needed to format output. + string _format_name; // name of format. Dimensions _dims; // various dimensions. EqBundles _eqBundles; // eq-bundles for scalar and vector. EqBundlePacks _eqBundlePacks; // packs of bundles w/o inter-dependencies. diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 342c4375..87efbcd4 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -60,13 +60,13 @@ ifneq ($(filter $(arch),avx snb ivb),) ARCH := avx else ifneq ($(filter $(arch),avx2 hsw bdw),) ARCH := avx2 -else ifneq ($(filter $(arch),avx512 skx skl clx),) +else ifneq ($(filter $(arch),avx512 avx512f skx skl clx),) ARCH := avx512 else ifneq ($(filter $(arch),knl),) ARCH := knl else ifneq ($(filter $(arch),knc),) ARCH := knc -else ifneq ($(filter $(arch),intel64),) +else ifneq ($(filter $(arch),intel64 cpp),) ARCH := intel64 else $(error Instruction-set architecture (ISA) not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64 (no explicit vectorization)) diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 2f542297..276b66ba 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -133,18 +133,17 @@ namespace { return next_p; } - // Add some code to the kernel to set default run-time options. - virtual void add_kernel_code() { + // Set BKC (best-known configs) found by automated and manual + // tuning. They are only applied for certain target configs. + virtual void set_BKC() { auto soln = get_soln(); // pointer to compile-time soln. - // These best-known settings were found by automated and manual - // tuning. They are only applied for certain target configs. - // Settings are only for SP FP and radius 8, which // can be checked by the YASK compiler. if (soln->get_element_bytes() == 4 && get_radius() == 8) { + // Add some code to the kernel to set default run-time options. // Change the settings immediately after the kernel solution // is created. soln->CALL_AFTER_NEW_SOLUTION @@ -179,8 +178,8 @@ namespace { // is actually an approximation. p(t+1, x, y, z) EQUALS next_p; - // Insert custom kernel code. - add_kernel_code(); + // Insert code from tuning. + set_BKC(); } }; @@ -218,8 +217,8 @@ namespace { // Define the value at t+1 to be equal to next_p. p(t+1, x, y, z) EQUALS next_p; - // Insert custom kernel code. - add_kernel_code(); + // Insert code from tuning. + set_BKC(); } }; From e998c9caf99011251de9337efd8abba029e6c185 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 7 Jun 2019 17:15:36 -0700 Subject: [PATCH 38/62] Add callback hook for format() and APIs for checking whether folding and clustering are set. --- include/aux/yc_solution_api.hpp | 3 +- include/aux/yk_solution_api.hpp | 8 ++--- include/yask_compiler_api.hpp | 60 +++++++++++++++++++++++++++------ src/compiler/lib/Expr.hpp | 2 -- src/compiler/lib/Solution.cpp | 10 ++++-- src/compiler/lib/Solution.hpp | 7 ++++ src/kernel/Makefile | 5 --- src/stencils/Iso3dfdStencil.cpp | 28 +++++++++++++-- 8 files changed, 94 insertions(+), 29 deletions(-) diff --git a/include/aux/yc_solution_api.hpp b/include/aux/yc_solution_api.hpp index 1d2cdad6..ec1b3e0c 100644 --- a/include/aux/yc_solution_api.hpp +++ b/include/aux/yc_solution_api.hpp @@ -114,7 +114,8 @@ namespace yask { For custom code using the YASK compiler library but not the YASK compiler utility, calling define() is possible but optional. */ - virtual void define(); + virtual void + define(); /// Access the underlying solution. inline yc_solution_ptr diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index 249a9247..5ad8c6c1 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -880,15 +880,15 @@ namespace yask { get_default_numa_preferred() const =0; #ifndef SWIG - /// **[Advanced]** Callback hook with \ref yk_solution parameter. + /// **[Advanced]** Callback type with \ref yk_solution parameter. typedef std::function hook_fn_t; - /// **[Advanced]** Callback hook with \ref yk_solution and step-index parameters. - typedef std::function hook_fn_2idx_t; - /// **[Advanced]** Register a hook function to be called at the beginning of yk_solution::prepare_solution(). + /// **[Advanced]** Register a function to be called at the beginning of yk_solution::prepare_solution(). /** A reference to the \ref yk_solution is passed to the `hook_fn`. diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 7a4cf5d9..6ffb6b36 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -32,6 +32,7 @@ IN THE SOFTWARE. #pragma once #include "yask_common_api.hpp" +#include #include namespace yask { @@ -294,23 +295,31 @@ namespace yask { The number of elements in a HW SIMD register is determined by the number of bytes in an element and the print format. + Example: For SP FP elements in AVX-512 vectors, the product of the fold lengths should be 16, e.g., x=4 and y=4. - @note If the product - of the fold lengths is *not* the number of elements in a HW SIMD - register, the fold lengths will be adjusted based on an internal - heuristic. In this heuristic, any fold length that is >1 is - used as a hint to indicate where to apply folding. - @note A fold can only be applied in a domain dimension. - @note Default length is one (1) in each domain dimension. */ + + If the product of the fold lengths is *not* the number of + elements in a HW SIMD register, the fold lengths will be + adjusted based on an internal heuristic. In this heuristic, any + specified fold length is used as a hint to determine the final + folding. + */ virtual void set_fold_len(const yc_index_node_ptr dim /**< [in] Dimension of fold, e.g., "x". This must be an index created by new_domain_index(). */, int len /**< [in] Length of vectorization in `dim` */ ) =0; - /// Reset all vector-folding settings. - /** All fold lengths will return to the default of one (1). */ + /// Determine whether any folding has been set. + /** + @returns `true` if any fold length has been specified; + `false` if not. + */ + virtual bool + is_folding_set() =0; + + /// Remove all vector-folding settings. virtual void clear_folding() =0; @@ -328,8 +337,15 @@ namespace yask { This must be an index created by new_domain_index(). */, int mult /**< [in] Number of vectors in `dim` */ ) =0; - /// Reset all vector-clustering settings. - /** All cluster multipliers will return to the default of one (1). */ + /// Determine whether any clustering has been set. + /** + @returns `true` if any cluster multiple has been specified; + `false` if not. + */ + virtual bool + is_clustering_set() =0; + + /// Remove all vector-clustering settings. virtual void clear_clustering() =0; @@ -376,6 +392,28 @@ namespace yask { /**< [out] Pointer to object to receive formatted output. See \ref yask_output_factory. */) =0; +#ifndef SWIG + /// **[Advanced]** Callback type for call_before_format(). + typedef std::function format_hook_t; + + /// **[Advanced]** Register a function to be called at the beginning of format(). + /** + A reference to the solution and the parameters to format() are passed to the `hook_fn`. + Any aliases to `format_type` as listed in the format() documentation + are replaced before the call. + + If this method is called more than once, the hook functions will be + called in the order registered. + + @note Not available in the Python API. + */ + virtual void + call_before_format(/** [in] callback function */ + format_hook_t hook_fn) =0; +#endif + /// **[Advanced]** Add block of custom C++ code to the kernel solution. /** This block of code will be executed immediately after the stencil solution diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index b2b2f3b2..b300af0c 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -83,8 +83,6 @@ namespace yask { typedef map VarMap; // map used when substituting vars. //// Classes to implement parts of expressions. - // The expressions are constructed at run-time when the - // StencilSolution::define() method is called. // The base class for all expression nodes. // NB: there is no clone() method defined here; they diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index de16374d..3388a95b 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -164,7 +164,11 @@ namespace yask { else if (_format_name == "avx512f") _format_name = "avx512"; - // Look for format match. + // Call hooks. + for (auto& hook : _format_hooks) + hook(*this, _format_name, output); + + // Create the appropriate printer object based on the format. // Most args to the printers just set references to data. // Data itself will be created in analyze_solution(). PrinterBase* printer = 0; @@ -191,10 +195,10 @@ namespace yask { "' is not recognized"); } assert(printer); - int vlen = printer->num_vec_elems(); - bool is_folding_efficient = printer->is_folding_efficient(); // Set data for equation bundles, dims, etc. + int vlen = printer->num_vec_elems(); + bool is_folding_efficient = printer->is_folding_efficient(); analyze_solution(vlen, is_folding_efficient); // Create the output. diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 51672cd9..417004e0 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -64,6 +64,7 @@ namespace yask { // Code extensions. vector _kernel_code; + vector _format_hooks; private: @@ -196,8 +197,10 @@ namespace yask { } virtual void set_fold_len(const yc_index_node_ptr, int len); + virtual bool is_folding_set() { return _settings._foldOptions.size() > 0; } virtual void clear_folding() { _settings._foldOptions.clear(); } virtual void set_cluster_mult(const yc_index_node_ptr, int mult); + virtual bool is_clustering_set() { return _settings._clusterOptions.size() > 0; } virtual void clear_clustering() { _settings._clusterOptions.clear(); } virtual void set_element_bytes(int nbytes) { _settings._elem_bytes = nbytes; } @@ -209,6 +212,10 @@ namespace yask { virtual void format(const std::string& format_type, yask_output_ptr output); virtual void + call_before_format(format_hook_t hook_fn) { + _format_hooks.push_back(hook_fn); + } + virtual void set_domain_dims(const std::vector& dims) { _settings._domainDims.clear(); for (auto& d : dims) { diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 87efbcd4..19bcdd04 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -79,17 +79,12 @@ ifeq ($(YC_STENCIL),) else ifneq ($(findstring iso3dfd,$(YC_STENCIL)),) def_pad_args := -ep 1 ifeq ($(ARCH),knl) - fold := x=2,y=8 - cluster := x=2 - def_block_args := -bx 160 -by 256 -bz 96 pfd_l1 := 1 pfd_l2 := 0 else ifeq ($(arch),avx512) - def_block_args := -bx 108 -by 28 -bz 132 pfd_l1 := 0 pfd_l2 := 2 else - def_block_args := -bx 48 -by 60 -bz 112 pfd_l1 := 0 pfd_l2 := 0 endif diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 276b66ba..9d376f19 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -138,11 +138,28 @@ namespace { virtual void set_BKC() { auto soln = get_soln(); // pointer to compile-time soln. - // Settings are only for SP FP and radius 8, which - // can be checked by the YASK compiler. + // Settings are only for SP FP and radius 8. if (soln->get_element_bytes() == 4 && get_radius() == 8) { + // Some format-specific YASK compiler settings. + soln->call_before_format + ([this](yc_solution& yc_soln, + const std::string& format_type, + yask_output_ptr output) { + + if (format_type == "knl") { + + // Set folding and clustering if neither is set. + if (!yc_soln.is_folding_set() && + !yc_soln.is_clustering_set()) { + yc_soln.set_fold_len(x, 2); + yc_soln.set_fold_len(y, 8); + yc_soln.set_cluster_mult(x, 2); + } + } + }); + // Add some code to the kernel to set default run-time options. // Change the settings immediately after the kernel solution // is created. @@ -153,7 +170,12 @@ namespace { // Check target ISA at kernel run-time for block-size. auto isa = kernel_soln.get_target_isa(); - if (isa == "avx512") { + if (isa == "knl") { + kernel_soln.set_block_size("x", 160); + kernel_soln.set_block_size("y", 256); + kernel_soln.set_block_size("z", 96); + } + else if (isa == "avx512") { kernel_soln.set_block_size("x", 108); kernel_soln.set_block_size("y", 28); kernel_soln.set_block_size("z", 132); From 44e6ccfb5de38350988cc434c8a4275747951702 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Sat, 8 Jun 2019 06:31:46 -0700 Subject: [PATCH 39/62] Separate target-setting from formatting in compiler. --- README.md | 3 +- include/aux/yk_solution_api.hpp | 4 +- include/yask_compiler_api.hpp | 94 +++++++++++------ src/compiler/compiler_main.cpp | 179 ++++++++++++++++---------------- src/compiler/lib/Settings.hpp | 1 + src/compiler/lib/Solution.cpp | 90 +++++++++------- src/compiler/lib/Solution.hpp | 41 +++++--- src/compiler/lib/YaskKernel.cpp | 10 +- src/kernel/Makefile | 2 +- src/kernel/lib/context.hpp | 6 -- src/stencils/Iso3dfdStencil.cpp | 39 +++---- 11 files changed, 267 insertions(+), 202 deletions(-) diff --git a/README.md b/README.md index a0d25627..a359a9bf 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,8 @@ YASK contains a domain-specific compiler to convert stencil-equation specificati - The default strings used in the kernel library and filenames to identify the targeted architecture were changed from Intel CPU codenames to [approximate] instruction-set architecture (ISA) names "avx512", "avx2", - "avx", "knl", "knc", or "intel64". + "avx", "knl", "knc", or "intel64". The YASK targets used in the YASK + compiler were updated to be consistent with this list. - The "mid" (roughly, median) performance results are now the first ones printed by the `utils/bin/yask_log_to_csv.pl` script. diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index 5ad8c6c1..60a99e36 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -90,10 +90,10 @@ namespace yask { /** @returns String describing the instruction-set architecture targeted during kernel compilation. - This is currently "avx512", "avx2", "avx", "knl", "knc", or "intel64". + See the allowed YASK kernel targets in yc_solution::set_target(). */ virtual std::string - get_target_isa() const =0; + get_target() const =0; /// Get the floating-point precision size. /** diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 6ffb6b36..961b5ba5 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -164,6 +164,45 @@ namespace yask { set_description(std::string description /**< [in] Any descriptive phrase. */ ) =0; + /// Get the current output target. + /** + @returns Current target. + + Throws an exception if the target hasn't been set via set_target(). + */ + virtual std::string + get_target() =0; + + /// Set the output target. + /** + Currently supported targets: + Type | Output + --------|-------- + intel64 | YASK kernel for generic 64-bit C++. + avx | YASK kernel for CORE AVX ISA. + avx2 | YASK kernel for CORE AVX2 ISA. + avx512 | YASK kernel for CORE AVX-512 ISA. + knl | YASK kernel for MIC AVX-512 ISA. + knc | YASK kernel for Knights Corner ISA. + dot | DOT-language description. + dot-lite| DOT-language description of var accesses only. + pseudo | Human-readable pseudo-code (for debug). + pseudo-long | Human-readable pseudo-code with intermediate variables. + + Deprecated alias "avx512f" will be converted to "avx512" and "cpp" to "intel64". + */ + virtual void + set_target(/** [in] Output target from above list */ + const std::string& format) =0; + + /// Determine whether target has been set. + /** + @returns `true` if set_target() has been called with a valid format; + `false` otherwise. + */ + virtual bool + is_target_set() =0; + /// Get current floating-point precision setting. /** @returns Number of bytes in a FP number. */ virtual int @@ -361,48 +400,35 @@ namespace yask { virtual std::vector get_equations() =0; - /// Format the current equation(s) and write to given output object. - /** Currently supported format types: - Type | Output - --------|-------- - intel64 | YASK stencil classes for generic 64-bit C++. - avx | YASK stencil classes for CORE AVX ISA. - avx2 | YASK stencil classes for CORE AVX2 ISA. - avx512 | YASK stencil classes for CORE AVX-512 ISA. - knl | YASK stencil classes for MIC AVX-512 ISA. - knc | YASK stencil classes for Knights Corner ISA. - dot | DOT-language description. - dot-lite| DOT-language description of var accesses only. - pseudo | Human-readable pseudo-code (for debug). - pseudo-long | Human-readable pseudo-code with intermediate variables. + /// Optimize and the current equation(s) and write to given output object. + /** + Output will be formatted according to set_target() and all other preceding + YASK compiler API calls. Progress text will be written to the output stream set via set_debug_output(). - Deprecated alias "avx512f" is allowed for "avx512" and "cpp" for "intel64". - @warning *Side effect:* Applies optimizations to the equation(s), so some pointers to nodes in the original equations may refer to modified nodes or nodes that have been optimized away after calling format(). In general, do not use pointers to nodes across calls to format(). */ virtual void - format(const std::string& format_type - /**< [in] Name of type from above table. */, - yask_output_ptr output - /**< [out] Pointer to object to receive formatted output. - See \ref yask_output_factory. */) =0; + output_solution(yask_output_ptr output + /**< [out] Pointer to object to receive formatted output. + See \ref yask_output_factory. */) =0; #ifndef SWIG - /// **[Advanced]** Callback type for call_before_format(). + /// **[Advanced]** Callback type for call_before_output(). typedef std::function format_hook_t; + yask_output_ptr output)> output_hook_t; - /// **[Advanced]** Register a function to be called at the beginning of format(). + /// **[Advanced]** Register a function to be called before a solution is output. /** - A reference to the solution and the parameters to format() are passed to the `hook_fn`. - Any aliases to `format_type` as listed in the format() documentation - are replaced before the call. + The registered functions will be called during a call to output_solution() + after the equations optimizations have been applied but before the + output is written. + + A reference to the solution and the parameter to output_solution() are passed to the `hook_fn`. If this method is called more than once, the hook functions will be called in the order registered. @@ -410,8 +436,8 @@ namespace yask { @note Not available in the Python API. */ virtual void - call_before_format(/** [in] callback function */ - format_hook_t hook_fn) =0; + call_before_output(/** [in] callback function */ + output_hook_t hook_fn) =0; #endif /// **[Advanced]** Add block of custom C++ code to the kernel solution. @@ -591,6 +617,14 @@ namespace yask { virtual void clear_dependencies() =0; + /// **[Deprecated]** Use set_target() and output_solution(). + inline void + format(const std::string& format_type, + yask_output_ptr output) { + set_target(format_type); + output_solution(output); + } + /// **[Deprecated]** Use new_var(). inline yc_var_ptr new_grid(const std::string& name, diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 080074d8..a83b4a24 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -45,28 +45,27 @@ namespace yask { yc_factory factory; // output streams. - map outfiles; + vector outfiles; // other vars set via cmd-line options. - CompilerSettings settings; - int vlenForStats = 0; - yc_solution_base* stencilSoln = NULL; string solutionName; int radius = -1; + int vlenForStats = 0; // Dummy object for backward-compatibility with old stencil DSL. StencilList stub_stencils; } // yask namespace. -void usage(const string& cmd) { +void usage(const string& cmd, + CompilerSettings& settings) { cout << "Options:\n" " -h\n" " Print this help message.\n" "\n" " -stencil \n" - " Select stencil solution (required)\n"; + " Set stencil solution (required)\n"; for (bool show_test : { false, true }) { if (show_test) cout << " Built-in test solutions:\n"; @@ -90,7 +89,21 @@ void usage(const string& cmd) { " -radius \n" " Set radius for stencils marked with '*' above (default is stencil-specific).\n" "\n" - " -elem-bytes " + " -target \n" + " Set the output format (required).\n" + " Supported formats:\n" + " avx YASK stencil classes for CORE AVX ISA (256-bit HW SIMD vectors).\n" + " avx2 YASK stencil classes for CORE AVX2 ISA (256-bit HW SIMD vectors).\n" + " avx512 YASK stencil classes for CORE AVX-512 ISA (512-bit HW SIMD vectors).\n" + " knc YASK stencil classes for Knights-Corner ISA (512-bit HW SIMD vectors).\n" + " knl YASK stencil classes for Knights-Landing (MIC) AVX-512 ISA (512-bit HW SIMD vectors).\n" + " intel64 YASK stencil classes for generic C++ (no explicit HW SIMD vectors).\n" + " pseudo Human-readable scalar pseudo-code.\n" + " pseudo-long Human-readable scalar pseudo-code with intermediate variables.\n" + " dot DOT-language description.\n" + " dot-lite DOT-language description of var accesses only.\n" + //" pov-ray POV-Ray code.\n" + " -elem-bytes \n" " Set number of bytes in each FP element (default=" << settings._elem_bytes << ").\n" " Currently, only 4 (single-precision) and 8 (double) are allowed.\n" " -domain-dims ,,...\n" @@ -171,19 +184,8 @@ void usage(const string& cmd) { " [-no]-print-eqs\n" " Print each equation when defined (default=" << settings._printEqs << ").\n" "\n" - " -p \n" - " Format output per and write to .\n" - " Supported format-types:\n" - " cpp YASK stencil classes for generic C++ (no explicit HW SIMD vectors).\n" - " avx YASK stencil classes for CORE AVX ISA (256-bit HW SIMD vectors).\n" - " avx2 YASK stencil classes for CORE AVX2 ISA (256-bit HW SIMD vectors).\n" - " avx512 YASK stencil classes for CORE AVX-512 & MIC AVX-512 ISAs (512-bit HW SIMD vectors).\n" - " knc YASK stencil classes for KNC ISA (512-bit HW SIMD vectors).\n" - " pseudo Human-readable scalar pseudo-code.\n" - " pseudo-long Human-readable scalar pseudo-code with intermediate variables.\n" - " dot DOT-language description.\n" - " dot-lite DOT-language description of var accesses only.\n" - //" pov-ray POV-Ray code.\n" + " -p \n" + " Write formatted output to .\n" //" -ps Print stats for all folding options for given vector length.\n" "\n" "Examples:\n" @@ -195,10 +197,11 @@ void usage(const string& cmd) { // Parse command-line and set global cmd-line option vars. // Exits on error. -void parseOpts(int argc, const char* argv[]) +void parseOpts(int argc, const char* argv[], + CompilerSettings& settings) { if (argc <= 1) - usage(argv[0]); + usage(argv[0], settings); int argi; // current arg index. for (argi = 1; argi < argc; argi++) { @@ -207,7 +210,7 @@ void parseOpts(int argc, const char* argv[]) // options w/o values. if (opt == "-h" || opt == "-help" || opt == "--help") - usage(argv[0]); + usage(argv[0], settings); else if (opt == "-fus") settings._firstInner = true; @@ -258,13 +261,17 @@ void parseOpts(int argc, const char* argv[]) // at least one value needed. if (argi + 1 >= argc) { cerr << "Error: value missing or bad option '" << opt << "'." << endl; - usage(argv[0]); + usage(argv[0], settings); } string argop = argv[++argi]; // options w/a string value. if (opt == "-stencil") solutionName = argop; + else if (opt == "-target") + settings._target = argop; + else if (opt == "-p") + outfiles.push_back(argop); else if (opt == "-vars") settings._varRegex = argop; else if (opt == "-eq-bundles") @@ -299,19 +306,6 @@ void parseOpts(int argc, const char* argv[]) }); } - // Print options w/format & filename args. - else if (opt == "-p") { - - // another arg needed. - if (argi + 1 >= argc) { - cerr << "Error: filename missing after '" << opt << - " " << argop << "'." << endl; - usage(argv[0]); - } - string argop2 = argv[++argi]; - outfiles[argop] = argop2; - } - // add any more options w/a string value above. else { @@ -341,7 +335,7 @@ void parseOpts(int argc, const char* argv[]) else { cerr << "Error: option '" << opt << "' not recognized." << endl; - usage(argv[0]); + usage(argv[0], settings); } } } @@ -350,51 +344,16 @@ void parseOpts(int argc, const char* argv[]) } if (argi < argc) { cerr << "Error: unrecognized parameter '" << argv[argi] << "'." << endl; - usage(argv[0]); + usage(argv[0], settings); } if (solutionName.length() == 0) { - cerr << "Error: solution not specified." << endl; - usage(argv[0]); + cerr << "Error: stencil solution not specified; use -stencil." << endl; + usage(argv[0], settings); } - - // Find the stencil in the registry. - auto& stencils = yc_solution_base::get_registry(); - auto stencilIter = stencils.find(solutionName); - if (stencilIter == stencils.end()) { - cerr << "Error: unknown stencil solution '" << solutionName << "'." << endl; - usage(argv[0]); + if (settings._target.length() == 0) { + cerr << "Error: target not specified; use -target." << endl; + usage(argv[0], settings); } - stencilSoln = stencilIter->second; - assert(stencilSoln); - auto soln = stencilSoln->get_soln(); - - cout << "Stencil-solution name: " << soln->get_name() << endl; - - // Set radius if applicable. - auto* srp = dynamic_cast(stencilSoln); - if (srp) { - if (radius >= 0) { - bool rOk = srp->set_radius(radius); - if (!rOk) { - cerr << "Error: invalid radius=" << radius << " for stencil type '" << - solutionName << "'." << endl; - usage(argv[0]); - } - } - cout << "Stencil radius: " << srp->get_radius() << endl; - } - cout << "Stencil-solution description: " << soln->get_description() << endl; - - // Copy cmd-line settings into solution. - // TODO: remove this reliance on internal (non-API) functionality. - auto sp = dynamic_pointer_cast(soln); - assert(sp); - sp->setSettings(settings); - - // Create equations from the overloaded 'define()' methods. - stencilSoln->define(); - cout << "Num vars defined: " << soln->get_num_vars() << endl; - cout << "Num equations defined: " << soln->get_num_equations() << endl; } // Main program. @@ -406,16 +365,62 @@ int main(int argc, const char* argv[]) { "Version: " << yask_get_version_string() << endl; try { - // Parse options and create the stencil-solution object. - parseOpts(argc, argv); + // Parse options. + CompilerSettings settings; + parseOpts(argc, argv, settings); + + // Find the requested stencil in the registry. + auto& stencils = yc_solution_base::get_registry(); + auto stencilIter = stencils.find(solutionName); + if (stencilIter == stencils.end()) { + cerr << "Error: unknown stencil solution '" << solutionName << "'." << endl; + usage(argv[0], settings); + } + auto* stencilSoln = stencilIter->second; + assert(stencilSoln); + auto soln = stencilSoln->get_soln(); + cout << "Stencil-solution name: " << soln->get_name() << endl; + + // Set radius if applicable. + auto* srp = dynamic_cast(stencilSoln); + if (srp) { + if (radius >= 0) { + bool rOk = srp->set_radius(radius); + if (!rOk) { + cerr << "Error: invalid radius=" << radius << " for stencil type '" << + solutionName << "'." << endl; + usage(argv[0], settings); + } + } + cout << "Stencil radius: " << srp->get_radius() << endl; + } + cout << "Stencil-solution description: " << soln->get_description() << endl; - if (outfiles.size() == 0) - cout << "Use the '-p' option to generate output from this stencil.\n"; + // Make sure that target is legal. + soln->set_target(settings._target); + cout << "Output target: " << soln->get_target() << endl; + + // Copy cmd-line settings into solution. + // TODO: remove this reliance on internal (non-API) functionality. + auto sp = dynamic_pointer_cast(soln); + assert(sp); + sp->setSettings(settings); + + // Create equations and change settings from the overloaded 'define()' methods. + stencilSoln->define(); + + // Apply the cmd-line settings again to override the defaults + // set in 'define()' + parseOpts(argc, argv, sp->getSettings()); + + // A bit more info. + cout << "Num vars defined: " << soln->get_num_vars() << endl; + cout << "Num equations defined: " << soln->get_num_equations() << endl; // Create the requested output. - for (auto i : outfiles) { - auto& type = i.first; - auto& fname = i.second; + if (outfiles.size() == 0) + cout << "Use the '-p' option to generate output from this stencil.\n"; + for (auto& fname : outfiles) { yask_output_factory ofac; yask_output_ptr os; @@ -423,7 +428,7 @@ int main(int argc, const char* argv[]) { os = ofac.new_stdout_output(); else os = ofac.new_file_output(fname); - stencilSoln->get_soln()->format(type, os); + stencilSoln->get_soln()->output_solution(os); } } catch (yask_exception& e) { cerr << "YASK Stencil Compiler: " << e.get_message() << ".\n"; diff --git a/src/compiler/lib/Settings.hpp b/src/compiler/lib/Settings.hpp index 3855d445..f82a76a8 100644 --- a/src/compiler/lib/Settings.hpp +++ b/src/compiler/lib/Settings.hpp @@ -37,6 +37,7 @@ namespace yask { // May be provided via cmd-line or API. class CompilerSettings { public: + string _target; // format type. int _elem_bytes = 4; // bytes in an FP element. string _stepDim; // explicit step dim. vector _domainDims; // explicit domain dims. diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 3388a95b..8f81183c 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -32,6 +32,11 @@ using namespace std; namespace yask { + StencilSolution::~StencilSolution() { + if (_printer) + delete _printer; + } + // Stencil-solution APIs. yc_var_ptr StencilSolution::newVar(const std::string& name, bool isScratch, @@ -153,58 +158,67 @@ namespace yask { _clusterEqBundles.optimizeEqBundles(_settings, "cluster", true, *_dos); } - // Format in given format-type. - void StencilSolution::format(const string& format_type, - yask_output_ptr output) { - _format_name = format_type; + // Set format. + void StencilSolution::set_target(const std::string& format) { + auto& target = _settings._target; + target = format; // Aliases. - if (_format_name == "cpp") - _format_name = "intel64"; - else if (_format_name == "avx512f") - _format_name = "avx512"; - - // Call hooks. - for (auto& hook : _format_hooks) - hook(*this, _format_name, output); + if (target == "cpp") + target = "intel64"; + else if (target == "avx512f") + target = "avx512"; // Create the appropriate printer object based on the format. // Most args to the printers just set references to data. // Data itself will be created in analyze_solution(). - PrinterBase* printer = 0; - if (_format_name == "intel64") - printer = new YASKCppPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (_format_name == "knc") - printer = new YASKKncPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (_format_name == "avx" || _format_name == "avx2") - printer = new YASKAvx256Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (_format_name == "avx512" || _format_name == "knl") - printer = new YASKAvx512Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); - else if (_format_name == "dot") - printer = new DOTPrinter(*this, _clusterEqBundles, false); - else if (_format_name == "dot-lite") - printer = new DOTPrinter(*this, _clusterEqBundles, true); - else if (_format_name == "pseudo") - printer = new PseudoPrinter(*this, _clusterEqBundles, false); - else if (_format_name == "pseudo-long") - printer = new PseudoPrinter(*this, _clusterEqBundles, true); - else if (_format_name == "pov-ray") // undocumented. - printer = new POVRayPrinter(*this, _clusterEqBundles); + if (target == "intel64") + _printer = new YASKCppPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + else if (target == "knc") + _printer = new YASKKncPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + else if (target == "avx" || target == "avx2") + _printer = new YASKAvx256Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + else if (target == "avx512" || target == "knl") + _printer = new YASKAvx512Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + else if (target == "dot") + _printer = new DOTPrinter(*this, _clusterEqBundles, false); + else if (target == "dot-lite") + _printer = new DOTPrinter(*this, _clusterEqBundles, true); + else if (target == "pseudo") + _printer = new PseudoPrinter(*this, _clusterEqBundles, false); + else if (target == "pseudo-long") + _printer = new PseudoPrinter(*this, _clusterEqBundles, true); + else if (target == "pov-ray") // undocumented. + _printer = new POVRayPrinter(*this, _clusterEqBundles); else { - THROW_YASK_EXCEPTION("Error: format-type '" + format_type + + _printer = 0; + target = ""; + THROW_YASK_EXCEPTION("Error: format-target '" + format + "' is not recognized"); } - assert(printer); + assert(_printer); + } + + // Format in given format-type. + void StencilSolution::output_solution(yask_output_ptr output) { + auto& target = _settings._target; + if (!is_target_set()) + THROW_YASK_EXCEPTION("Error: output_solution() called before set_target()"); + assert(_printer); + // Set data for equation bundles, dims, etc. - int vlen = printer->num_vec_elems(); - bool is_folding_efficient = printer->is_folding_efficient(); + int vlen = _printer->num_vec_elems(); + bool is_folding_efficient = _printer->is_folding_efficient(); analyze_solution(vlen, is_folding_efficient); + // Call hooks. + for (auto& hook : _output_hooks) + hook(*this, output); + // Create the output. - *_dos << "\nGenerating '" << _format_name << "' output...\n"; - printer->print(output->get_ostream()); - delete printer; + *_dos << "\nGenerating '" << target << "' output...\n"; + _printer->print(output->get_ostream()); } } // namespace yask. diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 417004e0..163dea9f 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -35,6 +35,7 @@ IN THE SOFTWARE. using namespace std; namespace yask { + class PrinterBase; // A base class for whole stencil solutions. This is used by solutions // defined in C++ that are inherited from StencilBase as well as those @@ -64,12 +65,12 @@ namespace yask { // Code extensions. vector _kernel_code; - vector _format_hooks; + vector _output_hooks; private: // Intermediate data needed to format output. - string _format_name; // name of format. + PrinterBase* _printer = 0; Dimensions _dims; // various dimensions. EqBundles _eqBundles; // eq-bundles for scalar and vector. EqBundlePacks _eqBundlePacks; // packs of bundles w/o inter-dependencies. @@ -86,7 +87,7 @@ namespace yask { auto so = ofac.new_stdout_output(); set_debug_output(so); } - virtual ~StencilSolution() {} + virtual ~StencilSolution(); // Identification. virtual const string& getName() const { return _name; } @@ -97,7 +98,7 @@ namespace yask { // Simple accessors. virtual Vars& getVars() { return _vars; } virtual Eqs& getEqs() { return _eqs; } - virtual const CompilerSettings& getSettings() { return _settings; } + virtual CompilerSettings& getSettings() { return _settings; } virtual void setSettings(const CompilerSettings& settings) { _settings = settings; } @@ -203,17 +204,33 @@ namespace yask { virtual bool is_clustering_set() { return _settings._clusterOptions.size() > 0; } virtual void clear_clustering() { _settings._clusterOptions.clear(); } - virtual void set_element_bytes(int nbytes) { _settings._elem_bytes = nbytes; } - virtual int get_element_bytes() const { return _settings._elem_bytes; } + virtual bool is_target_set() override { + return _settings._target.length() > 0; + } + virtual std::string get_target() override { + if (!is_target_set()) + THROW_YASK_EXCEPTION("Error: call to get_target() before set_target()"); + return _settings._target; + } + virtual void set_target(const std::string& format) override; + virtual void set_element_bytes(int nbytes) override { + _settings._elem_bytes = nbytes; + } + virtual int get_element_bytes() const override { + return _settings._elem_bytes; + } - virtual bool is_dependency_checker_enabled() const { return _settings._findDeps; } - virtual void set_dependency_checker_enabled(bool enable) { _settings._findDeps = enable; } + virtual bool is_dependency_checker_enabled() const override { + return _settings._findDeps; + } + virtual void set_dependency_checker_enabled(bool enable) override { + _settings._findDeps = enable; + } - virtual void format(const std::string& format_type, - yask_output_ptr output); + virtual void output_solution(yask_output_ptr output) override; virtual void - call_before_format(format_hook_t hook_fn) { - _format_hooks.push_back(hook_fn); + call_before_output(output_hook_t hook_fn) { + _output_hooks.push_back(hook_fn); } virtual void set_domain_dims(const std::vector& dims) { diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 7b4046ff..fc9a54c3 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -183,10 +183,18 @@ namespace yask { CounterVisitor cve; _eqBundles.visitEqs(&cve); - os << endl << " ////// Stencil-specific data //////" << endl << + os << "\n ////// Stencil-specific data //////" << endl << "class " << _context_base << " : public StencilContext {\n" "public:\n"; + // APIs. + os << "\n virtual std::string get_target() const override {\n" + " return \"" << _settings._target << "\";\n" + " }\n" + "\n virtual int get_element_bytes() const override {\n" + " return " << _settings._elem_bytes << ";\n" + " }\n"; + // Save data for ctor and new-var method. string ctorCode, ctorList, newVarCode, scratchCode; set newVarDims; diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 19bcdd04..00b290bf 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -629,7 +629,7 @@ $(YK_GEN_DIR)/yask_var_code.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(YK_CODE_FILE): $(YC_EXEC) $(MKDIR) $(dir $@) @- rm -f $@ - $(RUN_PREFIX) $< $(YC_FLAGS) $(EXTRA_YC_FLAGS) -p $(YC_TARGET) $@ | tee $(YC_REPORT_FILE) 2>&1 + $(RUN_PREFIX) $< $(YC_FLAGS) -target $(YC_TARGET) -p $@ $(EXTRA_YC_FLAGS) | tee $(YC_REPORT_FILE) 2>&1 @ grep -q -E 'End of .* code' $@ @- gindent -fca $@ || \ indent -fca $@ || \ diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index a9fc8c09..ab64c616 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -519,12 +519,6 @@ namespace yask { virtual void set_debug_output(yask_output_ptr debug) { KernelStateBase::set_debug_output(debug); } - virtual int get_element_bytes() const { - return REAL_BYTES; - } - virtual std::string get_target_isa() const { - return YSTR2(ARCH_NAME); - } virtual int get_num_vars() const { return int(varPtrs.size()); diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 9d376f19..2aa57db3 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -138,38 +138,29 @@ namespace { virtual void set_BKC() { auto soln = get_soln(); // pointer to compile-time soln. - // Settings are only for SP FP and radius 8. + // BKCs are only for SP FP and radius 8. if (soln->get_element_bytes() == 4 && get_radius() == 8) { - // Some format-specific YASK compiler settings. - soln->call_before_format - ([this](yc_solution& yc_soln, - const std::string& format_type, - yask_output_ptr output) { - - if (format_type == "knl") { - - // Set folding and clustering if neither is set. - if (!yc_soln.is_folding_set() && - !yc_soln.is_clustering_set()) { - yc_soln.set_fold_len(x, 2); - yc_soln.set_fold_len(y, 8); - yc_soln.set_cluster_mult(x, 2); - } - } - }); - - // Add some code to the kernel to set default run-time options. - // Change the settings immediately after the kernel solution - // is created. + // Compile-time defaults. + if (soln->is_target_set() && + soln->get_target() == "knl") { + + // Default folding and clustering for KNL. + soln->set_fold_len(x, 2); + soln->set_fold_len(y, 8); + soln->set_cluster_mult(x, 2); + } + + // Kernel run-time defaults. This code is run immediately + // after 'kernel_soln' is created. soln->CALL_AFTER_NEW_SOLUTION ( // Add extra padding in all dimensions. kernel_soln.apply_command_line_options("-ep 1"); - // Check target ISA at kernel run-time for block-size. - auto isa = kernel_soln.get_target_isa(); + // Check target at kernel run-time for block-size. + auto isa = kernel_soln.get_target(); if (isa == "knl") { kernel_soln.set_block_size("x", 160); kernel_soln.set_block_size("y", 256); From 86fdb1896ab69b1665f8bd26b7eb87cd584063e4 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Sat, 8 Jun 2019 12:56:35 -0700 Subject: [PATCH 40/62] More target aliases. --- src/compiler/lib/Solution.cpp | 9 ++++++-- src/kernel/Makefile | 16 +++++--------- src/kernel/lib/soln_apis.cpp | 2 +- src/stencils/Iso3dfdStencil.cpp | 39 +++++++++++++++++---------------- utils/lib/YaskUtils.pm | 3 ++- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 8f81183c..fe9b7a4e 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -163,10 +163,15 @@ namespace yask { auto& target = _settings._target; target = format; - // Aliases. + // Aliases for backward-compatibility. if (target == "cpp") target = "intel64"; - else if (target == "avx512f") + else if (target == "snb" || target == "ivb") + target = "avx"; + else if (target == "hsw" || target == "bdw") + target = "avx2"; + else if (target == "avx512f" || target == "skx" || + target == "skl" || target == "clx") target = "avx512"; // Create the appropriate printer object based on the format. diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 00b290bf..0c6fc7f0 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -69,15 +69,17 @@ else ifneq ($(filter $(arch),knc),) else ifneq ($(filter $(arch),intel64 cpp),) ARCH := intel64 else - $(error Instruction-set architecture (ISA) not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64 (no explicit vectorization)) + $(error Instruction-set architecture (ISA) not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64) endif +# Specify YC_TARGET on 'make' cmd-line to override ARCH. +YC_TARGET := $(ARCH) + # Defaults based on stencil type (and arch for some stencils). ifeq ($(YC_STENCIL),) $(error Stencil not specified) else ifneq ($(findstring iso3dfd,$(YC_STENCIL)),) - def_pad_args := -ep 1 ifeq ($(ARCH),knl) pfd_l1 := 1 pfd_l2 := 0 @@ -141,7 +143,6 @@ ifeq ($(ARCH),knc) ICC_ISA ?= -mmic MACROS += USE_INTRIN512 - YC_TARGET ?= knc def_block_threads ?= 4 pfd_l1 ?= 1 pfd_l2 ?= 2 @@ -155,7 +156,6 @@ else ifeq ($(ARCH),knl) ICC_ISA ?= -xMIC-AVX512 GCC_ISA ?= -march=knl MACROS += USE_INTRIN512 USE_RCP28 NUMA_PREF=1 - YC_TARGET ?= avx512 def_block_args ?= -b 64 def_block_threads ?= 8 pfd_l1 ?= 1 @@ -166,27 +166,23 @@ else ifeq ($(ARCH),avx512) ICC_ISA ?= -xCORE-AVX512 GCC_ISA ?= -march=knl -mno-avx512er -mno-avx512pf MACROS += USE_INTRIN512 - YC_TARGET ?= avx512 else ifeq ($(ARCH),avx2) ICC_ISA ?= -xCORE-AVX2 GCC_ISA ?= -march=haswell MACROS += USE_INTRIN256 USE_AVX2 - YC_TARGET ?= avx2 else ifeq ($(ARCH),avx) ICC_ISA ?= -xAVX GCC_ISA ?= -march=sandybridge MACROS += USE_INTRIN256 - YC_TARGET ?= avx else ifeq ($(ARCH),intel64) ICC_ISA ?= -xHOST GCC_ISA ?= -march=native - YC_TARGET ?= cpp else @@ -219,7 +215,7 @@ include $(YASK_BASE)/src/common/common.mk # Vars starting with 'YK_' apply to the stencil kernel. # Flags passed to stencil compiler. -YC_FLAGS += -stencil $(YC_STENCIL) -elem-bytes $(real_bytes) +YC_FLAGS += -stencil $(YC_STENCIL) -target $(YC_TARGET) -elem-bytes $(real_bytes) ifneq ($(fold),) YC_FLAGS += -fold $(fold) endif @@ -629,7 +625,7 @@ $(YK_GEN_DIR)/yask_var_code.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(YK_CODE_FILE): $(YC_EXEC) $(MKDIR) $(dir $@) @- rm -f $@ - $(RUN_PREFIX) $< $(YC_FLAGS) -target $(YC_TARGET) -p $@ $(EXTRA_YC_FLAGS) | tee $(YC_REPORT_FILE) 2>&1 + $(RUN_PREFIX) $< $(YC_FLAGS) -p $@ $(EXTRA_YC_FLAGS) | tee $(YC_REPORT_FILE) 2>&1 @ grep -q -E 'End of .* code' $@ @- gindent -fca $@ || \ indent -fca $@ || \ diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 8d039750..706511fb 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -272,7 +272,7 @@ namespace yask { #endif os << "\nOther settings:\n" " yask-version: " << yask_get_version_string() << endl << - " target-ISA: " << YSTR2(ARCH_NAME) << endl << + " target: " << get_target() << endl << " stencil-name: " << get_name() << endl << " stencil-description: " << get_description() << endl << " element-size: " << makeByteStr(get_element_bytes()) << endl << diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 2aa57db3..3423a932 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -133,12 +133,27 @@ namespace { return next_p; } + // Define equation for p at t+1 based on values from v and p at t. + virtual void define() override { + + // Get equation for RHS. + auto next_p = get_next_p(); + + // Define the value at t+1 to be equal to next_p. + // Since this implements the finite-difference method, this + // is actually an approximation. + p(t+1, x, y, z) EQUALS next_p; + + // Apply BKCs. + set_configs(); + } + // Set BKC (best-known configs) found by automated and manual // tuning. They are only applied for certain target configs. - virtual void set_BKC() { + virtual void set_configs() { auto soln = get_soln(); // pointer to compile-time soln. - // BKCs are only for SP FP and radius 8. + // Only have BKCs for SP FP (4B) and radius 8. if (soln->get_element_bytes() == 4 && get_radius() == 8) { @@ -180,20 +195,6 @@ namespace { } } - // Define equation for p at t+1 based on values from v and p at t. - virtual void define() { - - // Get equation for RHS. - auto next_p = get_next_p(); - - // Define the value at t+1 to be equal to next_p. - // Since this implements the finite-difference method, this - // is actually an approximation. - p(t+1, x, y, z) EQUALS next_p; - - // Insert code from tuning. - set_BKC(); - } }; // Create an object of type 'Iso3dfdStencil', @@ -211,7 +212,7 @@ namespace { virtual ~Iso3dfdSpongeStencil() { } // Define equation for p at t+1 based on values from v and p at t. - virtual void define() { + virtual void define() override { // Sponge coefficients. // In practice, the interior values would be set to 1.0, @@ -230,8 +231,8 @@ namespace { // Define the value at t+1 to be equal to next_p. p(t+1, x, y, z) EQUALS next_p; - // Insert code from tuning. - set_BKC(); + // Apply BKCs. + set_configs(); } }; diff --git a/utils/lib/YaskUtils.pm b/utils/lib/YaskUtils.pm index 131c8740..103b6e10 100644 --- a/utils/lib/YaskUtils.pm +++ b/utils/lib/YaskUtils.pm @@ -58,7 +58,7 @@ our @log_keys = 'best elapsed time (sec)', 'best num-steps-done', 'yask version', - 'target ISA', + 'target', 'stencil name', 'stencil description', 'element size', @@ -210,6 +210,7 @@ sub getResultsFromLine($$) { $line =~ s/rank.domain/local-domain/g; $line =~ s/grid/var/g; $line =~ s/Grid/Var/g; + $line =~ s/target.ISA/target/g; # special cases for manual parsing... # TODO: catch output of auto-tuner and update relevant results. From c7588ad318261ed7cbea1bb89a18167130d11673 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 10 Jun 2019 11:24:00 -0700 Subject: [PATCH 41/62] Fix bug caused by calling print_output() >1 time. --- src/compiler/compiler_main.cpp | 13 ++++---- src/compiler/lib/Solution.cpp | 58 ++++++++++++++++++++++------------ src/compiler/lib/Solution.hpp | 13 +++++--- 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index a83b4a24..5232540f 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -45,7 +45,7 @@ namespace yask { yc_factory factory; // output streams. - vector outfiles; + string outfile; // other vars set via cmd-line options. string solutionName; @@ -271,7 +271,7 @@ void parseOpts(int argc, const char* argv[], else if (opt == "-target") settings._target = argop; else if (opt == "-p") - outfiles.push_back(argop); + outfile = argop; else if (opt == "-vars") settings._varRegex = argop; else if (opt == "-eq-bundles") @@ -418,16 +418,15 @@ int main(int argc, const char* argv[]) { cout << "Num equations defined: " << soln->get_num_equations() << endl; // Create the requested output. - if (outfiles.size() == 0) + if (outfile.length() == 0) cout << "Use the '-p' option to generate output from this stencil.\n"; - for (auto& fname : outfiles) { - + else { yask_output_factory ofac; yask_output_ptr os; - if (fname == "-") + if (outfile == "-") os = ofac.new_stdout_output(); else - os = ofac.new_file_output(fname); + os = ofac.new_file_output(outfile); stencilSoln->get_soln()->output_solution(os); } } catch (yask_exception& e) { diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index fe9b7a4e..9ce425d0 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -32,9 +32,15 @@ using namespace std; namespace yask { - StencilSolution::~StencilSolution() { - if (_printer) + void StencilSolution::_free(bool free_printer) { + if (free_printer && _printer) delete _printer; + if (_eqBundles) + delete _eqBundles; + if (_eqBundlePacks) + delete _eqBundlePacks; + if (_clusterEqBundles) + delete _clusterEqBundles; } // Stencil-solution APIs. @@ -133,18 +139,18 @@ namespace yask { // Create equation bundles based on dependencies and/or target strings. // This process may alter the halos in scratch vars. - _eqBundles.set_basename_default(_settings._eq_bundle_basename_default); - _eqBundles.set_dims(_dims); - _eqBundles.makeEqBundles(_eqs, _settings, *_dos); + _eqBundles->set_basename_default(_settings._eq_bundle_basename_default); + _eqBundles->set_dims(_dims); + _eqBundles->makeEqBundles(_eqs, _settings, *_dos); // Optimize bundles. - _eqBundles.optimizeEqBundles(_settings, "scalar & vector", false, *_dos); + _eqBundles->optimizeEqBundles(_settings, "scalar & vector", false, *_dos); // Separate bundles into packs. - _eqBundlePacks.makePacks(_eqBundles, *_dos); + _eqBundlePacks->makePacks(*_eqBundles, *_dos); // Compute halos. - _eqBundlePacks.calcHalos(_eqBundles); + _eqBundlePacks->calcHalos(*_eqBundles); // Make a copy of each equation at each cluster offset. // We will use these for inter-cluster optimizations and code generation. @@ -152,13 +158,14 @@ namespace yask { // for sorting, making packs, etc. *_dos << "\nConstructing cluster of equations containing " << _dims._clusterMults.product() << " vector(s)...\n"; - _clusterEqBundles = _eqBundles; - _clusterEqBundles.replicateEqsInCluster(_dims); + *_clusterEqBundles = *_eqBundles; + _clusterEqBundles->replicateEqsInCluster(_dims); if (_settings._doOptCluster) - _clusterEqBundles.optimizeEqBundles(_settings, "cluster", true, *_dos); + _clusterEqBundles->optimizeEqBundles(_settings, "cluster", true, *_dos); } // Set format. + // Create new printer and intermediate data. void StencilSolution::set_target(const std::string& format) { auto& target = _settings._target; target = format; @@ -173,28 +180,34 @@ namespace yask { else if (target == "avx512f" || target == "skx" || target == "skl" || target == "clx") target = "avx512"; + + // Ensure all intermediate data is clean. + _free(true); + _eqBundles = new EqBundles; + _eqBundlePacks = new EqBundlePacks; + _clusterEqBundles = new EqBundles; // Create the appropriate printer object based on the format. // Most args to the printers just set references to data. // Data itself will be created in analyze_solution(). if (target == "intel64") - _printer = new YASKCppPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + _printer = new YASKCppPrinter(*this, *_eqBundles, *_eqBundlePacks, *_clusterEqBundles); else if (target == "knc") - _printer = new YASKKncPrinter(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + _printer = new YASKKncPrinter(*this, *_eqBundles, *_eqBundlePacks, *_clusterEqBundles); else if (target == "avx" || target == "avx2") - _printer = new YASKAvx256Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + _printer = new YASKAvx256Printer(*this, *_eqBundles, *_eqBundlePacks, *_clusterEqBundles); else if (target == "avx512" || target == "knl") - _printer = new YASKAvx512Printer(*this, _eqBundles, _eqBundlePacks, _clusterEqBundles); + _printer = new YASKAvx512Printer(*this, *_eqBundles, *_eqBundlePacks, *_clusterEqBundles); else if (target == "dot") - _printer = new DOTPrinter(*this, _clusterEqBundles, false); + _printer = new DOTPrinter(*this, *_clusterEqBundles, false); else if (target == "dot-lite") - _printer = new DOTPrinter(*this, _clusterEqBundles, true); + _printer = new DOTPrinter(*this, *_clusterEqBundles, true); else if (target == "pseudo") - _printer = new PseudoPrinter(*this, _clusterEqBundles, false); + _printer = new PseudoPrinter(*this, *_clusterEqBundles, false); else if (target == "pseudo-long") - _printer = new PseudoPrinter(*this, _clusterEqBundles, true); + _printer = new PseudoPrinter(*this, *_clusterEqBundles, true); else if (target == "pov-ray") // undocumented. - _printer = new POVRayPrinter(*this, _clusterEqBundles); + _printer = new POVRayPrinter(*this, *_clusterEqBundles); else { _printer = 0; target = ""; @@ -210,7 +223,10 @@ namespace yask { if (!is_target_set()) THROW_YASK_EXCEPTION("Error: output_solution() called before set_target()"); - assert(_printer); + + // Call set_target() to ensure intermediate data is clean + // before calling analyze_solution(). + set_target(target); // Set data for equation bundles, dims, etc. int vlen = _printer->num_vec_elems(); diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 163dea9f..294aac89 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -70,16 +70,19 @@ namespace yask { private: // Intermediate data needed to format output. + Dimensions _dims; // various dimensions. PrinterBase* _printer = 0; - Dimensions _dims; // various dimensions. - EqBundles _eqBundles; // eq-bundles for scalar and vector. - EqBundlePacks _eqBundlePacks; // packs of bundles w/o inter-dependencies. - EqBundles _clusterEqBundles; // eq-bundles for scalar and vector. + EqBundles* _eqBundles = 0; // eq-bundles for scalar and vector. + EqBundlePacks* _eqBundlePacks = 0; // packs of bundles w/o inter-dependencies. + EqBundles* _clusterEqBundles = 0; // eq-bundles for scalar and vector. // Create the intermediate data. void analyze_solution(int vlen, bool is_folding_efficient); + // Free allocated objs. + void _free(bool free_printer); + public: StencilSolution(const string& name) : _name(name) { @@ -87,7 +90,7 @@ namespace yask { auto so = ofac.new_stdout_output(); set_debug_output(so); } - virtual ~StencilSolution(); + virtual ~StencilSolution() { _free(true); } // Identification. virtual const string& getName() const { return _name; } From 2cd591882ae3480240162b6eddb7b6076646624c Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 11 Jun 2019 15:46:11 -0700 Subject: [PATCH 42/62] Create base clases for AWP stencils and move configs from Makefile. --- include/yask_compiler_api.hpp | 27 +- src/compiler/compiler_main.cpp | 10 +- src/compiler/lib/Expr.cpp | 2 +- src/compiler/lib/Expr.hpp | 17 +- src/compiler/lib/Settings.hpp | 1 + src/compiler/lib/Solution.cpp | 41 ++ src/compiler/lib/Solution.hpp | 5 + src/compiler/lib/YaskKernel.cpp | 10 +- src/kernel/Makefile | 47 +- src/stencils/AwpElasticStencil.cpp | 472 ---------------- src/stencils/AwpStencil.cpp | 843 ++++++++++++++++++++++------- src/stencils/Iso3dfdStencil.cpp | 34 +- src/stencils/TTIStencil.cpp | 19 + 13 files changed, 794 insertions(+), 734 deletions(-) delete mode 100644 src/stencils/AwpElasticStencil.cpp diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index 961b5ba5..d3eae862 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -400,6 +400,27 @@ namespace yask { virtual std::vector get_equations() =0; + /// Get the current prefetch distance for the given cache. + /** + @returns Prefetch distance in number of iterations + or zero (0) if disabled. + */ + virtual int + get_prefetch_dist(/** [in] Cache level: 1 or 2. */ + int level) =0; + + /// Set the prefetch distance for the given cache. + /** + If the prefetch distance is not set for a given cache, + a default will be used based on the target format. + */ + virtual void + set_prefetch_dist(/** [in] Cache level: 1 or 2. */ + int level, + /** [in] Number of iterations ahead to prefetch data + or zero (0) to disable. */ + int distance) =0; + /// Optimize and the current equation(s) and write to given output object. /** Output will be formatted according to set_target() and all other preceding @@ -445,6 +466,8 @@ namespace yask { This block of code will be executed immediately after the stencil solution is constructed in the kernel, i.e., at the end of a call to yk_factory::new_solution(). + The code may access the new solution via the reference + `kernel_soln` of type \ref yk_solution. Common uses of this facility include setting default run-time settings such as block sizes and registering call-back routines, e.g., via @@ -453,9 +476,9 @@ namespace yask { Unlike yk_solution::call_before_prepare_solution() and similar functions which have `std::function` parameters, the parameter to this function is a string because the code is not compiled - until the kernel library is built. + (or compilable) until the kernel library is built. - Alternatively , equivalent code can be added directly to any + Alternatively, equivalent code can be added directly to any custom application using the kernel library APIs. However, this function is useful when using the provided YASK kernel-performance utility launched via `bin/yask.sh`. It also diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 5232540f..28f86c92 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -125,6 +125,10 @@ void usage(const string& cmd, " formats with explicit lengths, lengths will adjusted as needed.\n" " -cluster =,...\n" " Set number of vectors to evaluate in each dimension.\n" + " -l1-prefetch-dist \n" + " Set L1 prefetch distance to iterations ahead. Use zero (0) to disable.\n" + " -l2-prefetch-dist \n" + " Set L2 prefetch distance to iterations ahead. Use zero (0) to disable.\n" " -vars \n" " Only process updates to vars whose names match .\n" " This can be used to generate code for a subset of the stencil equations.\n" @@ -313,7 +317,11 @@ void parseOpts(int argc, const char* argv[], // options w/an int value. int val = atoi(argop.c_str()); - if (opt == "-max-es") + if (opt == "-l1-prefetch-dist") + settings._prefetchDists[1] = val; + if (opt == "-l2-prefetch-dist") + settings._prefetchDists[2] = val; + else if (opt == "-max-es") settings._maxExprSize = val; else if (opt == "-min-es") settings._minExprSize = val; diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index fcf988ba..e9c0509f 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -684,7 +684,7 @@ namespace yask { } return str; } - string VarPoint::makeStr(const VarMap* varMap) const { + string VarPoint::_makeStr(const VarMap* varMap) const { string str = _var->getName() + "(" + makeArgStr(varMap) + ")"; return str; diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index b300af0c..202221ef 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -40,12 +40,14 @@ IN THE SOFTWARE. #include // Need g++ >= 4.9 for regex. -#define GCC_VERSION (__GNUC__ * 10000 \ +#ifdef __GNUC__ +#define GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) #if GCC_VERSION < 40900 #error G++ 4.9.0 or later is required #endif +#endif #include // Common utilities. @@ -115,7 +117,7 @@ namespace yask { return makePair(other.get()); } - // Return a simple string expr. + // Return a formatted expr. virtual string makeStr(const VarMap* varMap = 0) const; virtual string makeQuotedStr(string quote = "'", const VarMap* varMap = 0) const { @@ -814,10 +816,12 @@ namespace yask { VecType _vecType = VEC_UNSET; // allowed vectorization. LoopType _loopType = LOOP_UNSET; // analysis for looping. + // Cache the string repr. string _defStr; void _updateStr() { - _defStr = makeStr(); + _defStr = _makeStr(); } + string _makeStr(const VarMap* varMap = 0) const; public: @@ -895,7 +899,11 @@ namespace yask { // String w/name and parens around args, e.g., 'u(x, y+2)'. // Apply substitutions to indices using 'varMap' if provided. - virtual string makeStr(const VarMap* varMap = 0) const; + virtual string makeStr(const VarMap* varMap = 0) const { + if (varMap) + return _makeStr(varMap); + return _defStr; + } // String w/name and parens around const args, e.g., 'u(n=4)'. // Apply substitutions to indices using 'varMap' if provided. @@ -933,7 +941,6 @@ namespace yask { } // namespace yask. // Define hash function for VarPoint for unordered_{set,map}. -// TODO: make this more efficient. namespace std { using namespace yask; diff --git a/src/compiler/lib/Settings.hpp b/src/compiler/lib/Settings.hpp index f82a76a8..a9f9880d 100644 --- a/src/compiler/lib/Settings.hpp +++ b/src/compiler/lib/Settings.hpp @@ -43,6 +43,7 @@ namespace yask { vector _domainDims; // explicit domain dims. IntTuple _foldOptions; // vector fold. IntTuple _clusterOptions; // cluster multipliers. + map _prefetchDists; bool _firstInner = true; // first dimension of fold is unit step. string _eq_bundle_basename_default = "stencil_bundle"; bool _allowUnalignedLoads = false; diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 9ce425d0..17c74a38 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -74,6 +74,47 @@ namespace yask { auto& cluster = _settings._clusterOptions; cluster.addDimBack(dim->get_name(), mult); } + int StencilSolution::get_prefetch_dist(int level) { + if (level < 1 || level > 2) + THROW_YASK_EXCEPTION("Error: cache-level " + + to_string(level) + + " is not 1 or 2."); + if (_settings._prefetchDists.count(level)) + return _settings._prefetchDists.at(level); + else if (is_target_set()) { + auto target = get_target(); + + // Defaults for various targets. + if (target == "knc") { + if (level == 1) + return 1; + else + return 2; + } + if (target == "knl") { + if (level == 1) + return 1; + else + return 0; + } + else { + if (level == 1) + return 0; + else + return 2; + } + } + return 0; + } + void StencilSolution::set_prefetch_dist(int level, + int distance) { + get_prefetch_dist(level); // check legality. + if (distance < 0) + THROW_YASK_EXCEPTION("Error: prefetch-distance " + + to_string(distance) + + " is not positive."); + _settings._prefetchDists[level] = distance; + } yc_solution_base::soln_map& yc_solution_base::get_registry() { static yc_solution_base::soln_map* rp = 0; if (!rp) diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 294aac89..279d8c3c 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -188,6 +188,11 @@ namespace yask { call_after_new_solution(const string& code) { _kernel_code.push_back(code); } + virtual int + get_prefetch_dist(int level); + virtual void + set_prefetch_dist(int level, + int distance); virtual void add_flow_dependency(yc_equation_node_ptr from, yc_equation_node_ptr to) { auto fp = dynamic_pointer_cast(from); diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index fc9a54c3..2fb83bd0 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -171,9 +171,15 @@ namespace yask { auto& dname = dim.getName(); string ucDim = allCaps(dname); os << "#define CMULT_" << ucDim << " (" << - dim.getVal() << ")" << endl; + dim.getVal() << ")\n"; + } + os << "#define CMULT (" << _dims._clusterMults.product() << ")\n"; + + os << "\n// Prefetch distances\n"; + for (int level : { 1, 2 }) { + os << "#define PFD_L" << level << " (" << + _stencil.get_prefetch_dist(level) << ")\n"; } - os << "#define CMULT (" << _dims._clusterMults.product() << ")" << endl; } // Print YASK data class. diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 0c6fc7f0..4d3178e6 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -77,38 +77,7 @@ YC_TARGET := $(ARCH) # Defaults based on stencil type (and arch for some stencils). ifeq ($(YC_STENCIL),) - $(error Stencil not specified) - -else ifneq ($(findstring iso3dfd,$(YC_STENCIL)),) - ifeq ($(ARCH),knl) - pfd_l1 := 1 - pfd_l2 := 0 - else ifeq ($(arch),avx512) - pfd_l1 := 0 - pfd_l2 := 2 - else - pfd_l1 := 0 - pfd_l2 := 0 - endif - -else ifneq ($(findstring awp,$(YC_STENCIL)),) - YC_FLAGS += -min-es 1 - def_pad_args := -ep 1 - ifeq ($(ARCH),knl) - def_thread_divisor := 2 - def_block_threads := 4 - def_block_args := -bx 48 -by 48 -bx 112 - pfd_l1 := 1 - pfd_l2 := 0 - else ifeq ($(ARCH),avx512) - def_block_args := -bx 64 -by 8 -bz 108 - pfd_l1 := 1 - pfd_l2 := 0 - else - def_block_args := -bx 64 -by 8 -bz 64 - pfd_l1 := 1 - pfd_l2 := 2 - endif + $(error Stencil solution not specified) else ifneq ($(findstring ssg,$(YC_STENCIL)),) ifeq ($(ARCH),avx512) @@ -131,11 +100,6 @@ else ifneq ($(findstring fsg,$(YC_STENCIL)),) def_block_args := -bx 48 -by 4 -bz 128 endif -else ifeq ($(YC_STENCIL),tti) - ifeq ($(ARCH),avx512) - def_block_args := -bx 80 -by 16 -bz 40 - endif - endif # stencil-specific. # Default settings based on architecture. @@ -144,8 +108,6 @@ ifeq ($(ARCH),knc) ICC_ISA ?= -mmic MACROS += USE_INTRIN512 def_block_threads ?= 4 - pfd_l1 ?= 1 - pfd_l2 ?= 2 else ifeq ($(ARCH),knl) @@ -158,8 +120,6 @@ else ifeq ($(ARCH),knl) MACROS += USE_INTRIN512 USE_RCP28 NUMA_PREF=1 def_block_args ?= -b 64 def_block_threads ?= 8 - pfd_l1 ?= 1 - pfd_l2 ?= 0 else ifeq ($(ARCH),avx512) @@ -201,8 +161,6 @@ omp_misc_schedule ?= guided def_thread_divisor ?= 1 def_block_threads ?= 2 def_block_args ?= -b 32 -pfd_l1 ?= 0 -pfd_l2 ?= 2 ######## End of vars that control the function and performance of the kernel. @@ -373,7 +331,6 @@ else ifeq ($(check),1) endif # Set MACROS based on individual makefile vars. -MACROS += PFD_L1=$(pfd_l1) PFD_L2=$(pfd_l2) ifeq ($(streaming_stores),1) MACROS += USE_STREAMING_STORE endif @@ -827,7 +784,7 @@ stencil-tests: $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=ssg fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=ssg_merged fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=awp fold=x=2,y=2 - $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=awp_elastic fold=x=2,y=2 + $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=awp_abc fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=fsg_abc fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=fsg_merged fold=x=2,y=2 $(MAKE) clean; $(MAKE) $(STENCIL_TEST_ARGS) stencil=tti fold=x=2,y=2 diff --git a/src/stencils/AwpElasticStencil.cpp b/src/stencils/AwpElasticStencil.cpp deleted file mode 100644 index 677b1b63..00000000 --- a/src/stencils/AwpElasticStencil.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/***************************************************************************** - -YASK: Yet Another Stencil Kernel -Copyright (c) 2014-2019, Intel Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -* The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - -*****************************************************************************/ - -// Stencil equations for AWP elastic* numerics. -// *This version does not contain the time-varying attenuation memory vars -// or the related attenuation constant vars. -// This version also contains some experimental code for calculating the -// free-surface boundary values. -// http://hpgeoc.sdsc.edu/AWPODC -// http://www.sdsc.edu/News%20Items/PR20160209_earthquake_center.html - -// Set the following macro to use a sponge var instead of 3 sponge arrays. -//#define FULL_SPONGE_VAR - -// Set the following macro to define all points, even those above the -// surface that are never used. -#define SET_ALL_POINTS - -// Set the following macro to calculate free-surface boundary values. -#define DO_ABOVE_SURFACE - -// Set the following macro to use intermediate scratch vars. -//#define USE_SCRATCH_VARS - -// YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. -#include "yask_compiler_api.hpp" -using namespace std; -using namespace yask; - -// Create an anonymous namespace to ensure that types are local. -namespace { - - class AwpElasticStencil : public yc_solution_base { - - protected: - - // Indices & dimensions. - yc_index_node_ptr t = new_step_index("t"); // step in time dim. - yc_index_node_ptr x = new_domain_index("x"); // spatial dim. - yc_index_node_ptr y = new_domain_index("y"); // spatial dim. - yc_index_node_ptr z = new_domain_index("z"); // spatial dim. - - // Time-varying 3D-spatial velocity vars. - yc_var_proxy vel_x = yc_var_proxy("vel_x", get_soln(), { t, x, y, z }); - yc_var_proxy vel_y = yc_var_proxy("vel_y", get_soln(), { t, x, y, z }); - yc_var_proxy vel_z = yc_var_proxy("vel_z", get_soln(), { t, x, y, z }); - - // Time-varying 3D-spatial Stress vars. - yc_var_proxy stress_xx = yc_var_proxy("stress_xx", get_soln(), { t, x, y, z }); - yc_var_proxy stress_yy = yc_var_proxy("stress_yy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_zz = yc_var_proxy("stress_zz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_xy = yc_var_proxy("stress_xy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); - - // 3D-spatial Lame' coefficients. - yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); - yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); - yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); - - // Sponge coefficients. - // (Most of these will be 1.0.) -#ifdef FULL_SPONGE_VAR - yc_var_proxy sponge = yc_var_proxy("sponge", get_soln(), { x, y, z }); -#else - yc_var_proxy cr_x = yc_var_proxy("cr_x", get_soln(), { x }); - yc_var_proxy cr_y = yc_var_proxy("cr_y", get_soln(), { y }); - yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); -#endif - - // Spatial FD coefficients. - const double c1 = 9.0/8.0; - const double c2 = -1.0/24.0; - - // Physical dimensions in time and space. - yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); - yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); - - // For the surface stress conditions, we need to write into 2 points - // above the surface. Since we can only write into the "domain", we - // will define the surface index to be 2 points before the last domain - // index. Thus, there will be two layers in the domain above the surface. -#define SURFACE_IDX (last_domain_index(z) - 2) - - // Define some sub-domains related to the surface. -#define IF_BELOW_SURFACE IF_DOMAIN (z < SURFACE_IDX) -#define IF_AT_SURFACE IF_DOMAIN (z == SURFACE_IDX) -#define IF_AT_OR_BELOW_SURFACE IF_DOMAIN (z <= SURFACE_IDX) -#define IF_ONE_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 1) -#define IF_TWO_ABOVE_SURFACE IF_DOMAIN (z == SURFACE_IDX + 2) - -#ifdef USE_SCRATCH_VARS - yc_var_proxy tmp_vel_x = yc_var_proxy("tmp_vel_x", get_soln(), { x, y, z }, true); - yc_var_proxy tmp_vel_y = yc_var_proxy("tmp_vel_y", get_soln(), { x, y, z }, true); - yc_var_proxy tmp_vel_z = yc_var_proxy("tmp_vel_z", get_soln(), { x, y, z }, true); -#endif - - public: - - AwpElasticStencil() : - yc_solution_base("awp_elastic") { } - - // Adjustment for sponge layer. - void adjust_for_sponge(yc_number_node_ptr& val) { - -#ifdef FULL_SPONGE_VAR - val *= sponge(x, y, z); -#else - val *= cr_x(x) * cr_y(y) * cr_z(z); -#endif - } - - // Velocity-var define functions. For each D in x, y, z, define vel_D - // at t+1 based on vel_x at t and stress vars at t. Note that the t, - // x, y, z parameters are integer var indices, not actual offsets in - // time or space, so half-steps due to staggered vars are adjusted - // appropriately. - - yc_number_node_ptr get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto rho_val = (rho(x, y, z ) + - rho(x, y-1, z ) + - rho(x, y, z-1) + - rho(x, y-1, z-1)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xx(t, x, y, z ) - stress_xx(t, x-1, y, z )) + - c2 * (stress_xx(t, x+1, y, z ) - stress_xx(t, x-2, y, z )) + - c1 * (stress_xy(t, x, y, z ) - stress_xy(t, x, y-1, z )) + - c2 * (stress_xy(t, x, y+1, z ) - stress_xy(t, x, y-2, z )) + - c1 * (stress_xz(t, x, y, z ) - stress_xz(t, x, y, z-1)) + - c2 * (stress_xz(t, x, y, z+1) - stress_xz(t, x, y, z-2)); - auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_x); - - // Return the value at t+1. - return next_vel_x; - } - yc_number_node_ptr get_next_vel_y(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto rho_val = (rho(x, y, z ) + - rho(x+1, y, z ) + - rho(x, y, z-1) + - rho(x+1, y, z-1)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xy(t, x+1, y, z ) - stress_xy(t, x, y, z )) + - c2 * (stress_xy(t, x+2, y, z ) - stress_xy(t, x-1, y, z )) + - c1 * (stress_yy(t, x, y+1, z ) - stress_yy(t, x, y, z )) + - c2 * (stress_yy(t, x, y+2, z ) - stress_yy(t, x, y-1, z )) + - c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y, z-1)) + - c2 * (stress_yz(t, x, y, z+1) - stress_yz(t, x, y, z-2)); - auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_y); - - // Return the value at t+1. - return next_vel_y; - } - yc_number_node_ptr get_next_vel_z(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto rho_val = (rho(x, y, z) + - rho(x+1, y, z) + - rho(x, y-1, z) + - rho(x+1, y-1, z)) * (1.0 / 4.0); - auto d_val = - c1 * (stress_xz(t, x+1, y, z ) - stress_xz(t, x, y, z )) + - c2 * (stress_xz(t, x+2, y, z ) - stress_xz(t, x-1, y, z )) + - c1 * (stress_yz(t, x, y, z ) - stress_yz(t, x, y-1, z )) + - c2 * (stress_yz(t, x, y+1, z ) - stress_yz(t, x, y-2, z )) + - c1 * (stress_zz(t, x, y, z+1) - stress_zz(t, x, y, z )) + - c2 * (stress_zz(t, x, y, z+2) - stress_zz(t, x, y, z-1)); - auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; - adjust_for_sponge(next_vel_z); - - // Return the value at t+1. - return next_vel_z; - } - - // Free-surface boundary equations for velocity. - void define_free_surface_vel() { - - // Since we're defining points when z == surface + 1, - // the surface itself will be at z - 1; - auto surf = z - 1; - -#ifdef USE_SCRATCH_VARS - - // The values for velocity at t+1 will be needed - // in multiple free-surface calculations. - // Thus, it will reduce the number of FP ops - // required if we pre-compute them and store them - // in scratch vars. -#define VEL_X tmp_vel_x -#define VEL_Y tmp_vel_y -#define VEL_Z tmp_vel_z - VEL_X(x, y, z) EQUALS get_next_vel_x(x, y, z); - VEL_Y(x, y, z) EQUALS get_next_vel_y(x, y, z); - VEL_Z(x, y, z) EQUALS get_next_vel_z(x, y, z); - -#else - - // If not using scratch vars, just call the - // functions to calculate each value of velocity - // at t+1 every time it's needed. -#define VEL_X get_next_vel_x -#define VEL_Y get_next_vel_y -#define VEL_Z get_next_vel_z -#endif - - // A couple of intermediate values. - auto d_x_val = VEL_X(x+1, y, surf) - - (VEL_Z(x+1, y, surf) - VEL_Z(x, y, surf)); - auto d_y_val = VEL_Y(x, y-1, surf) - - (VEL_Z(x, y, surf) - VEL_Z(x, y-1, surf)); - - // Following values are valid one layer above the free surface. - auto plus1_vel_x = VEL_X(x, y, surf) - - (VEL_Z(x, y, surf) - VEL_Z(x-1, y, surf)); - auto plus1_vel_y = VEL_Y(x, y, surf) - - (VEL_Z(x, y+1, surf) - VEL_Z(x, y, surf)); - auto plus1_vel_z = VEL_Z(x, y, surf) - - ((d_x_val - plus1_vel_x) + - (VEL_X(x+1, y, surf) - VEL_X(x, y, surf)) + - (plus1_vel_y - d_y_val) + - (VEL_Y(x, y, surf) - VEL_Y(x, y-1, surf))) / - ((mu(x, y, surf) * - (2.0 / mu(x, y, surf) + 1.0 / lambda(x, y, surf)))); -#undef VEL_X -#undef VEL_Y -#undef VEL_Z - - // Define layer at one point above surface. - vel_x(t+1, x, y, z) EQUALS plus1_vel_x IF_ONE_ABOVE_SURFACE; - vel_y(t+1, x, y, z) EQUALS plus1_vel_y IF_ONE_ABOVE_SURFACE; - vel_z(t+1, x, y, z) EQUALS plus1_vel_z IF_ONE_ABOVE_SURFACE; - -#ifdef SET_ALL_POINTS - // Define layer two points above surface for completeness, even - // though these aren't input to any stencils. - vel_x(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - vel_y(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - vel_z(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; -#endif - } - - // Compute average of 8 neighbors. - yc_number_node_ptr ave8(yc_var_proxy& g, yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - return 8.0 / - (g(x, y, z ) + g(x+1, y, z ) + - g(x, y-1, z ) + g(x+1, y-1, z ) + - g(x, y, z-1) + g(x+1, y, z-1) + - g(x, y-1, z-1) + g(x+1, y-1, z-1)); - } - - // Some common velocity calculations. - yc_number_node_ptr d_x_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - return - c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); - } - yc_number_node_ptr d_y_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - return - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + - c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); - } - yc_number_node_ptr d_z_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - return - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + - c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); - } - - // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, - // define stress_D at t+1 based on stress_D at t and vel vars at t+1. - // This implies that the velocity-var define functions must be called - // before these for a given value of t. Note that the t, x, y, z - // parameters are integer var indices, not actual offsets in time or - // space, so half-steps due to staggered vars are adjusted - // appropriately. - - yc_number_node_ptr get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - auto next_stress_xx = stress_xx(t, x, y, z) + - ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_x_val(x, y, z)) + - (ave8(lambda, x, y, z) * - (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); - adjust_for_sponge(next_stress_xx); - - // Return the value at t+1. - return next_stress_xx; - } - yc_number_node_ptr get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - auto next_stress_yy = stress_yy(t, x, y, z) + - ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_y_val(x, y, z)) + - (ave8(lambda, x, y, z) * - (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); - adjust_for_sponge(next_stress_yy); - - // Return the value at t+1. - return next_stress_yy; - } - yc_number_node_ptr get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - auto next_stress_zz = stress_zz(t, x, y, z) + - ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_z_val(x, y, z)) + - (ave8(lambda, x, y, z) * - (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); - adjust_for_sponge(next_stress_zz); - - // return the value at t+1. - return next_stress_zz; - } - yc_number_node_ptr get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - // Compute average of 2 neighbors. - auto mu2 = 2.0 / - (mu(x, y, z ) + mu(x, y, z-1)); - - // Note that we are using the velocity values at t+1. - auto d_xy_val = - c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - auto d_yx_val = - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + - c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); - - auto next_stress_xy = stress_xy(t, x, y, z) + - ((mu2 * delta_t / h) * (d_xy_val + d_yx_val)); - adjust_for_sponge(next_stress_xy); - - // return the value at t+1. - return next_stress_xy; - } - yc_number_node_ptr get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - // Compute average of 2 neighbors. - auto mu2 = 2.0 / - (mu(x, y, z ) + mu(x, y-1, z )); - - // Note that we are using the velocity values at t+1. - auto d_xz_val = - c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - auto d_zx_val = - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + - c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); - - auto next_stress_xz = stress_xz(t, x, y, z) + - ((mu2 * delta_t / h) * (d_xz_val + d_zx_val)); - adjust_for_sponge(next_stress_xz); - - // return the value at t+1. - return next_stress_xz; - } - yc_number_node_ptr get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - - // Compute average of 2 neighbors. - auto mu2 = 2.0 / - (mu(x, y, z ) + mu(x+1, y, z )); - - // Note that we are using the velocity values at t+1. - auto d_yz_val = - c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + - c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - auto d_zy_val = - c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + - c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); - - auto next_stress_yz = stress_yz(t, x, y, z) + - ((mu2 * delta_t / h) * (d_yz_val + d_zy_val)); - adjust_for_sponge(next_stress_yz); - - // return the value at t+1. - return next_stress_yz; - } - - // Free-surface boundary equations for stress. - void define_free_surface_stress() { - - // When z == surface + 1, the surface will be at z - 1; - auto surf = z - 1; - - stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf) IF_ONE_ABOVE_SURFACE; - stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; - stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; - -#ifdef SET_ALL_POINTS - // Define other 3 stress values for completeness, even - // though these aren't input to any stencils. - stress_xx(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; - stress_yy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; - stress_xy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; -#endif - - // When z == surface + 2, the surface will be at z - 2; - surf = z - 2; - - stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf-1) IF_TWO_ABOVE_SURFACE; - stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; - stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; - -#ifdef SET_ALL_POINTS - // Define other 3 stress values for completeness, even - // though these aren't input to any stencils. - stress_xx(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - stress_yy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; - stress_xy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; -#endif - } - - // Define the t+1 values for all velocity and stress vars. - virtual void define() { - - // Define velocity components. - vel_x(t+1, x, y, z) EQUALS get_next_vel_x(x, y, z) IF_AT_OR_BELOW_SURFACE; - vel_y(t+1, x, y, z) EQUALS get_next_vel_y(x, y, z) IF_AT_OR_BELOW_SURFACE; - vel_z(t+1, x, y, z) EQUALS get_next_vel_z(x, y, z) IF_AT_OR_BELOW_SURFACE; - - // Define stress components. Use non-overlapping sub-domains only, - // i.e. AT and BELOW but not AT_OR_BELOW, even though there are some - // repeated stencils. This allows the YASK compiler to bundle all - // the stress equations together. - stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_BELOW_SURFACE; - stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_BELOW_SURFACE; - stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_BELOW_SURFACE; - stress_xz(t+1, x, y, z) EQUALS get_next_stress_xz(x, y, z) IF_BELOW_SURFACE; - stress_yz(t+1, x, y, z) EQUALS get_next_stress_yz(x, y, z) IF_BELOW_SURFACE; - stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_BELOW_SURFACE; - - stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_AT_SURFACE; - stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_AT_SURFACE; - stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_AT_SURFACE; - stress_xz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; - stress_yz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; - stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_AT_SURFACE; - - // Boundary conditions. -#ifdef DO_ABOVE_SURFACE - define_free_surface_vel(); - define_free_surface_stress(); -#endif - } - }; - - // Create an object of type 'AwpElasticStencil', - // making it available in the YASK compiler utility via the - // '-stencil' commmand-line option or the 'stencil=' build option. - static AwpElasticStencil AwpElasticStencil_instance; - -#undef DO_SURFACE -#undef FULL_SPONGE_VAR -#undef USE_SCRATCH_VARS - -} // namespace. diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index 8ab73c50..e76c4130 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -27,18 +27,52 @@ IN THE SOFTWARE. // http://hpgeoc.sdsc.edu/AWPODC // http://www.sdsc.edu/News%20Items/PR20160209_earthquake_center.html -// Set the following macro to use a sponge var instead of 3 sponge arrays. -//#define FULL_SPONGE_VAR - // YASK stencil solution(s) in this file will be integrated into the YASK compiler utility. #include "yask_compiler_api.hpp" using namespace std; using namespace yask; +// Set the following macro to use a 3D sponge var instead of 3 sponge arrays. +//#define FULL_SPONGE_VAR + +// The remainder of the macros apply only to the "abc" versions. + +// Set the following macro to define all points, even those above the +// surface that are never used. +#define SET_ALL_POINTS + +// Set the following macro to calculate free-surface boundary values. +#define DO_ABOVE_SURFACE + +// Set the following macro to use intermediate scratch vars. +//#define USE_SCRATCH_VARS + +// For the surface stress conditions, we need to write into 2 points +// above the surface. Since we can only write into the "domain", we +// will define the surface index to be 2 points before the last domain +// index. Thus, there will be two layers in the domain above the surface. +#define SURFACE_IDX (last_domain_index(z) - 2) + +// Define some sub-domains related to the surface. +#define BELOW_SURFACE (z < SURFACE_IDX) +#define AT_SURFACE (z == SURFACE_IDX) +#define AT_OR_BELOW_SURFACE (z <= SURFACE_IDX) +#define ONE_ABOVE_SURFACE (z == SURFACE_IDX + 1) +#define TWO_ABOVE_SURFACE (z == SURFACE_IDX + 2) +#define IF_BELOW_SURFACE IF_DOMAIN BELOW_SURFACE +#define IF_AT_SURFACE IF_DOMAIN AT_SURFACE +#define IF_AT_OR_BELOW_SURFACE IF_DOMAIN AT_OR_BELOW_SURFACE +#define IF_ONE_ABOVE_SURFACE IF_DOMAIN ONE_ABOVE_SURFACE +#define IF_TWO_ABOVE_SURFACE IF_DOMAIN TWO_ABOVE_SURFACE + // Create an anonymous namespace to ensure that types are local. namespace { - class AwpStencil : public yc_solution_base { + // Base class containing elastic equations for AWP stencils. + class AwpElasticBase : public yc_solution_base { + public: + AwpElasticBase(const string& name) : + yc_solution_base(name) { } protected: @@ -61,28 +95,18 @@ namespace { yc_var_proxy stress_xz = yc_var_proxy("stress_xz", get_soln(), { t, x, y, z }); yc_var_proxy stress_yz = yc_var_proxy("stress_yz", get_soln(), { t, x, y, z }); - // Time-varying attenuation memory vars. - yc_var_proxy stress_mem_xx = yc_var_proxy("stress_mem_xx", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_yy = yc_var_proxy("stress_mem_yy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_zz = yc_var_proxy("stress_mem_zz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_xy = yc_var_proxy("stress_mem_xy", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_xz = yc_var_proxy("stress_mem_xz", get_soln(), { t, x, y, z }); - yc_var_proxy stress_mem_yz = yc_var_proxy("stress_mem_yz", get_soln(), { t, x, y, z }); - - // 3D vars used for anelastic attenuation - yc_var_proxy weight = yc_var_proxy("weight", get_soln(), { x, y, z }); - yc_var_proxy tau2 = yc_var_proxy("tau2", get_soln(), { x, y, z }); - yc_var_proxy anelastic_ap = yc_var_proxy("anelastic_ap", get_soln(), { x, y, z }); - yc_var_proxy anelastic_as_diag = yc_var_proxy("anelastic_as_diag", get_soln(), { x, y, z }); - yc_var_proxy anelastic_xy = yc_var_proxy("anelastic_xy", get_soln(), { x, y, z }); - yc_var_proxy anelastic_xz = yc_var_proxy("anelastic_xz", get_soln(), { x, y, z }); - yc_var_proxy anelastic_yz = yc_var_proxy("anelastic_yz", get_soln(), { x, y, z }); - // 3D-spatial Lame' coefficients. yc_var_proxy lambda = yc_var_proxy("lambda", get_soln(), { x, y, z }); yc_var_proxy rho = yc_var_proxy("rho", get_soln(), { x, y, z }); yc_var_proxy mu = yc_var_proxy("mu", get_soln(), { x, y, z }); + // Spatial FD coefficients. + const double c1 = 9.0/8.0; + const double c2 = -1.0/24.0; + + // Physical grid spacing in time and space. + yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln()); + yc_var_proxy h = yc_var_proxy("h", get_soln()); // Sponge coefficients. // (Most of these will be 1.0.) #ifdef FULL_SPONGE_VAR @@ -93,18 +117,11 @@ namespace { yc_var_proxy cr_z = yc_var_proxy("cr_z", get_soln(), { z }); #endif - // Spatial FD coefficients. - const double c1 = 9.0/8.0; - const double c2 = -1.0/24.0; - - // Physical dimensions in time and space. - yc_var_proxy delta_t = yc_var_proxy("delta_t", get_soln(), { }); - yc_var_proxy h = yc_var_proxy("h", get_soln(), { }); - - public: - - AwpStencil() : - yc_solution_base("awp") { } +#ifdef USE_SCRATCH_VARS + yc_var_proxy tmp_vel_x = yc_var_proxy("tmp_vel_x", get_soln(), { x, y, z }, true); + yc_var_proxy tmp_vel_y = yc_var_proxy("tmp_vel_y", get_soln(), { x, y, z }, true); + yc_var_proxy tmp_vel_z = yc_var_proxy("tmp_vel_z", get_soln(), { x, y, z }, true); +#endif // Adjustment for sponge layer. void adjust_for_sponge(yc_number_node_ptr& val) { @@ -116,13 +133,14 @@ namespace { #endif } - // Velocity-var define functions. For each D in x, y, z, define vel_D + // Velocity functions. For each D in x, y, z, define vel_D // at t+1 based on vel_x at t and stress vars at t. Note that the t, // x, y, z parameters are integer var indices, not actual offsets in // time or space, so half-steps due to staggered vars are adjusted // appropriately. - void define_vel_x() { + virtual yc_number_node_ptr + get_next_vel_x(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { auto rho_val = (rho(x, y, z ) + rho(x, y-1, z ) + rho(x, y, z-1) + @@ -137,10 +155,11 @@ namespace { auto next_vel_x = vel_x(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_x); - // define the value at t+1. - vel_x(t+1, x, y, z) EQUALS next_vel_x; + // Return expr for the value at t+1. + return next_vel_x; } - void define_vel_y() { + virtual yc_number_node_ptr + get_next_vel_y(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { auto rho_val = (rho(x, y, z ) + rho(x+1, y, z ) + rho(x, y, z-1) + @@ -155,10 +174,11 @@ namespace { auto next_vel_y = vel_y(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_y); - // define the value at t+1. - vel_y(t+1, x, y, z) EQUALS next_vel_y; + // Return expr for the value at t+1. + return next_vel_y; } - void define_vel_z() { + virtual yc_number_node_ptr + get_next_vel_z(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { auto rho_val = (rho(x, y, z) + rho(x+1, y, z) + rho(x, y-1, z) + @@ -173,11 +193,80 @@ namespace { auto next_vel_z = vel_z(t, x, y, z) + (delta_t / (h * rho_val)) * d_val; adjust_for_sponge(next_vel_z); - // define the value at t+1. - vel_z(t+1, x, y, z) EQUALS next_vel_z; + // Return expr for the value at t+1. + return next_vel_z; + } + + // Compute inverse of average of 8 neighbors. + yc_number_node_ptr + ave8(yc_var_proxy& g, + yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + return 8.0 / + (g(x, y, z ) + g(x+1, y, z ) + + g(x, y-1, z ) + g(x+1, y-1, z ) + + g(x, y, z-1) + g(x+1, y, z-1) + + g(x, y-1, z-1) + g(x+1, y-1, z-1)); } - // Stress-var define functions. For each D in xx, yy, zz, xy, xz, yz, + // Some common velocity FD calculations. + // Note that these use vel values from t+1. + yc_number_node_ptr + d_x_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); + } + yc_number_node_ptr + d_y_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + + c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); + } + yc_number_node_ptr + d_z_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + + c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); + } + yc_number_node_ptr + d_xy_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); + } + yc_number_node_ptr + d_yx_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + + c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); + } + yc_number_node_ptr + d_xz_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + + c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); + } + yc_number_node_ptr + d_zx_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + + c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); + } + yc_number_node_ptr + d_yz_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + + c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); + } + yc_number_node_ptr + d_zy_val(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return + c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + + c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); + } + + // Stress functions. For each D in xx, yy, zz, xy, xz, yz, // define stress_D at t+1 based on stress_D at t and vel vars at t+1. // This implies that the velocity-var define functions must be called // before these for a given value of t. Note that the t, x, y, z @@ -185,206 +274,572 @@ namespace { // space, so half-steps due to staggered vars are adjusted // appropriately. - void define_stress_xx(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, - yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, - yc_number_node_ptr tau1) { + virtual yc_number_node_ptr + get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto stress_mem_xx_old = stress_mem_xx(t, x, y, z); + auto next_stress_xx = stress_xx(t, x, y, z) + + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_x_val(x, y, z)) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); + adjust_for_sponge(next_stress_xx); - auto next_stress_mem_xx = tau2(x, y, z) * stress_mem_xx_old + - (1.0 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_as_diag(x, y, z) * (d_y_val + d_z_val) - - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); + // Return expr for the value at t+1. + return next_stress_xx; + } + virtual yc_number_node_ptr + get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto next_stress_xx = stress_xx(t, x, y, z) + - ((delta_t / h) * ((2. * mu_val * d_x_val) + - (lambda_val * (d_x_val + d_y_val + d_z_val)))) + - delta_t * (next_stress_mem_xx + stress_mem_xx_old); + auto next_stress_yy = stress_yy(t, x, y, z) + + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_y_val(x, y, z)) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); + adjust_for_sponge(next_stress_yy); - adjust_for_sponge(next_stress_xx); + // Return expr for the value at t+1. + return next_stress_yy; + } + virtual yc_number_node_ptr + get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + + auto next_stress_zz = stress_zz(t, x, y, z) + + ((delta_t / h) * ((2 * ave8(mu, x, y, z) * d_z_val(x, y, z)) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))); + adjust_for_sponge(next_stress_zz); - // define the value at t+1. - stress_mem_xx(t+1, x, y, z) EQUALS next_stress_mem_xx; - stress_xx(t+1, x, y, z) EQUALS next_stress_xx; + // Return expr for the value at t+1. + return next_stress_zz; } - void define_stress_yy(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, - yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, - yc_number_node_ptr tau1) { + virtual yc_number_node_ptr + get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto stress_mem_yy_old = stress_mem_yy(t, x, y, z); + // Compute average of 2 neighbors. + auto mu2 = 2.0 / + (mu(x, y, z ) + mu(x, y, z-1)); - auto next_stress_mem_yy = tau2(x, y, z) * stress_mem_yy_old + - (1 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_z_val) - - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); + auto next_stress_xy = stress_xy(t, x, y, z) + + ((mu2 * delta_t / h) * (d_xy_val(x, y, z) + d_yx_val(x, y, z))); + adjust_for_sponge(next_stress_xy); - auto next_stress_yy = stress_yy(t, x, y, z) + - ((delta_t / h) * ((2. * mu_val * d_y_val) + - (lambda_val * (d_x_val + d_y_val + d_z_val)))) + - delta_t * (next_stress_mem_yy + stress_mem_yy_old); + // Return expr for the value at t+1. + return next_stress_xy; + } + virtual yc_number_node_ptr + get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - adjust_for_sponge(next_stress_yy); + // Compute average of 2 neighbors. + auto mu2 = 2.0 / + (mu(x, y, z ) + mu(x, y-1, z )); - // define the value at t+1. - stress_mem_yy(t+1, x, y, z) EQUALS next_stress_mem_yy; - stress_yy(t+1, x, y, z) EQUALS next_stress_yy; + auto next_stress_xz = stress_xz(t, x, y, z) + + ((mu2 * delta_t / h) * (d_xz_val(x, y, z) + d_zx_val(x, y, z))); + adjust_for_sponge(next_stress_xz); + + // Return expr for the value at t+1. + return next_stress_xz; } - void define_stress_zz(yc_number_node_ptr lambda_val, yc_number_node_ptr mu_val, - yc_number_node_ptr d_x_val, yc_number_node_ptr d_y_val, yc_number_node_ptr d_z_val, - yc_number_node_ptr tau1) { + virtual yc_number_node_ptr + get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { - auto stress_mem_zz_old = stress_mem_zz(t, x, y, z); + // Compute average of 2 neighbors. + auto mu2 = 2.0 / + (mu(x, y, z ) + mu(x+1, y, z )); - auto next_stress_mem_zz = tau2(x, y, z) * stress_mem_zz_old + - (1 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_as_diag(x, y, z) * (d_x_val + d_y_val) - - (mu_val + 0.5 * lambda_val) * anelastic_ap(x, y, z) * (d_x_val + d_y_val + d_z_val)); + auto next_stress_yz = stress_yz(t, x, y, z) + + ((mu2 * delta_t / h) * (d_yz_val(x, y, z) + d_zy_val(x, y, z))); + adjust_for_sponge(next_stress_yz); - auto next_stress_zz = stress_zz(t, x, y, z) + - ((delta_t / h) * ((2. * mu_val * d_z_val) + - (lambda_val * (d_x_val + d_y_val + d_z_val)))) + - delta_t * (next_stress_mem_zz + stress_mem_zz_old); + // Return expr for the value at t+1. + return next_stress_yz; + } - adjust_for_sponge(next_stress_zz); + // Free-surface boundary equations for velocity. + void define_free_surface_vel() { + + // Since we're defining points when z == surface + 1, + // the surface itself will be at z - 1; + auto surf = z - 1; + +#ifdef USE_SCRATCH_VARS + + // The values for velocity at t+1 will be needed + // in multiple free-surface calculations. + // Thus, it will reduce the number of FP ops + // required if we pre-compute them and store them + // in scratch vars. The downside is more memory + // and memory accesses. +#define VEL_X tmp_vel_x +#define VEL_Y tmp_vel_y +#define VEL_Z tmp_vel_z + VEL_X(x, y, z) EQUALS get_next_vel_x(x, y, z); + VEL_Y(x, y, z) EQUALS get_next_vel_y(x, y, z); + VEL_Z(x, y, z) EQUALS get_next_vel_z(x, y, z); + +#else - // define the value at t+1. - stress_mem_zz(t+1, x, y, z) EQUALS next_stress_mem_zz; - stress_zz(t+1, x, y, z) EQUALS next_stress_zz; + // If not using scratch vars, just call the + // functions to calculate each value of velocity + // at t+1 every time it's needed. +#define VEL_X get_next_vel_x +#define VEL_Y get_next_vel_y +#define VEL_Z get_next_vel_z +#endif + + // A couple of intermediate values. + auto d_x_val = VEL_X(x+1, y, surf) - + (VEL_Z(x+1, y, surf) - VEL_Z(x, y, surf)); + auto d_y_val = VEL_Y(x, y-1, surf) - + (VEL_Z(x, y, surf) - VEL_Z(x, y-1, surf)); + + // Following values are valid one layer above the free surface. + auto plus1_vel_x = VEL_X(x, y, surf) - + (VEL_Z(x, y, surf) - VEL_Z(x-1, y, surf)); + auto plus1_vel_y = VEL_Y(x, y, surf) - + (VEL_Z(x, y+1, surf) - VEL_Z(x, y, surf)); + auto plus1_vel_z = VEL_Z(x, y, surf) - + ((d_x_val - plus1_vel_x) + + (VEL_X(x+1, y, surf) - VEL_X(x, y, surf)) + + (plus1_vel_y - d_y_val) + + (VEL_Y(x, y, surf) - VEL_Y(x, y-1, surf))) / + ((mu(x, y, surf) * + (2.0 / mu(x, y, surf) + 1.0 / lambda(x, y, surf)))); +#undef VEL_X +#undef VEL_Y +#undef VEL_Z + + // Define layer at one point above surface. + vel_x(t+1, x, y, z) EQUALS plus1_vel_x IF_ONE_ABOVE_SURFACE; + vel_y(t+1, x, y, z) EQUALS plus1_vel_y IF_ONE_ABOVE_SURFACE; + vel_z(t+1, x, y, z) EQUALS plus1_vel_z IF_ONE_ABOVE_SURFACE; + +#ifdef SET_ALL_POINTS + // Define layer two points above surface for completeness, even + // though these aren't input to any stencils. + vel_x(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + vel_y(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + vel_z(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; +#endif } - void define_stress_xy(yc_number_node_ptr tau1) { - auto mu_val = 2.0 / - (mu(x, y, z ) + mu(x, y, z-1)); + // Free-surface boundary equations for stress. + void define_free_surface_stress() { - // Note that we are using the velocity values at t+1. - auto d_xy_val = - c1 * (vel_x(t+1, x, y+1, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y+2, z ) - vel_x(t+1, x, y-1, z )); - auto d_yx_val = - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x-1, y, z )) + - c2 * (vel_y(t+1, x+1, y, z ) - vel_y(t+1, x-2, y, z )); + // When z == surface + 1, the surface will be at z - 1; + auto surf = z - 1; - auto stress_mem_xy_old = stress_mem_xy(t, x, y, z); + stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf) IF_ONE_ABOVE_SURFACE; + stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; + stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-1) IF_ONE_ABOVE_SURFACE; - auto next_stress_mem_xy = tau2(x, y, z) * stress_mem_xy_old - - (0.5 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_xy(x, y, z) * (d_xy_val + d_yx_val)); +#ifdef SET_ALL_POINTS + // Define other 3 stress values for completeness, even + // though these aren't input to any stencils. + stress_xx(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; + stress_yy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; + stress_xy(t+1, x, y, z) EQUALS 0.0 IF_ONE_ABOVE_SURFACE; +#endif - auto next_stress_xy = stress_xy(t, x, y, z) + - ((mu_val * delta_t / h) * (d_xy_val + d_yx_val)) + - delta_t * (next_stress_mem_xy + stress_mem_xy_old); + // When z == surface + 2, the surface will be at z - 2; + surf = z - 2; - adjust_for_sponge(next_stress_xy); + stress_zz(t+1, x, y, z) EQUALS -get_next_stress_zz(x, y, surf-1) IF_TWO_ABOVE_SURFACE; + stress_xz(t+1, x, y, z) EQUALS -get_next_stress_xz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; + stress_yz(t+1, x, y, z) EQUALS -get_next_stress_yz(x, y, surf-2) IF_TWO_ABOVE_SURFACE; - // define the value at t+1. - stress_mem_xy(t+1, x, y, z) EQUALS next_stress_mem_xy; - stress_xy(t+1, x, y, z) EQUALS next_stress_xy; +#ifdef SET_ALL_POINTS + // Define other 3 stress values for completeness, even + // though these aren't input to any stencils. + stress_xx(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + stress_yy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; + stress_xy(t+1, x, y, z) EQUALS 0.0 IF_TWO_ABOVE_SURFACE; +#endif } - void define_stress_xz(yc_number_node_ptr tau1) { - auto mu_val = 2.0 / - (mu(x, y, z ) + mu(x, y-1, z )); + // Define the t+1 values for all velocity and stress vars. + virtual void defineBase() { - // Note that we are using the velocity values at t+1. - auto d_xz_val = - c1 * (vel_x(t+1, x, y, z+1) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x, y, z+2) - vel_x(t+1, x, y, z-1)); - auto d_zx_val = - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x-1, y, z )) + - c2 * (vel_z(t+1, x+1, y, z ) - vel_z(t+1, x-2, y, z )); + // Define velocity components. + vel_x(t+1, x, y, z) EQUALS get_next_vel_x(x, y, z); + vel_y(t+1, x, y, z) EQUALS get_next_vel_y(x, y, z); + vel_z(t+1, x, y, z) EQUALS get_next_vel_z(x, y, z); - auto stress_mem_xz_old = stress_mem_xz(t, x, y, z); + // Define stress components. + stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z); + stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z); + stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z); + stress_xz(t+1, x, y, z) EQUALS get_next_stress_xz(x, y, z); + stress_yz(t+1, x, y, z) EQUALS get_next_stress_yz(x, y, z); + stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z); + } + + // Define the t+1 values for all velocity and stress vars + // with ABC. + virtual void defineBaseABC() { - auto next_stress_mem_xz = tau2(x, y, z) * stress_mem_xz_old - - (0.5 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_xz(x, y, z) * (d_xz_val + d_zx_val)); + // Define velocity components. + vel_x(t+1, x, y, z) EQUALS get_next_vel_x(x, y, z) IF_AT_OR_BELOW_SURFACE; + vel_y(t+1, x, y, z) EQUALS get_next_vel_y(x, y, z) IF_AT_OR_BELOW_SURFACE; + vel_z(t+1, x, y, z) EQUALS get_next_vel_z(x, y, z) IF_AT_OR_BELOW_SURFACE; + + // Define stress components. Use non-overlapping sub-domains only, + // i.e., AT and BELOW but not AT_OR_BELOW, even though there are some + // repeated stencils. This allows the YASK compiler to bundle all + // the stress equations together. + stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_BELOW_SURFACE; + stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_BELOW_SURFACE; + stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_BELOW_SURFACE; + stress_xz(t+1, x, y, z) EQUALS get_next_stress_xz(x, y, z) IF_BELOW_SURFACE; + stress_yz(t+1, x, y, z) EQUALS get_next_stress_yz(x, y, z) IF_BELOW_SURFACE; + stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_BELOW_SURFACE; + + stress_xx(t+1, x, y, z) EQUALS get_next_stress_xx(x, y, z) IF_AT_SURFACE; + stress_yy(t+1, x, y, z) EQUALS get_next_stress_yy(x, y, z) IF_AT_SURFACE; + stress_xy(t+1, x, y, z) EQUALS get_next_stress_xy(x, y, z) IF_AT_SURFACE; + stress_xz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; + stress_yz(t+1, x, y, z) EQUALS 0.0 IF_AT_SURFACE; + stress_zz(t+1, x, y, z) EQUALS get_next_stress_zz(x, y, z) IF_AT_SURFACE; + + // Boundary conditions. +#ifdef DO_ABOVE_SURFACE + define_free_surface_vel(); + define_free_surface_stress(); +#endif + } - auto next_stress_xz = stress_xz(t, x, y, z) + - ((mu_val * delta_t / h) * (d_xz_val + d_zx_val)) + - delta_t * (next_stress_mem_xz + stress_mem_xz_old); + // Set BKC (best-known configs) found by automated and/or manual + // tuning. They are only applied for certain target configs. + virtual void set_configs() { + auto soln = get_soln(); // pointer to compile-time soln. + + // Only have BKCs for SP FP (4B). + if (soln->get_element_bytes() == 4) { + + // Compile-time defaults. + if (soln->is_target_set()) { + auto target = soln->get_target(); + if (target == "knl") { + soln->set_prefetch_dist(1, 1); + soln->set_prefetch_dist(2, 0); + } + else if (target == "avx512") { + soln->set_prefetch_dist(1, 1); + soln->set_prefetch_dist(2, 0); + } + else { + soln->set_prefetch_dist(1, 1); + soln->set_prefetch_dist(2, 2); + } + } + + // Kernel run-time defaults, e.g., block-sizes. + // This code is run immediately after 'kernel_soln' is created. + soln->CALL_AFTER_NEW_SOLUTION + ( + // Add extra padding in all dimensions. + kernel_soln.apply_command_line_options("-ep 1"); + + // Check target at kernel run-time. + auto isa = kernel_soln.get_target(); + if (isa == "knl") { + + // Use half the threads: 2 threads on 2 cores per block. + kernel_soln.apply_command_line_options("-thread_divisor 2 -block_threads 4"); + + kernel_soln.set_block_size("x", 48); + kernel_soln.set_block_size("y", 48); + kernel_soln.set_block_size("z", 112); + } + else if (isa == "avx512") { + kernel_soln.set_block_size("x", 64); + kernel_soln.set_block_size("y", 8); + kernel_soln.set_block_size("z", 108); + } + else { + kernel_soln.set_block_size("x", 64); + kernel_soln.set_block_size("y", 8); + kernel_soln.set_block_size("z", 64); + } + ); + } + } + }; - adjust_for_sponge(next_stress_xz); + // The elastic version of AWP that does not contain the time-varying + // attenuation memory vars or the related attenuation constant vars. + class AwpElasticStencil : public AwpElasticBase { + public: + AwpElasticStencil() : + AwpElasticBase("awp_elastic") { } - // define the value at t+1. - stress_mem_xz(t+1, x, y, z) EQUALS next_stress_mem_xz; - stress_xz(t+1, x, y, z) EQUALS next_stress_xz; + // Define the t+1 values for all velocity and stress vars. + virtual void define() override { + defineBase(); + set_configs(); } - void define_stress_yz(yc_number_node_ptr tau1) { + }; - auto mu_val = 2.0 / - (mu(x, y, z ) + mu(x+1, y, z )); + // The elastic version of AWP with free-surface absorbing boundary conditions. + class AwpElasticABCStencil : public AwpElasticBase { + public: + AwpElasticABCStencil() : + AwpElasticBase("awp_elastic_abc") { } - // Note that we are using the velocity values at t+1. - auto d_yz_val = - c1 * (vel_y(t+1, x, y, z+1) - vel_y(t+1, x, y, z )) + - c2 * (vel_y(t+1, x, y, z+2) - vel_y(t+1, x, y, z-1)); - auto d_zy_val = - c1 * (vel_z(t+1, x, y+1, z ) - vel_z(t+1, x, y, z )) + - c2 * (vel_z(t+1, x, y+2, z ) - vel_z(t+1, x, y-1, z )); + // Define the t+1 values for all velocity and stress vars. + virtual void define() override { + defineBaseABC(); + set_configs(); + } + }; - auto stress_mem_yz_old = stress_mem_yz(t, x, y, z); + // The base for the anelastic version of AWP with time-varying + // attenuation memory vars and the related attenuation constant vars. + class AwpBase : public AwpElasticBase { + public: + AwpBase(const string& name) : + AwpElasticBase(name) { } - auto next_stress_mem_yz = tau2(x, y, z) * stress_mem_yz_old - - (0.5 / h) * tau1 * weight(x, y, z) * - (mu_val * anelastic_yz(x, y, z) * (d_yz_val + d_zy_val)); + protected: - auto next_stress_yz = stress_yz(t, x, y, z) + - ((mu_val * delta_t / h) * (d_yz_val + d_zy_val)) + - delta_t * (next_stress_mem_yz + stress_mem_yz_old); + // Time-varying attenuation memory vars. + yc_var_proxy stress_mem_xx = yc_var_proxy("stress_mem_xx", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_yy = yc_var_proxy("stress_mem_yy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_zz = yc_var_proxy("stress_mem_zz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_xy = yc_var_proxy("stress_mem_xy", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_xz = yc_var_proxy("stress_mem_xz", get_soln(), { t, x, y, z }); + yc_var_proxy stress_mem_yz = yc_var_proxy("stress_mem_yz", get_soln(), { t, x, y, z }); - adjust_for_sponge(next_stress_yz); + // 3D vars used for anelastic attenuation + yc_var_proxy weight = yc_var_proxy("weight", get_soln(), { x, y, z }); + yc_var_proxy tau2 = yc_var_proxy("tau2", get_soln(), { x, y, z }); + yc_var_proxy anelastic_ap = yc_var_proxy("anelastic_ap", get_soln(), { x, y, z }); + yc_var_proxy anelastic_as_diag = yc_var_proxy("anelastic_as_diag", get_soln(), { x, y, z }); + yc_var_proxy anelastic_xy = yc_var_proxy("anelastic_xy", get_soln(), { x, y, z }); + yc_var_proxy anelastic_xz = yc_var_proxy("anelastic_xz", get_soln(), { x, y, z }); + yc_var_proxy anelastic_yz = yc_var_proxy("anelastic_yz", get_soln(), { x, y, z }); - // define the value at t+1. - stress_mem_yz(t+1, x, y, z) EQUALS next_stress_mem_yz; - stress_yz(t+1, x, y, z) EQUALS next_stress_yz; + public: + + yc_number_node_ptr + tau1(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return 1.0 - tau2(x, y, z); } - // Call all the define_* functions. - virtual void define() { + // The velocity functions are the same as those defined in AwpBase. + // Memory components are added to the stress functions. + + virtual yc_number_node_ptr + get_next_stress_mem(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr stress_mem_old, + yc_number_node_ptr d_val) { + auto next_stress_mem = tau2(x, y, z) * stress_mem_old + + (1.0 / h) * tau1(x, y, z) * weight(x, y, z) * + (ave8(mu, x, y, z) * anelastic_as_diag(x, y, z) * d_val - + (ave8(mu, x, y, z) + 0.5 * ave8(lambda, x, y, z)) * + anelastic_ap(x, y, z) * (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))); + return next_stress_mem; + } + virtual yc_number_node_ptr + get_next_stress(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr stress_old, + yc_number_node_ptr stress_mem_old, + yc_number_node_ptr next_stress_mem, + yc_number_node_ptr d_val) { + + auto next_stress = stress_old + + ((delta_t / h) * ((2. * ave8(mu, x, y, z) * d_val) + + (ave8(lambda, x, y, z) * + (d_x_val(x, y, z) + d_y_val(x, y, z) + d_z_val(x, y, z))))) + + delta_t * (next_stress_mem + stress_mem_old); + adjust_for_sponge(next_stress); + + // Return expr for the value at t+1. + return next_stress; + } - // Define velocity components. - define_vel_x(); - define_vel_y(); - define_vel_z(); - - // Define some values common to the diagonal stress equations. - auto lambda_val = 8.0 / - (lambda(x, y, z ) + lambda(x+1, y, z ) + - lambda(x, y-1, z ) + lambda(x+1, y-1, z ) + - lambda(x, y, z-1) + lambda(x+1, y, z-1) + - lambda(x, y-1, z-1) + lambda(x+1, y-1, z-1)); - auto mu_val = 8.0 / - (mu(x, y, z ) + mu(x+1, y, z ) + - mu(x, y-1, z ) + mu(x+1, y-1, z ) + - mu(x, y, z-1) + mu(x+1, y, z-1) + - mu(x, y-1, z-1) + mu(x+1, y-1, z-1)); - - // Note that we are using the velocity values at t+1. - auto d_x_val = - c1 * (vel_x(t+1, x+1, y, z ) - vel_x(t+1, x, y, z )) + - c2 * (vel_x(t+1, x+2, y, z ) - vel_x(t+1, x-1, y, z )); - auto d_y_val = - c1 * (vel_y(t+1, x, y, z ) - vel_y(t+1, x, y-1, z )) + - c2 * (vel_y(t+1, x, y+1, z ) - vel_y(t+1, x, y-2, z )); - auto d_z_val = - c1 * (vel_z(t+1, x, y, z ) - vel_z(t+1, x, y, z-1)) + - c2 * (vel_z(t+1, x, y, z+1) - vel_z(t+1, x, y, z-2)); + virtual yc_number_node_ptr + get_next_stress_mem_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return get_next_stress_mem(x, y, z, + stress_mem_xx(t, x, y, z), + d_y_val(x, y, z) + d_z_val(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_xx(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) override { + return get_next_stress(x, y, z, + stress_xx(t, x, y, z), + stress_mem_xx(t, x, y, z), + get_next_stress_mem_xx(x, y, z), + d_x_val(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_mem_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return get_next_stress_mem(x, y, z, + stress_mem_yy(t, x, y, z), + d_x_val(x, y, z) + d_z_val(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_yy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) override { + return get_next_stress(x, y, z, + stress_yy(t, x, y, z), + stress_mem_yy(t, x, y, z), + get_next_stress_mem_yy(x, y, z), + d_y_val(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_mem_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + return get_next_stress_mem(x, y, z, + stress_mem_zz(t, x, y, z), + d_x_val(x, y, z) + d_y_val(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_zz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) override { + return get_next_stress(x, y, z, + stress_zz(t, x, y, z), + stress_mem_zz(t, x, y, z), + get_next_stress_mem_zz(x, y, z), + d_z_val(x, y, z)); + } + + virtual yc_number_node_ptr + get_next_stress_mem2(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr stress_mem_old, + yc_number_node_ptr d_val, + yc_number_node_ptr mu_val, + yc_number_node_ptr anelastic) { + auto next_stress_mem = tau2(x, y, z) * stress_mem_old - + (0.5 / h) * tau1(x, y, z) * weight(x, y, z) * + (mu_val * anelastic * d_val); + return next_stress_mem; + } + virtual yc_number_node_ptr + get_next_stress2(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z, + yc_number_node_ptr stress_old, + yc_number_node_ptr stress_mem_old, + yc_number_node_ptr next_stress_mem, + yc_number_node_ptr d_val, + yc_number_node_ptr mu_val) { + auto next_stress = stress_old + + ((mu_val * delta_t / h) * d_val) + + delta_t * (next_stress_mem + stress_mem_old); + adjust_for_sponge(next_stress); + return next_stress; + } + virtual yc_number_node_ptr + get_next_stress_mem_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x, y, z-1)); + return get_next_stress_mem2(x, y, z, + stress_mem_xy(t, x, y, z), + d_xy_val(x, y, z) + d_yx_val(x, y, z), + mu_val, + anelastic_xy(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_xy(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) override { + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x, y, z-1)); + return get_next_stress2(x, y, z, + stress_xy(t, x, y, z), + stress_mem_xy(t, x, y, z), + get_next_stress_mem_xy(x, y, z), + d_xy_val(x, y, z) + d_yx_val(x, y, z), + mu_val); + } + virtual yc_number_node_ptr + get_next_stress_mem_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x, y-1, z)); + return get_next_stress_mem2(x, y, z, + stress_mem_xz(t, x, y, z), + d_xz_val(x, y, z) + d_zx_val(x, y, z), + mu_val, + anelastic_xz(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_xz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) override { + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x, y-1, z)); + return get_next_stress2(x, y, z, + stress_xz(t, x, y, z), + stress_mem_xz(t, x, y, z), + get_next_stress_mem_xz(x, y, z), + d_xz_val(x, y, z) + d_zx_val(x, y, z), + mu_val); + } + virtual yc_number_node_ptr + get_next_stress_mem_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) { + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x+1, y, z)); + return get_next_stress_mem2(x, y, z, + stress_mem_yz(t, x, y, z), + d_yz_val(x, y, z) + d_zy_val(x, y, z), + mu_val, + anelastic_yz(x, y, z)); + } + virtual yc_number_node_ptr + get_next_stress_yz(yc_number_node_ptr x, yc_number_node_ptr y, yc_number_node_ptr z) override { + auto mu_val = 2.0 / + (mu(x, y, z ) + mu(x+1, y, z)); + return get_next_stress2(x, y, z, + stress_yz(t, x, y, z), + stress_mem_yz(t, x, y, z), + get_next_stress_mem_yz(x, y, z), + d_yz_val(x, y, z) + d_zy_val(x, y, z), + mu_val); + } + }; + + // The anelastic version of AWP with time-varying attenuation memory + // vars and the related attenuation constant vars. + class AwpStencil : public AwpBase { + public: + AwpStencil() : + AwpBase("awp") { } - auto tau1 = 1.0 - tau2(x, y, z); + // Define the t+1 values for all velocity and stress vars. + virtual void define() override { + defineBase(); - // Define stress components. - define_stress_xx(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); - define_stress_yy(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); - define_stress_zz(lambda_val, mu_val, d_x_val, d_y_val, d_z_val, tau1); - define_stress_xy(tau1); - define_stress_xz(tau1); - define_stress_yz(tau1); + // Define memory components. + stress_mem_xx(t+1, x, y, z) EQUALS get_next_stress_mem_xx(x, y, z); + stress_mem_yy(t+1, x, y, z) EQUALS get_next_stress_mem_yy(x, y, z); + stress_mem_xy(t+1, x, y, z) EQUALS get_next_stress_mem_xy(x, y, z); + stress_mem_xz(t+1, x, y, z) EQUALS get_next_stress_mem_xz(x, y, z); + stress_mem_yz(t+1, x, y, z) EQUALS get_next_stress_mem_yz(x, y, z); + stress_mem_zz(t+1, x, y, z) EQUALS get_next_stress_mem_zz(x, y, z); + + set_configs(); } }; - // Create an object of type 'AwpStencil', - // making it available in the YASK compiler utility via the + // The anelastic version of AWP with free-surface absorbing boundary conditions. + class AwpABCStencil : public AwpBase { + public: + AwpABCStencil() : + AwpBase("awp_abc") { } + + // Define the t+1 values for all velocity and stress vars. + virtual void define() override { + defineBaseABC(); + + // Define memory components using same sub-domains as the stress vars. + for (auto cond : { BELOW_SURFACE, AT_SURFACE, ONE_ABOVE_SURFACE, TWO_ABOVE_SURFACE }) { + stress_mem_xx(t+1, x, y, z) EQUALS get_next_stress_mem_xx(x, y, z) IF_DOMAIN cond; + stress_mem_yy(t+1, x, y, z) EQUALS get_next_stress_mem_yy(x, y, z) IF_DOMAIN cond; + stress_mem_xy(t+1, x, y, z) EQUALS get_next_stress_mem_xy(x, y, z) IF_DOMAIN cond; + stress_mem_xz(t+1, x, y, z) EQUALS get_next_stress_mem_xz(x, y, z) IF_DOMAIN cond; + stress_mem_yz(t+1, x, y, z) EQUALS get_next_stress_mem_yz(x, y, z) IF_DOMAIN cond; + stress_mem_zz(t+1, x, y, z) EQUALS get_next_stress_mem_zz(x, y, z) IF_DOMAIN cond; + } + set_configs(); + } + }; + + // Create objects for all AWP stencils, + // making them available in the YASK compiler utility via the // '-stencil' commmand-line option or the 'stencil=' build option. + static AwpElasticStencil AwpElasticStencil_instance; + static AwpElasticABCStencil AwpElasticABCStencil_instance; static AwpStencil AwpStencil_instance; + static AwpABCStencil AwpABCStencil_instance; } // namespace. diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 3423a932..1ac71b5a 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -148,7 +148,7 @@ namespace { set_configs(); } - // Set BKC (best-known configs) found by automated and manual + // Set BKC (best-known configs) found by automated and/or manual // tuning. They are only applied for certain target configs. virtual void set_configs() { auto soln = get_soln(); // pointer to compile-time soln. @@ -157,24 +157,34 @@ namespace { if (soln->get_element_bytes() == 4 && get_radius() == 8) { - // Compile-time defaults. - if (soln->is_target_set() && - soln->get_target() == "knl") { - - // Default folding and clustering for KNL. - soln->set_fold_len(x, 2); - soln->set_fold_len(y, 8); - soln->set_cluster_mult(x, 2); + // Compile-time defaults, e.g., folding and prefetching. + if (soln->is_target_set()) { + auto target = soln->get_target(); + if (target == "knl") { + soln->set_fold_len(x, 2); + soln->set_fold_len(y, 8); + soln->set_cluster_mult(x, 2); + soln->set_prefetch_dist(1, 1); + soln->set_prefetch_dist(2, 0); + } + else if (target == "avx512") { + soln->set_prefetch_dist(1, 0); + soln->set_prefetch_dist(2, 2); + } + else { + soln->set_prefetch_dist(1, 0); + soln->set_prefetch_dist(2, 0); + } } - // Kernel run-time defaults. This code is run immediately - // after 'kernel_soln' is created. + // Kernel run-time defaults, e.g., block-sizes. + // This code is run immediately after 'kernel_soln' is created. soln->CALL_AFTER_NEW_SOLUTION ( // Add extra padding in all dimensions. kernel_soln.apply_command_line_options("-ep 1"); - // Check target at kernel run-time for block-size. + // Check target at kernel run-time. auto isa = kernel_soln.get_target(); if (isa == "knl") { kernel_soln.set_block_size("x", 160); diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index 845f3a09..916fa69f 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -89,7 +89,26 @@ namespace // for spatial order = 4. virtual void define_so4 () { + // Set BKC (best-known configs) found by automated and/or manual + // tuning. + // Only have BKCs for SP FP (4B). + auto soln = get_soln(); // pointer to compile-time soln. + if (soln->get_element_bytes() == 4) { + // Kernel run-time defaults, e.g., block-sizes. + // This code is run immediately after 'kernel_soln' is created. + soln->CALL_AFTER_NEW_SOLUTION + ( + // Check target at kernel run-time. + auto isa = kernel_soln.get_target(); + if (isa == "avx512") { + kernel_soln.set_block_size("x", 80); + kernel_soln.set_block_size("y", 16); + kernel_soln.set_block_size("z", 40); + } + ); + } + auto temp161 = 2.5e-2 * (-u (t, x - 1, y, z) + u (t, x + 1, y, z)); auto temp163 = -7.5e-2 * u (t, x, y, z) + 1.0e-1 * u (t, x, y + 1, z) - 2.5e-2 * u (t, x, y + 2, From 8868affe62d8f54832c8c8cfe6e32adf9ec1b116 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 11 Jun 2019 16:13:41 -0700 Subject: [PATCH 43/62] Move default settings for SSG and FSG from Makefile to stencil code. --- src/kernel/Makefile | 32 +++----------------- src/stencils/FSGElasticStencil.cpp | 47 ++++++++++++++++++++++++++++++ src/stencils/SSGElasticStencil.cpp | 34 +++++++++++++++++++++ 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 4d3178e6..1f1644f0 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -54,6 +54,9 @@ YK_ARCH := $(arch) # Specify YC_STENCIL on 'make' cmd-line to pass different stencil name to YASK compiler. YC_STENCIL := $(stencil) +ifeq ($(YC_STENCIL),) + $(error Stencil not specified) +endif # Set 'ARCH', converting codenames to ISA names. ifneq ($(filter $(arch),avx snb ivb),) @@ -72,36 +75,9 @@ else $(error Instruction-set architecture (ISA) not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64) endif -# Specify YC_TARGET on 'make' cmd-line to override ARCH. +# Specify YC_TARGET on 'make' cmd-line to override ARCH for YASK compiler. YC_TARGET := $(ARCH) -# Defaults based on stencil type (and arch for some stencils). -ifeq ($(YC_STENCIL),) - $(error Stencil solution not specified) - -else ifneq ($(findstring ssg,$(YC_STENCIL)),) - ifeq ($(ARCH),avx512) - def_block_args := -bx 96 -by 16 -bz 80 - else - def_block_args := -bx 64 -by 16 -bz 96 - endif - -else ifneq ($(findstring fsg,$(YC_STENCIL)),) - ifeq ($(ARCH),knl) - omp_region_schedule := guided - def_block_args := -b 16 - def_thread_divisor := 4 - def_block_threads := 2 - pfd_l1 := 0 - pfd_l2 := 2 - else ifeq ($(ARCH),avx512) - def_block_args := -bx 188 -by 12 -bz 24 - else - def_block_args := -bx 48 -by 4 -bz 128 - endif - -endif # stencil-specific. - # Default settings based on architecture. ifeq ($(ARCH),knc) diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index ea256f09..d1eb6236 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -278,6 +278,51 @@ namespace fsg { } } + // Set BKC (best-known configs) found by automated and/or manual + // tuning. They are only applied for certain target configs. + virtual void set_configs() { + auto soln = get_soln(); // pointer to compile-time soln. + + // Only have BKCs for SP FP (4B). + if (soln->get_element_bytes() == 4) { + + // Compile-time defaults, e.g., prefetching. + if (soln->is_target_set()) { + auto target = soln->get_target(); + if (target == "knl") { + soln->set_prefetch_dist(1, 0); + soln->set_prefetch_dist(2, 2); + } + } + + // Kernel run-time defaults, e.g., block-sizes. + // This code is run immediately after 'kernel_soln' is created. + soln->CALL_AFTER_NEW_SOLUTION + ( + // Check target at kernel run-time. + auto isa = kernel_soln.get_target(); + if (isa == "knl") { + // Use only 1 thread per core. + kernel_soln.apply_command_line_options("-thread_divisor 4 -block_threads 2"); + + kernel_soln.set_block_size("x", 16); + kernel_soln.set_block_size("y", 16); + kernel_soln.set_block_size("z", 16); + } + else if (isa == "avx512") { + kernel_soln.set_block_size("x", 188); + kernel_soln.set_block_size("y", 12); + kernel_soln.set_block_size("z", 24); + } + else { + kernel_soln.set_block_size("x", 48); + kernel_soln.set_block_size("y", 4); + kernel_soln.set_block_size("z", 128); + } + ); + } + } + // Call all the define_* functions. virtual void define() { @@ -312,6 +357,8 @@ namespace fsg { if ( hasBoundaryCondition() ) fsg_bc.stress(t,x,y,z); + + set_configs(); } }; diff --git a/src/stencils/SSGElasticStencil.cpp b/src/stencils/SSGElasticStencil.cpp index 1f907b15..356428b5 100644 --- a/src/stencils/SSGElasticStencil.cpp +++ b/src/stencils/SSGElasticStencil.cpp @@ -136,6 +136,39 @@ class SSGElasticStencil : public ElasticStencilBase { s_tl_zz(t+1, x, y, z) EQUALS next_zz; } + // Set BKC (best-known configs) found by automated and/or manual + // tuning. They are only applied for certain target configs. + virtual void set_configs() { + auto soln = get_soln(); // pointer to compile-time soln. + + // Only have BKCs for SP FP (4B). + if (soln->get_element_bytes() == 4) { + + // Kernel run-time defaults, e.g., block-sizes. + // This code is run immediately after 'kernel_soln' is created. + soln->CALL_AFTER_NEW_SOLUTION + ( + // Check target at kernel run-time. + auto isa = kernel_soln.get_target(); + if (isa == "knl") { + kernel_soln.set_block_size("x", 16); + kernel_soln.set_block_size("y", 16); + kernel_soln.set_block_size("z", 32); + } + else if (isa == "avx512") { + kernel_soln.set_block_size("x", 96); + kernel_soln.set_block_size("y", 16); + kernel_soln.set_block_size("z", 80); + } + else { + kernel_soln.set_block_size("x", 64); + kernel_soln.set_block_size("y", 16); + kernel_soln.set_block_size("z", 96); + } + ); + } + } + // Call all the define_* functions. virtual void define() { @@ -150,6 +183,7 @@ class SSGElasticStencil : public ElasticStencilBase { define_str(t, x, y, z, s_bl_yz, v_bl_w, v_tl_v ); define_str_TL(t, x, y, z); + set_configs(); } }; From c8a60e42a8a07ed5bf2511bd88bc36cc89ebc929 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 11 Jun 2019 17:03:17 -0700 Subject: [PATCH 44/62] Move target-specific defaults from Makefile to kernel. Pass prefetch flags from Makefile to YASK compiler. --- src/compiler/compiler_main.cpp | 6 +- src/compiler/lib/YaskKernel.cpp | 3 +- src/kernel/Makefile | 147 +++++++++++++++----------------- src/kernel/lib/factory.cpp | 2 + src/kernel/lib/settings.cpp | 13 ++- src/kernel/lib/settings.hpp | 3 - src/kernel/yask_main.cpp | 2 + 7 files changed, 89 insertions(+), 87 deletions(-) diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 28f86c92..e845933b 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -193,9 +193,9 @@ void usage(const string& cmd, //" -ps Print stats for all folding options for given vector length.\n" "\n" "Examples:\n" - " " << cmd << " -stencil 3axis -radius 2 -fold x=4,y=4 -p pseudo - # '-' for stdout\n" - " " << cmd << " -stencil awp -elem-bytes 8 -fold x=4,y=2 -p avx2 stencil_code.hpp\n" - " " << cmd << " -stencil iso3dfd -radius 4 -cluster y=2 -p avx512 stencil_code.hpp\n"; + " " << cmd << " -stencil 3axis -radius 2 -fold x=4,y=4 -target pseudo -p - # '-' for stdout\n" + " " << cmd << " -stencil awp -elem-bytes 8 -fold x=4,y=2 -target avx2 -p stencil_code.hpp\n" + " " << cmd << " -stencil iso3dfd -radius 4 -cluster y=2 -target avx512 -p stencil_code.hpp\n"; exit(1); } diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 2fb83bd0..8e5d95b0 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -87,7 +87,8 @@ namespace yask { "#define YASK_STENCIL_NAME \"" << _stencil.getName() << "\"\n" "#define YASK_STENCIL_CONTEXT " << _context << endl; - os << "\n// FP precision:\n" + os << "\n// target:\n" + "#define YASK_TARGET \"" << _settings._target << "\"\n" "#define REAL_BYTES (" << _settings._elem_bytes << ")\n"; os << "\n// Number of domain dimensions:\n" diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 1f1644f0..41421ad4 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -34,58 +34,64 @@ numa ?= 1 pmem ?= 0 real_bytes ?= 4 allow_new_var_types ?= 1 +streaming_stores ?= 0 +omp_par ?= omp parallel +omp_par_for ?= omp parallel for +omp_for ?= omp for +omp_region_schedule ?= dynamic,1 +omp_block_schedule ?= static,1 +omp_misc_schedule ?= guided trace ?= 0 trace_mem ?= 0 check ?= 0 -# NB: setting the "trace" var just includes the tracing code. -# To actually output the trace, you must also use the "-trace" -# run-time option. Enabling tracing is off by default because -# it adds a few MiB to the binary and can impact perfomance -# even if not used, but only around 1%. +# NB: setting the "trace" and "trace_mem" vars just includes the tracing +# code. To actually output the trace, you must also use the "-trace" +# run-time option. Including the "trace" code has a small impact on +# binary size and performance, even if not used. Including the "trace_mem" +# code has a large impact, even if not used. # If 'arch' isn't set, determine default architecture by running kernel -# script w/special knob. Do not assume it has been installed in -# $(BIN_OUT_DIR) yet. -arch ?= $(shell $(BASH) ./yask.sh -show_arch) - -# Specify YK_STENCIL and/or YK_ARCH on 'make' cmd-line to name binaries differently. -YK_STENCIL := $(stencil) -YK_ARCH := $(arch) - -# Specify YC_STENCIL on 'make' cmd-line to pass different stencil name to YASK compiler. -YC_STENCIL := $(stencil) -ifeq ($(YC_STENCIL),) - $(error Stencil not specified) -endif - -# Set 'ARCH', converting codenames to ISA names. +# script w/special knob. +# The "knc" arch must be set manually because it is always cross-compiled. +# (Do not assume 'yask.sh' has been installed in $(BIN_OUT_DIR) yet.) +arch ?= $(shell $(BASH) ./yask.sh -show_arch) + +# Set 'TARGET' from 'arch', converting codenames and other aliases to ISA names. +# 'TARGET' is the canonical target name. +# The possible values must agree with those in the APIs and YASK compiler. ifneq ($(filter $(arch),avx snb ivb),) - ARCH := avx + TARGET := avx else ifneq ($(filter $(arch),avx2 hsw bdw),) - ARCH := avx2 + TARGET := avx2 else ifneq ($(filter $(arch),avx512 avx512f skx skl clx),) - ARCH := avx512 + TARGET := avx512 else ifneq ($(filter $(arch),knl),) - ARCH := knl + TARGET := knl else ifneq ($(filter $(arch),knc),) - ARCH := knc + TARGET := knc else ifneq ($(filter $(arch),intel64 cpp),) - ARCH := intel64 + TARGET := intel64 else - $(error Instruction-set architecture (ISA) not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64) + $(error Target not recognized; use arch=avx512, avx2, avx, knl, knc, or intel64) endif -# Specify YC_TARGET on 'make' cmd-line to override ARCH for YASK compiler. -YC_TARGET := $(ARCH) +# Specify YK_STENCIL and/or YK_ARCH on 'make' cmd-line to name binaries differently. +YK_STENCIL := $(stencil) +YK_ARCH := $(arch) -# Default settings based on architecture. -ifeq ($(ARCH),knc) +# Specify YC_STENCIL on 'make' cmd-line to pass different stencil name to YASK compiler. +YC_STENCIL := $(stencil) + +# Specify YC_TARGET on 'make' cmd-line to override target for YASK compiler. +YC_TARGET := $(TARGET) + +# Default compiler settings based on target. +ifeq ($(TARGET),knc) ICC_ISA ?= -mmic MACROS += USE_INTRIN512 - def_block_threads ?= 4 -else ifeq ($(ARCH),knl) +else ifeq ($(TARGET),knl) # NUMA_PREF=1 causes YASK to use MCDRAM on a node in "flat" memory mode. It # will fall-back to NUMA node 0 in "cache" memory mode. It will *NOT* do @@ -94,28 +100,26 @@ else ifeq ($(ARCH),knl) ICC_ISA ?= -xMIC-AVX512 GCC_ISA ?= -march=knl MACROS += USE_INTRIN512 USE_RCP28 NUMA_PREF=1 - def_block_args ?= -b 64 - def_block_threads ?= 8 -else ifeq ($(ARCH),avx512) +else ifeq ($(TARGET),avx512) ICC_ISA ?= -xCORE-AVX512 GCC_ISA ?= -march=knl -mno-avx512er -mno-avx512pf MACROS += USE_INTRIN512 -else ifeq ($(ARCH),avx2) +else ifeq ($(TARGET),avx2) ICC_ISA ?= -xCORE-AVX2 GCC_ISA ?= -march=haswell MACROS += USE_INTRIN256 USE_AVX2 -else ifeq ($(ARCH),avx) +else ifeq ($(TARGET),avx) ICC_ISA ?= -xAVX GCC_ISA ?= -march=sandybridge MACROS += USE_INTRIN256 -else ifeq ($(ARCH),intel64) +else ifeq ($(TARGET),intel64) ICC_ISA ?= -xHOST GCC_ISA ?= -march=native @@ -126,19 +130,16 @@ $(error Internal error: arch lists are not consistent) endif # arch-specific. -# general defaults for vars if not set above. -streaming_stores ?= 0 -omp_par ?= omp parallel -omp_par_for ?= omp parallel for -omp_for ?= omp for -omp_region_schedule ?= dynamic,1 -omp_block_schedule ?= static,1 -omp_misc_schedule ?= guided -def_thread_divisor ?= 1 -def_block_threads ?= 2 -def_block_args ?= -b 32 +# Turn off prefetching at O0 or O1. +ifneq ($(filter -O0 -O1,$(YK_CXXOPT)),) + pfd_l1 := 0 + pfd_l2 := 0 +endif -######## End of vars that control the function and performance of the kernel. +# Turn on checking at O0. +ifneq ($(filter -O0,$(YK_CXXOPT)),) + check := 1 +endif # Common settings. YASK_BASE ?= $(abspath ../..) @@ -149,7 +150,7 @@ include $(YASK_BASE)/src/common/common.mk # Vars starting with 'YK_' apply to the stencil kernel. # Flags passed to stencil compiler. -YC_FLAGS += -stencil $(YC_STENCIL) -target $(YC_TARGET) -elem-bytes $(real_bytes) +YC_FLAGS := -stencil $(YC_STENCIL) -target $(YC_TARGET) -elem-bytes $(real_bytes) ifneq ($(fold),) YC_FLAGS += -fold $(fold) endif @@ -174,6 +175,12 @@ endif ifneq ($(step_dim),) YC_FLAGS += -step-dim $(step_dim) endif +ifneq ($(pfd_l1),) + YC_FLAGS += -l1-prefetch-dist $(pfd_l1) +endif +ifneq ($(pfd_l2),) + YC_FLAGS += -l2-prefetch-dist $(pfd_l2) +endif # Kernel base names. YK_BASE := yask_kernel @@ -286,17 +293,6 @@ ifeq ($(pmem),1) MACROS += USE_PMEM endif -# Turn off prefetching at O0 or O1. -ifneq ($(filter -O0 -O1,$(YK_CXXOPT)),) - pfd_l1 := 0 - pfd_l2 := 0 -endif - -# Turn on checking at O0. -ifneq ($(filter -O0,$(YK_CXXOPT)),) - check ?= 1 -endif - # Turn on debug macros. ifeq ($(trace_mem),1) MACROS += CHECK TRACE TRACE_MEM @@ -313,11 +309,9 @@ endif MACROS += ALLOW_NEW_VARS=$(allow_new_var_types) # Default cmd-line args. -YK_CXXFLAGS += -DDEF_ARGS='"$(DEF_ARGS)"' - -# arch. -UC_ARCH := $(shell echo $(ARCH) | tr '[:lower:]' '[:upper:]') -MACROS += ARCH_$(UC_ARCH) ARCH_NAME=$(ARCH) +ifneq ($(DEF_ARGS),) + YK_CXXFLAGS += -DDEF_ARGS='"$(DEF_ARGS)"' +endif # MPI settings. ifeq ($(mpi),1) @@ -360,11 +354,11 @@ ifneq ($(filter %icpc %icc,$(notdir $(YK_CXX))),) # Intel compiler YK_CXX_VER_CMD := $(YK_CXX) -V MACROS += USE_SVML -# Use 512-bit code on SKX and CLX. -# (Commented out because it doesn't help performance, and it breaks Devito.) -ifeq ($(ARCH),avx512) - #YK_CXXFLAGS += -qopt-zmm-usage=high -endif + # Use real 512-bit code. + # (Commented out because it doesn't help performance, and it breaks Devito.) + ifeq ($(TARGET),avx512) + #YK_CXXFLAGS += -qopt-zmm-usage=high + endif else # not Intel compiler YK_CXXFLAGS += $(GCXX_ISA) -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-but-set-variable @@ -799,7 +793,7 @@ realclean: clean echo-settings: @echo "Build environment for" $(YK_EXEC) on `date`; \ $(YK_CXX) --version; \ - echo ARCH=$(ARCH); \ + echo TARGET=$(TARGET); \ echo BLOCK_LOOP_CODE="\"$(BLOCK_LOOP_CODE)\""; \ echo BLOCK_LOOP_INNER_MODS="\"$(BLOCK_LOOP_INNER_MODS)\""; \ echo BLOCK_LOOP_OPTS="\"$(BLOCK_LOOP_OPTS)\""; \ @@ -858,11 +852,6 @@ echo-settings: echo YK_TAG=$(YK_TAG); \ echo arch=$(arch); \ echo cluster=$(cluster); \ - echo def_block_args=$(def_block_args); \ - echo def_block_threads=$(def_block_threads); \ - echo def_pad_args=$(def_pad_args); \ - echo def_rank_args=$(def_rank_args); \ - echo def_thread_divisor=$(def_thread_divisor); \ echo fold=$(fold); \ echo host=`hostname`; \ echo omp_block_schedule=$(omp_block_schedule); \ diff --git a/src/kernel/lib/factory.cpp b/src/kernel/lib/factory.cpp index 3f109a7c..6fcf2079 100644 --- a/src/kernel/lib/factory.cpp +++ b/src/kernel/lib/factory.cpp @@ -60,9 +60,11 @@ namespace yask { auto sp = make_shared(ep, op); assert(sp); +#ifdef DEF_ARGS // If no source, init settings from default args. if (!source.get()) sp->apply_command_line_options(DEF_ARGS); +#endif return sp; } diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index b5d6511c..1f239aeb 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -239,6 +239,17 @@ namespace yask { _dims(dims), max_threads(env->max_threads) { auto& step_dim = dims->_step_dim; + // Target-dependent defaults. + int def_blk_size = 32; // TODO: calculate based on actual cache size and stencil. + num_block_threads = 2; + if (YASK_TARGET == "knl") { + def_blk_size = 64; // larger L2. + num_block_threads = 8; // 4 threads per core * 2 cores per tile. + } + else if (YASK_TARGET == "knc") { + num_block_threads = 4; // 4 threads per core. + } + // Use both step and domain dims for all size tuples. _global_sizes = dims->_stencil_dims; _global_sizes.setValsSame(0); // 0 => calc from rank. @@ -253,7 +264,7 @@ namespace yask { _block_group_sizes.setValsSame(0); // 0 => min size. _block_sizes = dims->_stencil_dims; - _block_sizes.setValsSame(def_block); // size of block. TODO: calculate good value. + _block_sizes.setValsSame(def_blk_size); _block_sizes.setVal(step_dim, 0); // 0 => default. _mini_block_group_sizes = dims->_stencil_dims; diff --git a/src/kernel/lib/settings.hpp b/src/kernel/lib/settings.hpp index 83686692..dacab910 100644 --- a/src/kernel/lib/settings.hpp +++ b/src/kernel/lib/settings.hpp @@ -189,9 +189,6 @@ namespace yask { protected: - // Default sizes. - idx_t def_block = 32; // TODO: calculate this. - // Make a null output stream. // TODO: put this somewhere else. yask_output_factory yof; diff --git a/src/kernel/yask_main.cpp b/src/kernel/yask_main.cpp index ac344676..a5c679af 100644 --- a/src/kernel/yask_main.cpp +++ b/src/kernel/yask_main.cpp @@ -207,7 +207,9 @@ struct MySettings { "Stencil name: " YASK_STENCIL_NAME << endl; // Echo invocation parameters for record-keeping. +#ifdef DEF_ARGS os << "Default arguments: " DEF_ARGS << endl; +#endif os << "Binary invocation:"; for (int argi = 0; argi < argc; argi++) os << " " << argv[argi]; From 488affdedf11d2f8e5e026919f7105116a5182c1 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 11 Jun 2019 17:05:56 -0700 Subject: [PATCH 45/62] Fix L1-prefetch-dist option. --- src/compiler/compiler_main.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index e845933b..54be64ec 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -319,21 +319,18 @@ void parseOpts(int argc, const char* argv[], if (opt == "-l1-prefetch-dist") settings._prefetchDists[1] = val; - if (opt == "-l2-prefetch-dist") + else if (opt == "-l2-prefetch-dist") settings._prefetchDists[2] = val; else if (opt == "-max-es") settings._maxExprSize = val; else if (opt == "-min-es") settings._minExprSize = val; - else if (opt == "-radius") radius = val; else if (opt == "-elem-bytes") settings._elem_bytes = val; - else if (opt == "-ps") vlenForStats = val; - else if (opt == "-halo") settings._haloSize = val; else if (opt == "-step-alloc") From 5536e42f1ead4d1778d5878aec6bf4d8e4fbea51 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Wed, 12 Jun 2019 08:48:00 -0700 Subject: [PATCH 46/62] Improve detection of failed YASK compile. --- src/kernel/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 41421ad4..7e130749 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -28,6 +28,7 @@ # command-line that control kernel configuration and performance. # Initial defaults. +# These can be overridden on the 'make' command-line. stencil ?= iso3dfd mpi ?= 1 numa ?= 1 @@ -549,11 +550,12 @@ $(YK_GEN_DIR)/yask_var_code.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(MKDIR) $(YK_GEN_DIR) $(PERL) $< -v $(NVDIMS) > $@ +# NB: 'set -o pipefail' ensures failure of command before '| tee' is visible. $(YK_CODE_FILE): $(YC_EXEC) $(MKDIR) $(dir $@) @- rm -f $@ - $(RUN_PREFIX) $< $(YC_FLAGS) -p $@ $(EXTRA_YC_FLAGS) | tee $(YC_REPORT_FILE) 2>&1 - @ grep -q -E 'End of .* code' $@ + set -o pipefail; \ + $(RUN_PREFIX) $< $(YC_FLAGS) -p $@ $(EXTRA_YC_FLAGS) | tee $(YC_REPORT_FILE) 2>&1 @- gindent -fca $@ || \ indent -fca $@ || \ echo "note:" $@ "is not properly indented because no indent program was found." From 515b295eda9a3b209fe51d8433910fa3c8cc8323 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Wed, 12 Jun 2019 08:50:18 -0700 Subject: [PATCH 47/62] Explicitly run perl for loop gen. --- src/kernel/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 7e130749..33b8ca8d 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -530,7 +530,7 @@ $(YK_GEN_DIR)/yask_sub_block_loops.hpp: $(GEN_LOOPS) $(YK_CODE_FILE) $(YK_GEN_DIR)/yask_misc_loops.hpp: $(GEN_LOOPS) $(YK_CODE_FILE) $(MKDIR) $(YK_GEN_DIR) - $< -output $@ $(MISC_LOOP_OPTS) $(EXTRA_LOOP_OPTS) $(EXTRA_MISC_LOOP_OPTS) "$(MISC_LOOP_CODE)" + $(PERL) $< -output $@ $(MISC_LOOP_OPTS) $(EXTRA_LOOP_OPTS) $(EXTRA_MISC_LOOP_OPTS) "$(MISC_LOOP_CODE)" $(YK_GEN_DIR)/yask_layout_macros.hpp: $(GEN_LAYOUTS) $(YK_CODE_FILE) $(MKDIR) $(YK_GEN_DIR) From 89159d2894692458fe847e68f4971b00019bd47e Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 14 Jun 2019 13:55:15 -0700 Subject: [PATCH 48/62] Fix gcc errors and warnings. Also some cleanup. --- src/kernel/Makefile | 10 ++++++---- src/kernel/lib/settings.cpp | 4 ++-- src/kernel/lib/yask.hpp | 6 +++--- src/stencils/Iso3dfdStencil.cpp | 2 +- utils/bin/yask_tuner.pl | 6 +++--- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 33b8ca8d..72e54606 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -105,7 +105,7 @@ else ifeq ($(TARGET),knl) else ifeq ($(TARGET),avx512) ICC_ISA ?= -xCORE-AVX512 - GCC_ISA ?= -march=knl -mno-avx512er -mno-avx512pf + GCC_ISA ?= -march=skylake-avx512 MACROS += USE_INTRIN512 else ifeq ($(TARGET),avx2) @@ -339,7 +339,8 @@ YK_CXXFLAGS += -I$(VTUNE_DIR)/include YK_LIBS += $(VTUNE_DIR)/lib64/libittnotify.a endif -# compiler-specific settings +# compiler-specific settings. +# TODO: make check for Intel compiler more robust. ifneq ($(filter %icpc %icc,$(notdir $(YK_CXX))),) # Intel compiler YK_CXXFLAGS += $(ISA) -debug extended -restrict -ansi-alias -fno-alias @@ -353,7 +354,7 @@ ifneq ($(filter %icpc %icc,$(notdir $(YK_CXX))),) # Intel compiler #YK_CXXFLAGS += -qopt-report=5 #YK_CXXFLAGS += -qopt-report-phase=VEC,PAR,OPENMP,IPO,LOOP YK_CXX_VER_CMD := $(YK_CXX) -V - MACROS += USE_SVML + MACROS += USE_SVML USE_ALWAYS_INLINE # Use real 512-bit code. # (Commented out because it doesn't help performance, and it breaks Devito.) @@ -362,7 +363,8 @@ ifneq ($(filter %icpc %icc,$(notdir $(YK_CXX))),) # Intel compiler endif else # not Intel compiler - YK_CXXFLAGS += $(GCXX_ISA) -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-but-set-variable + YK_CXXFLAGS += $(GCC_ISA) -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-but-set-variable + MACROS += USE_ALWAYS_INLINE endif # compiler. diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index 1f239aeb..b2e2dc38 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -242,11 +242,11 @@ namespace yask { // Target-dependent defaults. int def_blk_size = 32; // TODO: calculate based on actual cache size and stencil. num_block_threads = 2; - if (YASK_TARGET == "knl") { + if (string(YASK_TARGET) == "knl") { def_blk_size = 64; // larger L2. num_block_threads = 8; // 4 threads per core * 2 cores per tile. } - else if (YASK_TARGET == "knc") { + else if (string(YASK_TARGET) == "knc") { num_block_threads = 4; // 4 threads per core. } diff --git a/src/kernel/lib/yask.hpp b/src/kernel/lib/yask.hpp index 62b75647..226710dd 100644 --- a/src/kernel/lib/yask.hpp +++ b/src/kernel/lib/yask.hpp @@ -89,10 +89,10 @@ typedef int MPI_Request; #endif // Conditional inlining -#ifdef CHECK -#define ALWAYS_INLINE inline -#else +#if defined(USE_ALWAYS_INLINE) && !defined(CHECK) #define ALWAYS_INLINE __attribute__((always_inline)) inline +#else +#define ALWAYS_INLINE inline #endif // Additional type for unsigned indices. diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index 1ac71b5a..c9507aae 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -153,7 +153,7 @@ namespace { virtual void set_configs() { auto soln = get_soln(); // pointer to compile-time soln. - // Only have BKCs for SP FP (4B) and radius 8. + // BKCs are only for SP FP (4B) and radius 8. if (soln->get_element_bytes() == 4 && get_radius() == 8) { diff --git a/utils/bin/yask_tuner.pl b/utils/bin/yask_tuner.pl index 025c7dc9..d2f2b7cf 100755 --- a/utils/bin/yask_tuner.pl +++ b/utils/bin/yask_tuner.pl @@ -1356,9 +1356,9 @@ sub fitness { # various commands. my $testCmd = "$runCmd -v $runArgs"; # validation on a small problem size. - my $simCmd = "$runCmd $args -t 1 -dt 1 $runArgs"; # simulation w/1 trial & 1 step. - my $shortRunCmd = "$runCmd $args -t $shortTrials -trial_time $shortTime $runArgs"; # fast run for 'upper-bound' time. - my $longRunCmd = "$runCmd $args -t $longTrials -trial_time $longTime $runArgs"; # normal run w/more trials. + my $simCmd = "$runCmd $args -num_trials 1 -trial_steps 1 $runArgs"; # simulation w/1 trial & 1 step. + my $shortRunCmd = "$runCmd $args -num_trials $shortTrials -trial_time $shortTime $runArgs"; # fast run for 'upper-bound' time. + my $longRunCmd = "$runCmd $args -num_trials $longTrials -trial_time $longTime $runArgs"; # normal run w/more trials. # add kill command to prevent runaway code. if (-x $killCmd) { From 5c63b3c18af37c4b19467ddfd5e6ef69cfc8f1d9 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Mon, 17 Jun 2019 09:12:58 -0700 Subject: [PATCH 49/62] Change rank_domain_offsets to Indices type. --- src/kernel/lib/context.cpp | 4 ++-- src/kernel/lib/context.hpp | 2 +- src/kernel/lib/indices.hpp | 31 ++++++++++++++++++++++++++++++- src/kernel/lib/setup.cpp | 29 ++++++++++++----------------- src/kernel/lib/soln_apis.cpp | 2 +- src/kernel/lib/stencil_calc.cpp | 4 ++-- 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index fae2623b..0ad5fe2f 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -831,7 +831,7 @@ namespace yask { #endif // Init block begin & end from region start & stop indices. - ScanIndices block_idxs(*dims, true, 0); + ScanIndices block_idxs(*dims, true); block_idxs.initFromOuter(region_idxs); // Time range. @@ -1004,7 +1004,7 @@ namespace yask { } // Init mini-block begin & end from blk start & stop indices. - ScanIndices mini_block_idxs(*dims, true, 0); + ScanIndices mini_block_idxs(*dims, true); mini_block_idxs.initFromOuter(adj_block_idxs); // Time range. diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index ab64c616..6dc8af3d 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -242,7 +242,7 @@ namespace yask { ScratchVecs scratchVecs; // Some calculated sizes for this rank and overall. - IdxTuple rank_domain_offsets; // Domain index offsets for this rank. + Indices rank_domain_offsets; // Domain index offsets for this rank. idx_t rank_nbytes=0, tot_nbytes=0; idx_t rank_domain_pts=0, tot_domain_pts=0; diff --git a/src/kernel/lib/indices.hpp b/src/kernel/lib/indices.hpp index 8c12a1e5..f7c38deb 100644 --- a/src/kernel/lib/indices.hpp +++ b/src/kernel/lib/indices.hpp @@ -148,6 +148,9 @@ namespace yask { _idxs[i] = val; _ndims = n; } + void setValsSame(idx_t val) { + setFromConst(val); + } // Some comparisons. // These assume all the indices are valid or @@ -306,6 +309,14 @@ namespace yask { tmp.addDimBack(names[i], _idxs[i]); return tmp.makeDimValStr(separator, infix, prefix, suffix); } + std::string makeDimValStr(const IdxTuple& names, // ignore values. + std::string separator=", ", + std::string infix="=", + std::string prefix="", + std::string suffix="") const { + auto tmp = names.getDimNames(); + return makeDimValStr(tmp, separator, infix, prefix, suffix); + } // Make string like "4, 3, 2". std::string makeValStr(int nvals, @@ -376,7 +387,25 @@ namespace yask { // start stop (index = 2) // Ctor. - ScanIndices(const Dims& dims, bool use_vec_align, IdxTuple* ofs); + ScanIndices(const Dims& dims, bool use_vec_align); + ScanIndices(const Dims& dims, bool use_vec_align, Indices* ofs) : + ScanIndices(dims, use_vec_align) { + if (ofs) { + DOMAIN_VAR_LOOP(i, j) { + assert(ofs->getNumDims() == ndims - 1); + align_ofs[i] = (*ofs)[j]; + } + } + } + ScanIndices(const Dims& dims, bool use_vec_align, IdxTuple* ofs) : + ScanIndices(dims, use_vec_align) { + if (ofs) { + DOMAIN_VAR_LOOP(i, j) { + assert(ofs->getNumDims() == ndims - 1); + align_ofs[i] = ofs->getVal(j); + } + } + } // Init from outer-loop indices. // Start..stop from point in outer loop become begin..end diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index 2b0219f1..01c95e90 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -38,7 +38,7 @@ namespace yask { } // ScanIndices ctor. - ScanIndices::ScanIndices(const Dims& dims, bool use_vec_align, IdxTuple* ofs) : + ScanIndices::ScanIndices(const Dims& dims, bool use_vec_align) : ndims(NUM_STENCIL_DIMS), begin(idx_t(0), ndims), end(idx_t(0), ndims), @@ -57,12 +57,6 @@ namespace yask { // Set alignment to vector lengths. if (use_vec_align) align[i] = fold_pts[j]; - - // Set alignment offset. - if (ofs) { - assert(ofs->getNumDims() == ndims - 1); - align_ofs[i] = ofs->getVal(j); - } } } @@ -75,8 +69,8 @@ namespace yask { STATE_VARS(this); // Init various tuples to make sure they have the correct dims. - rank_domain_offsets = domain_dims; - rank_domain_offsets.setValsSame(-1); // indicates prepare_solution() not called. TODO: add flag. + rank_domain_offsets.setFromTuple(domain_dims); + rank_domain_offsets.setFromConst(-1); // indicates prepare_solution() not called. TODO: add flag. max_halos = domain_dims; wf_angles = domain_dims; wf_shift_pts = domain_dims; @@ -293,7 +287,7 @@ namespace yask { // Adjust my offset in the global problem by adding all domain // sizes from prev ranks only. if (rdeltas[di] < 0) - rank_domain_offsets[dname] += rsizes[rn][di]; + rank_domain_offsets[di] += rsizes[rn][di]; } // 2nd pass. } // is inline w/me. @@ -485,7 +479,8 @@ namespace yask { gp->set_min_pad_size(dname, opts->_min_pad_sizes[dname]); // Offsets. - gp->_set_rank_offset(dname, rank_domain_offsets[dname]); + auto dp = dims->_domain_dims.lookup_posn(dname); + gp->_set_rank_offset(dname, rank_domain_offsets[dp]); gp->_set_local_offset(dname, 0); } @@ -782,8 +777,9 @@ namespace yask { bbtimer.start(); // Rank BB is based only on rank offsets and rank domain sizes. - rank_bb.bb_begin = rank_domain_offsets; - rank_bb.bb_end = rank_domain_offsets.addElements(opts->_rank_sizes, false); + rank_bb.bb_begin = dims->_domain_dims; + rank_domain_offsets.setTupleVals(rank_bb.bb_begin); + rank_bb.bb_end = rank_bb.bb_begin.addElements(opts->_rank_sizes, false); rank_bb.update_bb("rank", *this, true, &os); // BB may be extended for wave-fronts. @@ -1136,10 +1132,9 @@ namespace yask { // Does everything start on a vector-length boundary? bb_is_aligned = true; - for (auto& dim : domain_dims.getDims()) { - auto& dname = dim.getName(); - if ((bb_begin[dname] - context.rank_domain_offsets[dname]) % - dims->_fold_pts[dname] != 0) { + DOMAIN_VAR_LOOP(i, j) { + if ((bb_begin[j] - context.rank_domain_offsets[j]) % + dims->_fold_pts[j] != 0) { if (os) *os << "Note: '" << name << "' domain" " has one or more starting edges not on vector boundaries;" diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 706511fb..16a78171 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -282,7 +282,7 @@ namespace yask { os << " num-ranks: " << opts->_num_ranks.makeDimValStr(" * ") << endl << " rank-indices: " << opts->_rank_indices.makeDimValStr() << endl << - " local-domain-offsets: " << rank_domain_offsets.makeDimValStr() << endl; + " local-domain-offsets: " << rank_domain_offsets.makeDimValStr(dims->_domain_dims) << endl; if (opts->overlap_comms) os << " mpi-interior: " << mpi_interior.bb_begin.makeDimValStr() << diff --git a/src/kernel/lib/stencil_calc.cpp b/src/kernel/lib/stencil_calc.cpp index b05d7a92..1f7b1273 100644 --- a/src/kernel/lib/stencil_calc.cpp +++ b/src/kernel/lib/stencil_calc.cpp @@ -222,7 +222,7 @@ namespace yask { // Init sub-block begin & end from block start & stop indices. // Use the 'misc' loops. Indices for these loops will be scalar and // global rather than normalized as in the cluster and vector loops. - ScanIndices misc_idxs(*dims, true, 0); + ScanIndices misc_idxs(*dims, true); misc_idxs.initFromOuter(mini_block_idxs); // Stride sizes and alignment are one element. @@ -274,7 +274,7 @@ namespace yask { // Init sub-block begin & end from block start & stop indices. // These indices are in element units and global (NOT rank-relative). - ScanIndices sub_block_idxs(*dims, true, 0); + ScanIndices sub_block_idxs(*dims, true); sub_block_idxs.initFromOuter(mini_block_idxs); // Sub block indices in element units and rank-relative. From 27ee5d98738fbc5babd98905a0767f5636a31b64 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 18 Jun 2019 09:31:19 -0700 Subject: [PATCH 50/62] Update asm-viewing utility. --- src/kernel/Makefile | 4 +- src/kernel/lib/setup.cpp | 1 - utils/bin/{get_loop_stats.pl => view_asm.pl} | 193 ++++++++++++------- 3 files changed, 121 insertions(+), 77 deletions(-) rename utils/bin/{get_loop_stats.pl => view_asm.pl} (68%) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 72e54606..b20d8677 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -247,7 +247,7 @@ GEN_LOOPS := $(UTILS_BIN_DIR)/gen_loops.pl # Other scripts and cmds. GEN_LAYOUTS := $(UTILS_BIN_DIR)/gen_layouts.pl -GET_LOOP_STATS := $(UTILS_BIN_DIR)/get_loop_stats.pl +VIEW_ASM := $(UTILS_BIN_DIR)/view_asm.pl # Compiler and default flags. ifeq ($(mpi),1) @@ -874,7 +874,7 @@ echo-settings: # won't rebuild if only '-Fa' is added.) code-stats: @echo "Code stats for stencil computation:" - $(PERL) $(GET_LOOP_STATS) -p -f=calc_loop_of_clusters factory.s + $(PERL) $(VIEW_ASM) -p -l -f=calc_loop_of_clusters factory.s # Print some usage info. help: diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index 01c95e90..2e0d0fee 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -70,7 +70,6 @@ namespace yask { // Init various tuples to make sure they have the correct dims. rank_domain_offsets.setFromTuple(domain_dims); - rank_domain_offsets.setFromConst(-1); // indicates prepare_solution() not called. TODO: add flag. max_halos = domain_dims; wf_angles = domain_dims; wf_shift_pts = domain_dims; diff --git a/utils/bin/get_loop_stats.pl b/utils/bin/view_asm.pl similarity index 68% rename from utils/bin/get_loop_stats.pl rename to utils/bin/view_asm.pl index 7781b673..0e59d06b 100755 --- a/utils/bin/get_loop_stats.pl +++ b/utils/bin/view_asm.pl @@ -23,7 +23,8 @@ ## IN THE SOFTWARE. ############################################################################## -# Purpose: find SIMD inner loops in asm file(s) and +# Purpose: expand info in asm files. +# Optionally, find SIMD inner loops in asm file(s) and # report some stats on them. use strict; @@ -31,9 +32,11 @@ my $minInstrs = 2; my $printAsm = 0; -my $targetLabel = ""; +my $simdOnly = 0; +my $loopsOnly = 0; my $targetText = ""; my $targetFn = ""; +my @fnames; sub usage { my $msg = shift; @@ -41,10 +44,11 @@ sub usage { warn "$msg\n" if defined $msg; die "usage: [options] file...\n". "options:\n". - " -p print instrs\n". - " -f= print only loops in matching function\n". - " -l= print only loops at matching label\n". - " -t= print only loops with matching text\n"; + " -p print instrs in addition to stats\n". + " -l view only inner loops\n". + " -s view funcs/loops only with SIMD code\n". + " -f= view only in matching function\n". + " -t= view only if containing matching text\n"; } for my $arg (@ARGV) { @@ -54,34 +58,93 @@ sub usage { } elsif ($arg eq '-p') { $printAsm = 1; - next; } - elsif ($arg =~ /^-(\w+)=(.*)$/) { + elsif ($arg eq '-l') { + $loopsOnly = 1; + } + elsif ($arg eq '-s') { + $simdOnly = 1; + } + elsif ($arg =~ /^-(\w+)=(.+)$/) { my ($key, $val) = ($1, $2); - if ($key eq "l") { $targetLabel = $val; } - elsif ($key eq "t") { $targetText = $val; } + if ($key eq "t") { $targetText = $val; } elsif ($key eq "f") { $targetFn = $val; } else { usage("error: unknown option '$key'"); } - next; } + elsif ($arg =~ /^-/) { + usage("error: unknown or badly-formatted option '$arg'"); + } + else { + die "error: cannot read '$arg'\n" if !-r $arg; + push @fnames, $arg; + } +} +usage() if !@fnames; + + +my @lines; # following stats apply to these lines. +my $ninstrs = 0; # num instrs. +my %istats; # instr stats. +my %astats; # arg stats. +my %fstats; # src-file stats. +my %rstats; # SIMD reg stats. +my $curFn = ""; - my $fname = $arg; +sub clearStats() { + $ninstrs = 0; + undef %istats; + undef %astats; + undef %fstats; + undef %rstats; + undef @lines; +} + +sub printLines() { + if ($ninstrs > $minInstrs && + (!$simdOnly || scalar %rstats > 0) && + (!$targetFn || $curFn =~ /$targetFn/) && + (!$targetText || grep(/$targetText/, @lines))) { + print "\n"; + if ($loopsOnly) { + print "non-" if !scalar %rstats; + print "SIMD loop:\n"; + } + print "Function '$curFn'\n" if defined $curFn; + print @lines if $printAsm; + print "$ninstrs total instrs\n"; + print "Instr counts per instr type (FLOP count is a subtotal):\n"; + for my $key (sort keys %istats) { + my $value = $istats{$key}; + printf "%4i $key\n", $value; + } + print "Instr counts per operand type:\n"; + for my $key (sort keys %astats) { + my $value = $astats{$key}; + printf "%4i $key\n", $value; + } + print "Instr counts per source file:\n"; + for my $key (sort keys %fstats) { + my $value = $fstats{$key}; + printf "%4i $key\n", $value; + } + print "Num SIMD regs used: ".(scalar keys %rstats)."\n"; + } +} + + +for my $fname (@fnames) { + my %loopLabels; # labels that begin inner loops. my %files; # map from file index to source file-name. my %dirs; # map from file index to source dir-name. my %dirIndices; # map from dir-name to dir index. - my %loopLabels; - my %astats; # arg stats. - my %istats; # instr stats. - my %fstats; # src-file stats. - my %rstats; # SIMD reg stats. for my $pass (0..1) { my %labels; + my $asmLine = 0; my $getData = 0; - my ($locInfo, $srcFile, $curFn); # strings describing current location. - my @lines; # lines to print. + my ($locInfo, $srcFile); # strings describing current location. # Header. if (!$pass) { @@ -97,7 +160,7 @@ sub usage { } } - open F, "<$fname" or usage("error: cannot open '$fname'"); + open F, "c++filt < $fname |" or usage("error: cannot open '$fname'"); while () { chomp; @@ -130,34 +193,42 @@ sub usage { } } - # new function. - elsif (/^\s*\.section/) { - undef $curFn; + # begin function. + elsif (/^\#\s+[-]+\s+Begin\s+(.+)/) { + $curFn = $1; + clearStats(); + } + + # end function. + elsif (/^\#\s+[-]+\s+End /) { + printLines() if $pass && !$loopsOnly; + clearStats(); } # unmangled function name, e.g., # # --- yask::Indices::setFromInitList(yask::Indices *, const std::initializer_list &) - elsif (/^\#\s+---\s+(.*)/) { - $curFn = $1; + elsif (/^\#\s+[-]+\s+(\w+)::(.+)/) { + $curFn = "$1::$2"; + } + + # parameter. + elsif (/^\#\s+parameter/) { + push @lines, "$_\n" if !$loopsOnly; } # label, e.g., #..B1.39: # Preds ..B1.54 ..B1.38 elsif (/^\s*(\S+):/) { my $lab = $1; - #warn "$lab: @ $asmLine\n"; $labels{$lab} = $asmLine; # beginning of an inner loop? - if ($pass && exists $loopLabels{$lab}) { - - # clear loop data. - undef %istats; - undef %astats; - undef %fstats; - undef %rstats; - undef @lines; + if ($pass && $loopsOnly && exists $loopLabels{$lab}) { + + # clear previous loop data. + clearStats(); } + push @lines, "$_\n" if $lab =~ /\.\.B/; } # line of code, e.g., @@ -166,6 +237,7 @@ sub usage { my ($instr, $args, $comment) = ($1, $2, $3); $asmLine++; push @lines, "$_\t$locInfo\n"; + $ninstrs++; # collect stats in this instr. { @@ -187,7 +259,7 @@ sub usage { $itype = 'packed DP'; } - # reg stats. + # SIMD reg stats. if ($args =~ /[xyz]mm(\d+)/) { $rstats{$1}++; } @@ -264,46 +336,19 @@ sub usage { # this assumes loops jump backward. if (exists $labels{$lab}) { - my $dist = $asmLine - $labels{$lab}; + # remember for 2nd pass. $loopLabels{$lab} = 1; - #warn "$lab: $dist instrs\n"; - - # 2nd pass: print results under certain conditions. - if ($pass && - $dist > $minInstrs && - scalar keys %rstats && - (!$targetFn || $curFn =~ /$targetFn/) && - (!$targetLabel || $lab =~ /$targetLabel/) && - (!$targetText || grep(/$targetText/, @lines))) { - print "\nSIMD loop $lab:\n"; - print "'$curFn'\n" if defined $curFn; - print @lines if $printAsm; - print "$dist total instrs\n"; - print "Instr counts per instr type (FLOP count is a subtotal):\n"; - for my $key (sort keys %istats) { - my $value = $istats{$key}; - printf "%4i $key\n", $value; - } - print "Instr counts per operand type:\n"; - for my $key (sort keys %astats) { - my $value = $astats{$key}; - printf "%4i $key\n", $value; - } - print "Instr counts per source file:\n"; - for my $key (sort keys %fstats) { - my $value = $fstats{$key}; - printf "%4i $key\n", $value; - } - print "Num SIMD regs used: ".(scalar keys %rstats)."\n"; - } - # we only want inner loops, - # so we can delete all label info now. - undef %labels; - undef %istats; - undef %astats; - undef %fstats; - undef %rstats; + # Print loop. + if ($pass && $loopsOnly) { + printLines(); + + # we only want inner loops, + # so we delete all previous label info now. + undef %labels; + + clearStats(); + } } } } @@ -311,5 +356,5 @@ sub usage { } } -print "To see the asm code for the above loop(s), run '$0 -p @ARGV'.\n" +print "To see the asm code for the above, run '$0 -p @ARGV'.\n" if !$printAsm; From 9a98bb9ac3668873a8f7060fce668dbde4e89b51 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Tue, 18 Jun 2019 16:27:24 -0700 Subject: [PATCH 51/62] Remove the extraction of the debug ostream from STATE_VARS because it was preventing inlining. --- src/compiler/lib/Cpp.cpp | 13 +- src/compiler/lib/Cpp.hpp | 1 + src/kernel/lib/alloc.cpp | 28 ++-- src/kernel/lib/auto_tuner.cpp | 56 +++---- src/kernel/lib/auto_tuner.hpp | 2 +- src/kernel/lib/context.cpp | 4 +- src/kernel/lib/context.hpp | 4 +- src/kernel/lib/generic_var.cpp | 14 +- src/kernel/lib/settings.cpp | 4 +- src/kernel/lib/settings.hpp | 18 +-- src/kernel/lib/setup.cpp | 77 +++++---- src/kernel/lib/soln_apis.cpp | 273 +++++++++++++++----------------- src/kernel/lib/stencil_calc.cpp | 61 ++++--- src/kernel/lib/yask.hpp | 43 ++++- src/kernel/lib/yk_var.cpp | 16 +- src/kernel/lib/yk_var.hpp | 6 +- 16 files changed, 308 insertions(+), 312 deletions(-) diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index 46f972c8..dc3e456f 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -56,7 +56,7 @@ namespace yask { string optArg) { // Get/set local vars. - string varPtr = getLocalVar(os, gp.getVarPtr(), _var_ptr_type); + string varPtr = getLocalVar(os, gp.getVarPtr(), _var_ptr_restrict_type); string stepArgVar = getLocalVar(os, gp.makeStepArgStr(varPtr, _dims), _step_val_type); string res = varPtr + "->" + fname + "("; @@ -94,7 +94,7 @@ namespace yask { string gtype = folded ? "YkVecVar" : "YkElemVar"; // Get/set local vars. - string varPtr = getLocalVar(os, gp.getVarPtr(), CppPrintHelper::_var_ptr_type); + string varPtr = getLocalVar(os, gp.getVarPtr(), CppPrintHelper::_var_ptr_restrict_type); string stepArgVar = getLocalVar(os, gp.makeStepArgStr(varPtr, _dims), CppPrintHelper::_step_val_type); @@ -171,7 +171,7 @@ namespace yask { bool isNorm) { // Get/set local vars. - string varPtr = getLocalVar(os, gp.getVarPtr(), CppPrintHelper::_var_ptr_type); + string varPtr = getLocalVar(os, gp.getVarPtr(), CppPrintHelper::_var_ptr_restrict_type); string stepArgVar = getLocalVar(os, gp.makeStepArgStr(varPtr, _dims), CppPrintHelper::_step_val_type); @@ -409,10 +409,11 @@ namespace yask { auto* var = gp.getVar(); bool is_unique = (var->getStepDim() == nullptr); // || (!var->is_dynamic_step_alloc() && var->get_step_alloc_size() == 1); - string type = is_unique ? "auto* restrict " : "auto* "; + string type = is_unique ? CppPrintHelper::_var_ptr_restrict_type : + CppPrintHelper::_var_ptr_type; // Print type and value. - os << _linePrefix << type << ptrName << " = " << vp << _lineSuffix; + os << _linePrefix << type << " " << ptrName << " = " << vp << _lineSuffix; } // Get expression for offset of 'gp' from base pointer. Base pointer @@ -652,7 +653,7 @@ namespace yask { string CppStepVarPrintVisitor::visit(VarPoint* gp) { // Pointer to var. - string varPtr = _cvph.getLocalVar(_os, gp->getVarPtr(), CppPrintHelper::_var_ptr_type); + string varPtr = _cvph.getLocalVar(_os, gp->getVarPtr(), CppPrintHelper::_var_ptr_restrict_type); // Time var. auto& dims = _cvph.getDims(); diff --git a/src/compiler/lib/Cpp.hpp b/src/compiler/lib/Cpp.hpp index db705c67..c73e2844 100644 --- a/src/compiler/lib/Cpp.hpp +++ b/src/compiler/lib/Cpp.hpp @@ -42,6 +42,7 @@ namespace yask { public: static constexpr const char* _var_ptr_type = "auto*"; + static constexpr const char* _var_ptr_restrict_type = "auto* restrict"; static constexpr const char* _step_val_type = "const auto"; CppPrintHelper(const CompilerSettings& settings, diff --git a/src/kernel/lib/alloc.cpp b/src/kernel/lib/alloc.cpp index 3d3a28e9..c30dd68e 100644 --- a/src/kernel/lib/alloc.cpp +++ b/src/kernel/lib/alloc.cpp @@ -65,10 +65,11 @@ namespace yask { // Alloc data depending on magic key. shared_ptr p; - os << "Allocating " << makeByteStr(nb) << - " for " << ng << " " << type << "(s) "; + string msg = "Allocating " + makeByteStr(nb) + + " for " + to_string(ng) + " " + type + "(s) "; if (mem_key == _shmem_key) { - os << "using MPI shm...\n" << flush; + msg += "using MPI shm"; + DEBUG_MSG(msg << "..."); p = shared_shm_alloc(nb, &env->shm_comm, &mpiInfo->halo_win); // Get pointer for each neighbor rank. @@ -93,21 +94,22 @@ namespace yask { } else if (mem_key >= _pmem_key) { auto dev_num = mem_key - _pmem_key; - os << "on PMEM device " << dev_num << "...\n" << flush; + msg += "on PMEM device " + to_string(dev_num); + DEBUG_MSG(msg << "..."); p = shared_pmem_alloc(nb, dev_num); } else { if (mem_key == yask_numa_none) - os << "using default allocator"; + msg += "using default allocator"; else if (mem_key == yask_numa_local) - os << "preferring local NUMA node"; + msg += "preferring local NUMA node"; else if (mem_key == yask_numa_interleave) - os << "interleaved across all NUMA nodes"; + msg += "interleaved across all NUMA nodes"; else if (mem_key >= 0) - os << "preferring NUMA node " << mem_key; + msg += "preferring NUMA node " + to_string(mem_key); else - os << "using mem policy " << mem_key; - os << "...\n" << flush; + msg += "using mem policy " + to_string(mem_key); + DEBUG_MSG(msg << "..."); p = shared_numa_alloc(nb, mem_key); } @@ -182,7 +184,7 @@ namespace yask { auto p = _var_data_buf[numa_pref]; assert(p); gp->set_storage(p, npbytes[numa_pref]); - os << gb.make_info_string() << endl; + DEBUG_MSG(gb.make_info_string()); } // Determine padded size (also offset to next location). @@ -213,7 +215,7 @@ namespace yask { // Otherwise, just print existing var info. else if (pass == 1) - os << gb.make_info_string() << endl; + DEBUG_MSG(gb.make_info_string()); } // Reset the counters @@ -631,7 +633,7 @@ namespace yask { // Finalize interior BB if there are multiple ranks and overlap enabled. if (env->num_ranks > 1 && opts->overlap_comms) { - mpi_interior.update_bb("interior", *this, true); + mpi_interior.update_bb("interior", this, true); TRACE_MSG("MPI interior BB: [" << mpi_interior.bb_begin.makeDimValStr() << " ... " << mpi_interior.bb_end.makeDimValStr() << ")"); } diff --git a/src/kernel/lib/auto_tuner.cpp b/src/kernel/lib/auto_tuner.cpp index af1000ff..f4ff1938 100644 --- a/src/kernel/lib/auto_tuner.cpp +++ b/src/kernel/lib/auto_tuner.cpp @@ -85,7 +85,7 @@ namespace yask { if (!rank_bb.bb_valid) THROW_YASK_EXCEPTION("Error: run_auto_tuner_now() called without calling prepare_solution() first"); - os << "Auto-tuning...\n" << flush; + DEBUG_MSG("Auto-tuning..."); YaskTimer at_timer; at_timer.start(); @@ -121,7 +121,7 @@ namespace yask { } // Wait for all ranks to finish. - os << "Waiting for auto-tuner to converge on all ranks...\n"; + DEBUG_MSG("Waiting for auto-tuner to converge on all ranks..."); env->global_barrier(); // reenable normal operation. @@ -132,13 +132,13 @@ namespace yask { // Report results. at_timer.stop(); - os << "Auto-tuner done after " << steps_done << " step(s) in " << - makeNumStr(at_timer.get_elapsed_secs()) << " secs.\n"; + DEBUG_MSG("Auto-tuner done after " << steps_done << " step(s) in " << + makeNumStr(at_timer.get_elapsed_secs()) << " secs."); if (state->_use_pack_tuners) { for (auto& sp : stPacks) - sp->getAT().print_settings(os); + sp->getAT().print_settings(); } else - _at.print_settings(os); + _at.print_settings(); print_temporal_tiling_info(); // Reset stats. @@ -146,18 +146,18 @@ namespace yask { } // Print the best settings. - void AutoTuner::print_settings(ostream& os) const { + void AutoTuner::print_settings() const { + STATE_VARS(this); if (tune_mini_blks()) - os << _name << ": best-mini-block-size: " << - target_sizes().makeDimValStr(" * ") << endl; + DEBUG_MSG(_name << ": best-mini-block-size: " << + target_sizes().makeDimValStr(" * ")); else - os << _name << ": best-block-size: " << - target_sizes().makeDimValStr(" * ") << endl << - _name << ": mini-block-size: " << - _settings->_mini_block_sizes.makeDimValStr(" * ") << endl; - os << _name << ": sub-block-size: " << - _settings->_sub_block_sizes.makeDimValStr(" * ") << endl << - flush; + DEBUG_MSG(_name << ": best-block-size: " << + target_sizes().makeDimValStr(" * ") << endl << + _name << ": mini-block-size: " << + _settings->_mini_block_sizes.makeDimValStr(" * ")); + DEBUG_MSG(_name << ": sub-block-size: " << + _settings->_sub_block_sizes.makeDimValStr(" * ")); } // Access settings. @@ -179,8 +179,8 @@ namespace yask { if (best_rate > 0.) { target_sizes() = best_sizes; apply(); - os << _name << ": applying size " << - best_sizes.makeDimValStr(" * ") << endl; + DEBUG_MSG(_name << ": applying size " << + best_sizes.makeDimValStr(" * ")); } // Reset all vars. @@ -259,11 +259,11 @@ namespace yask { return; // Done. - os << _name << ": finished warmup for " << - csteps << " steps(s) in " << - makeNumStr(ctime) << " secs\n" << - _name << ": tuning " << (tune_mini_blks() ? "mini-" : "") << - "block sizes...\n"; + DEBUG_MSG(_name << ": finished warmup for " << + csteps << " steps(s) in " << + makeNumStr(ctime) << " secs\n" << + _name << ": tuning " << (tune_mini_blks() ? "mini-" : "") << + "block sizes..."); in_warmup = false; // Restart for first real measurement. @@ -316,10 +316,10 @@ namespace yask { return; // Print progress and reset vars for next time. - os << _name << ": search-dist=" << radius << ": " << - makeNumStr(rate) << " steps/sec (" << - csteps << " steps(s) in " << makeNumStr(ctime) << - " secs) with size " << target_sizes().makeDimValStr(" * ") << endl; + DEBUG_MSG(_name << ": search-dist=" << radius << ": " << + makeNumStr(rate) << " steps/sec (" << + csteps << " steps(s) in " << makeNumStr(ctime) << + " secs) with size " << target_sizes().makeDimValStr(" * ")); csteps = 0; ctime = 0.; @@ -446,7 +446,7 @@ namespace yask { // Reset AT and disable. clear(true); - os << _name << ": done" << endl; + DEBUG_MSG(_name << ": done"); return; } TRACE_MSG(_name << ": new search radius=" << radius); diff --git a/src/kernel/lib/auto_tuner.hpp b/src/kernel/lib/auto_tuner.hpp index 76bc4aa1..9dd3a7ed 100644 --- a/src/kernel/lib/auto_tuner.hpp +++ b/src/kernel/lib/auto_tuner.hpp @@ -126,7 +126,7 @@ namespace yask { void eval(); // Print the best settings. - void print_settings(std::ostream& os) const; + void print_settings() const; // Apply settings. void apply(); diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 0ad5fe2f..2136f904 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -1529,9 +1529,9 @@ namespace yask { idx_t StencilContext::compareData(const StencilContext& ref) const { STATE_VARS_CONST(this); - os << "Comparing var(s) in '" << name << "' to '" << ref.name << "'..." << endl; + DEBUG_MSG("Comparing var(s) in '" << name << "' to '" << ref.name << "'..."); if (varPtrs.size() != ref.varPtrs.size()) { - cerr << "** number of vars not equal." << endl; + TRACE_MSG("** number of vars not equal"); return 1; } idx_t errs = 0; diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 6dc8af3d..c03af3dc 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -46,9 +46,9 @@ namespace yask { // Calc values and set valid to true. // If 'force_full', set 'bb_num_points' as well as 'bb_size'. void update_bb(const std::string& name, - StencilContext& context, + StencilContext* context, bool force_full, - std::ostream* os = NULL); + bool print_info = false); // Is point in BB? // 'pt' must have same dims as BB. diff --git a/src/kernel/lib/generic_var.cpp b/src/kernel/lib/generic_var.cpp index c0c83aa7..8b7dea8e 100644 --- a/src/kernel/lib/generic_var.cpp +++ b/src/kernel/lib/generic_var.cpp @@ -56,15 +56,11 @@ namespace yask { // Alloc required number of bytes. size_t sz = get_num_bytes(); - os << "Allocating " << makeByteStr(sz) << - " for var '" << _name << "'"; -#ifdef USE_NUMA - if (numa_pref >= 0) - os << " preferring NUMA node " << numa_pref; - else - os << " on local NUMA node"; -#endif - os << "...\n" << flush; + string loc = (numa_pref >= 0) ? + "preferring NUMA node " + to_string(numa_pref) : + "on default NUMA node"; + DEBUG_MSG("Allocating " << makeByteStr(sz) << + " for var '" << _name << "' " << loc << "..."); _base = shared_numa_alloc(sz, numa_pref); // No offset. diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index b2e2dc38..afbf7acc 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -638,7 +638,9 @@ namespace yask { // Make sure all user-provided settings are valid and finish setting up some // other vars before allocating memory. // Called from prepare_solution(), during auto-tuning, etc. - void KernelSettings::adjustSettings(std::ostream& os) { + void KernelSettings::adjustSettings(KernelStateBase* ksb) { + yask_output_ptr op = ksb ? ksb->get_debug_output() : nullop; + ostream& os = op->get_ostream(); auto& step_dim = _dims->_step_dim; auto& inner_dim = _dims->_inner_dim; diff --git a/src/kernel/lib/settings.hpp b/src/kernel/lib/settings.hpp index dacab910..fcc10557 100644 --- a/src/kernel/lib/settings.hpp +++ b/src/kernel/lib/settings.hpp @@ -31,6 +31,7 @@ namespace yask { class StencilContext; class YkVarBase; class YkVarImpl; + class KernelStateBase; // Some derivations from var types. typedef std::shared_ptr YkVarPtr; @@ -282,10 +283,7 @@ namespace yask { // values as needed. // Called from prepare_solution(), so it doesn't normally need to be called from user code. // Prints informational info to 'os'. - virtual void adjustSettings(std::ostream& os); - virtual void adjustSettings() { - adjustSettings(nullop->get_ostream()); - } + virtual void adjustSettings(KernelStateBase* ksb = 0); // Determine if this is the first or last rank in given dim. virtual bool is_first_rank(const std::string dim) { @@ -594,13 +592,15 @@ namespace yask { // Macro to define and set commonly-needed state vars efficiently. // '_ksbp' is pointer to a 'KernelStateBase' object. // '*_posn' vars are positions in stencil_dims. + // It is critical that statements here can be easily optimized + // away by the compiler if some vars are not needed. Thus, + // avoid accessing vars in virtual classes or calling any + // functions with side-effects. #define STATE_VARS0(_ksbp, pfx) \ pfx auto* ksbp = _ksbp; \ assert(ksbp); \ - pfx auto* state = ksbp->_state.get(); \ + pfx auto* state = ksbp->get_state().get(); \ assert(state); \ - assert(state->_debug.get()); \ - auto& os = state->_debug.get()->get_ostream(); \ pfx auto* env = state->_env.get(); \ assert(env); \ pfx auto* opts = state->_opts.get(); \ @@ -643,11 +643,11 @@ namespace yask { virtual ~KernelStateBase() {} // Access to state. - KernelStatePtr& get_state() { + ALWAYS_INLINE KernelStatePtr& get_state() { assert(_state); return _state; } - const KernelStatePtr& get_state() const { + ALWAYS_INLINE const KernelStatePtr& get_state() const { assert(_state); return _state; } diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index 2e0d0fee..d5f760b9 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -322,10 +322,10 @@ namespace yask { } else { num_neighbors++; - os << "Neighbor #" << num_neighbors << " is MPI rank " << rn << - " at absolute rank indices " << rcoords.makeDimValStr() << - " (" << rdeltas.makeDimValOffsetStr() << " relative to rank " << - me << ")"; + DEBUG_MSG("Neighbor #" << num_neighbors << " is MPI rank " << rn << + " at absolute rank indices " << rcoords.makeDimValStr() << + " (" << rdeltas.makeDimValOffsetStr() << " relative to rank " << + me << ")"); // Determine whether neighbor is in my shm group. // If so, record rank number in shmcomm. @@ -336,12 +336,9 @@ namespace yask { env->shm_group, &s_rank); if (s_rank != MPI_UNDEFINED) { mpiInfo->shm_ranks.at(rn_ofs) = s_rank; - os << " and is MPI shared-memory rank " << s_rank; - } else { - os << " and will not use shared-memory"; + DEBUG_MSG(" is MPI shared-memory rank " << s_rank); } } - os << ".\n"; } // Save manhattan dist. @@ -754,7 +751,7 @@ namespace yask { STATE_VARS(this); real_t seed = 0.1; - os << "Initializing vars...\n" << flush; + DEBUG_MSG("Initializing vars..."); YaskTimer itimer; itimer.start(); for (auto gp : varPtrs) { @@ -762,16 +759,16 @@ namespace yask { seed += 0.01; } itimer.stop(); - os << "Var initialization done in " << - makeNumStr(itimer.get_elapsed_secs()) << " secs.\n" << flush; + DEBUG_MSG("Var initialization done in " << + makeNumStr(itimer.get_elapsed_secs()) << " secs."); } // Set the bounding-box for each stencil-bundle and whole domain. void StencilContext::find_bounding_boxes() { STATE_VARS(this); - os << "Constructing bounding boxes for " << - stBundles.size() << " stencil-bundles(s)...\n" << flush; + DEBUG_MSG("Constructing bounding boxes for " << + stBundles.size() << " stencil-bundles(s)..."); YaskTimer bbtimer; bbtimer.start(); @@ -779,12 +776,12 @@ namespace yask { rank_bb.bb_begin = dims->_domain_dims; rank_domain_offsets.setTupleVals(rank_bb.bb_begin); rank_bb.bb_end = rank_bb.bb_begin.addElements(opts->_rank_sizes, false); - rank_bb.update_bb("rank", *this, true, &os); + rank_bb.update_bb("rank", this, true, true); // BB may be extended for wave-fronts. ext_bb.bb_begin = rank_bb.bb_begin.subElements(left_wf_exts); ext_bb.bb_end = rank_bb.bb_end.addElements(right_wf_exts); - ext_bb.update_bb("extended-rank", *this, true); + ext_bb.update_bb("extended-rank", this, true); // Remember sub-domain for each bundle. map bb_descrs; @@ -819,15 +816,15 @@ namespace yask { spbb.bb_begin = spbb.bb_begin.minElements(sbbb.bb_begin); spbb.bb_end = spbb.bb_end.maxElements(sbbb.bb_end); } - spbb.update_bb(sp->get_name(), *this, false); + spbb.update_bb(sp->get_name(), this, false); } // Init MPI interior to extended BB. mpi_interior = ext_bb; bbtimer.stop(); - os << "Bounding-box construction done in " << - makeNumStr(bbtimer.get_elapsed_secs()) << " secs.\n" << flush; + DEBUG_MSG("Bounding-box construction done in " << + makeNumStr(bbtimer.get_elapsed_secs()) << " secs."); } // Copy BB vars from another. @@ -1015,7 +1012,7 @@ namespace yask { BoundingBox new_bb; new_bb.bb_begin = bdpt; new_bb.bb_end = bdpt.addElements(scan_len); - new_bb.update_bb("sub-bb", *_context, true); + new_bb.update_bb("sub-bb", _context, true); cur_bb_list.push_back(new_bb); } // new rect found. @@ -1084,7 +1081,7 @@ namespace yask { bb.bb_end[odim] = bbn.bb_end[odim]; TRACE_MSG(" merging to form [" << bb.bb_begin.makeDimValStr() << " ... " << bb.bb_end.makeDimValStr() << ")"); - bb.update_bb("sub-bb", *_context, true); + bb.update_bb("sub-bb", _context, true); break; } } @@ -1098,7 +1095,7 @@ namespace yask { } // Finalize overall BB. - _bundle_bb.update_bb(get_name(), *_context, false); + _bundle_bb.update_bb(get_name(), _context, false); bbtimer.stop(); TRACE_MSG("find-bounding-box: done in " << bbtimer.get_elapsed_secs() << " secs."); @@ -1106,12 +1103,12 @@ namespace yask { // Compute convenience values for a bounding-box. void BoundingBox::update_bb(const string& name, - StencilContext& context, + StencilContext* context, bool force_full, - ostream* os) { + bool print_info) { + + STATE_VARS(context); - auto dims = context.get_dims(); - auto& domain_dims = dims->_domain_dims; bb_len = bb_end.subElements(bb_begin); bb_size = bb_len.product(); if (force_full) @@ -1120,24 +1117,24 @@ namespace yask { // Solid rectangle? bb_is_full = true; if (bb_num_points != bb_size) { - if (os) - *os << "Note: '" << name << "' domain has only " << - makeNumStr(bb_num_points) << - " valid point(s) inside its bounding-box of " << - makeNumStr(bb_size) << - " point(s); multiple sub-boxes will be used.\n"; + if (print_info) + DEBUG_MSG("Note: '" << name << "' domain has only " << + makeNumStr(bb_num_points) << + " valid point(s) inside its bounding-box of " << + makeNumStr(bb_size) << + " point(s); multiple sub-boxes will be used."); bb_is_full = false; } // Does everything start on a vector-length boundary? bb_is_aligned = true; DOMAIN_VAR_LOOP(i, j) { - if ((bb_begin[j] - context.rank_domain_offsets[j]) % + if ((bb_begin[j] - context->rank_domain_offsets[j]) % dims->_fold_pts[j] != 0) { - if (os) - *os << "Note: '" << name << "' domain" - " has one or more starting edges not on vector boundaries;" - " masked calculations will be used in peel and remainder sub-blocks.\n"; + if (print_info) + DEBUG_MSG("Note: '" << name << "' domain" + " has one or more starting edges not on vector boundaries;" + " masked calculations will be used in peel and remainder sub-blocks."); bb_is_aligned = false; break; } @@ -1149,10 +1146,10 @@ namespace yask { auto& dname = dim.getName(); if (bb_len[dname] % dims->_cluster_pts[dname] != 0) { if (bb_is_full && bb_is_aligned) - if (os && bb_is_aligned) - *os << "Note: '" << name << "' domain" - " has one or more sizes that are not vector-cluster multiples;" - " masked calculations will be used in peel and remainder sub-blocks.\n"; + if (print_info && bb_is_aligned) + DEBUG_MSG("Note: '" << name << "' domain" + " has one or more sizes that are not vector-cluster multiples;" + " masked calculations will be used in peel and remainder sub-blocks."); bb_is_cluster_mult = false; break; } diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 16a78171..4d61608e 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -116,19 +116,18 @@ namespace yask { reset_auto_tuner(true, false); // Report ranks. - os << endl; - os << "Num MPI ranks: " << env->get_num_ranks() << endl; - os << "This MPI rank index: " << env->get_rank_index() << endl; + DEBUG_MSG("\nNum MPI ranks: " << env->get_num_ranks() << + "\nThis MPI rank index: " << env->get_rank_index()); // report threads. { - os << "Num OpenMP procs: " << omp_get_num_procs() << endl; + DEBUG_MSG("Num OpenMP procs: " << omp_get_num_procs()); int rt, bt; int at = get_num_comp_threads(rt, bt); - os << "Num OpenMP threads avail: " << opts->max_threads << - "\nNum OpenMP threads used: " << at << - "\n Num threads per region: " << rt << - "\n Num threads per block: " << bt << endl; + DEBUG_MSG("Num OpenMP threads avail: " << opts->max_threads << + "\nNum OpenMP threads used: " << at << + "\n Num threads per region: " << rt << + "\n Num threads per block: " << bt); } // Set the number of threads for a region. The number of threads @@ -142,9 +141,8 @@ namespace yask { [&](idx_t start, idx_t stop, idx_t thread_num) { }); // Some var stats. - os << endl; - os << "Num vars: " << varPtrs.size() << endl; - os << "Num vars to be updated: " << outputVarPtrs.size() << endl; + DEBUG_MSG("\nNum vars: " << varPtrs.size() << + "\nNum vars to be updated: " << outputVarPtrs.size()); // Set up data based on MPI rank, including local or global sizes, // var positions. @@ -153,7 +151,7 @@ namespace yask { // Adjust all settings before setting MPI buffers or sizing vars. // Prints adjusted settings. // TODO: print settings again after auto-tuning. - opts->adjustSettings(os); + opts->adjustSettings(this); // Set offsets in vars and find WF extensions // based on the vars' halos. Force setting @@ -183,8 +181,8 @@ namespace yask { allocScratchData(); allocMpiData(); allocTimer.stop(); - os << "Allocation done in " << - makeNumStr(allocTimer.get_elapsed_secs()) << " secs.\n" << flush; + DEBUG_MSG("Allocation done in " << + makeNumStr(allocTimer.get_elapsed_secs()) << " secs."); init_stats(); @@ -196,45 +194,43 @@ namespace yask { void StencilContext::print_warnings() const { STATE_VARS(this); #ifdef CHECK - os << "*** WARNING: YASK compiled with CHECK; ignore performance results.\n"; + DEBUG_MSG("*** WARNING: YASK compiled with CHECK; ignore performance results."); #endif #if defined(NO_INTRINSICS) && (VLEN > 1) - os << "*** WARNING: YASK compiled with NO_INTRINSICS; ignore performance results.\n"; + DEBUG_MSG("*** WARNING: YASK compiled with NO_INTRINSICS; ignore performance results."); #endif #ifdef MODEL_CACHE - os << "*** WARNING: YASK compiled with MODEL_CACHE; ignore performance results.\n"; + DEBUG_MSG("*** WARNING: YASK compiled with MODEL_CACHE; ignore performance results."); #endif #ifdef TRACE_MEM - os << "*** WARNING: YASK compiled with TRACE_MEM; ignore performance results.\n"; + DEBUG_MSG("*** WARNING: YASK compiled with TRACE_MEM; ignore performance results."); #endif #ifdef TRACE_INTRINSICS - os << "*** WARNING: YASK compiled with TRACE_INTRINSICS; ignore performance results.\n"; + DEBUG_MSG("*** WARNING: YASK compiled with TRACE_INTRINSICS; ignore performance results."); #endif - TRACE_MSG(" WARNING: YASK run with -trace; ignore performance results"); + TRACE_MSG("*** WARNING: YASK run with -trace; ignore performance results"); } void StencilContext::print_temporal_tiling_info() const { STATE_VARS(this); - os << - " num-wave-front-steps: " << wf_steps << endl << - " num-temporal-block-steps: " << tb_steps << endl; + DEBUG_MSG(" num-wave-front-steps: " << wf_steps << + "\n num-temporal-block-steps: " << tb_steps); // Print detailed info only if temporal tiling enabled. if (wf_steps > 0 || tb_steps > 0) { - os << - " wave-front-angles: " << wf_angles.makeDimValStr() << endl << - " num-wave-front-shifts: " << num_wf_shifts << endl << - " wave-front-shift-amounts: " << wf_shift_pts.makeDimValStr() << endl << - " left-wave-front-exts: " << left_wf_exts.makeDimValStr() << endl << - " right-wave-front-exts: " << right_wf_exts.makeDimValStr() << endl << - " ext-local-domain: " << ext_bb.bb_begin.makeDimValStr() << - " ... " << ext_bb.bb_end.subElements(1).makeDimValStr() << endl << - " temporal-block-angles: " << tb_angles.makeDimValStr() << endl << - " num-temporal-block-shifts: " << num_tb_shifts << endl << - " temporal-block-long-base: " << tb_widths.makeDimValStr(" * ") << endl << - " temporal-block-short-base: " << tb_tops.makeDimValStr(" * ") << endl << - " mini-block-angles: " << mb_angles.makeDimValStr() << endl; + DEBUG_MSG(" wave-front-angles: " << wf_angles.makeDimValStr() << endl << + " num-wave-front-shifts: " << num_wf_shifts << endl << + " wave-front-shift-amounts: " << wf_shift_pts.makeDimValStr() << endl << + " left-wave-front-exts: " << left_wf_exts.makeDimValStr() << endl << + " right-wave-front-exts: " << right_wf_exts.makeDimValStr() << endl << + " ext-local-domain: " << ext_bb.bb_begin.makeDimValStr() << + " ... " << ext_bb.bb_end.subElements(1).makeDimValStr() << endl << + " temporal-block-angles: " << tb_angles.makeDimValStr() << endl << + " num-temporal-block-shifts: " << num_tb_shifts << endl << + " temporal-block-long-base: " << tb_widths.makeDimValStr(" * ") << endl << + " temporal-block-short-base: " << tb_tops.makeDimValStr(" * ") << endl << + " mini-block-angles: " << mb_angles.makeDimValStr()); } } @@ -246,65 +242,59 @@ namespace yask { tot_nbytes = sumOverRanks(rank_nbytes, env->comm); rank_domain_pts = rank_bb.bb_num_points; tot_domain_pts = sumOverRanks(rank_domain_pts, env->comm); - os << - "\nDomain size in this rank (points): " << makeNumStr(rank_domain_pts) << - "\nTotal allocation in this rank: " << makeByteStr(rank_nbytes) << - "\nOverall problem size in " << env->num_ranks << " rank(s) (points): " << - makeNumStr(tot_domain_pts) << - "\nTotal overall allocation in " << env->num_ranks << " rank(s): " << - makeByteStr(tot_nbytes) << - endl; + DEBUG_MSG("\nDomain size in this rank (points): " << makeNumStr(rank_domain_pts) << + "\nTotal allocation in this rank: " << makeByteStr(rank_nbytes) << + "\nOverall problem size in " << env->num_ranks << " rank(s) (points): " << + makeNumStr(tot_domain_pts) << + "\nTotal overall allocation in " << env->num_ranks << " rank(s): " << + makeByteStr(tot_nbytes)); // Report some sizes and settings. - os << "\nWork-unit sizes in points (from smallest to largest):\n" - " vector-size: " << dims->_fold_pts.makeDimValStr(" * ") << endl << - " cluster-size: " << dims->_cluster_pts.makeDimValStr(" * ") << endl << - " sub-block-size: " << opts->_sub_block_sizes.removeDim(step_posn).makeDimValStr(" * ") << endl << - " mini-block-size: " << opts->_mini_block_sizes.makeDimValStr(" * ") << endl << - " block-size: " << opts->_block_sizes.makeDimValStr(" * ") << endl << - " region-size: " << opts->_region_sizes.makeDimValStr(" * ") << endl << - " local-domain-size: " << opts->_rank_sizes.removeDim(step_posn).makeDimValStr(" * ") << endl << - " global-domain-size: " << opts->_global_sizes.removeDim(step_posn).makeDimValStr(" * ") << endl; + DEBUG_MSG("\nWork-unit sizes in points (from smallest to largest):\n" + " vector-size: " << dims->_fold_pts.makeDimValStr(" * ") << endl << + " cluster-size: " << dims->_cluster_pts.makeDimValStr(" * ") << endl << + " sub-block-size: " << opts->_sub_block_sizes.removeDim(step_posn).makeDimValStr(" * ") << endl << + " mini-block-size: " << opts->_mini_block_sizes.makeDimValStr(" * ") << endl << + " block-size: " << opts->_block_sizes.makeDimValStr(" * ") << endl << + " region-size: " << opts->_region_sizes.makeDimValStr(" * ") << endl << + " local-domain-size: " << opts->_rank_sizes.removeDim(step_posn).makeDimValStr(" * ") << endl << + " global-domain-size: " << opts->_global_sizes.removeDim(step_posn).makeDimValStr(" * ")); #ifdef SHOW_GROUPS - os << - " sub-block-group-size: " << opts->_sub_block_group_sizes.makeDimValStr(" * ") << endl << - " block-group-size: " << opts->_block_group_sizes.makeDimValStr(" * ") << endl; + DEBUG_MSG(" sub-block-group-size: " << opts->_sub_block_group_sizes.makeDimValStr(" * ") << endl << + " block-group-size: " << opts->_block_group_sizes.makeDimValStr(" * ")); #endif - os << "\nOther settings:\n" - " yask-version: " << yask_get_version_string() << endl << - " target: " << get_target() << endl << - " stencil-name: " << get_name() << endl << - " stencil-description: " << get_description() << endl << - " element-size: " << makeByteStr(get_element_bytes()) << endl << - " local-domain: " << rank_bb.bb_begin.makeDimValStr() << - " ... " << rank_bb.bb_end.subElements(1).makeDimValStr() << endl; + DEBUG_MSG("\nOther settings:\n" + " yask-version: " << yask_get_version_string() << endl << + " target: " << get_target() << endl << + " stencil-name: " << get_name() << endl << + " stencil-description: " << get_description() << endl << + " element-size: " << makeByteStr(get_element_bytes()) << endl << + " local-domain: " << rank_bb.bb_begin.makeDimValStr() << + " ... " << rank_bb.bb_end.subElements(1).makeDimValStr()); #ifdef USE_MPI - os << - " num-ranks: " << opts->_num_ranks.makeDimValStr(" * ") << endl << - " rank-indices: " << opts->_rank_indices.makeDimValStr() << endl << - " local-domain-offsets: " << rank_domain_offsets.makeDimValStr(dims->_domain_dims) << endl; + DEBUG_MSG(" num-ranks: " << opts->_num_ranks.makeDimValStr(" * ") << endl << + " rank-indices: " << opts->_rank_indices.makeDimValStr() << endl << + " local-domain-offsets: " << rank_domain_offsets.makeDimValStr(dims->_domain_dims)); if (opts->overlap_comms) - os << - " mpi-interior: " << mpi_interior.bb_begin.makeDimValStr() << - " ... " << mpi_interior.bb_end.subElements(1).makeDimValStr() << endl; + DEBUG_MSG(" mpi-interior: " << mpi_interior.bb_begin.makeDimValStr() << + " ... " << mpi_interior.bb_end.subElements(1).makeDimValStr()); #endif - os << - " vector-len: " << VLEN << endl << - " extra-padding: " << opts->_extra_pad_sizes.removeDim(step_posn).makeDimValStr() << endl << - " minimum-padding: " << opts->_min_pad_sizes.removeDim(step_posn).makeDimValStr() << endl << - " L1-prefetch-distance: " << PFD_L1 << endl << - " L2-prefetch-distance: " << PFD_L2 << endl << - " max-halos: " << max_halos.makeDimValStr() << endl; + DEBUG_MSG( " vector-len: " << VLEN << endl << + " extra-padding: " << opts->_extra_pad_sizes.removeDim(step_posn).makeDimValStr() << endl << + " minimum-padding: " << opts->_min_pad_sizes.removeDim(step_posn).makeDimValStr() << endl << + " L1-prefetch-distance: " << PFD_L1 << endl << + " L2-prefetch-distance: " << PFD_L2 << endl << + " max-halos: " << max_halos.makeDimValStr()); print_temporal_tiling_info(); - os << endl; // Info about eqs, packs and bundles. - os << "Num stencil packs: " << stPacks.size() << endl; - os << "Num stencil bundles: " << stBundles.size() << endl; - os << "Num stencil equations: " << NUM_STENCIL_EQS << endl; + DEBUG_MSG("\n" + "Num stencil packs: " << stPacks.size() << endl << + "Num stencil bundles: " << stBundles.size() << endl << + "Num stencil equations: " << NUM_STENCIL_EQS); // Info on work in packs. - os << "\nBreakdown of work stats in this rank:\n"; + DEBUG_MSG("\nBreakdown of work stats in this rank:"); for (auto& sp : stPacks) sp->init_work_stats(); } @@ -394,12 +384,13 @@ namespace yask { } } - static void print_pct(ostream& os, double ntime, double dtime) { + static string print_pct(double ntime, double dtime) { + string msg; if (dtime > 0.) { float pct = 100. * ntime / dtime; - os << " (" << pct << "%)"; + msg = " (" + to_string(pct) + "%)"; } - os << endl; + return msg; } /// Get statistics associated with preceding calls to run_solution(). @@ -511,95 +502,79 @@ namespace yask { } if (steps_done > 0) { - os << - "\nWork stats:\n" - " num-steps-done: " << makeNumStr(steps_done) << endl << - " num-reads-per-step: " << makeNumStr(double(p->nreads) / steps_done) << endl << - " num-writes-per-step: " << makeNumStr(double(p->nwrites) / steps_done) << endl << - " num-est-FP-ops-per-step: " << makeNumStr(double(p->nfpops) / steps_done) << endl << - " num-points-per-step: " << makeNumStr(tot_domain_pts) << endl; + DEBUG_MSG("\nWork stats:\n" + " num-steps-done: " << makeNumStr(steps_done) << endl << + " num-reads-per-step: " << makeNumStr(double(p->nreads) / steps_done) << endl << + " num-writes-per-step: " << makeNumStr(double(p->nwrites) / steps_done) << endl << + " num-est-FP-ops-per-step: " << makeNumStr(double(p->nfpops) / steps_done) << endl << + " num-points-per-step: " << makeNumStr(tot_domain_pts)); if (psteps != steps_done) { - os << - " Work breakdown by stencil pack(s):\n"; + DEBUG_MSG(" Work breakdown by stencil pack(s):"); for (auto& sp : stPacks) { idx_t ns = sp->steps_done; idx_t nreads = sp->tot_reads_per_step; idx_t nwrites = sp->tot_writes_per_step; idx_t nfpops = sp->tot_fpops_per_step; string pfx = " '" + sp->get_name() + "' "; - os << pfx << "num-steps-done: " << ns << endl << - pfx << "num-reads-per-step: " << makeNumStr(nreads) << endl << - pfx << "num-writes-per-step: " << makeNumStr(nwrites) << endl << - pfx << "num-est-FP-ops-per-step: " << makeNumStr(nfpops) << endl; + DEBUG_MSG(pfx << "num-steps-done: " << ns << endl << + pfx << "num-reads-per-step: " << makeNumStr(nreads) << endl << + pfx << "num-writes-per-step: " << makeNumStr(nwrites) << endl << + pfx << "num-est-FP-ops-per-step: " << makeNumStr(nfpops)); } } - os << - "\nTime stats:\n" - " elapsed-time (sec): " << makeNumStr(rtime) << endl << - " Time breakdown by activity type:\n" - " compute time (sec): " << makeNumStr(ctime); - print_pct(os, ctime, rtime); -#ifdef USE_MPI - os << - " halo exchange time (sec): " << makeNumStr(htime); - print_pct(os, htime, rtime); -#endif - os << - " other time (sec): " << makeNumStr(otime); - print_pct(os, otime, rtime); + DEBUG_MSG("\nTime stats:\n" + " elapsed-time (sec): " << makeNumStr(rtime) << endl << + " Time breakdown by activity type:\n" + " compute time (sec): " << makeNumStr(ctime) << + print_pct(ctime, rtime) << endl << + " halo exchange time (sec): " << makeNumStr(htime) << + print_pct(htime, rtime) << endl << + " other time (sec): " << makeNumStr(otime) << + print_pct(otime, rtime)); if (psteps != steps_done) { - os << - " Compute-time breakdown by stencil pack(s):\n"; + DEBUG_MSG(" Compute-time breakdown by stencil pack(s):"); for (auto& sp : stPacks) { auto& ps = sp->stats; double ptime = ps.run_time; string pfx = " '" + sp->get_name() + "' "; - os << pfx << "time (sec): " << makeNumStr(ptime); - print_pct(os, ptime, ctime); + DEBUG_MSG(pfx << "time (sec): " << makeNumStr(ptime) << + print_pct(ptime, ctime)); } - os << " other (sec): " << makeNumStr(optime); - print_pct(os, optime, ctime); + DEBUG_MSG(" other (sec): " << makeNumStr(optime) << + print_pct(optime, ctime)); } #ifdef USE_MPI - os << - " Compute-time breakdown by halo area:\n" - " rank-exterior compute (sec): " << makeNumStr(etime); - print_pct(os, etime, ctime); - os << - " rank-interior compute (sec): " << makeNumStr(itime); - print_pct(os, itime, ctime); - os << - " Halo-time breakdown:\n" - " MPI waits (sec): " << makeNumStr(wtime); - print_pct(os, wtime, htime); - os << - " MPI tests (sec): " << makeNumStr(ttime); - print_pct(os, ttime, htime); double ohtime = max(htime - wtime - ttime, 0.); - os << - " packing, unpacking, etc. (sec): " << makeNumStr(ohtime); - print_pct(os, ohtime, htime); + DEBUG_MSG(" Compute-time breakdown by halo area:\n" + " rank-exterior compute (sec): " << makeNumStr(etime) << + print_pct(etime, ctime) << endl << + " rank-interior compute (sec): " << makeNumStr(itime) << + print_pct(itime, ctime) << endl << + " Halo-time breakdown:\n" + " MPI waits (sec): " << makeNumStr(wtime) << + print_pct(wtime, htime) << endl << + " MPI tests (sec): " << makeNumStr(ttime) << + print_pct(ttime, htime) << endl << + " packing, unpacking, etc. (sec): " << makeNumStr(ohtime) << + print_pct(ohtime, htime)); #endif // Note that rates are reported with base-10 suffixes per common convention, not base-2. // See https://www.speedguide.net/articles/bits-bytes-and-bandwidth-reference-guide-115. - os << - "\nRate stats:\n" - " throughput (num-reads/sec): " << makeNumStr(p->reads_ps) << endl << - " throughput (num-writes/sec): " << makeNumStr(p->writes_ps) << endl << - " throughput (est-FLOPS): " << makeNumStr(p->flops) << endl << - " throughput (num-points/sec): " << makeNumStr(p->pts_ps) << endl; + DEBUG_MSG("\nRate stats:\n" + " throughput (num-reads/sec): " << makeNumStr(p->reads_ps) << endl << + " throughput (num-writes/sec): " << makeNumStr(p->writes_ps) << endl << + " throughput (est-FLOPS): " << makeNumStr(p->flops) << endl << + " throughput (num-points/sec): " << makeNumStr(p->pts_ps)); if (psteps != steps_done) { - os << - " Rate breakdown by stencil pack(s):\n"; + DEBUG_MSG(" Rate breakdown by stencil pack(s):"); for (auto& sp : stPacks) { auto& ps = sp->stats; string pfx = " '" + sp->get_name() + "' "; - os << - pfx << "throughput (num-reads/sec): " << makeNumStr(ps.reads_ps) << endl << - pfx << "throughput (num-writes/sec): " << makeNumStr(ps.writes_ps) << endl << - pfx << "throughput (est-FLOPS): " << makeNumStr(ps.flops) << endl << - pfx << "throughput (num-points/sec): " << makeNumStr(ps.pts_ps) << endl; + DEBUG_MSG(pfx << "throughput (num-reads/sec): " << makeNumStr(ps.reads_ps) << endl << + pfx << "throughput (num-writes/sec): " << makeNumStr(ps.writes_ps) << endl << + pfx << "throughput (est-FLOPS): " << makeNumStr(ps.flops) << endl << + pfx << "throughput (num-points/sec): " << makeNumStr(ps.pts_ps)); } } diff --git a/src/kernel/lib/stencil_calc.cpp b/src/kernel/lib/stencil_calc.cpp index 1f7b1273..acb651c3 100644 --- a/src/kernel/lib/stencil_calc.cpp +++ b/src/kernel/lib/stencil_calc.cpp @@ -800,11 +800,10 @@ namespace yask { num_writes_per_step = 0; num_fpops_per_step = 0; - os << - "Pack '" << get_name() << "':\n" << - " num bundles: " << size() << endl << - " pack scope: " << _pack_bb.bb_begin.makeDimValStr() << - " ... " << _pack_bb.bb_end.subElements(1).makeDimValStr() << endl; + DEBUG_MSG("Pack '" << get_name() << "':\n" << + " num bundles: " << size() << endl << + " pack scope: " << _pack_bb.bb_begin.makeDimValStr() << + " ... " << _pack_bb.bb_end.subElements(1).makeDimValStr()); // Bundles. for (auto* sg : *this) { @@ -832,50 +831,44 @@ namespace yask { idx_t fpops_bb = fpops1 * bb.bb_num_points; num_fpops_per_step += fpops_bb; - os << " Bundle '" << sg->get_name() << "':\n" << - " num reqd scratch bundles: " << (sg_list.size() - 1) << endl; + DEBUG_MSG(" Bundle '" << sg->get_name() << "':\n" << + " num reqd scratch bundles: " << (sg_list.size() - 1)); // TODO: add info on scratch bundles here. if (sg->is_sub_domain_expr()) - os << " sub-domain expr: '" << sg->get_domain_description() << "'\n"; + DEBUG_MSG(" sub-domain expr: '" << sg->get_domain_description() << "'"); if (sg->is_step_cond_expr()) - os << " step-condition expr: '" << sg->get_step_cond_description() << "'\n"; + DEBUG_MSG(" step-condition expr: '" << sg->get_step_cond_description() << "'"); - os << - " bundle size (points): " << makeNumStr(bb.bb_size) << endl; + DEBUG_MSG(" bundle size (points): " << makeNumStr(bb.bb_size)); if (bb.bb_size) { - os << - " valid points in bundle: " << makeNumStr(bb.bb_num_points) << endl; + DEBUG_MSG(" valid points in bundle: " << makeNumStr(bb.bb_num_points)); if (bb.bb_num_points) { - os << - " bundle scope: " << bb.bb_begin.makeDimValStr() << - " ... " << bb.bb_end.subElements(1).makeDimValStr() << endl << - " bundle bounding-box size: " << bb.bb_len.makeDimValStr(" * ") << endl; + DEBUG_MSG(" bundle scope: " << bb.bb_begin.makeDimValStr() << + " ... " << bb.bb_end.subElements(1).makeDimValStr() << endl << + " bundle bounding-box size: " << bb.bb_len.makeDimValStr(" * ")); } } - os << - " num full rectangles in box: " << sg->getBBs().size() << endl; + DEBUG_MSG(" num full rectangles in box: " << sg->getBBs().size()); if (sg->getBBs().size() > 1) { for (size_t ri = 0; ri < sg->getBBs().size(); ri++) { auto& rbb = sg->getBBs()[ri]; - os << - " Rectangle " << ri << ":\n" - " num points in rect: " << makeNumStr(rbb.bb_num_points) << endl; + DEBUG_MSG(" Rectangle " << ri << ":\n" + " num points in rect: " << makeNumStr(rbb.bb_num_points)); if (rbb.bb_num_points) { - os << " rect scope: " << rbb.bb_begin.makeDimValStr() << - " ... " << rbb.bb_end.subElements(1).makeDimValStr() << endl; - os << " rect size: " << rbb.bb_len.makeDimValStr(" * ") << endl; + DEBUG_MSG(" rect scope: " << rbb.bb_begin.makeDimValStr() << + " ... " << rbb.bb_end.subElements(1).makeDimValStr() << endl << + " rect size: " << rbb.bb_len.makeDimValStr(" * ")); } } } - os << - " var-reads per point: " << reads1 << endl << - " var-reads in rank: " << makeNumStr(reads_bb) << endl << - " var-writes per point: " << writes1 << endl << - " var-writes in rank: " << makeNumStr(writes_bb) << endl << - " est FP-ops per point: " << fpops1 << endl << - " est FP-ops in rank: " << makeNumStr(fpops_bb) << endl; - + DEBUG_MSG(" var-reads per point: " << reads1 << endl << + " var-reads in rank: " << makeNumStr(reads_bb) << endl << + " var-writes per point: " << writes1 << endl << + " var-writes in rank: " << makeNumStr(writes_bb) << endl << + " est FP-ops per point: " << fpops1 << endl << + " est FP-ops in rank: " << makeNumStr(fpops_bb)); + // Classify vars. VarPtrs idvars, imvars, odvars, omvars, iodvars, iomvars; // i[nput], o[utput], d[omain], m[isc]. for (auto gp : sg->inputVarPtrs) { @@ -907,6 +900,8 @@ namespace yask { omvars.push_back(gp); } } + yask_output_ptr op = ksbp->get_debug_output(); + ostream& os = op->get_ostream(); print_var_list(os, idvars, "input-only domain"); print_var_list(os, odvars, "output-only domain"); print_var_list(os, iodvars, "input-output domain"); diff --git a/src/kernel/lib/yask.hpp b/src/kernel/lib/yask.hpp index 226710dd..5cb66293 100644 --- a/src/kernel/lib/yask.hpp +++ b/src/kernel/lib/yask.hpp @@ -150,24 +150,51 @@ typedef std::uint64_t uidx_t; #define NUMA_PREF yask_numa_local #endif -// macro for debug message. -#ifdef TRACE -#define TRACE_MSG0(os, msg) do { if (opts->_trace) { \ +// Macro for debug message. + +// 'os is an ostream. +#define DEBUG_MSG0(os, msg) do { \ KernelEnv::set_debug_lock(); \ - (os) << "YASK: " << std::boolalpha << std::dec << \ + (os) << std::boolalpha << std::dec << \ msg << std::endl << std::flush; \ KernelEnv::unset_debug_lock(); \ + } while(0) + +// 'state' is a pointer to a KernelState. +#define DEBUG_MSG1(state, msg) do { \ + assert(state->_debug.get()); \ + auto& os = state->_debug.get()->get_ostream(); \ + DEBUG_MSG0(os, msg); \ + } while(0) + +// Macro for debug message when 'state' is defined. +#define DEBUG_MSG(msg) DEBUG_MSG1(state, msg) + +// Macro for trace message. +// Enabled only if compiled with TRACE macro and run with -trace option. +#ifdef TRACE + +// 'os is an ostream. +#define TRACE_MSG0(os, msg) do { if (opts->_trace) { \ + DEBUG_MSG0(os, "YASK: " << msg); \ + } } while(0) + +// 'state' is a pointer to a KernelState. +#define TRACE_MSG1(state, msg) do { if (opts->_trace) { \ + DEBUG_MSG1(state, "YASK: " << msg); \ } } while(0) #else #define TRACE_MSG0(os, msg) ((void)0) +#define TRACE_MSG1(state, msg) ((void)0) #endif -// macro for debug message when 'os' is defined. -#define TRACE_MSG(msg) TRACE_MSG0(os, msg) +// Macro for trace message when 'state' is defined. +#define TRACE_MSG(msg) TRACE_MSG1(state, msg) -// macro for mem-trace. +// Macro for mem-trace when 'state' is defined. +// Enabled only if compiled with TRACE_MEM macro and run with -trace option. #ifdef TRACE_MEM -#define TRACE_MEM_MSG(msg) TRACE_MSG0(os, msg) +#define TRACE_MEM_MSG(msg) TRACE_MSG1(state, msg) #else #define TRACE_MEM_MSG(msg) ((void)0) #endif diff --git a/src/kernel/lib/yk_var.cpp b/src/kernel/lib/yk_var.cpp index fbd86520..13166cc9 100644 --- a/src/kernel/lib/yk_var.cpp +++ b/src/kernel/lib/yk_var.cpp @@ -331,14 +331,14 @@ namespace yask { int maxPrint) const { STATE_VARS(this); if (!ref) { - os << "** mismatch: no reference var.\n"; + DEBUG_MSG("** mismatch: no reference var."); return _allocs.product(); // total number of elements. } // Dims & sizes same? if (!_ggb->are_dims_and_sizes_same(*ref->_ggb)) { - os << "** mismatch due to incompatible vars: " << - make_info_string() << " and " << ref->make_info_string() << ".\n"; + DEBUG_MSG("** mismatch due to incompatible vars: " << + make_info_string() << " and " << ref->make_info_string()); return _allocs.product(); // total number of elements. } @@ -394,12 +394,12 @@ namespace yask { errs++; if (errs <= maxPrint) { if (errs < maxPrint) - os << "** mismatch at " << _ggb->get_name() << - "(" << opt.makeDimValStr() << "): " << - te << " != " << re << endl; + DEBUG_MSG("** mismatch at " << _ggb->get_name() << + "(" << opt.makeDimValStr() << "): " << + te << " != " << re); else - os << "** Additional errors not printed for var '" << - _ggb->get_name() << "'.\n"; + DEBUG_MSG("** Additional errors not printed for var '" << + _ggb->get_name() << "'"); } } } diff --git a/src/kernel/lib/yk_var.hpp b/src/kernel/lib/yk_var.hpp index 958a43cb..1cdf6384 100644 --- a/src/kernel/lib/yk_var.hpp +++ b/src/kernel/lib/yk_var.hpp @@ -659,7 +659,7 @@ namespace yask { virtual void alloc_storage() { STATE_VARS(gbp()); gg().default_alloc(); - os << gb().make_info_string() << std::endl; + DEBUG_MSG(gb().make_info_string()); } virtual void release_storage() { STATE_VARS(gbp()); @@ -1007,7 +1007,7 @@ namespace yask { // Indices must be normalized and rank-relative. // It's important that this function be efficient, since // it's indiectly used from the stencil kernel. - inline const real_vec_t* getVecPtrNorm(const Indices& vec_idxs, + ALWAYS_INLINE const real_vec_t* getVecPtrNorm(const Indices& vec_idxs, idx_t alloc_step_idx, bool checkBounds=true) const { STATE_VARS_CONST(this); @@ -1047,7 +1047,7 @@ namespace yask { } // Non-const version. - inline real_vec_t* getVecPtrNorm(const Indices& vec_idxs, + ALWAYS_INLINE real_vec_t* getVecPtrNorm(const Indices& vec_idxs, idx_t alloc_step_idx, bool checkBounds=true) { From 96864db550aeab9319c9021a1c68bf040f13e40e Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Wed, 19 Jun 2019 13:14:40 -0700 Subject: [PATCH 52/62] Remove old intro doc. --- docs/YASK-intro.pdf | Bin 1215799 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/YASK-intro.pdf diff --git a/docs/YASK-intro.pdf b/docs/YASK-intro.pdf deleted file mode 100644 index 98c14207cdd0453f3b5153dfd13aa3bda67aa7b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1215799 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

    1@E(cuQKcgwH=EC# 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

    R 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

    ^`Oark`ig5l`s=$3GxK_Gt;@PM9~ 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 )=GlO4@v)Wk% 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

    akDHqklKNvKO>g?6cT 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

    qR(d{@yLd6qq}>Y-^XQI8e;*+XMTwZ1ehR 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

    7vXZ6@82gqA(<)>^9)+3yWvd3%h)saV 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

    D{{e4AO{}5 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%0D?SmL%-v^D>81BU?Z_^rIH%Da-#VzoyP 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�F_=#(q+mw8&1 zXW!4szMx|TBp;U?4!9OX3QP4UUnSkjZReF7+F*U8XRBN}9(vS%e>5DJRH1shg^T(Y zXQ5*#%9N9myS;ZCd#agV^cWR7Xxf!Bn>0Tx6-uFkfD}ZL?rOpKYR{ zc}1Vv4qK6~VK4yDUS@uhJ(0zlY-H2uEY?sPXsCptfBy{$pDu_3@*-L4=ORp*?i<2zv#4iBO3woq#b;v3!3FLI33iqh2EfCI^F#2a43no8k zKCEy1?LGVgxm?4|`!uOBG{M(3%=1hyIaF>hg9gnGmZ8;sbBPnq#+R)WZV{OTy))Ij zx+HI9*C=8LbWc0^*gks<7FSEPngN4sa7EFQvx8YMvdf;*1j)o4#9AZVLph{J;uXc}To&VKfrBSEtK!a@F{mixs z;Lja>wHC8sle1TX=X8zSvr8b?z*^%D`q0Wy%R6=k7yiU$W&!lvHL9WNv zcW3qS(e;JJy}~40Zr8&E#bfuQCAKV%4mv3lI8pyck*YCJ8Q!5Y28&YR{a8%v!eaZs ze&}PF@^m0gqPnU9K#J>Pjw2d6%z9 zpY>5fPNWK}3*CK)BUe?w-bbYWdCS(o3#)9_6zO zB>TyJNqQMAS;1UOR*P55SquG@S9|y`2>Koxm3Y}__bY(sC-F~|pKzDoA$KW#(nipR zTf*l-X(jOd;wf9eZE_f&C)QckTi&}2iGil}#`Ze&3T%Gb{0<4nec4o}u|*%RLJdeTaFh0Yba^Q)5H z3G4K6yR8D-laGEMhTk48YN{Yaim9QDu%n6?>h;U&f*A%<=}Fkf;KmehS%BPfS<3NU zIo$dWzN2irnf{N5lQ^1GuUFW+IKw{gDYQB35^wkI3jz1C<2I3bel_)+sM2n#xmJ@3 zR&tHIcaHhx6!l2gd3JVnlFEF^v~pX@vSP^?d|QrTb;0+z;jOrCY8D$YzH*v-0+X84 z{s89U9L%HucE1?x=}=dKHMyuGnLA~?#+j;RP4q$rB zmoYb3PuSFj)EqL}Im)LsCyqxK#}@}Iw@O!&H#L`zw$hNy|S+mP|koAA^JyiXFD_t2ylc7ixHH_(WNgsIIJ~th;P@@@jH$ zvJ;&I9g^BYp`8La3DV!s6V&!om4_)4Zvxc={vZtL-_AdYt-zP9j5HNj=l=X)h5H0C+p3bDjm&|xHq3Ncc54*f zaIV5}8=q6?LKl6TLvOJby!J&%gepB%j_W!x)7-i|j}zJ6xYTBPR}Xod+qE)}9hsBq zPbX++(X~@tYY9OJ zA@Pq!*c_QgZFSzhKkN#@@|v=XQAi&$k=3C(q{=8*4u$g?Yt_{$0Pzn$E{MJHlg+m) z2VM-LMZN6|*Xk?sve`_wxkl5-wkSI4$z?Kl)&GBXk4$j->($=s8W*nd;?SAD4cr|&G@#@I=g0KlYGepPy5A$ z>r=`uG_7>u8P5Ob^4>pQIvR)nTqPEYXB3+7$wX3edPaFRAT&YSM3USDgbqOV15f#d zrJtZ%?j{wl6&}^hBvWMI*-8r8RLf!G^NmlzK)!w*GChx6v!1 z=UVXZ56%x6fsNN60vo3L1A^?f=Nfaj+1849Hu7%;KFDsCVma%xqE*fn=(9p)l8S0t zxa||l6vAa4AfcLk`_hD*NUEXnXstSXUw-w~-S+Cg7I&u{H{HTaeacAy-G;}GDK-=a zgm5jgs_$WoM^=NEwtfljxiiULMnJ^}$xc-t&EYA<7^+b#M``m>d|w)nt`KUgj8 zDpIz1cs286LJ!MKYjh`sKM&_&t`?o{fS%nBZ;#&dL~^g)Z0Cvw?A41*Tyta9cag{j zKVGT44)N#t(KousxgJ z|1a9!0xGUG+ZIkBxCM7e@F0bI0l|a2ySoRs;8s9@;10pvg1fuBySw{eIj6htx%b`v zZ@<3djWL;fGHZ`rRBiiM-`Z=1nSqf8t*n%}O2R=k zjLb5Noqg*h^JXR@eK*F(b1T)F?%>%A?nVvUNtU3NI?QIW_X^oNIW%G^?ww?UQiRqV zJ7W>Kug)xvd#37{*=jsaEZK6DRcU)o6IwxZ#+t51tOv3S(y1ujpw%?+5k zyGG3?OYBxOkCdV1JKs#>(uQ*vT(coyih)Q|3Kw=>KjUE%K^4SceG!O7#LHe8x1kEe z0)xb}IR=OdoBYb?oDo((sP*t8s%I!sYX`TX0>sjY_}rDLHK>!4YXQgVAUwOoG?9R* zt3nE=HQOC7`?YWI{HZ+d{ONdk^L`z2;~q5t;AI2kJ6LyVv2_IUaeYc7jyc%q?YeZX zJ7AwtYUM`QxNoHB9*(~{$v%Iog9dmRKizLebYG%F_l_oL<#rE|nG2o%qRd^Tdf9n6 zcTkR0I`@#7MNB^2uyMTP)*nzGd(?MlUvhb1udMD3z zuWoG2c3(E5X?m1~=@5_J0!}wBHJ^H1T4X*Ld(3(eW4Chhdahz%r=M=rc3(dGhtb=f zFB+V*!arMKr#~>izN)XJ>MV473_VtW8^2(uuWuAJ+?fMf0>eh_&mA>AJh4~Dx=kAI zC;%;qVK)04iw$?kfR?JT(}Ru1#yd^y)xqvthx2#+RMm0hE62HGUK`~yYt zXATWzSXaSgiOwHmLld?Wa1W37!kJ0%Y74jgW~xW;o;Km5Sfh@?83TMj1sFT-D+R<^ zqsW-HFwl*={9R!e2NB)3=c9E+kESNZCj4)V0!Lt%5yMep5D&g`qu#_r?;erf^qYp8 zw(f20Q4=oJi_XSjrYvRC3q>Z`J_wBE2#sbHi#<4t1r4a>WU6h??mk)Esfu{}L$)V*)OvEgCQYq; zUNStyMGb```>*>h@;Ge#5=7jI+wL0uXRr8cJHc0Y$cB-0yhf*X#i@MhN-X5 zy^a>w*`;&lCtd8m!kx)E1fa#WV?4T)%fM5=Pu3O-$xIjf8eGMK&Nb| zIwxCY7-U$;4mLvDdpI~tzd|9|H~=hM4p&AV+;4C2qC@jjgNkvJtO+~=S4;>N7$(bS zI!lQP?P5C_&FXNhiFoZ?EL|*x7E!%c4w>z*`o=r$?@r%6hZiVC zo>(S50tDz@q))k*eHLbqdp!w}v-hDq}DrT_uXV z89?afscQe2lby-5H(gy&bj@BeBNr8kOqK10H$BIp;F^q-IZ-OLI`vg*p#@>OYQC^K zd$^E$=fG<6S6*4OqA29|r-79@)g|c_?dc z#{ufW#HVZz!j9(opOG+2$3+WCSY@5*ZuLEz)~J+9uirmEOCUQFNb)^6gg`|0s_7 zg-~$@Twy>qAR7$4F|#YaP6ZvCSnpB4*zah|HtC5REU+0$_G(TMXSo-Fi}v*X8nJ!R zS}qtgzP(OdOsZ|Fn<26~a-*ezLKVCPW4fI;>P}O>s395K`IoaHxe#Y;mkDZ7Nv$(Y(=rMn3L@@|D z=Z@4VG&qs~aC?=cSLoCqjWIX3@4qgdAEv!t?s=__XH>Q5h^_u0#E)L!OK?(L-N)&L zc$RjOTwUHvf1t;SE(#TGEe(Jgh~B#$##3E zlLD*l=eaHTjn#bk3np!!1S2y_yYiEu2`ddmSU|OUDV_FLY2nXlVy8u!tLdYiI*+cd zSelJx>oE+J9-mOCJGUPPaH0yfLJ^H}5vkI{03BU1`n<8YDuqlU&_WQeJd~18x53dg zk+9&VZ3gE-$sargs2Sop)wXGKnWK`p_|1BH41=A7@L!& zwSjLhvtjIljvO}BMQV$&wB{pE1-BtrFx12}IMaO?6a_KN*Jv~JE=UzQ>~*ncLiG&FPH%^Eyp%$mnXNt!I2 zZiSN=vob@?i)-|?G4=y9jnGJ{c}j&@{P5h#)k3!2%^~xQ)F8a^itRn+#q5Nv-j%n- z$g_Qg9Bpi&Dzr=|b2&j;0OlD15QRoBy%@W@oEW){pW_|*86iR7?>#3Ajd{_O?~lF~ zKz-IOrbgoRjW|;zE>vBOoF(56CnX^Lr$&l_bZ;in3*4*kB}iDDmH)G^9Og5)Q&7oM zJm?dO!>>Wr4ZQ*iBA@IvXp|oUxIa1>?}#DcdL6o5`*t`hSF&ejk9B4~2vy zvEllCXnv=X%q*i=rU4Q#_$s)=>WaSrf1ARkD5GW*yk+J3U&FZca zkv_!}yX1F1>c~FgemoSl&5ss9!|Gou5!jU2Hr34zBaHBmYi?S%sllj2PjWrihq4`8a~YDAaDU;|4=>kR)() zj|?%x#m(OO$IBT%f{_QDv+6s{4fgO&r)meroT1XKw!yPAjxXcVv zt1F}zR4J{BW7uZI@c*>g9ZgCsJJsg{IW_uIN(@JonM`OBsvL*rxppiG9ezb{YV^7# zwWrXTjKndU3?^1>52-!nF7SS+Ovp1y$fLfzLcCN|q6oGgAZ1XJwA2(`tcqAr<+dtL zWt)-4x5x{xne16GGdQlUaQaVnz3PZ2tqCBG8Ji~2-EpX1d`FYqp)`ecqzBK$z_Y5N zWnOjGawyh*h7I3B1Aj-H^DsI5sf_HErvFv^qBZ)d?87Tf-z(QeYs59Z9~e*cl)E(j z_gwZZDXe2X4<-iBRTVGuw$v(V<5g)miHk=Q%5u%U&Y#qt?h^8BVlH`p zbZRowV6q=3oalYB0mmkBW8Gpk`zR@`2F;3AQ|IcCi88F57l?i?>+0&aeq=mH?)E8Q%^=-f9?`fgq5Z+ipe&)_ z9cR#-TI$A%nUgU*9m+%&IrpHXr%~RsV$?7f8@RilABm{z+?-#9ICCYfNL+VcC5{>v z>7c%$8i+P5%7_tcirkzNqEs5VCtSKP4x5@~=Y+?xsW1E&!DGr990#U8(?tG3M0Mja zCcik`>Y)rHXgcQK7N{pq5MSfK{RfPlCGb*w_D;bd@4YA;G5l_MT%_;gnime8{9JoZ zxu1j{One72AV5nA{_&PR@z~&uO$C|xX0rj@^eG!o?ZQw1dk=n=pM4K`wiC&gbm<*W z2IZA+@;cTYlINQ89>Vhn{D;mrbx6=1ALO`J{BkmAAt0)#m)e*=n z{&EN35(w^3+OqyqI}uZk9jZ%=(dl)A{<~GF{z?R?196-v+HK!Lm(7~S9D;B;N~j(m zfi5ctY|zg>{TRyR>Thvl@alrOKr?M5{G3q`^v-OKxtGRF(yEX1I?o&gvE8f1 zNTVLgEct{1Z^z@2#t@?`(>}^X{1oy+r_vbz422dFVJ5mJWU3lxX#nkkGWOnp`)s?^ znBORm>rCV{Me?O*CEGli3hXJT2XM(P(-_K5eC;iC*2j#L8dSP6Z}LfAIX&m1G}q_4B=` zI6^_LrZDn0WkMeo6j~-+!biC1k5KaM5N2bF&}d2g4s{TgV-V^BG^R+2V}Xbkl%r(T zK}8vmnt%JO>*{@3Ghcm5Z3(~no!Ig$y4D&$346oOcoeT!_$7fFEjQG^U}CUfLZ%YgQ2xG3 z4Th=UWnS@kLWo+M1d~20H2zDs#Lo?K`E#@amk`CKzuHR_qhwxh7WH6`{883P?{HpV zcztB_u%94#{YKXj?$F@ZY3}fxI^RY`xx7aX0Z|MKnWHCvv6=YWS4*e-`;VK7kF;=?!x9$94(@TT}db0Y(?@(sY4A8(~HajWCbe@dD{ zst9P@`F)WxhdExS-Ww`CQ}6Qy*rMOM*`B~P=QlNHrXx}sg@FuXzQ`zlKu!9F8~p)S z{sShhZUD=dAVgF6;S5gAw`@^KOMgG2piBLKwQ-jF9QT zEawL=ue+7n{Ip-`azw$+MGJ~?xAR1}3gmS&qKIf=03EI~2tY@RPFNR%C?icQV_a@< zjwu9*B;R`NQ&g2nrXfIioC>JE3v=~`TJ25AlMjlSby)eVgTD^$Ew+*guI9{>X5&+` zH0e?n@#~r?jl__Ood0JonL_PL*nTb^p6`G&qhl+=1)+=&=c(*%L9OWFiq)=qJU-h^z^1|HA9AlmpyJe16ewaVg{4gDA_)AM|K#%b-jV^z>m z1M?(dib@~#q(fzBgCi#EA@#~qj9V+M1R)Yin|C{DCAA~GWPlk1p>d~u0cx^{C0>PD zSMI+njB!bdXa)6f5Q9(|(Cl@86q7h1p|}sq6Hqhb@(yVAtdcCCKPqpmn7hfIFiH7S z>ITpX_>nx%!dBRj-;{K<#Lm^CxuaHKqyB?(b_TTyq!Umi*39a|>@XQiNqUsJ>Oyf; zP&cXdHHAS%Ul2Rq!XR_tBoo6Bfas;6h5Iw8Hi11~JV0G}AWrYNb7Pj5r2UmUi(L23 zRoKD4QmT1Oqp!Roy9WQDPF$D~4%;3dX56ShGIgnfvi}b?Mq0Hoasx*hn#qVY8C87J096xa(I9JV7zIwmll3_fb_>tYuK@i zBWxM+`t-*pE`K}&IRjdAkZ^cKJ|h-uPgWoy>ruX*C=$2%oLpxFp3_u$_P=HQm(BL5 zPT_>%IYkKpghJ{NQ0d7wAV{qF{bkVB{YcQmoiav|t3UB4qkZlB4EgNMw;=Gu9qbKr ze){2suuDhaiTpnZl=i=R9cYwOe=V4W{Th$$jR-?BVZNJY@JvbnggdQ#sY4lCaxPVo)EI!?o z2*Up%vFWCS5gf+_w5nzQAthye6w75V(Lk+U`v$WKo7+R@_B$?|4QgY<`a@|RY9mW@ zCMR*s&Vz}K+aN82BRqpyoW`Cx)}B&Er|=4k|AkeiR)4`^9-nzu8pbLSxmUNxF9b+? z?Yrc#?y@Bf#AjUL>1kxYux4W>kNr}W@Tov3S(vCfW7dlxbX^uir6sgaB91NB5IiCL z1CaFHSuoc`DAbIzWPUJtCM-7>X=#;eR1JLZID;|$<5u)WrBlcS zgQDGl;r9Rth^(*;4U}Ayt=-(|rdko@gg>sxmfzh&Y|6TY=oJ3> z?F~F1oQYW-`1@`-K!qnV&JY?X#{$aI!$8V5#i_Z94Wj#}17S(B2yk!+2p#hgCAV#p z0W^sB3Elt9T z?i}<-s`1P}7Cg>Ri0BD0)%=qC=z94<{c(K3CaG7Ft}P^>T9d4(|H+)GHEF0U7n_+E zV^ffk7hLH-Kfz*4%((4u*qM+s7epnhKko|{?RHTF{e=Qt6oW7wcUD)LX$<1ZG`UwU$8hJCfpn_-}+w zVy}ZeHYSbOd`)-j-6-^4F6W(L#M)118$th~1*L?cC?_k-kNJ1u$@VS*>8-KgxB2(F z|C78UtZI)G^dh*}{7xM7#Ie=;kq`OauJ3=eS}S@)=VFyZGyuwFj*0{~(WYft&#&pB zOyC%>*cpywAh69rUok|ETqG7p=`VuL4KVZ;W(evc{I@;7$rZdeks_CPj(4q`zRzfG ze#AG7dUJw&GdI|`Y0@{lTd&=(ZN}Q#G8?v||85{a4q$mSfS~))hHkUTx8arGtTD2_ zpln1=-I39$mfoS6e`WLM&MgNr0?+U2))B@7NeFd=^<_K1XT zKQzFM^8}ype?`f1f4}UvM1 z*e04(+1j49|Fy4iA6KAE#5~=Q}o z=FxUA0Dmz-PbcbGrz&VU9Nm3Q!+1eE<P+aPf6v zupD(oznAH!+%z??P;^>evE=hKyy7!@PE${ApSmMw>eDv~XSfTEEt z$G9fR$L4RQIuMov`0C4Hgk`B>?I<(&*R%wiXSY(!^rYqvtpKs^EpAj6&5~a#gph zL~<9mki^{?h3iECl!rDdrSXv&3o3>$4EEOXOrKkF5TnuYUrCh4@5-X{s9Y})jN1Wv z+lxGRTkDIrmsWgh-TW=XqNmh6GZV={D_KLCUPGDuB&l}2rj7~9yQVp#kvN;j{D+l2 zxHyKICO9e@Zf9eD=|oE;!@*Y;PSUFb$JKjcVbm?B93>I&<#_0dOs88alyFO=gZaM8 zp{fV;|5Rrxh@<6_!ZI_I3qCC+4HEz_i(#WMKQfUBiI^Jti?Ep*3i?|He@8-P%8ZlD zCr3B$e;1CJPY!9`|LuK5fGw@BM$Ob+#$K1|MDT2Pi#5XPBOhoTeU8SP=>^FKfcu@k z^XfFuoA3Ft1pof20dX=?hiu}2fHYkQq4tE<(I9LoXqU3?aOZ>{ecotKMXb3za~Wqp zSEsgbTSMjiMt>(d9c%Ia2BM|;Tbzkp7Bcz4UgnhIkj>KA-}u<%Pmuqd!mEa6i-mY zZi0gs2Cqpfz;Xt+O&SRkzWA~p@V!V@A5*+of8}1T5xM42wsE8(X_wy4hOnt)7pXkT zDS7YEal~7=-l|*zP;;`=^n2opD#$>#y$U_0sEsl{7w%q39lf4)7*TA@XEaqW6c_|q zl;G~QR4kzpNm|wh?SlD2R$EDejhDFBx!xB=$R9=TQ8dqiN06J`Y3L-%8B! z3i}o|l-zJodh%1LjGs8M2}jV!j$38HABTAPvG-FyNfnRYU~;z|4NqFc6r{Po`g`|h z=U%3eS8=_S%$O|^sw{zqDmN~{LwZGhKAj-kT|3gi~GaW{w2hgrWZed8Xo12fEP z#n<@x%O7@GsTT}e{elmxeI>3J<={XN_Wn@xSK~f;<1bulOhL4Xf^kC?fc1NYGuq;B zySh21W}a`A+s#+J6WtHjF?nsigx(+dkuZj65$_lhziy?>iIU zg2VB*zmJ>DvePvNg7s(l6*@orG(x}AdT#>iy;^x9y`7yGdb?c+ZDGfgXVxm?QE7^J ze#H21(2TJ8IpR%({1(R*`e9h7IT`twCD>ickSlNK*Pvtp)YwSWutFb+s^d)O3*Nmm zXyfv?^zZ+atczBO?qGoS#lKH`mpx`L+w0hw*Zsj`_xzrx>h_4WYQ}B0apm^adLF%U zm)hx+!|4>WU^=A}M&Z1DO1%w5;V?tnGcJ@kcO$4E{2NN{uQvX(1ZSG+%Lj=Xnrm2s z?Q6!iUHNm)ECFjgulT^#9I+aj;WeC%6ga&v8=g$#oe&-jbV{CaanSoszcOKVBmL5B zfxFC#DTu_BoxPI}wyiDI{r+BK#M0l;&A7jf%J}+R*)i<~mkVVtRf{Tda(jp`OlCRb zS)}%;=T*#@IjpO>NS8>t^V6B^mXXVc{|)fPLcJ2#Y5Z~8m$h1&wcjoPjv z50Pk@9_r~;3Q_DrnP3f?5DgmKSYn=6$*Uy+Fm}`@Q#;vXAP;e@kmfCz!8o@-B7F_! zP#WwbbW!N+yG1QC05zp15Rw}AHZU*Yclok{0lHwwZkm0Kg`O{BxyE8S zu`*}IwPeOE{(<=G9zUER_7R6|4?VeCAY1hp;$Yl5zV`b} z_aZH!&EL5Dg3N30Po=^CqhxQ!!boU_gv0_hss=WFo}Xn|4118jjE|k zBoaUR(2QaSR5O{fB*@2eqG9F5s)NzM1%Ka@GYN$t$|)D7#8R8&41~bP3VoxZQ5q4C zt-8!ER>b9Q^(WNnh@jW&jW6Gnm^&vwx+8INM{R8OUDj^5F4L{Wu2`g*JAMJso5YLG zZ_7Ek{?H=IK`s@%)?|CbPF3lBu?24<`A7p> zRVh@l*;@{E1Aolupm};1k%l*fuC6$4&vkPGt z2bde`HfbpE@)vcR^6*?CF1Sgn_OOdR%uRnU@BJJl@gvLTFd_JLwt-%e`?aM}YE$KE7_zWL6#IjzaplOf&GcC4K)KQ5icCqzpsWBn#n87`Q&>~v z$5%6NMdd4}4)@ zd>u3U9G0VJU)+Z!IKOS@JlJeL9F|u?0VS8=Zu63b1dDF##z$RjI z_*~cOwWqHIafYp{ab}G>melsg7yXA;5do#tutF~Ek`tyNk?Agz@U906eG~MGs=zrl z!J{h!19ZEJ5DwMOMep zUv66~Jc5<1+jx=Ya(uu`Hl$)}NP}R8K!G0FJ{)+p{lL??pM0k>-^#3*zTfz{@Fi^0 zRD09ijr^1|9a=&6#L*FSPFoyIxOw1?XH;T*fCLqV+9@$cQ1{4n;}q^S`n2HhEuK2l zKcD2RHec1ozuZiyU_Re@9%1^`J>n1Xb_|8J#6mu)^9jfd^AFYfdKX*@)aD%{{W$jQ z>OGn31BLBfBe{9{X|LWj+Kos0L7MIMwzU&HyWGHAwGxj;;|@Q9bal?G{BWNDHvqR4 z{!#7*Z%RcHdz@N{LAv53!D;!yJBbQ;M&(dla_=MWu53?<5|a{7r7=*=j6uouP~MNm z(lu*T<#B$sheQ`1EX`5z2kjOj`pC^~JLM@ouN)Wm6wZdBaia)8(Lu(03%TH$e11Mb z(ekhFBt*|1IEs$S2auH`b+2I^=({ft6Wu>uI;j~2VFm}ks5T=O#WU_&4P^wl+UQTU zY!BktF_T&we;rnBM6`%!955D{1H}%O+v6$&ItPqY>k(<<_12l(%zHYFRBI6rI7{Kw-KJtlO;K5a^v(c|&;^QLIM^5EFU6I}Vh&Cd8*J)a} z^MS_|_V8hQf&pjWhZJ0P=FJ@&Pv*HNlonje7bhrs=`70E#Wji}bw4eOmfLV!!e$n| zNeVa9te{*QPlrVzda1c;xa1k#$=p*<_eFoHQ|4 zRT0#S1MHfEcFg%5YBK88$293oi?LXg5jI^>Jg0qsnS-~K>7YKwNw=4R#UdRB%beuA ze=mE6l-=r!J$dP9&fIK;HSh7j>9p93bIa7zTz%Cl_X_biZP4m=q!RgjW6+BH>P~H0 zhl1~<+lg$c8i{mRvCeBb=Yw?1IMY05OUzc>8+biePK1Bb8TeSP$HP`^GUQ&N2eY{x z243~|@7T>1>g38rUFNZ>)PXtrAb0vrrwT=KtPs5@oS9&~@V`)8uwICG@%v7A#y@C0 z(shQhmup8ATXhrh1egL!fi!7vt16M{fZplHo7j40~Oy+zZTDc2MD5BQ(=HU!BAVEsF7MM{$)GyI!clypfgKk^&B=lh^4p0!ER~TeOB{CX`sjAntiSy`#v`i5V*s+d3t? zaF&Pv3C>^fL)y9`vv)(|N8|;GKCR($@+SzQB*Gb>ayuZ; zJ^+hn)`t(zb{t(Uxtd&48AUmJG+nUfFnfRrDByq}5QV-itSy2OtJ6ZWmOwe*vG_qF zlV<>~qEUb`-~TzKY#S#?gxAK`FNHgoVDjD9nnXmbs{lz3C}>D0h6>1)iV>p-ysI^gc#VS=2-+-ulEaoO!RL%w{tC_*cw!1Mbp%VDt~-6ZbZ4y9Bf zE%dlOAiM))+ItWkK`1dN;0j>UGFHBb#fFG(A+-qHIWFtusZ7?xpH&ce@I1RT{+xzphpOY7})rO_CVVg^>gJeI0HRxrqt zeq{KFDAw^RVXfBTi*fc!A%gd_6P8gD<5-)(57iDVtQ8>7 zUm!#vb+FkB$1(oxuzH8mNy>l(p0{#gafz6r-RK4boaatJ*W^jG!i!>)E?V4=;1#o~ zKu6It1kW0r))f!jkRUoYQqET}Ohh}QtD+=8nYS%WGD_>Q<47S7L{%_O+&y=T9w7DF zLgl*%CU)(L1a62Dof~kT8`Ou;C!#>MTn*biXBQs4-YvJhYCP!_gdbIR{{h!kV9+7B ze9Zmmih9R=>8{OodGZd_=-PtJ<7g)Q8K;x-?o(2^*v^U|`1VeuJ z(>{5I2%cMIz)lO;)g=Pwub=&OOJonZX#l3l7~$2g2=YQYQya)m{ElZB zF@)_gGL=^_!NzRkLljB#Ld?mg#^}SAS&33CRUv;fslMUBe+YyK&U~Z)-$>N^$`Frv zDjyE<4-sg=+3z;~8;MTt5E5N4)URm=6FZY?i@k&tvqqGFc>D0GO!)E!oIQV#*@`bm ztehR3`&VF%Pmv_43n_$|nxjh5Wfcgs)CA}LHcw}woh|wsYqplvFRbZYYvY^IVjPzFhaU68$GL>ssJXpsIvtAs?(Gn0^y6^))v2 z@mu3Ba*OY4@%bzAd1L+pbg9#9Vf&|IZ`+7?L@ zfu1Hva_f5t0aKJ9g?*n8a$?^{bWTH(|0`2gLMWd+wBSF1WC{({JOs8z$X}f#>sd*4 zA#V+QVT$UutW@Pv8=5I_?lb%)EhWgd_?a#F3tKXdVbyt|Tso|CA^GZv`2$b;q?Sn3 z{0T`_I7!vLjF_9oO4-VHVZ(}W5-DqCnL)w>!pan>xT-#TyUG;u+k9#!E&ki8uu9)u zO|SNQXjGEHc|*=*T9cS<%RkoZw`Wruq4*E;$5#S!LQ%0^xe2>}CYMyRfChg#UtFZZ zNgN`;$T|s?br#NVBr%i=qcx8brmM^s#;WPd!cvqu^Vw5~)HxNf5m@#TxG-}+cFi@4M-8~1W@C};l zi(bsW6?G^MrZ6a!L_`>s^m5VAD|vuK#0ZsHCgV8d`*6L23m;B!jUq1Nk9MjbK2~Y{ zyPceAT)Xmt`iex1KLh~-AF;Q;huQbBhGbLNO_4<; z-3kIEhL-`7+!c=(wkuEL^ENghDb14Cwy3eF7cu)R>c*V1m^US>Jv=Qy3^69Ua) zPy!4xZE4M6Bk?*AMl+w6*7^g93VXBC&hjaN2XK*Y9fDB9LQrb?8I}j|DC8{Yl=UH36bl>wijkvyXp=UR|I&@i+AkGeIHO`MJ(=;FC0oEdz`=30(Dnl`3rCMOjOOu!BqPY>%Q=PR_;s$#d8g-bIQG7Y<0up~xG%+OMF zq)OD5c1LBYoLpGLSOZZ{VF*=Y$P7}Gmn^F~N;~OU&4hc(tW3vbhsgOn6)%3bN%oy3 zMtb;0m7E7#=;*&`KDXxI9i39OXzQmnC?>~3QW7oSapCnYGFRj=$nHiNR_p)Tmn8=u~=QA=2F)Tt>AqSQZP zUE?*EW$a43e%SLwY^Kk44qHLk=b?`NDHz7oBScO=i0iIs71PL3n+&Q8!YTkAqxamv z(b-Tqb5(2eADWmhhs{7$x1<5phcKDz^mB3c_;jMj0hGzF!AG8XUQmfo($~ej^RKn3 z`WY?4QsaEeG*_PbKfMy%SRkK00^MX@0*)HxQu-0a_df~nnD<{~U^(_pusNR^iahpD zjea#TFKVQyNl2tTOjJ7i$v>U-td2vi)s7wKZwVtK^NKZl^1|LxVk zwOu>7U_Mhi)<(R|d-yvwgS$PDsB)bJ2iYVOVPx~JI5a6t@6%~wUVYN+P_H2`#U*26 zgnKNF?HILu#(KaX5V{N^AO?jrG?G2B7^liCZ)Qb5vW^`lh4N4ea2nz=lKX! zeXO7Pm>nM;S_QWv2S@vi-1`i|x;nc?MRoDOnRB-Os&0S$mo8F_R|q^XiF}yP_PWVW z=lOpvpLTuB$f-q!7ry)zgbhhtUs)YZKn=_y%ea#&1=LLHyotrqHY!qXLFVvY^VNwB z4lwiilHGl}_fxh|e@FO~Ef`+UTe5tdQ!>b`F`~m;a?Gw%l0<(>QcPJGOxZjP*%%C2 zK`>mVU|-OMcn-da9DM6JGo!}h<#EBweYbAP^6?}Eu z(?NMY%=G5DDhvAOrdtha^Fpxp^;rH3I+wwoEDF*>@X6I!GLc&qBd1{ZSVGY_7(W4Njmo4xvZT@oQQp(e%W% zmJ>3Ml`_6*>&LxILf+($WY0+3no~BP6G#R0cVX`q+Zx^)>n3XgYq8(}1RB6)tgu?3^aIa_prweF@)Z1Z(*qSC#HYG0j>r z!gZ~B91_G6A_(-3?_^J{g5sb(kB$Hk!~hwlBmE<2Bd`|)L+Tx-eg7LkN4_8y;N!V*A1ZMzRs$eriu+psvA#CWOwV0 zYbc@%kIQa+o}GO3CCalWlP*8_NK!iZjEw4t;t;UAI;ql?nO2yJ*YXGIQ}O~^ocj~5@~hDDWPf$=#qQCjDTD8JY`gNr%`y|RiX9M z^0TrXd$QVB`(A2rV4aZX#MH_A5exo86x_LklMP1{WY@Lj*^XzzyitCYzO=*|=Ts`G zN1Lj7tU{G`SCNmk8-mC2Mzl-!&*&Znw8L()pZPxY&3yOpgJONXfaSrmbvJ3gGOzHNRU2R#tEr}G^n z$A5&_I6CQ4xVtJ+E6ABEoxo4Ok0TnC;w~2nIvK&-Sv0|p?Wn)b19_P3Ze# z?YFr8vPO?n%}f+j!BIT|tFAI>AlrSe#)Hauw-VdrlGz7;Eqg9Y%2H6r33uYtZ%Z%f zQ?SI|{CG-oC$j;v+f8Un$Cc8{RVvn~dGJjn+D|Gt(49)Xs-(+req`W{Ja+|+J{re^ zHvd1i-a4wS?g<-hp}4ygch}-hi@Uo!6nA%bcXxL$ZpEG8u7Tpg<>vi;_q%`HwKCby zo_R7eCue0RM=~RivFkU=8R}ZOKVdz337FSgE)(j0|JV^W_8~gB!_6Oi;vYR>6`Z~Q z%%5NpIb!-RGox)Gh($x*sofbpe~vR%V^yz5=hOEHXI55gICZAs37wlsSU=CNex8-O z(S7QyP1eWQF=6~z7Sljg#C(2~eE!)E#m-S14#p{F0ZpQKGF`Ial``%bmBZDkg!~ zShH$TIDW1vDs3p(25?h3iI?6@h+OA-sI(vA|Bv;Lh@)H+EDWGbIk?oBpsMMYf_B=1 z47FP2*kAn8&-y{WGZ4LN3cb6N8DEc^a;#TO$Gk9>V>)@vE{*&8crLE}zO%YDy6bO% z96tea+y-J*GU%UQk%&e1o|IEe?HEffpm#a)#prgnFFVfBT}3atJCYXg%4H$PhX26{!yo#-@hp zA;1>E(}+;`9=n}$2I(t?eb8*R_E(@8m-sRC>mQ-WS(w4`9O7TuD%@NdfS;%2x!uEf z)j~rFiBebZAs4;T{;oMUuk46;Yd)M2vt4z_kwh^A`@k~8GT%;nA#Ko@7qvrgwSP3< z4=8Nz%vl)6OH4uHDbGH8^MQBo8!LO)xzmGLtayace(gNrK58eXXii9OcXV6m7tR7X z7VLGzvT0PZ+&+0XLqIQCv3D*no&@xPqy>SS;YPCOPOE%w3~4ZH$!j&bCi9Z-a^Y3X zcD_3RE4&x4^?ml`TelldeeVg*#lu&!f8j6C8fMKhpMn0@l}vG;8qcuq=OdZ^3kn^) zY6Oo$Ags%Ujr{q(Q3K6LwE^A_6+w(C8t{vdeElM`Y!xmju#w64aeuY$-C7!xE7kVB z(KUviI`_&_@J3n-#3&k5H#*|Z|0StH;sW2Q7is+-n=*_|w)iZrU6fogN+hdlnCPcT zffQYW=ZjIQS&}}_tTb5xZG;6`eJYOq4|?vBVjVFg*(zPGTcm|A)GgSG>s!54nR0Vw zBU9>!0opox1-J@@9d;Gj*ylD;YdYQ=WpMSlOPrFopuH&EN4F%t^qr?$;sDcu>DD-B>1V~Q z`9O_R4a@XXjWd9y5TG6~W}SX^0J>SXe5ZP+`sd_ZX$F5 z)~)Za=&${~es(2)@p9$lJi2uUTv|E31qP({Lfje-5;`Ncnmr{x?{4MaTCQ$|=#jUd z+Xm>|2Wuy8SGijfpGw@z+eX)w%t@Cpm8#PXvB_;P*{-Q<(6XC`J!D=mzFKu3341m@ zaPdgy6^$ICdRD2^`cs5ksof%ahN+W>PZInK;Md8k9yx;LQGONGr|~c1n8=^Vx1PSW zxV6xZ{_{(}h%iOtFKZTceX2?8Pp6zeYJ6nWTfJeit{XdtS{yaxF%vDU#yE~6koy;u$u033zrnD^of9Iz)Fdq z^NOLpd@Wop2JxX)KbO7KDmYcEHNt_SATPNJQWwQ~q}DKP(CFNrV)!;DFFJ1#F`{c2 zuPd|56yjN}`Kl~{Z<@#)g?2j6oY^YFcbXy76#2(&Qk!R-XB__;|11Gz^EB(R>+SD5 z@jE!4g&Z?MN_$p|Z0Dn2&b>SaA2Yg^g3MPeIGNFhddKL_nSVBP?U>U2Sv0cfk9?1< zom>CxyfFiNA!VbCV;`=7m*9S;z^zcdRXxpw9CmsVnNbHUOx9>Pa)67NnCdsQ6nYwI z#jj9sL0(Yb>fvFHyU3!@#DXLhh2bEQnwR)Mvki!Y=-5X+fIB%`Igo*oSCxEjU)Afy zx97ACG5J*XEuve-zQX>Lp4b z`Xi2OX4mGsnyVt9(`G3aNabGKrM3mMQ*N(@*_^J*_FCltqAgF}E%hxY=cz(2u_#pI zEFtJSa)`!Wvn@+zKG1Sbw(wez*1d9r5rW*dw+2QAO1FCkQU_A? z0lT9G$?pCR8V>CMfm3XkJ1=N~Afj#Z0df)hdW~z3xmj-p54O`Q0U|_LXpi@xfdRv- zNJB}MO>Z_2j;DAonhaFg>pVCrsN_Eu!HfgySDl954O`#wFW}ughseILUp+_Q-2B-? z!&2IgfJMF%&WZaP3h&>68vc0V$xE~#p9)N zPjwZ0DpcI=^%=WO)U)MH?`3gsu)Q%qGe5JvWC^g;u-9(UX~}++Z}Dy^=Ms4Fa4CA! zzaKia*q%6jJ4Ltmb2NMC-gn>1zUTQVlfgRSKk}==;~MduVf#}c~x&ycApA(%SQ!hc`eR`#Zk3dad^C79}Z_xTq3UW;(G(OQ|9~&aC2Ac9FP~5OF^m zBie{(#a_vlEABsTl$Lp+5SMRwlJ7^Q``6a)Oohv)i9Nw7z=>onPe{U9U zgE0K4%|au4+Jlfk-7#bN%0tL)D(zw9wNEM^r|{mmEes;QV$DRyqK(Y%Dp4SuZtrg4 z4SnTsOr4;x*M1tkdBrCX0N)Jv``t8NHiaikM&D{Bn+L|4>l~%pQ^24VWKLW60a8WR zsHw8`+`rg1Q8R7Jjx~?gGVvQ%kd^?73qErC^{BFAHL6KWA<#E}ZM|Z#8P{)JP|edG z)`@3Fn1Z-ZJK|Iq-XfodePx{X^)N8h&eT7498NpQ|73jD`Jlbh*F86@cqPAs>wPzW zQ})}RLh*0P@tv}1h(#BeMm%(AekLrX_A**XM}Gp5 zj_Y@gL|LYJtZ1vx!1*oI=zBVhau@v`cB&_X%y)OkdS^HIsuU;pcE@Zve}>zsu`dve zW_2@==>G@C3*?4;LbzuNbWCl4y2_Vt+5WYSg5h6|Np=-YFw?g4$t;LZ+B`PAYFRPZ)%a+mcxe7I?KWiU(@|XzhQ?hh*Jaaa>kN7ce`eVg5|YO@6BFg-OIaU_fk`&s!K-VudbOOn1-Z^XPTa%~cS;*UeQz zyxZL#n0`5jB`;AoC4@(1)gglT0 zs8%9(D&j$5XO4|OFG~E3>sMtIwCyuqbnG+o!ng>E1M8M4yk>gVd&0sx2)E9yGPstr zrJ4KVfBe{F2I7?RI7Q`%=1)EzzTStvDKQn+mn4SuHhy4Cw}M3jr|O|)^+lm&7%WR* z+5GRv5GdcW6)dq}2?t9(DE}1YNgT@KM-4ng2r@X3T`r05b2$f&ahAE$rUqSp4y>FvT5tXrm z8eNsX|HIaj#c8tid!U-Zwlr5Y&TUUE&ux)dHSnR>0DI3bbLf5H$gi@~!1{iYk4A1Y za=WtA9b4>5S9)ZG?S9_nejY1@R=ub^?J!R}$lIFgamjd7rMa`b41pZ6v^(S@EAWF3 zb-%#)v=!d*?IPt!d@h*1114P3eL!_`)!0hh{s{_rAHsDdjpv0azI0r@S9@2y!oUrz#0`W@U{gf; zRVQMN`a4hQX9Alll9)_brIF;o-;xT#OjC(t$wT~7aZ=wJ{Aj1qO2>wr0xA--qO6cV z$;+m?;ap1_9c(H~E-lVsS%EgUbzV5NFPgqVD>LfOipTBnzRJ@Yr?J+B+A#}$s*`6w zK*`#XHcisCB6>E(G<`toddx75Nf+RsQ{w zajV>-@sD2*PI|2Bq4CULmpB8WfMBe5>L1AKmBNg%C1}R>VMTZU{~tX4iDPIFNH0kZ zmZEuL7)}gX3D8+C6079v$qNi+2?(-U!n|!PZ4ra3D2zDC zObltUQI{t3#b;~-tY!#WL&ek2Hxb$x-^#iZFV$}qI3z@_#VN;b4t$DIk93c8bR!k% zLlqk9Ju5xfXMj!s=@ywGxO9@$BlM#dO-gXUCg zF{Xnoh@w^z%f=})hC94THZ{IwWLoS=UDw7g+&xO5vZgjB{U{B#5#}UxlVVlRRrO0$b@_&HvC#S|AoP+AeCIF-^FAz?!8q#xaVODSLiejTr*4`K>Niy%>$S zcr-zkxia0*DsjfFWKv#~H$74Q>zO%;-Mn07CXjqsNZlDt+eJmVeI!ChchXRoezXJI zNSA)5BW=7RZKNY@x&vE9XIcHQ=~O*to-uizkuT8hHNcpuSd+m4B7BpZNDN%7Qc~o; z@bo9F_b+e7AL|&W7_kpg52Difmc;P5k-vUBTzI0#(4Kig&QYk@uk@>kC#a6bxfqVg z54)djr9dpL#wY$(B4>2@nXVjw6D2wtO%{W5CLC21p;JPGZyuJ}(1@Ezlm;(D`u@Z4 zmy+QxtrSDnB3P4ObSA&>O@5&n4oA~Ct8&A4j)s{S2_c^3esv2%HaOg+rMI@-frpxvS?(Yy}3_1YSptC=-6L*0OsKtEZz$pyJxcc)Z3u+ zci@|s^yQjac7VI}>6)F#Hg?Njq*ba~k6VUTdOuglvn-{YYAcsw7X4oC>g_p+dbdNj z?@}{O+_1~+iC$TpG5j^Cyl%@%oOMuI@^lOXO%X0jP4O-3x(%S;>?2cb z_L@1O{Jl*)%#GrmoI5~3@Twbx*{3Cd8Dq6Q&OLw=QskoUZ;8kA(;MrDpY=`zaZ{cZ zRl-QQ7fdgfqC1gd6;CP$!U5k`^U~+6PeEV9(5u6^!>!t<%S2Cs&%5Yj&c#`mAH*bn zu71|^&f%Fe?9=&mFNuoqJBDG;Uwr@cw=Rmdc_Wa^6@l6)eMXWkYNyBP56o|rWL_`o zZMPx`go}qivd?bI*_&na-#k7L!-$M-jIqpDiv7wVteYdO{1JLNH-!L{br_<~#DHQC zp{H4PSLmJ6RNXYQFOw`5VzyFnb`5-vc6W_+&yFo15@o7?L4^II+{9l;>yNvT&pi3J z)rmR#>X|Qkm5t)L>E&K@NnWM42V|vvAM0%ul*iNa0$8u^GI}EgMhJ1|`_>6X@4_-s zcWC)d{dRIr%~YndLoETa*Fjd1PZs@_+q10)iw|ENVz43wQVC;fqR}tN;)?e2Ctd;? zE#ME{U~U9Z@19Aq{c}7JFnIckOST@qIe{zU-hUkn42{Vq9`P3Okzf<#MYot?v$!pP zoMP-qYTw)1;1BJycLdh_wDv~O=!x#EK>hb;GNxfQ_Ue<}Sc7y0foKqxoyd7tcySxC zjR;b?c9vx=CN>^#F_PVaU{ygbg#)FSa4Nsbf&bEsay5Nx`QTOJ_b1J;0LiA!t$W*n zvm;q=3VQFXh)^8zk-6E2&(6?}KZUboH?;-ls@7)(&&TkU!nEVxUaG5_Y$OQ_W1m!o z+H~=80LHro&RxYniANM%6ZrX=pvQcLf*2Jq-zmwv49|6!qbGQe;`)pe42zZQtLH0d zlAEyLsanNWa4QCdrd*-H#~0p4^yUc$76YoSpQC^9iDtRXZ9d*1L#vN)Z8#;SyBD17 z-?ri((|1oI*8;A%8Xg~54wz5#YE|67wDRFsTjh-8Uyhx4?^QOO{H_mJvnk6IDPuiO zs1MvLMtGdeGlyYr+K>s!6P%ih)5#rGmOLdT{HwZf%5L8d}K!5ON zd=7eF?wyDvGE}#jkLnQWLVkBqS>VYtn~U!ohJAgDSW{RFbd#6tb%*M>zxnK0Avj~< z%C2S<)%J(pTYP#8dyYDQi${4k%<7!Gr#|<8SM3mVtMZ4rkJ~D58^z#5F6e#!cl|1% zP>|B+io`HL12CC+c|TlvhVOPWe58(BbYk1FeLLwMmcOU*PI``i?I-X@xA8TfGXNw( zSWE79uX(Wby&3SdV`+{lH=n51Yvnu{Z5!q9nbu1j^_8&tZ#Xt7a2l4;4%;EsQ=ZiO z-3ScAjHDSdqI{biD+>JBrA(A}Y& zWq9C0o>Jla$kY4Vckso3%k2Vh@`C=?_#M1+xFGvyYq$@u10%V_xS6*DXR8RYz(_bq z{O-VJ4dvKyw>?P_&M|;q3yR*MK!*0xR&>XwHoCe-66w-CVuNDc!i@lIVN2vwTmV*rTWL{nnf5j&_-^ zVvQe+Rt9>`CNS)Glr}!l!k-2E&dhnUSj}m!kckP{H8RtmuC|A+y1552g0iQ>`Ybr| zuV5pu)EFVgGGVS<(4JgBl3D+lm}uPUWK2HYog5QsZkY=Xab=nFQm=5JtS#<)9-2Fg zkZL=_NZY1^w=w@ak#$)H%Cz$_FMG82FV3sq{_g$7Z0_qnsw~~Zr+SW=9FVn!_B)LNJj+o35m=a?)E`fCnxMuhTqmX;%iSR^a8k;WOXc|!e5KFv z@GXDg#^Ph!tlod5Cs^505cwyA&`R8%mZWZo-gC8jggMYnlRJF_zY995%z6L7)p`(m z`%y&KUyS8ZKYFSYo4AP0ooEeg_GRd6BRanL^`rNWpZ?QR9;@$_(&$nCt8F~_w&Je9 zEO%MCmHp*tH%cnI=kKI`cRz^kN-HzoOdC}1+1~lydGkM+Lyz0THuOJJX`uX{*PQO3 z;Ku$Shqs@_KJndHLHDXG2#W7tW_cNAm4mBM_`u|m`wNYiJ$*2WXRnxJIh;W{<4l0B zEsj2B8Rbd$(z)zps1$(#a>f}+GE2JYFW07 zS@f6_pJRUtsU)#fS}#^-DePQZhB}QgE#~~PZ4E!~<5*|;6JbPPUtgPn2o+@komG+l z=j1RqYn*z7#t4NrZCRAneRc*@*&;Nn${&UABMdiiw%E?Y1nYFY=mv|NtQtNte8c># z@ote&#$W%rwSHe9;+kfZeyw3b#an?QTY?p1c1}R`L`XBfM2HVXO{4=lWnPbnRU?M^dTYU2@7=S0RMyZ}5Hej&_OG@#P zW??N=ykv70e^JEpAsS^3RXmLihvzS`>Tzah}ULtwxO2AjXZcAVEAVICx?fv70ZY>GuXs0hYI-U;|6kwhZm38Y@oS|V*86f{^V z=sm$rB0M)0%d=>{HGXkV?O^a8)Fq;KQ=&GH_Ffwm=P^-r8u3+RvY-^#wAE$Uu)35y zuUVVdIAVDLZKx(K4wq;X-36WeKZNH3*A>C4t|alt6w7s3v$}$O6zV<5Z-2P}yym`9 zM|0tjbMjaV24+ljD)OP)@Kp!wP|q~R^WKvVDle) zFbGe)kc@j;1t+5b&gy9j3_8`ZBz$bt9EatrqYjePMjRo*W7!B(tn_Ak4N=@{-SUv5(0|O|V1l1D$YFC9tmXrNJt2TycK-zfAz(fT{?Ve^{GhJI zn)8zGKhO#WSL)NFTgJ=3H*IOjC>`3%Pg5}64W#E&5CNJ{-xW$OWY^A~D^q|TNg;P= zsB}=0DbiMlhIWjiOy&UD5_2Uf5_@E|UtW}dFxAR{n2Jaw+TVC?SspnG%Q955zi#~~ z&Ng>J2((Kl1sr*lLLAhItN|8c|2nEbTwRI?Jnk>2bj?Ag$fNA1ifo-4(TNKLhK&S< zWwGVXNfk2q@iJ^kK?lz}?Vr1pyxQZJcg^jUH%M7SsmMZ7B@_nb1kO0C?%+X$)Q-UFM5DD~ zlmC_@xv+_dhnZRVHsdF1!P}g>wlw#=^c;lGV*uefYj}tyysaBj4(U&MU=M##Z}=u> z^u{>xv=MXD4t-$HbYL&Fdu5}l9fNZ~Dw{fxV*k24Dtj%^ z`QhU)n0w58jiY$Ve2{McO#Z|u-N+0!b~_H3 z#`i}meX)6OO$mEG;BtBceLyd@&VS}cJ!QYisZPz%RM>R)+YlPl}>` zTDUKi*4GCtGptpORJF>C8mem2o~|1Cyc$xQgftE_#uNjc74dD}CS>Vq`t!lEyqfSo zAT!^nbx$-`jufQCZAs2Bv%IOFaB`*yw`MY)*bK927RgB`f1T%!-I@e?0b;kxDgLn+ z5$pBoTm@<0j~HpnlmF!29unR%S(EWiGF99NuBB#8yiz*+6r|}^3iFW^3|VnYM>*)e zPl+$c(Qm?$K4tVS4jDT%q3Mgi2yXsN`xJl9$fn(xnO4Pcz9XrkhnXBu9h;d;iNy1w znL$n-qLC3~W_>tv;K{)sM|1jCcW23izlZybzT7t9)iA~ohfehu4whQ_UY18nUUYl> z7Rj3Qlm0V0X(z>g??ROa%M;u(L(*SjCg7;siHboefq4Hy;?`evcII6&pZui%*7=!d z-{3E^;a%w)G^g{CZi{JNPPn=+^GR_o!XX45Db7TwssU3{bOM6z*N4eNwv;wqrto*` zPW+>q#B;;X>^G!`>?60;iv&IgD7T4R%UPz*cs9oT0^VH=(tX-0*kv^_HD0r7#8fGe zYT88MOH~Tp&(?lUIu&xTp_E;XLoFA-3cm_k*}7`oC9J9#SP;@x#l&!4>D5qK4?Or? zHzDR_vW(k$Sjn%+sU(-Mt;!+B_<*N8)`VSUtA!xifE{AU2s@yS8q`Yi%|--vB?z@9 zw28r{@b~0@Iz>3}0AmC0KhdgKX2#e6VqkBxA!Brb`ifzusjL z%PGMo(svfzL#SX8UR*>5VmKlZo}M86h(}~Ea>C!xj9;?@-vbQ4EF(cfLnb2RgaHE< z5k)5EzVy)JVk1htE$^x=f%12ST*}ONB-hY?i@@mw*EW0w6lSHJE4mFc`LslEqlL3E z9*Dr>qKFcxV#L7QnNTn$iG%vR7b=w~$dg1|$wtUVP7$lAC0)rW$tWv+m6(=L?DHfN zq(G|wavg|bDoZ(~oR^UlXO7j6dNP}zMD64E;@Q{u#iyt=nVE3w;X)93IyoO15zIr1 zeEjV@3-#(n91n#tnR-x`*2k~T8)_p)e=?(I4AE=q5RJ2H8VQ5i`m)7)ju(9CWdP8o zvIV@JWh)wgOW|D(xH+T zW5l2|%A^rxQ8NDDq;!4v7e_{9n>iI-M(`+}MUKsAQihqN#y%EXIe#?I5sy^Pt?qFO z-V|*#YdOPA4ja7`sNZ54a=Z#gu$t%zZUm>=YquE~I9mmyq%Lr+^*>|28p;o_vBs<5 zfAe5=Ezs_7bpc6}zDSyMNUxd&ZKb-fZnF35Y zp|sq9v4kS~HJ}|$-my&4*`n(1>x}k?7wa7Wd&)qE&EFR4Lpz-RxSog|plV)6ltJ%D z$^vkv)oc0cFK3|_)?q9Mf6i9Y!1PmT#Z1!3&0DZ}BdjRjBPdIA*{Cal#}1i&9cbK? zA*(jRXV`L-IjL^Sq@(3S+WW=1m7%TXN!};?{@Jk3OzXU`&C zfFsntI%84LdAH!cI(reKjd+T)i5((sfR5u^*4$4l73+6113*a&t%mr|w z599)vZtHH;9;^TS6NaDwPtYZ}3>j`0;X&Sxw(KzbCAn@~wkvMqn`~Fv#-?rDEhAV# z&?Vq}8lCa8-2&Mct@&hSclu|4c6bmyj!~U%PNx%iiH6=*bvR=0Pqk3WdyIUf~S;s1D$ z=4qa{COim~K4e0H@8!2Dt2*YH(^E}f*(dqU(-@E3Z~0OTpUv2h(>te_?=lQH&HUD) zp3UGoRhdS#CK*s1CO}RY$_&lF`=^@F*eBhb`Zg6}!Ce5&nkbzoqBB+6458Oz@D4|&NOahOr__8LMDRXE{E0rzl%-6K0wigh?>Q*h z2tf$D>@C4U2{^h$x^XV&C_j+u5bA!)*umNb`08d)c)>F6k#2@*?-LDf4G7TeZSU$I zb}@IvYkzx$c_c5Dn8Wzj?k7tAfYhWlNtZ4VGCHt0un1e5KNs~5#?D`_1K&e*A5d?D zlm=)@Vvt6Q+|C(WOzrpfcUuklowV{vnLPwN2sx93xlpw~3q2bcSHsY2KIdpwzh9J= zT?n<9d=}!pqQsJmP!#As5aWv#CDQDZzJ-q_k|mNgwCn$pc_7nnz?r90=2s>V6gQ_p zNL#z6#Bab!B&5Zl{W-lSrYl-`!BaA5(Gj#zOt{NaB2gcwADi;Mm`geN)OLOYbsMb* za<8xGQ*@PQ9nT1S6K06I5p^h*o3f@+ISu^T(lxr~phP2_zxx=27Ds{YXB=AB;b(yP~*|EA8Nfz*eVz%a7fjqm%G|YG2J+Rvi ztdndM{OS3g;0H@9;G)prc}}frDpbh(3a7S5%^#RTy~n6(W?$GuQ~=Yz{Q|cPa`u9q zK@QDV#Pb`xqnUnz!&+0InIsbRd_c7ZvU(v7HhM9Lo|7(FpzJ}s(gOP)_0rPS`J=viUqV;+KD*^*?p0=Cw^M6B)PMvD zu^({|@s|pMjEwA+j0yHHTN5%Yd_+KnB<31vK!D}k7bR6iVa#6?6_y@?l>8>JtfLY! zq~aLg24z3}U0>X0dsqrGsGmP}y!8z7>jYbKc^{W5ovW&<_X+uBB`HQ@+Bg#|+`N{tNJly*`2Z; zv!pi@3gVK@EVP3mD7#dD-1F5Gs3Q7VG3Q1%)bfaiYzedU59p>O?NcR@?3w5#tQlYQ zo9zod5OuG?i$U+>-Gxzt)_^$2L+GYgpU#iAY-hwl*4Wv&S&;R{YG37@$nmP$&%jv9 zIMPq(pqw=)aW!MLLa5&X`6P1^#IU=hMqn^~jaPTaGb%LeKt7b-@xe&2GYa}M;lMWp z!0nxJz}XR?r>sQHU-}}l67Gm(1688E?@x*Wc`p*#j$wc9?lk!m{9i}zq&=E26TCFm zoc?S5uw-0$3-08-V8jzv-M` zO>bI=zNJynO5)DomaK9rF8I;F1b= z8h2PZ$u7$%;>nX_STSzgac|6#2i}ll4Bo5*gvn(gOXz?nTK=#DTe-XucP=Zq8_Hks zTdQzmV0i326G~t(?7%uik`HB$G}IdN%rgdH)tz;K1l%EnF|+t2-elw2nNLk3wzHYT z4CNxa!&ON_%wC7wXr-;@uF6F{xo`iX?X8uofqJa_l`zuhVZ8KM!VMwKGAlOj80mQ3 z;2lX#`q4?-2%(G9Ae)o((=VFAL9az9WY0li0gB+rQM;clz8hkD(jjR~=BovpPr@F5 zyfXxoaYx2pG9thuiDnnPCj{zXJH`(}0{Cz*F;U;??@XcChTmUoA&A-l2AR60I4`o& z2BpNxq0IFSIQ4X9ZwehUDU_HC-emq^g0M|#l_KAa-xu1aKh4EgN_n*p@TeQ%t-w?^D zh}t`-34@ac_Nc%E?V2q^}z!M6LygwyR*16BKyg4Vj@1L_*A4m$ow0G6)z?SI&{}RK@ zKq^6vo|?*YFKS#RK~T=j-^Yiuc0{GpoRV8ut&XpI_Zn(!zS>%XeEan>mh*ql-2Zu4 z@g=qIl^`ahMoER2TPr z*?Pfry06S=wKiVSj`6gr?1g4uSbUj1#m}o;H!53~;<~|_hq=p*MhIlcwD zhn!67wm8BZ0|H-!m03)X2mkQk-j!ADRH6)A@L*zQ$Ogi}i}#1&R>q40Eq#BOotdyy zhk+UkroNfEL(0!le-Q!~1kt_(oFZ{klz|8ttiD(2C zn{ZI*i|A5=q(R8i$gVu*rdHV7Bnazt3*$xl-VW>7Ma>^wcha;jb9dd#kn^-pSYS3V z*vR3Ua;^`Ky|>JM#Q^%qc$@2<@dZ0&y~I&`f_4wl))BbnMD`#~bdM zJN;*dCm29VT+hC$%$fnf^Q!d2p+O~xXB%VBILMs3VL0{(6O<=LiP`mlcIMwd`0qKH zr;dHBIpY9t>PGiJGs2%Zwt9|Z*A!1e0fc(?3_#}8Im5LVD@*wu*WrPESTFVpxB*+S zP;f7QwNP{x)c>WtL%l-{8!Q=o)4vuN^qDp6wP4$EJ@&@F69|6JoAjBzeyTG(lx(o1 zFoGi&RNTFHHfOtcm@%s02?c%70N6qNV{NHy{cBIN+=31c5+fq zGA(<8vGXFAh>5rZqSN(Dx>QsSJy+uQ=f(v9h0NGd+1E`{<&xRM1YOkrOEE(6FL!LW zgh_2O-4L3RsVz80wJoFp`C?fui9-ZdMkHpKKrM#Y^ke7-U!~a}XPkeip{{KMh{NVY z@NxUOgx~ehhAaQd2d3zj{5Ud{l6#}QcZZjHCYzHIrcQ7}RYfBd%_8nbP&h|emobnm z{NhJ=O-%B;r1BTQsaIvIc(HU{38xpO@vV73RcxqyPRPj9njYg z$aG>86<<~Y9@`NH)Lve0Zlw;X%;KAv1KtrkaV89CzNe-`KKZ7+X>6jTluk?tPedoY zFitdmv7-cDk_pxFWA@L8ZcV3{-x8R~ei4E;F%4Q!?qm$;!Rs8l{ZiVyz#3pLll8_S zDnY4Xg)S-bc|`VnCGGbm`eU-&R70>Nl( zdYDW$6$tQ010klsNb6h+5=m-Bu{JAT(x9ZtKt5T~%>VL&)h=w_6i8qT5p5#pTY&91 z?$jcw#i#(%<)%bKuA;ZxWG)e8kS+#+g;WMxib2ET62 zz)^-5Kv??4-|~y~cd|3dGrWHH;Z*_TcRvFBQZtfLSd&LoQMhgD(jb>CicbE=#BixN zF+B46UgRAS`x1i~G|x&uTJxvL`$-m|^i#@=RP9qnmhQHd`cZ-LE zs)4+0vE{Wo$@Qw%do$bvBqOYv@=1`vsr{VVP9?@nsZyG!SE;f)BIvA0e>X11vlG8p z4)nzSW14vDeCJCGi6gVwrCEeG-m(6%1M^)+I`8Acu|DtSB==(z?<1SgR$qCizx^%` zT-W&-Xii*)a8|ibypPJZ+9%ZAi2~`4C7i{;t!Ngq!<~hQrCa#*wK4m8N(Y+7Mv+s) z8nb_T;6zF?3Zq{%+51igp8eYo-+HqIRINz|G`KrvWW zhO$sb;n}8u8O?l`asDI_Uz+FY^#k9MngNa#!4_eu0l5(AHyPa917I%TVRxhWYmS(X zW|&F`0;x*SM!L6~Pt*ny=rW;R+>7}%WAtS@p-Cp=Grh3}OM})1{&$@+9mw&B>Czu( z^{Ku&w{IjIP(eGoq5X{&sQ#)fnlK1)E%uESfj>pQ+ac>;`1QA0<|T%2v!vg;+3#r= z`9-fORTJiaeCuQUw!z-Q9Gm`g549#?&LfE(7|yA7Jo|UKccp;uXZvmsS**rLC+$BI zBwqS&_KZIk0fW@*@<np^KfeC zVGW>?t*m7k=T|FSl|t(?Oh#2~x<#*WX^y$Ff4}gbr9mrM;a!$<-1rPeKCe?6b)FTS z>g=jDSY)o)%GoyF^gM;6kk_TO$YnID@s{PPF*LP&%GTjPjWop_4WVzncwRSRG?)`N zAnU#^sjaY%jBZQLQXgPA_h)UG7Ny=JrnRLv}(jv7pdAsY5n17-TLeaD{6#$^hXorn5U{{5fS7Tr6pAp zv_~mEnqmJ6`h(QvBk!f9ckzVNQbr|tN^(^1e3!1$@>BCoKBd%=tDEXaT_<=w<6<)9 z1>;%-CeREjd7Ls4`9wc{4JSJ1*Xw2~Q$41UzTe81q>=iXm`QbJE@;&d{k}FUuL$cRoDf$a@;pgrmfu|lNhcf$AU(&aCYG#m?3&mJqD!KR@@`;j)|gj@SH0+;6?* zwxba03#i7x^$d!`xAT?hGs{nKQ)j;VR=OXysw;JSiO-BWgQ6g;m!>BH}i+w*D@)M@^a=J~LqS>_LWif;12NvytF z`I@0Ax(pzAhjZ|X}OrQFfU*%-$z zwVTWri<=jtu^*RjolC6KlsEsps&s|=0{8x@%?Z@Oca5ouJa*8X%I`zpdRhL*I`gtbx2zATmvzAUBi(6twY$^Zc2Bz>-D3~6htgDgxP2GhZ%?;>PBYwX z?z^;JQ07UIIJHwm&Aj!Wz$?)VL7bOJ<(53n2<>h~Ea*Y|D*GyuokR>YyPvq9h%|-I z94XV3W0aM=i|EIE3HmC&^g?TdF$jM_z$+0+L@G{HoJiy+@+*!Yh}TYpTPkiTKVE*E z&rvK)EUfrD!iNZ7Bh0ColbD*A>aROtC9HJaB9Ev$69M)6>rTELTi_g^ADDi!*7j!SI^@UWr_*{)3>fL~_recjhUGPlsA}wPnejiH) zE+@*^3HxmPPCZNUS=F;l^*c>Bc|o)z>TZ~5_+52#-@Up;y7*pI-OPW~T~UG{XgY+j z3t=C^9}%ARg1~vtvV2eZ9&v^?F*`B4VlKiv2#^sWXDlZ&Wtx{`tP_uQoyU3|9_s}> z){8Nw=TcjHzP*OJySp&52ce9KGMF9BE6gh>WHvQhAl}k!g?MZ8YQ)=^Z4kf4yaw^M zs67LXcHWmXeHI@RdHdX_^XB?u4@jK%y%7!+Kf%@uZb-)^CZ9u^@-RxtIK>Pu74&ZWg z4d8n7Manf_GPfcAu6c-Z%x}zZp-+#SrzpqDuyQDa^;(|Q$LfoCf9np)vIbhi5T9sG z1$@|g9GJP*T*T*F3jvo{pvqcrZJ@CAoV5|~Me9YtSFIg@f{#(_zb&+4ov=mI+1TxEJR7@%-2t$Z-3jnU`$oWSb~lpk z?shN4Z?o$~A* z_M5=(w%6c)N2u;0k9uY7nzRUhJY+bFyPM#RdXSjLigG9$P_5Y*p-e%8dO!_It{X{Vnzl zBx#%b8X1tPHv!*r-vZq0?gf0ueFt#AyPvY%58MwB|Iqyq@PK;&@SuATP|Q81`&;+7 z_!svtWW@EjA*>6@74wtSS=vsa%9{hf_k1JH-$559Iw$`_ zlj8^ZUeGTSp^i!-yWvWBD%BC3$0cv@sfa#u#G| zA8V8WKhA)KXxweUQ#U4}J(=56xjl{Blej&Z+mpCGp=F$ZLCa*a){t2XC_K(JZZCsJ zk;?65vD9iTwPBXpFiUNirBh`&3y~}zh78H_S4vxa`_6NNKkh4eI*`v+rXb6o2l;Gi z0AgnKO67TZAWJD}NSU1F_rD6FuwDyUc1TEwcYzf#EAy`kctt8%` zN9LKO9}%Sf4fb9l_}(4Z9(E6mnw}UhlHJ?xgHh8L`4r^a28-ZT_f?YJ?e2EOU&DBj z-PhgMk-Ed(fw8mG-HG@c?i)OkSN;nl*Y%DRBATBHj+4!lk4Dsd0a>Q2{D-eIecmna2#!8f0Wvl{5SQ)DEr12!; zYm7CB3*8Z7i$mzfy0FZIeGz8+BFy$hm^Dil+ZSQhFF9;SgxPio!)llhziENB0QS{F z*bb_-$XZ0%)?#Zh;!CV0z%PY0p;|9kF90uWhg|EpbsX^%)=A+1X`Moza;t)}ZL$ea zvL!qN*;Wu&Z4L2|jakjkurm?A+%EBSs?PRBnC*)&+ZSQBFT!kJgxS6bvwaa}`yy=L z2Ad*}b)v}@MA)8UPeIK|JK|d#RM{u&6Of6M_9?{6?Q+B`Y(X20c6f#45UGyj$dv6U z4rp^i4rp^SoD9S>olL~DoGiq{PB!xAI1ylSom^n@93AnfV<2uiCgPS8L;NbIIpQsx zmZUhXoK}dpc3LBTHLMlQY2&m3<{H>6iqp<%hq$m@6z5u}1LD^?*CF1~>4^CC&h?0Q zayp^Z4bBa~2|AGvGX(LWPATF$oE^yjrt>D?Th3d6 zdz?MMzwNvW_@46~;IEut0q%GH1F0W6u*scYI|l(jc76*e=BfzKRZ*U+qC8hc*@ntv z8!C@&s64iz^4NyTU>horZKyo9q4L;<%Hz2$hi#}R+faFIL*=mzmB%(z9Eyb9k0mMR4C^IF(ls#JRpP={@s%cvqwm6#;t-Y#l!~ zpIl%&h_x8+gyubBJqF_tB4!qv^)RaopGSoc(}6-5Iq*#2z5E*U_AYoSVwX`i>Kj+0 z)D6%e!$Ir4#$@;%bD%qfUGOW6^WPc2hj$?AjB;%zMtEPc&4K11iea43q`3KrIh(3u zw6CBV<|=bF)xwzHKy@(YH&I>q6z@_!^CR;kst?cN8@dRd#c^r?&mw~wTGg%U)CfLB zf4Uex#XxEdy)cn3u_jxSsR*9M!*nTo7ERzytf$MY=dI_d7=Fa7bh)(y-b4xa>k8|L zb%d_8zO?>A&Df`C&KjWwkMmY+%e3Zk+m?NSb{M^5sXeUv19YwZXZz380i*X@x(?$l zhdMgVF_x}ptG+W^@;9;scYzJRg1R~{I4@8)=QZaw>h65td_X;%gp;72khzPf7i8`x z>J58-IrV`(zl!?Co{2p}{bD;~JL%@w-q>F1&ldhIJTu(Na(Nres4S)vMf{d6WzZb?aP zL*qS3x|b#9yS(W&)Rz6|!Ja)l1d=k$^G(Mq(+15i@w|8*#p7n&q-t?HZd3JmEbdZ%ym~yJ zYQ}5DYfE4&T9(MU0&h|02ruW5^8IJ#Bnz!1bAqoJ z-!3Genpq9nqJ~+6G_#gji$Z1{vkv5=(7XsUdqcA!<(Q4l#uPD&%pz!oCT0`NhQcP& zF#|q@=lnDKXB4-ev7e!8@L!Kn_1LLcg6govR8M#+ye=V`F4~j1J(=5+xIKy6lhIy% z#4kdtGPf#os}i>=ajU`-OW9ls+gw`G=3+WzrbA{rWTr!6Iuxcu*jd$CA|;kci6t_J zB~oIE%wUPkWQh#3L}sx>$}Eu*B(j_|w*qn*V!4!9F0)xKRmf$Slz29zGtAOyvUD0O zoe`E!6Ve$YJ?=tAqb#E)%c#XNn#VGl%VSskN}*|5?@tn|C3VH3-fw|*kQ}!-V;-*f>M(-rZLPTD4VH^Fm-uMoet{ik&&jZ5%u+` zn=Dq#S#uC;4xQJ!jLd&~<1!pQPhUD*PlF#6N?yK+y z#EQjeZyiBMyu$KIp1calQ#drDV%`Z#$=Eb+uTSjObV=hxt8?9XT#w`e=MHtj1^0e; z0c&`b=_RIDVtQq!SJaiuqltJlNj#cl=D5NfSD7x2=?XE&GkFAM#dSRSFhBWRrZ4(|(_O{|}J~Im++O-!TSwr`n&i|t`|?| z7dH<0%Wtdp4rE zRrbxxn`-Cu_S0!zNaMO8?5;Za+c;eo)8!vYJi?#r#J?O>;?m_>B>z7qwP$p;SAb6N zAr%+q_)RKi-cA?ap(Kk_QcXT&Oy%l{6rS?Sk zP&oR_=r1Wdx;MI)a-wfX-$to-yjJ&7B>EoO7AKROAK3OA(Kpb>xhTkH3UZi&NPvQO zqwk`upd***$n&(R(6IX{sZD3F2M{%)m|ra6Wf(Dd8N!RKk9jKMMlet5t_};zbZuBr z1#SV)>5k`LjyA@@f)UUL8c{JXxmaPm2CDD9jl$y zj$-U7y4DzL48_?ytY)pT)=+ip73&qsXTPup{KB17ll{Wl?C%!vUQnT!q1_BO1G>Jh zdyzMTHxlRKq_Ee&2Y6m_q!6EVIhMxClw;t99@vJBURN_noT<*7$!E^gV9wNJ&eUSg)Mn1qVa^mVX9}4!^_epb&fv@s zdCLCZXY^*i%_RTtGdg-}BS~!P_ZiKpv4<5F&HGG=n4byr^L&bVc8-|Cr@Iew>Oyxb zX55?7}-K1iNq;g*`dz;5(W0P*TpolVac5q=!zgg?+0Kdo8(MuiA63K7y2q zUe*1Pd&L?+s*MrS)T8lXU>frdH1Q6!#_PwS ze`EfJO!K(;PmJv9Rt-pTEvptJw~kc@l3UlR56Nv{T?{!bvWlo4^RPbiu#q*{nnI1O zsn%2~;`N|Qt@+jhYQj6s#k{Xv!s|X)@m_Ls-b-%5`?W23zxEnl^=!*4n(cUHr@hn7 z=}y=3e(iO<%5y#M*LLFl+8dliOrp*)C8p3#F)gN1*H}g@OxV#1T@73e;VG3Me=Dpmevs$o(`cM zN<2E|RG}R%JVh<}Om32*$In9-Tv$qzt3+ZgYYtO7SB!VRHsZDUx~!9~71X#nZVvdG z=jOp`GF(vT#$1;ax29VYmRlXS4zxp&TLjCk*e!!T>9(XCw~c!Z zMcnpod(?KF+mUqlX1720RpQ-Vs)DY0|6aOyhnYOBDNexe@}BH`PisC$;x{zUrLm$f zqYbggCR2>}%gI=1ECN>Sh%3Aot{N+hRd{w!8c)GG|GBXa&uD|O0ng|;V-udy%f>6P z#phY`V1+NV7Q+f(W-WtOdcs--%UkSE*Rf7or(kVYSQS*yCOZq(cD5a%CU%~kN0-}C zJ5D9`<#tnQWq<25qiZh6tm5a-f-3p5K=8*JZjJt5$DgEJi<8|anG*}yb4~VtnXw!# ziqjB^u?BrsjpvPxXzL~8CA9JidYi?)4fDx`Z0>E2wFG-Hs7gI^DJUZV-aM4jCFX{5}(zO z@id=cx%zidC%nnz?=%+&_85kt?NZo83hz#;MwwBDmd2;|D6@ZbdNZroSE%sz6(mx5 zm0RQ8q7bijXC{B+BEx%@NAb-zNi8dWdzt)grs(Aofs+s8-H{|EGmVqw5^=wbjFIjA zmU0Pd>mIPYgv}K)o;IFEf7To8LH%Z9GpIjod`h`I>qU9KGmNi|zmsVkH;$8Iipx=B zywmTR!_2#=nmN)OMK#TF<^-y3t}>sbLh~u}XLJ$o^fxkJHMdh^w&RM}j%#B6&OA() znSU_6qv!@c8PM6f-@2b}Wc#iQ?7R7N6YRU6QdeuawVZlbtF0%gr}ezGk$SVO z*OzU*esJ96w75bp^qyeF*kZm`BXz?r-QoORZnyYk=&6FQ6ciOKF|_aWKt2k%H@ z??7?#P5Tp=vcNS#fljj{lrNOqrcG~wTiVe#qH{LCDrZj zb_Zn=|31h}pTNPVHC*gpllcExiBhXAKlNs9v94B_#t92roOB`g1NS2_Tcf4=yz_TP z+ai^7QM&HbYSS|BS9INd?JX0&da`c2mR%dPzvuo3s6OES2KLxt_rEFcJ6cn?1aS$C zOJt{aDP6CX<)RMjh*#6;sr<_-yLviR{5!8pHQ93M>g9PN&F`wIP+4mc>noYhC#mM+ z=3EM;IUcB2TISWe@;mBn0c&6$uumClF|&xXQJKcyjBnt>igQo7(1uTA^a*Wfur{=y z4Sx+y`aARY6lV>X&l<26Yrq25dUg5SQz3NRaCovpyVYmyb`fj02G&oZ*BbJ$_I0<686irmLO1oKf(9gTft zxEooobzxn06YH<8th2hYp6bqLpnC8bsGhNnv5oMEUx~d!z4;7OpV*&bf1t~wCXMHpj{z55IxVY zjmW?BD{K9?nd{SS{TsNw{SmrLU;D?`o*c5Sl8AkO?8`@_LFb-=Q_6C_d1$Yk`tTe( z>a$R)!6PLlVC_F4LIm+&j*x|{g#C1KjzdT0c=+1>4D(BIx`o%)BG+~}#V}6c`86s2 z9H%IMCdJd`Gje1;Pp5h3$ef-|bLEJArVl89$$H`p8m#KHc|^$X6as_fyLCF>^$|N2UAgBl0~e-RyJuQq(SJ zQ{UZdk^}M)KJexJRpI@lL1E!{6hi+$;P8Ix;n_O-U7z!Q_-)t!!1IClsNRA=L7$4= zf53ufgtVW-za0qg*Rx?i9U1X@lzkkrcVont5qmLW3*`sc2ZF+H{ZN7?HU{zI#Bb$C zCK9=1I?+XH(A!%fq(evq3c$7GLLa(=Ilm?l@A*l{YaqzD&&xI&A>g%^O3)93U^OG} z2^IF9P-E|j7;GWDg7wBItT85F?}<-f>m&(#PkbC(CyCg5;*;2lNX9EaC~QS2u=m7E z*n1)xuL5}qdrw5;l^+^xMZAhve!PaQh&b#$@iA;g#N$;UuSfi{k@v)>uodwsycXnT z>^<=^)?HJu_r#~M-S_DOkL*3DNu0^?T1)wImBY`iDTGuP-DwMjlCz-*n2{a zEr(a|s?AjFJ&}aHClYZhdINh;yn?+alCk%M0((!qfjxO%#hyH|*oWc`>_ZWceJDPK zeJI|58lA)~aGeBO{R8_2oZ4I3``Ww1?+))xptY93``bPCNyd}@h#&J9daDCL?7sc( zjlJ5v&+XBWQUX5zWZ>PZcUSl3pJY8r!mBj-y(P5bZC~bIE$n?xCXxGOIU@7J`DMi7 z)=OdQMuBHeWj|#Fe&>Mfr>ww!$`tlfR^Yi**-u#ka`*j|6$ie_0f+}74-)5r?vVc% zR@zf|UO`E;KyRRoeEsC9ACxlk7+-jDKk{7?5Au_R(jR!zi)vKfkNsEC{tvq1J^KCB z13q5%|5o7RNqjsi<5zIGlDG^MxC|)l*RRGUp}-}fz$Kx?C2pS^qDhJme8EjX3@6h={&GKs^5@ zAlcu5#Qp~IIg-Cl3Q>dK&-Sbo*}H(mbKqz%w0Znh2-yPw?qB$iIOt16KH^ubRwvRS zO&oqxf*k$TsK1se!JilTP zt+?ZGulUiOyHQ3g9eLa@-+ksdl;i5VJx|SN0`C{CNARvb z!$UdDeP9kci{$5}Z%-bMkrLYr_-=ob2f3&JH~NVpj*HjCY4L`5Q@kZEi}!>_;;Q(NpAa|1 zEq+SeHBqK0lg1QpN{U?X;j2D$?J}BDO=+fdxg1QHrfic|zG@R~GMdbCxkdPLIbbx| zOfHi*QYME=#uPBsnCc_gWNI~a94;ACm#Np(Z@Oq2G>t?`=D9L4jhQA)Q<0LvD03n> zW18dFWG7cL5e zLa%XC7!k&V31N!kd8;rZ%yE6f0yilv33r4QVNF;UHX~t9*cSFgr5FttlpxfI$>MR4 zha@7I9pXu$OUw{@#Vny-%rI^mH~CeN4bsIN2zgj~lE?@PvTTtD>1!enK@!$Q^aZ;8 zZ$G|>G8)HE6=U#NNElL}e6;_(1MwoiQ}a~mumtp1X?!}L$!GIgp5~3bnYZyS*lKw% zAAoob#OwJc*xDep@*R8^>~rzGe19ZdH)Fp^MB%T#zJ$N`8jZi}`ZD@j1&QA99z!Id z_g^p#m`ETq7v}1?My`cx=Q_C_?mRcZUFL?lQEr^O#!YiKxSQN9ZkfBst-^n_?;*Fr zZE?GZ&r^I9;`16lo=@Ua@&B8A8qiaZ)XoKxJL$|KR&{wbs@e77a zx-P?z;fmp^VbXBjFl(5HJqdDvJ&T6hhP#IQkp7Y3G0={|XCw?EqsmZgj4{R;6ZJQY zjm8w?3H=R_d(L>u&}}@et1-4f$VJkP`9{_#8YYcaEIShDe4|5$=c@4+#a?)?cXpkK zG2|Oqg9yaZ9T2y&7xIs@7wC?Iv-VhAJpR{h!54^1)b3_Hgz0L`&W5Fcaj zuq!}I#Bcu9nh$?Z#;m)Y^NS;Tu^qj}*yK<*f|;nm$S2rC-+v^qcx^{az%juu3+Xjb#(qWcE0FlFeYV^dm?jmN}+3>L=J7 zki4uPWOH<}Ah{J}Bk8sIwQL@eo_CF9KsuJq@*sVaqv;4;zz5pSOP zKxBrN5%<=TK2e{dKcPRRKdnEb&xLLNTa=zVF;sG z`ndiYNXN3z#)0&fvvIJU*0RR zM7;OCrVsWtpr>>-*wn&iOB9)2+G-x=RJ^x}iwu)?LwEeY3sbhOX_+Te?Z0>mYAd z7t+n2jn^&ej_Yo}8P?s^-Pb*MGo0(rb)Rhl*^hK>y2lW9ko1C1hG0}*%+8mP?1SKD zVsvf9Z}JVM7j6S*?}9cs{m(lP@^_tHNa=iXGa0?1Fh7Vbf8RvqO&m(v=$RZ(?CXu zn}KXVE+8*Z0H_A29;ivqn+A;#bW?)vI<)OQ^uIqM>mtw~&Fmrz`G7KOOU#Gpv8l0A#}Ha?gHHhdI0nY=rPcaT<++VG>j^;jd^dopC0Tt+y>AV zrANo1{|EaMfl`2=Pi0O4od!Dd-WJs#lM9r8Xv+eLhqhKA$HA6jJo0%ne)-y%Fi;&( z;|JTKw)NB&+Bef8p9em#{q(udP&-g(WZNFOKi(sX=>h(EpaHpV7_bwV;X_-v=a_Nj zYX!Ll`2}o&SYXBIz~}+=7lZ-p3K{`h3fciX3wi+07YqQRqb?T=7mOB+7hEftF1S%} zv*1?2a>2cVRg4c0;u{59fN1Y7P0>-bhK{F`0Oh!hsdO5hPG{2D7`4yDY1#;Arfq;O z+6x$h>6N_Ws*bT8dcU!(^CN9ZxY33>_;@n`5cdVyY|@6aoNYxFw3NpI78 zI;Ace^iPBd7?S~y>rMh@=&}HFba{Y`jt7)%Htm(8l8qC!81%Q zlh3fQ7om6%w=xbu590?6Gj)KCOv?ebGo4HibDkMsE;GZ-C^ODnW2OO-v>Or5P39Kh zGDgI?$E-3BnGI%()?&;)h$H^4p3+C@HTrna`87D6s!!9WLp)QTt=H;l(CZPJ58^hx z3(yPJfmUCmuLo=bO<$|;0KFc?djb35*o(;CkgW~<46*~j#yE^%YXGi+Er6|zh;@N5 z;UJDI4W(>rusLkr0Wx4UWU&%!XWgui4PmUs*Z|nfwgH}Fy8-*y3xJo{A;2r_RX}vq zBzv8mW#`#N_BMN$z0W>iAF+?w9rlrdFsKmXc#I(q_^{WIXh<=f&@ap2dyW0Zi^f5~5#yL~0^^i%#yA(5M?*7cYk-Ke9^uQlY1}sMaY`m}Tl_9Uf!dD?QG$lwF!TuVh5;c-NIk$bAssMN$QHB$ zEf_JH58^h#1?Uw5fav+17C&#(;%9hTeANDvyvS2L^aKw-VVe`~U|hk7p5x8oy_@n= zJYidmMu?y2#fk~&X`XnJ?hrG?EQ~qN#PdW3kQXIDyXXe=i6KBZN~{$d#AdNgJSTRG zec}c265x<{1@Njk33y$c1)LWbA(z`2?~3=u2jU~~vAAO*Oe%~q7~{kp@sTMJ;wh#R zfTv8S0neCn5np_4$~Unl5ja+p!{jmfO<_}=snOH|*ly|s>@l4;4VW$i4x2_z;}E}Q znuhc@Og8~819A}Fi|k!BJv42YwoJQXvY9eR9iYY>FD4_tImw)APBW)R;+f`b zv(`+TjTp@bXfwM2z2*R5jkzAM$=nLqVeSI#HTRn@ng`7z<}uTjdBQwpo-xmvry#xn z@g?&eamT!3Uc8`=Ei@`g%X+PJProOvN)M$CRw->syQ~u3FNIWLRG~)DqIO#tUzk*wN_P~d6{Z7b z7G}$BtWb;Uw~#J07NR=MEVP-ms2mDih2FvdDwDz*F_56hw3kM5F4Ecp)g%f~Ng)?&hTsVh%xx$6QrNTR0Ug1jN8kdLqnZotL&BATe z=M?Voxu_?xDy`AhSboErU`^&XP|G*vTaQ~$8uzRj)+}p|HP6aed8=f#>or!l)mN}= z4OwexjkUqrY;A)y=O9hDwa_s<b1oU#m#_i#pjB<={v=J^iuJK;!DLt#aD{2g6;t&P&`?Dy?9n`+d^;geDNa4xm|ph zRTkebeo*|V_;K-$ov^ErhG~zn$JrC@DfScgQ|P|1pSGW|=Yp0Fy1G3dBWoA!R#^kL zJ1}}M`Z0!4F7`SZ?Tz*py2IXX@1*5iT5*Y{B)%j`)`3e>F{WWmXKt2c zGUFxLC0allA<|k)j2O)&wi1`Dsg`(40wp!fMoE216Cm(`(^}FYYpo?+7<)1Hqr1N3 zBE~@(OGZk@^kXFx`jL{Ul9`e@{Y=S%eyU`tqu}UTY2-0X>v~cg#BG9gB|J(5vI#+i}-%-|@il$nn^cClQVvCn5KQPL(sp z8RtxNrZ`VHPdQIJ&p30P`A*g;A|1d)IIS=W$fFGIx8*U~>2P|4K{VPr{mw8NZJl+_ zM$-W5wVW;H8fUw+#o6iXah`V$I4_&(oWssh=LvaSHdD@VG1+;|IgNA)=M6#Yyy?7! z#&qX0NWSM>-5+h851kum{BmxYwa#4^CGNPQTpGZ5SJM7S;YxL-xzb&ku55^FU9`*S zGP`Up7rHu^*A;Np$UUuC>#BD(nYFG~7xa^^E?2Ls-*wS7=o)d{b&a_uTvM(Y*PLs? zwdA_vT5+wp)={~+HnE&-Q=@CoR9C7jjb2ZuFF=k-Q zLg!GLgE6m^DdojBS8J&x_LbU^Hd5*q7YkjbzS58!FRjJcfX0H-X4LDJHkY=c5=PoZ z={bzuNOLIEmiCoiDAb~O=_QQKr9-7xOdF+FOD9320KKC0dg*NGysSkOx)7EwVr(!| zrO-lP?_I$Ar4Qs0A4VU*(nqC_OLyc^-c7hw?ill)JI(iCQp?hGLuKh@nJ7(JwtKZqTSglO%8X^^GFzFe%v%;Ht0}85Ybt9k z>nQ6g>n-bdZlsTPs^H+brAW^2+u+N>8*W z){~$g^CWwYdrr#MfhWV0WnA#&c=9}qCj<2Vbr0{6Ja&)U<3ppWC*-M>^>9yvrx{}# z;5kpXr_Xc2bICL0x#GF%ne<%u%zEZMi=Nw_yPo@=2cAcs$DW;XLbgDSspTqTl5FY7 zHbr?%d0cs-Y~_`wl%D`RRestyfyVmsGhA(XZuuD@sXV`&Ef>qJo}qF_xyLhU7{@97 z<>B(W^2YL(@^;zIVtwVEth>CY{5O~jhxSN`8~kZ@`vRchK+KtE6aDilsC$&@y62~s06%8-c)aztg9G0z3JXe zF3+3o)$$u&+H3Thy*97Q>y_<6Z@^pQt@k#0TfH4f&+&G7d%gWIu7PFky@+wpJK`Oa z?Pc!-Li;UjJ72||DU^$M2IHKN=3Ouhc$d6)45Qu^?;6;=VE=m8y_??cNPG`rg%asY z7144@BI~sx7GnZBtBT}`;}s_>l5so(V^&2@MV@i5f~nw*d&q{ZkSgpIZrNh3@L>#L ztmW=jG;p&O%@u9?h-}P48ezq`itdU&*{-a(P;seZh})^SQgIa!_`sR0xGvk670DPg zFlHewu3{GBJjTU}+ZA`gas>Oa;(o=0ibr5Af)!cuxMIgg7$$H)>Aujr*>N4}8CKFrPD(+NvRCZPNR`yq3tQ@QysT`}EsGO>tshq1^s9Z8_AgsKD`pL=_*|w6g za;*|Z>dH-XcI9^Eo?q#Y_Q(1Y{K@{~{*(R;f0jSTpXX=%JYbez^4tAxzt11SSnF@_ zH~ZTF&jEJ(`--~(FBEs9zSMuoKjgpSzv`d#U-!@Y=lzTR+y1-$`~C<1NB+nD9n_0f z5ml9wLIikSY`tiVG!%QbH#}r$VPgXF|E5 zeDhd{4T&MEuO;L#YeSxpA21xM3pIvXLhX7DU?*Tt=zM4(bU8E}8V!wyt{FQ*)1e!o zo1t5w<vYPwomO;;PM&DFNz z?rK-HH~2`-r8-buQ(a%(RNY$LA&gXaRrd zAuK^D0fz0e)gN|;ec@2JHrxh8ev1_v_( z{!8Ht;Y;BmG`@$gAR9b=2$?ND5DeuZL%4O)NYgUIe@yzAM&7W^eGkimy|c z3ExL|NBDtk^@ksYABT64{!@s&Yd=nIkpGJy$e)v21V!$Uza*686N)5M)G$0`V%9M17KYjXF;K9`P~iB=rZx>(tk&uM;0vunGf_c#JuwCz6iU z9s3fIeC+$jzE7lRAP}F{q-q2rRb$q;2vJj}`A>vX^A*kah&IifW}W!9=8wANivEwlUDNMq=T#?lgS|2L7pPdk$ogf_LE;Hi^%VgKO~)sZz;Y- zHYn?re@OmYWvjA{{CCQ8%0D5Sm0wYQg=|%RRrxjYkCbmKze%<$N0npbA1f!6e?@jF zzo+~j*`xd$<$ou?qWppKhh(4fmhwmBSC#jaE9BRdYs!Bj2b4cm{*=6={JHWM zDxZ*p$3AxKW8|M5`_ZvIa#(dtb%I<{{l4n=$;YZcP-T!mSAAZUL;g~gtI8vvs0vgx zrBpF0fl{eVDi@_um8*PIvdXWjqf%9WsA{49mFkaG-PGq*J*olfP1W0~ANxf5)Z6NhtACIBraDdiIciLORvo6M)n8KgQtRqJRsX3XM*UUwfZ`SP zJL*xz$JAr$amB~gf2p2SB&)BfzpqG9|FwEik*5B8^|B&MeMh~f$X5T8`WFgaR9e(k zg*EDDFTJ7oiRPD@Un*k>l4vA`@N@W6gqk2eLj#$Cx+2ti5KpsgeWBg5D^XHZPP(L# z;-w@hRZ5f6rA#_Y%9gYeO+S!~l3B7zF3BqeGEaUs@v~>78mazsC#5E-RqBwsq+Y52 zvx!;jXblIn_YK_Me@>9l-gltYKOvtG3TWf8gi`Yb%@>Gcnm09X;s+$le#en>=7e@Fct+%G?(mWXI-nOY`ds2@{5 zhP&n`)K3TvwMzX@xOaX^{S@w_l;U42GKmyLt|FI6RcIAj;tfTf;w*6-)jV+`<{L5JAU*?E z6hp?nx4yyRBbqHfOUP1dX+SfAXg(0xc$Q0mLzXM3e*xN`0qnNiw%o<@eh0IDQj8Rb zX8EvXnpM#xmx@G_ju185;YOYd1lLY zJ`^g498ymAJ-T=9T;kG8S>V_w#R=PWd?Bn^x+# zEn}CV`|K%S#_^KhDSOJtFEwLc@2ZA3t#?g>(t9^Bs9En;M(4ENZFR<%QK;`G&KjMJ zDS?S86_bDWq5d`m{k?sGlkWV%37rP!m*O-wzo^s3{LbRC#SRNP5m7Z z<(p7iFtc*FGO|0zaba8XtfzDO#Aa{_{%^l_rbGn=8 zIl}4Tj&?^oJ>47J8=PM5&F*+7=HBMs>13G5I^D@Ov2~`C-2YLyR)5K_YwCI zC(p#$mz`_fmF`Msu=~2Z)*0e%a5p-`+_&7foZ;@l)HAAz_R z2ZbZdQkh#mkN;Bo>i=hc-oyOP!P_g~?G^F%^YHdmy#0Ku7kBsKzF5%$rMN8aw#AFPySp#$ zP~6?!-4|aze#t-ia-KUgncSI-o|AizJVA{`J7?go6&9C^Cc=1unRwu1SYz1SN=B+fVys7UEJH7r1 z6r{1;#77leFM8Izy~Zf`#|qSCk-ffI{jSkUbVsnWDio-D-yeQH>y!u0c6Z9ta40h+ zH5uq>(OxMP)aJ2d%K*S$4&MM5v)ed6J0;jvG$gAv_7fToBc^0q=U3rwE+x`$B2jZr zU%MV(O(0<2Pll(XJu}u zZ{7>`xr^JM|GEjLqjvX)rR&j~DHq!98*v1KIv-Ez6Xc2M5~SmOoXp(z)n;~a3bGJr zdLP<>3~7NcD_AEPecn3+6Di(no^BT>;02D#d#W{62a!jssCA}lp2W=qPnI{miL&;M z2d<6p12i{wBTJrd7ar(~M3b?ADFChe=(DiNs9Fw?+Ky|@e_2=gn15$#j23+Ca@&|` zy_NwbcnrHXdJ2E*%X^;X$RZHgs5mxF5HUEf+g~_+1V*(7pVi%LWC{%lEOBIAJiVwt zO?iXtt=}XWmHLOb@sqTfZ&tVQ^V8O*?eqUh%SBl^D1<)C@O1ZapGY-96ho;~k_KFd z$vCPYJ}KIQ;IX#hQ;SUDl-J#h6!1o>$#v>_9A9ygM|MoYNxte;k6BpY_w05uK1tB z*y!g=irf@sD?iuDTjkjlI0Gt(j<)Tk*26RU^<8IMa^_zlHbq+|$y{Dp-VlAOHRjjJ zto@@j(EOf~SMxUp?XW6Y;ePOJ16bE6s~Wh`w&){NUekACd3_{6r4IxS5x$=u#MrKp zs81QTFtj`4ny-ymk863xabmc^c2#t{*{E|czbMUfaV_t8zn)aZ7J9LMrHv)>#9ZHa z(YCUBF9cg%a*eWC=dyKvu6&eeZ3=AUxf~7K6{HObqe(oL(6DE2^~uV1i#&|fx0m0O z|Gk;wcoOdZUTQS-0GD53b+kj!Q5Kr8q-SDe@4h?cHPa4u={)sa>aCStX?;Dls7*^Y zUXB)$cYRs<9RFN_9}i*hjEUHxeo-tij^!?^Fzermg&tbP@7|CZt%3g*Edc>v)W94ObheJ53+hpZ`9D zYCk1@H(;j)$85-IY;Z&yCAU!)St==BBVo-rOgj?F6!HQFEectP9QZ9>Cz@#hg<3_n zc=<^zgrj+UsgCU(R+IOreE0O|2ZG6U{~gq%1F*$$Snggwnj{^x>BO?o9mwv}LQlTD zN8{Z_h>y>wlhl^+Rxu1=$o2gaqUKXzzmH~iIvroCVxd$o%x~LO^pYxa_&$ROIa^7` zx{T+c$%+-MxxMjp_`al(K9ewh5=yq`*f){Fr^hb+T))Z)FwEK*9gFu&81IaCq`s*% z*wyaW7?z`10`xhS8BA88g0JsnI+q{H95Q#?=pQ4g9+_l2&z~amXEmv)4PtLwJ0YDn zin7D$?Ay-MvIMO7Lh-g<_DYjx7zF`BIH}<=3+~%Ui(W~+B4h3H zaqQu+>7u%8eo`{Xh==V<)TC7@Q5hVMVD0^RddlbJ#(1#oYV13i{(}Yo?dhZBbIdAo za{{Djup&`cpi$o@Zxy#0bgLKg#MbC(69lEyX?3h~yvY|gNHkA(9N3LqXnQXr*v#Q@ zvCv4_jB?lhw*z-bFYhkH^~8b4Y8+|geD&VJb^m+{kD@u)#Pb>@`ftBrReA^VP+6tR z-rQJO)&kW%zUU*o)H6fE&|; zu{eJ*q*`P_~?u5)=n(<$Y1cpBv$H%E=hJ4&VLm??um4voIo|d;iCk`Bkf}7nH|OoMfOxsq_Ut=$Gldj?|A=`Nz|mlG?WPp~n&a*%Wm{MM<|3Md!pHDmewNaeEg z541pP`LH#f5dKa6awA)7Z#<|{+y{q0=^Cp2d_R2ULTdY{sTq1W6i^Qmv=zz29ex7) zdQ9pMmispNIWi|>+5`QL45LV0jtt*Ccs+9?trGv8^QAs3q#~;xwo4X!?TS*2KJ#n2Kqb4 zR>+t8N#&4}c70n2p&-k9_~|4kBl|Ubl#A@`3hc)mApE%i+{4q2Rgwh$!J0kceT(?^ zxdPdQ=IOz%EBs5f$OFU6>m*qYS2myW%cR+=_r6lsUqlUrPWn<=vhA($R^{gl{7wXu zLf%8y(~Y*F7l%tS#0+$p0Vi%7lH7#Aq3gc5nYhTG@%rV^P*iV}Hk{!X`kuFpGJ=?u zZY?bcp zZ#K6N`Ue9z(?~b7ZbO$QH$N-QV39w7Klh@pV!@&@x8<3cleRhKc9eQ0y*2_q^%i4=(__bzh@5n;Flm7uikN=&gK? zbGFN!@wwaKy(bn{^)R622_p1M==wrDmTQEP-#w$`>f#rLznRhUp7PVo#RoF0R~ls) zj$D=CtR+pyB4?`dU}~h?*?TyB0I+@0kca zAv-dhaJik$gZYfWiyUlchcELEZd{W}sY9FH@zYau-e4p?*! zfZ-{ryxhXVcYh2KqKPD<4Mcu)&l^ID+6)e&8DzqG^&de!!;9pEFgBq!eQpY@<`}ze zOfyF>vY1rkY$FjIpETX_x-{90*%a|>RVnq&iHPO*%ySG~rx5wC7(i$$Q!DdUS&XH` zKFgBZpKFGuh;|$r#6#2)uNo!4VsUviXWoGYqqTFCANyNUS+iMr$s|m)is|*)t$OOF z#9FvrWV9dF0GS$o!%TrKZhXt|zr$Vecp8xC)v;8W+SoKe%`h~_GEObk3u4ZdjO$9& z|BwN{k*FueR8eB`seLvklQ{CnVz`1@98&1U*B3h6M9D&i7q3(8@Yi@`+fP~WHo?Y} z%e)_k+RfMH&kmGZWB6Vx`%i9Lw@5ApdKx{LzfZ8%W3GN$Wi*Fx|1@ToJ+@^qjIT!+ znG59}{K9jOr)&uyyECa^@EN6BxBK4Dpl?~PmTD?f6|^PtS3%xsxpoE>gbGSM4Q`nn zpPY{;^b?}Yt};)+xX@%w7+XKgjmf3MBY4U+pH!MP_-y7Bia3B3nf?uz%MH;Dk=|I5`nV8NrNG2;*}!hgFjMK7W1ve=-}jb^`$Iz)b=}vPklo@ED35Wc zQK(Ng<~Vhl=dStix8(lllE#pC!e}UO_FC}O5gF8K-bV*H6I*eLki6tIV#}zVp%X}` z1^<``zzFjI&*?Vi?&|fASD5p~I+02FkT|iYhlVfPs5DZ5ybNZ4)!Szj$He@I3L}JB z>_tz8UNbjR;G!Ekkq!ir&p!OMzO)=d0Kgq+91DE_NrhQX=9)r^Qy}hRllz;VYi=i( z^M(>n%JWEX7MJq52xal&B_2I6buSC-4$g$yupUnZJu94&HpxUvAwwJplj;hZh6tnB zMD3*tWv2?}gl^Ca`!0aI6ZJjCh(*mHFz&F?u@R8;fZv_tcG+NmFJ&QLT_xyUw;k`3jbS)djNm7 zZ~*#U9vG`~NsNwk0L-;?y{_#ls5e6Q`1EqI4J3BPyb`|*8KNLdskz6cTd z^1$qU$C#5p8k(*ydY*=;?Sbk}+-!0g;cMV_{!e_rt;sh!9%&e(HDBqJoef)oPIk^W zLY-fZ^e{(crP960P?T&e3rYGIONw=$XqbTl3rT(wI)yuKyHoU1d-9_ez-?vIH&>s8 zb0OrG3ldY@`OO06EdV^DsjWe*IS zcW%@8Q>Y9}hzCKUKbnD|ILf8aX1ENz>DUayf&`cYawe|JG4u%}v39>@Kz-Z+v~7#Z z44QndKxJw%cn{)z7h*efEiU~6!nOM=PMuvI={nF<^`^L*t)hx;^82UiY%K+3O@K8U zEc=x#Zs0z9T4MVxhf4y7q50O-!|0p>A9#3)1z8jra$}v$MDr5Gbxp}Tzox@*)u9U0AMXXbBfR~0ya!n4aA}CEj|p1z z;sPoBG1~^XoXHf6yy6UJDVC6wf4}aZI12vcUH>ty6W3W&+43{{T}(>)DbRuxiNySw z)vbTCK35;t+nLQfL2{+e+*#;QVL4NB#cUeNxGWskU^WF!fe3{)EaaVOr%oYEz?G4$ z7m(E+o|VqJ!EtF&*E-`yI`xq8>qZ_&w2|8IG~qD~t3(9d#CN;>?OgQ0t1u0J;i+k6 z1{ph{&ZnPQnvt=~ySK);FDJM^8QH;8I{33L`-E5b2Kvw*!|-vD!wB1u+K^s|ANVfm zF6lTS65{fPZIIAgX?|5roTp|_bEz@#PlEb|3=iO^1tKLpmHU9bU%eTN)kGfn9u%uI zLzAa{s|B}~0Ub}852@9|K{u3Ks7feNCkmpo@_G7XM5cc|grAba5E3L6aT{f|W;YMI zCVYYK(&+1nykq3wGlo!w zVT9!_Yvjk#)=u;fQ zJv@>}jpFns`#oHX+1g%7>-+$x-_LF61!<8L^L=jT94@|4s4+#w?SnOb`lH%IbdO) zJFQSk5JnQ$#HukuJq zE$EDDZBE4CZdFLp4#2-3#=dcpoW&#zpv%!_Mk#6cR?eU9jgcy+58HJ#5Sxr3 z)J=Tbu%fbb0ml9`E#WlBM@+{RSZ7=wAKRw9(pSaRA8h>a_fo8IL9 zx57waCp`6#ou?;`Tf>}H>>T|?;|mSV--{o3T#h0rEP)hcGQz~zZJ}UOHowR4!iUB% z+oy);4koJMJ^vr_B)caP4RL!=3cx6Z{Hjv_m*DhAU*q+968VNWwUX0M<{i8=L`Ra$ zD&w=QnzQ9a<)v*IC5>C8S8MRIVwJx&x<3vb_9VJ|IDAD?PoS6~>D7log(rc;6)o&)9oNob6C!h7J{M{x`T8tLDb1*K9(gcy zBJmm)_q@?*bx(iX7!QhRfV5CwV@$R{A-8b6XH!tzy9S^&>zz;Nt7pwd|D4qA1WLT+ zrvseZRip!))|pu)ZpMjoPrhaPMaIarrMS~^VMCF$VI{uL83#G!lCd#a5cbSIeU`nC zyg(~l>1RwHQVOi5zv~Rs>#T0UQv~lR_2~0YI1r852rr71`1;t87ak7}IhuknV+s|D zn}O3jgLxYs2f70>mb^3UGDkdURMZL<{GFv%U|l@Mru1n?t$Fbjfq9_>uvC%`&RGci zG-<5ch|rZ&VMYO1GU(&N=yRP{tjVOJOPM?!*EAJJJG-dmpfkHkpWgg~9L7ll<3!Me z(@DeLv~H7-mt0}O`5Z&M`OKc>BXc)mw3(3gnJJEpy1%dKxeCDBphOer=myhU zEz}{?*~331ZRgaS0w@HDK}sPn4Q`hExVaLlln-Sq~PR6$FvsF;OA7c*W|9|dk%QGX+br(nqlOR$VvFbyby<$l zg}qhPZQE_5oBe-!e_VP%83w&r_||6N{q;q}#!w^0L<3VCI2or6ffT%MG)mPMr7>Bi z_0lgt-g=2cpIMhwaP}NxB6IfF=8903B#+Ou=`1DdvDwY~gyJ~NMIHzXPAfq^xqdmu zv+Fza2$F5_($$V>wE}hE7b(wvs`_Wftv%V{b&16^I7K`zXYEn~A;O`cTm-Aag=#(k zdt#@!_ck!!%!NwlhzZIw0DHNlZ5_<(DdKWD_=1?!Yk0o}lZ+YGYK?fYBue~p@s+E2 z(s5U0`3H#xMjA=Pp#y}i)-)^kD&wP>m;)ylu28)vTBBvvu4BvI{qLg5;0!SqsohVW zZ+WM$z^^m7zb3q(YGI3kdppj(CHDg}!zF~&PLWd?&0h_(XYBF4uC=r@Ah>js;`O zJK(LZ4EI)i5Yr5&v#bWYW~j)12D5l~k-Bqw>woD;T&(>tuEC2^?E2l9Ss>f7Yr}V- zx=OoP*sQM^eyH0#S#)LQuM*yLsF=gDI+P1gW5)ztOm4tJDN^218W%?wH~7A9H+@i- zJ-s1t4Y+BjEnb>}7{6VATyl_alWZ~yrRWO7-1`vMD;3lkfJHxE-*#=s9IQq<{Yye&qk8T6P-CH!%}o(MrDTgs2d>vMaO+lVV(##fPbz(4se{=2FaArfM>aNk*Qa_9Hs&40HUE@( ze0L8n>oz9>Ix|(Q=#DFkl4z6{oEI+>#gEf8xO|u)O4%J7a*a6G2#{ zZ1m3j#`W8ll`?^J?jU))9R#O4sUI^NVQx)Pn%IFGlnvf7M*LIl< zwcv^=0b=VYO6ZKynmOdv@DFL~r4vaXJ4EVe)&~HKaXZ-v5!7rQk4dcgAQV}|*B?D; zfMKQ-GoQv7{#|tx25TxmhyK;RfAyr`_tcJICw*bkC^?lGHpL9Cs|NoEq4#`T;q|SO zOI*~xj#1KDMDY~lESK_^&iXlyHV*d?789VgU;o5Q5_j+7?P0yN)dPzDJE<+#ln1D=;q#D9rkWKYzBlKv)We5!Hov7 z2_#5T1WF^DdRxXy??r$>CW@Sor7N+k{ieL>NKH&rleIE{0J>k$o%4asW@D7SLDBu5 z4dep~UfnIX92iZBg>saDU-9+sFNe#77%%bWl#TDp6ylPKHj{*4~W|I*DlP!>p zG?q@R#~Zv`AYi$cWV|K2lQo^m7`8IB)i~MGXmLc(NS5*Q$oP!joacco#vnq*_43|0jX}~MWrzcc&as5K z_hu)MZeo1h8WS~%(Hir{ZXdcTWyBfiG6syF84uG~ya3V|fr!fWtm;0Sc4y?C|4u-I zIzaE#ST&0HpO%MBY=5_T)NcL5uYc-RG6Le`;u*7TuMS;ZQfYb2p zAuO4UIMf5L@K%m{#BnX3ZOB>hu0@(98Pyog3XeWXdfLD1;G08V5vz000~L9+2pwLO zw{p0mP(ki#c%U#IOuudKr{yZqDOtm*l>?TtpvPX7Ek@F&AH_ zk_k(9s|UMf(j}C3M+<&jg}2er%uH%H^Xqy4cw>#Rt3y_$s`u19f)d&9O;z`>H>qD5 zmQ{|`>Pzt*S2s;6cl@89Ch(QITRmUiO;P~mj>K~ zjY!IOX{>OPpS5?$J)TkB(3#qC&;@?qW8< za8Gwzz;iyJ7E%^Sb%xy2-qhIUH`iDS1A-@}D;=*Ubh~*FYAXaPIxxp&c+a-N17_CN zr2!X#I46XE1h5FWXP{r8*gYE|FKRiaGZqx8@(%*o@a4_7E*Aa zwJdf{C}W^yd`xQiD}of-V3%2e*@EFA;8Y?a>{7JN6q_+Ls< zPViQdIPljGqQf)#Jrh919G}#Ggs0!`II_cP#_oTr^nDtD_sj%Dwgxpmb+k7>13MHn z5O|lxN?d_pkmztC*fyO_EU0j^$ z_j1nuJY$H1oo3JgW3Q_Ay&-EvosJGk~dqK@52X7t9o`b48es?7$y zP3M%DQ)#LjloE~Kw6%X2*R|_FjQSulx?&dL>W%F##+ie9mKQ(855xjYe;lu9Ysc~8 zdvFM&CP>5qFfu4<;f_n%F@GC)`?>hG`n&xOuU9+V3x}#qOJT{uZn&Ecv4}D~a@(yw zuzeZ#1ayfDZToycw=QhLW{Y_3@?Sm1JINfb(NIKU55dIB6~qd;pzw?Iw_EX#p8Q6# zW??lIxam4}Qh%hiMpx1{R|CcwrrfD*ZT-PSF9MqzhHOylo>)b#dZclC-hnM*X-6wg zh?K6CP7AV7**{qemh|cM-|OfHXLgn)h?Qn+PmOtCfu}}FFb=zB&KumZ$A?FaOI`9u z?t=9o5kwdqq^ljBWhTOugysOzZxWL_s24>?g}Ql&;_&UPkt zCQjQcNn2o#Ryls77;BFJFIRD#xD)FztKn!Sf*hQGE$%yx#p8V7v^;h$jl^Rve` zL`eX=zfA*Rt+RK`4``P}hXj8z;Wl$Na|VgU_P@SdUyh(i-w%z`-Z0AvhJVAL#8bQI zn@t0@KQ0DkV&CTf>tfs0oz#~Lj7LUbrwE?xBpo}UOOPv3H%9+81ZPj%4k)GWJpDa>`@1Vb^B7fvTJhlG*jMyp=t^&9c*=XD zK-(oH@}vaAqEO%+8#IrgSXr|4LSf}srBV?(xmT=$+mm>ojC1Gk|6xuJWM0tVthUl3 zOLNgDxgKUjmarks?rwlS^ZZ0G_sAjlhWL(Hi*o_^z3GA!zFCii>Ap-77XHI{R4GA9)VH5*IvTyn2swlOo zwF^9Kl!bU?I>fI@TA*c4XPUBw*DiH0Y3lomu|rw*(IQ4gTnkE8l{df=n8W1 zAC#cFKcHV<>Zx~z9lOR%>`-Kxtp(?+kg2}r&&j@H7Di>+8TJCgdt4d+TnhFz))~lv zL<+z%&+qQzm3FrC?PZ^YN)PUfQQaHRudOrGi)L=O-rt{j;mXkXI|K^pyi=!#s;c7* zVs6DtZ-Uh)KFo25vX3zq9l5?@4uK{1hJZ>GB1>0Br8fgqaqSM1gvbBAIwe0XeP3{y ztOv_4z?cd;MUPmNv;NKkDD>p#7r(!QW9onK-eY|}PIEfrDN(8ol`Z`7LL~P_L=W6K z$-dH)_F3T9X^kr_@#0Dl0q#wxx$6v&ykEL;tV!&Ut3&j~?vrr+>%q;yb9~=IZ0- zoK-~xO0qII5&wsLPo-%gfxEi3Q?t}4B}d`u=fI40mY=&qErXs;lkLP#EPzKDrJ2rL zGyCKTcDbWGsyH!J)aBxL zKJU`!IsaqwyJ`=0p~_74XM4fC%pcMf)oD%H`l?l0Td5vu?G;L89LMP`*}~Jw`_roR zoJ?vX^Vg7%6*3GnR24m_#~(4LQ7ih9>vh`av$-sobjn;rtrqy}ZO-uXv6ksTqC^3l zE%cy$CmJFQ`7ZtwD-ixs3O*#-uhN(;8`!vzS zS3?_INiESEy*=VCEfq(``(t4E0Z-mTFhDQN5zxpf$M=~GYZ`!Q^1)5>D4obl7l zXeOuNx-1T|XMskw z8LiXkIp<8ed>(4F618*y@=6NgUoObWbg@|6I(33cLnYtYzM$1Ce9{>rrUouB*8>wM z&O!Li!D-pJ0WVqYMnRPfiPqFs^>ApfB`@we;X3KMZ#Baz@jBKzo(+m?Kx>aQ?QMW( zulLr>7I{F-<>RH6o1h?O2WBSfMvfheAWouHo5$6-mgOMtpSWo}z2SPCEf`skQ>|>zi{^xCo72Bi&66Y}=H%9-nGvU!s!ZjZApEsZmAt#&vX$d;tEF<+`{jV(+B#q`GSaw>~@Vw8c!JhOQGpg{8U2xZo#|-f_EOhs*3yHS%=KapZ_#$KFQ`T8Lj# z|X$GGQ!XB2vjF(Jj>n(**J=Bv;Qf}(b z+9p?DNq^{F{mCp$om1xm{TNiQ>y5Bncc4`cb1QCnxm7DO$szusgHDT+sluQU_?2~* z5V`)#orZ`1a)42owm_i9-Jj(SsYCVFIiq8w=_L0%Y#}y3{%rK1B5}}hwTDuBvhsvn zQ#h&4{JT-`&}%mdq+?j!d#YFmjFD)P6=O6r7e_UZo4Zt!>C~ncHXm6qK%7AEwwRH{ zdL!Sx7n%#r(~3oEA!9mh7eB@(JPp*`fK~~qrG1c!WfzcivF1wPNvg^{DagQF%xZ=o z!u%6VmHsVt&I6)f0Tie}v!Gmd2PqIO(1_Ljz^Er$&UcY+EgG}DSP8@jXzOJ zH45_xJ)h#ZWjxb2f1mxlQNhcqyOn688oqY-15Bfc$F*qU-Cipvb$oUfk!ltmEfCWS zo-NZnS+OghaXpTBvhl9!$lAZoC%E;0B8Neq3}1_Veu|Xb8#P=<=Vnb!9Ovb4HO2YB zy=Mv4sdRpvR!|ff@g@CR8nH8PsJ6BI}~nQRv*(gDUtu* z&mxy#JPOGe_SYGXCI4rlpn z_+>H-yk9M%oJvb#Y<7P}5r?J!O%FwtK(N0sY!`H3c3^YhTg7iCY*x}-4ONglr&tA$ zuuQMUKmB*jdaYH#bt+Z6B_+edEgI}j%kB`a*l&7h>1w`C%l)$TS$xaGQk}3AljEHu zA%dizIgbxAw}_?02K`RfETu#Mk_w(GKo=LUDl6&71WC{B*yZqt6ErRyA|;ibZ81ny zP2mX}rw0iee2F3yuf}SOz^v%yt;$6#BPBAbrqq0BLoexXI%cN{C+g4VE^{Gt{WVl; z-mnnkOvrUkaIcI^ZKnYm4T_4Zr$lRzb0G3pK`PnG>-U;7fq(4(Rvw75M>ypdSd2A2 zZZ0>AwN5nl*HqFm?{TW9IH`PdsR^St7Lw{d)PHz>xPAz$CVi(6z-!b?)=YyaPN9x^_3M7Kh$0Oq72_oqA{0VL z;ldFj5Yp~*mJEeTPuQhlABSbmapdM%s@#g*s#39dNLKvS4_gmkk5npSno2n&cEHVz zqBvv2b?j4p438-2V>epLd6dy+WYPG_5Sq}JujNusfg4Itld1(O*RP1;`V){b0YU1x z*XHHXAhWbo)8Zv3UooT-HT7ww!oEyk;nKAXd zUMIL-K*vK1xJb@~+fiF9u2T+u6-u_sv&7nIsiBrPN^1T~P)1|C0jBK}c{*d`_QXf?cbF)HFAM0{*h^2n3TZN$fW zY&$t*qDfi*t)I=4gm*MXo#3U<^Vr4`H*u2Vns|5HaE)B&?&6Vplv4Xh^nK3Ww2VKb ziR_Bt;Hfn3$LmBNfgNtRus;fJ5@V$xV4-V_s|m!0W||qtSN-d1km?`fPmOfsX;GR% zeSbmaOJZzo=XhnS3}f*=9pZ}~882X+5#d8Ty ztEJ&45;Y+PsN|U2v=8Hn%yv`%^U5(LmsP=-<#`-PrvVVsLXg!tzp8pumgua{RPLc# zWluJT@<|!J;ltWbgIPZHV1D^tBVmhIZJ* zRqP=9m^lo9qGt&-?XFboS-sqwex47bZ2G92RkJ7SXI!dc}3BA|`UvVw2{4 zDVWgc-fz92wga&YPh5z5;Jr(;$_u?y>eDF_)@jZh=1DmqoEJbl$qeEG%GV92D{l4> zmg^_kR&|dKKRx{;Bm!{w&Yf6!wZACN4=tAh7J7n86S!Cn+h^Dn+h^?zm?mPUM08>b z>Z-{Imvdz`^aF8rV5x@Vx)uHDz?WvuRkhw%2!fUVzk~0q%sq*giisH~Iw_PoVHTYa zcO%?(cdI&FRf%U|T#dz%$t7<(WlQ~gC&8nSg@$YM)izd5!9jQ00;UaVD^xI4!u>3l z;g<8A(+PTk4$~C3cealK`=@Vi^XoXJ}31JM}>{FzwOR{C7v2%#kQ_Fw& z`j@jG(+REP5H`eG%?lmV3c4F7n?&q~X9e^%!k+O3FB12FU6~eYrYTLp?C$%?=z#_B znXknGBv_+8iiuU)`2mmL3uO(oY)GKDrJi*}MC9vgywMg4n)j zxnL>KHjKdX%$i8D@2o;{$#vUgi`fawu}C{=n>mGtS$h;D%x8+;6ADJL@cyjdo}qqn zwm+w-9xl>_PWfPMSUb+e!IC;Hmo7YhGZ9r+GU*@1J*-YMb;=$5do31XxRDD67F<+s z9weLbUptQyw2yt{7QgUN-MFK~721E9-a0u<*5!X8^fo_x><8tc8%PDSu6X8FzgGKQ&8Sn3x%rPdpzRvM*qp~2TBi}~JX7QcEC zzxpgM-Eiic72@XV zT4u>j6p4oxlr+rl)S(SJ3N0Q=EdZs~4kd@Fh*Y)4%{^v^i!|;iKSk82J$Eu+73v}! zyj8vL0e7_vfmUOQk-s>$8 z{H(jwncA7ahmxN3z)}ijIDHP6eOD#bD4hO6zYN4yP5Vf)QHbG$vhi+xXMTMN|8w&T zHT?gy2JU?qV=`jcuMoB+B-K9yZAs~HwW2m+=~;IAU)n@J?ER7#EBCjo9;2Vw`M+P^ zR;-PT_)~C~q1`M!m^l5@>n18Mid6S!JEWg*3tftKL<;@{tcbW>lv28>bj*MF3i4AX z3XJ`%8OC)(l1A{7y@!qHvrIEt4)A>0|MNxu`mtYb^jW$Dt{%x=$Xw=cn&^n!=t?=n z?|&*5=D|i*2l#y$G7VbKTE=2As0%gP48S3)yJdvi!^UTQ)+PAVi*&_j7vpUpm$<6h z0{K21!)^c1(4tPA@sV1xG+v#K29(ec20x8%ku=MA76X+9sUnIcIY}JHcoYa9K{%-* zWDW}0EPkf`XCo8mlq+Nz*VTND5w52Ea*e782Of@n*gt2E`1n( zProKpRo}z5_ldVKT?}6oUp*+naj;Y7r$*&(MYl0%7Zi+N_u2!EUIIl~za{a3Iw2hU zwSXl(#wA#;P(s0?5cIB^rfQiZd8MNpCc9sAu)Oih0_ydw%eV%Md8JI;`oh<9iY3b= zyYZ{4*>Uxv7T6-cns7>TkGIyUHMzD6r?p?$xW17;r$4uziXxRhTaPx%(v9B7abZj^qBX@3Wh`SQRO@=Ij0Y=ZqUCcOwTNm|4)6ef$b+uvzP9v+G z&yzg`jwwQRD1>4LzE^m+NzcDEI9o))Kye6d(*hGNu>oK)eMN5WxR{L z=M8)Q>-6`dXeTXxdXgk1xz}leqjFB0%?RSIOS9T}VpNFqE|x9o zP|>chS>M(3p#OEXmlAOj%W%?O*|qayqF`Vmas0*b{T|}A_+!oQ4T!YtdK=K5;b<6v zT6&2JgCQ;9cV88)Eh=3?Xz9QBiYu6BDVgSd5zdI(u!{*IRT(%zPp(cd`!wV}uNG*b z#vfn#@bK>@fl?0RVq>pK^GHpJL44%3y>uf1bFYoPFq~xot2TdCnMU)z^}Ui)(J1}R zaBeNO6M|ae^DDtC$?Yc&KkeT)4xPI8g5G@NX#0pL1b*gOvhNRG za6}zo2!gxx`-mU8M=rev9HZO!E$$(8Ko5SwV6DUh5yN@wTjKlMnnuCb%q&(G(>2!9 zvunY%fJL~tFPQsk)gl~0;5jBLv%Ue zXG4~9-PPlg=+q(fhMa!%bZ2tKm`H1@AQ>4d`1!|$Z$a_iKY*B2{=0oqD zrl!w_**dEfHdy^HGrvg|>B2)IdYYPaS5cti{IsOsFv6t!daKOD_|J*1?*0P4ciKt_ zVl~lc;z)OYmPztT^OiSJ>!7|0wUx#HRu#h2x3WF56lrOH%%;QU0B zk5GaH5w+C&aR67Mcl>EBI`T2K0Bf3#^@GJEPmCT5n!n=<|52`!b_;T)cnh_ntZTvZ zCS1OaA?||6r>MXsQPZW0)7DxNs-(4V4JbFURIT4zST8#FiDGzUmi~*n|CU*!HV&8e zFoPVX8qua*I>Z+WIJ{vR>Z>(iM#uiHn)$}qwOxVE+N|m{TuKbDOAZ=Xa~*6If?Flb(FUlC(<~;%H`GV)u zo_tu(0?%f6RiE*A**cHtk=RQf#S?_Z{H&*ft@nK3`GCFR+3xu~OZRkny69gCt+(uM zou>|Vms?*uSziZP-*setUnJ}M5?NmlS>N?!eKW}VeuAv;2C}|cWPLwH);EW&Zvk0f z{^i_5w)6Dwc*wiUY$j}0{HsVT6DzqUNUvoJ6+%cb{9{7Ry9KWe3$;SM&`@$#XxgwO zv3pr5z#-Imfy?y>T7-d+y(UU|FYZ6{9&WX_1q z@wSV5#C`s)eucN)Y`56P+s*wmYC9lbjr_F@cK$5hJpV3?K(Z&#lZO$1%kvgS{2fmr zM!eJ`KyPG^jFqW_|N9Ml(Vhmy9n$>#xe}X0%upC^U+nDrPvoP2_D~10{H9X0ODpCE z377pLV3_CcHZoSY*GjKp?41#o>d*HVBINtMegSd0e+y*YPw%N8(<0u-Db$u1f6dZ1 zwx5kqo43L%XGJlz?eMzed*9Ng|W?#aXx3Jk-PvN;Tafk0X(-qjivb} zd^dcPzB|5qkY;`JzD3`X-|1WQr}#a-?fwj3r9X>$dXu#-yp7g<#`77xZNH1v!9}Y> z3at*Qo(ilEZdw;!rgdTcZ*ZlJZD6_dy!3BS(>e&7uZ8B~Z+o_Jj~}+gW}mV@f;Obu zZ!$iHwHEcDfnuAl$vR)bj(R>$PE51=TAxaPviyN%ncwee+L70paBcUh>yNG3mgi~b z$CX>_nM_WAQwiq-3Gv`6cwNKboYk)l{{(%!b~~THk5{*0bst~+7t+U~}Ji%n#Yoxc5BJ-iK8{3JGS%g4%z zX*O@`$JBEmLGDZ_)4i(Pu{H1cJni|oa%;8S1pV(lm2f_g5D%_`*EI~zS$!ApzkjTL zT)T~H_hTZf`|;wxkbb;uzg4WKUM;RJ-d0>!ytBBmcz5yM;{9NE@j-Bi&JPzKMSL8b z1pUQliqC@4;tSwR@g;DD&aa`|nc|z^HkdA+DV{4{D1HQ{ix)~5aB;aLwRo;1tt6A= z?2@CDOB~#uU?ecm=MmlSzB zD6I<|LD?AM9_06Ud%b;-PkV`8cWP&{Iz2m)?aL$>vVxB(l zT?9*|PLKjT-X-sRX$HtD%_TV>6qY(m^Gm&SE`V~drBtW$>e6lA#nQUcouzfSz7gyO zdqG|4esHk#5Xpx@d1)i!qjY{8oCN))XXyNF=_u;BPA zU?$<(xzdHwN2Lp84Dno<3#67YkVfa3W!cD!lLrdQijZCgq_T>#P?-U0Kt)+Cs4r^( zO?2K;){6LmMLXy$>qh!9aH8x~*+AJK7zXFSsj`dUGPp|db)?+_Q{XP;50u>p55Pk@ zf9$iD4fv9MZeKds0CGUGZxh%IiYfLZO#ziarF^$92DXCjbiTv43vsh=&vUcS*XHX0 zUA`lbdmwX;_lJG5Dxs@KMLeOMPCN zeM@WMcXAIGIQ<#^ERu5}=Tmy2mF^{((w|w6K>mL@{C_j9_HXmoft^-d?QcZfi1S7| zUtNB;f3JT(IB3O(z+rF{@Vw)=?j-1^_>BK7;!$t`9QR-HU-4h_-vqZQp7zfmo&yWu zivLl71zdqtkY>f1ARFWXo>vekvM2+RC0AH+2pFKodgtWtn=O!A06C+J36 zOW;`GMBo${2n<3V3=Grxxxht=FN3Q{8w^|z+_ESGk|kGIaR?ZoCNLGa8@LZ1fQMiz z@K~^$Z4r`z8`uLaLb`chVFSnk>48CEldxGR27aJ`O+uxh3Nc|T*bY=-hp>y{W?_%8 z542fvA{}d_b%7%!_u&4$pbzv2r-dPkN38fX&5^oxf|jv+n+&eHiPPa`gf zmsW9QS+;(mpm-YaUnmynR|@{?#GK@kQl&KDqQ4ENN_kR&R0Q(quf7FRg%kpYRD-yd z@6uFXO6>&`7DsQ*o@(!>IdCg#tbYI>Fc-c1dHw5_z=&@u@FX#iOEqMrxfb(Ds zj9caS?*o(a9r+%Z1@o57Sp-Y+9mNS!fCuMoh%-PI$TiDZzX%9Qxw1vkK{eP0yhNR{ z(~@}}|6QO_*{ke_e2~%)DTh&}TB$3kQI5j5YJi_L48Lm_KG-n%Yc(aq%5gKMJnpw) z+?10@@8{?IR{+G^PrI&+!k23B`r%(qfxFz#A|GqBa>0x#kNasD*W$fMzr@e^F9XQK zI4d{l*MS*j4lIC2;3kLv<=>L$=sXpq1v8bIU^boSDbpxZ5M=y$gGER$3rfKX5aNHc z57q|jA#)l^hJ$#%V2gKiuoWCY9;ZFn8SD=7zgH&X4KW38h^c9tSW?KeJ^2UwEthpAHA( z`zP`*TK6U;G5#I$bR2u=tL%23V*fd%ALi*!7cXgZ@)X-~O5e_pN!R(&Sx71K^hNyz zs%JN)=kco?GhBAHP?-ighN%8Is%>HAOYHVeXCC8UKA+;PqLe?hzNXH1hN5qtg}Z6-)TQX#|FndeVrb)*{@N`DKmZL3+)a&)i6g#^K0+}j>G(yaK@+&e1G0H z`VxB$eWCp_eJ|Zhve)q=UIUf?B~Q1#Vtun6NA@%NLVGdQu*i>&YPzE97?s%C- zWHV2(<&wOcYA9rUcQb0Ob0a_6-s5E)1tdGE#Aa;vFT2A84bjK24Xk#Y{vRRi=CXGt#N>Gq?PGGIRA5{)%o zb%qslog{gL?xphf;4bNWHw2!-Zc}apUAvdc)KTAd(%owr&Do_tr{3eaZYsZzRrH2?L(UPNX72eo9o`9w?qnU5g93+m^yHP;-Mr5k*& zgeAUjLg@cdcm8o!RaO7r=f}M>5{)=>2Sy~KVHodR=J!1VILzFcK_wm{L-IjHLnK2a zqmhsdi4Y0NFA?$}@+Bg^M21L2L`sN6ghYsBJ`?f~5fTv+0TB_>%)Q^W-un!WeocKn z-}>X>yw*COv-aBi>>q3Iv+p^>T9i3NQ_ULHm;Th1VKL*9uUOiy@daj5^ZU8WW!e@e zC;b@y23P7g7xFHkm#)(KINQ;z(y?=v+Sa9sWe|?3mN17txd%x#eO{d2Mm=}ySSWV4 zfQ#YT@Ji)!_buRUl=e+xcC={ymAfF3krDqsd@b`-^Im0ZqFDM(d-boG*YK>ni22KX>B%10 z)g0<}9g?Z^(j)ZhYH)2jrTvp0kIr~fXVZ$=T7KJUB**DhEuk~~I+eI3#BLiv51&G^ zGd+#5(0D5+7^%bPXT$rXUlkr9V%;+AHkSSt_iDy&TQpJzwKdf618I$uGCuQnErB+! zr`4CK9Xdmq5##BB!+Kw56Qi?Tb)s0Kv}+sQCbjp9Sj~>uRg0PU2zk$GYIL2J@3g2y z*1Bd^NbSj7@>XhX1&iDtOKPq1NGGkE_c5$`l#Z0SsBM?tSWEwZ6isc*4e3|luX4u( z7Ov$ykp3EZwYMj0ZwUV`c@L5IIF_&W-(7n{tet2kq~4nTE4W$LPkMVhI_uD1WjTGa zlo|0jsgF^@HMHm}-0K<}U0O@<7++@t`p;1QC#iFGxC-eCS<6h>syZH)99hE}QjN|u z;_pnQPkLbIJnym&giisTO*!Ej`!p@u&C0C$i@5JO@FZ$v1>Q~xtHAr80AGg>Au6-rTsICwRet6WKGs}{vdoKZCuC7Q_NhOkNy^$i@V%OeNHfH zsc@~Xqi6Ik&(VhqY%3@yTjlaJ*Rj6HN;O#T8(pY>M=Z1Wd8zaBM%ELrmAf2e1#4zb z6;b|Ly|2vTzcUjrXJwA@#EkL$Ra@P|9M54!_^h;J&_BV2AF8Ze*t!qjDf@jliZ0uRuu2E=jQXV;@+bkrYldsp3&GnRm!CmBbc+3B=t%AEW_p}GY9=}Z>GKX zJT^Ad^c1{}dAgbQ{#JSByswdBIw==C4lLZpe=!D6yhMHpW4_=EI*jl_RF^QG3o$Ih z=q)y43x4Kpd=?v%#YSVX5m>_5EBC_j&1++<*yt)@TooHj#YR!Fu?&crVxy(lI4NOl z6dRqvdfLZ3w2gQYMmfQ6vyEwDo7+M;M_4PyRM4N0jIT zVI&S4gM;WBHtvRvxM5>$*eDxed<`2}<2amX8a9rGji3?6&ahE4Y!A?TVT=r-V}x-r zY(xwj^TNitup?qE!N#+&ZO8w%jb35nRzzrvja3mwsj!wnWC|OT!bYR8aVWwF6vUng zqfQWS!bX~~F($GZBO6!3MwGCzB*G{X#E-BsBW#2S8ymt#g|P7;Y$OO91HwjsuyG%3 z#0MMeA&lTa>;@aP!NzN_ks54_1{BfU$BuEY|I54ZNWxZuu&Ck zJOvv`!NyPsqbFEz^LB>X8DXO#*fp$Om&bL1Et+#yZC*OL=x4!YMSNzZ)zFl+hfp5Lvhkoy^$9vnKc)7R! z?X72f>(f5;W^eu2+gjnf-g>RK{_3r#dh4U!dZ)L3=|hk7))zf%i}gPrdY;EtLvQoe z&pf?neal;~^46cc^(1e7$XoC6)^B|1G2U8;UA62p$UaS2bJDl^1BH){$c{JtK5!>+ z01m)OaFu_9^2ki^6yep8$H4=^6TyAKA0bz%@ba*(g|g6Dy^XdTjx=%iAY?X?@C(1o9hBOZXK!KGyY$@~Fl; zFj-noEUGn(Wi3`4i%wM=%UZ2Arnv1n#pzkmrD|hYr?nMX-QX9LM}M#7Tbxx0ejPdX zll3Hc5O{)GTI6SHX||2gqpF{st2nC@nyu6}NjZ0*)16c-Cu;!wby_{2)Ggo($cvHe zh5tn**&m|JI__>~M+?|R=OIe|KE2e!9bNAJ74S3URXeG)Ta$(#fmZhqTb-ojJJ7im{jY!rz_ZBJ0A?0vVaZY2 zoAohTp?3)kHNkF^(Fm!dz&>~R6Mgb9k|e1=Q|pB%vpl%9{NKa>6U_|rD(bwMIx}{e zCpFS&=I7w=YWeW$%y+;g@VVNPVd|4`W=&=q*zyASqsVREb>MZBwif;yB)IIC7VpK|iS55W7AYcsii z2mTpy#;EO^-0MfkUr?NODFLes>u?sGL*$ZCb3diO*W9uEF0=3R2b^QXe4oZ*cpL zdN2InkUS6PU814wW+ElS6#&PS2cSB5uK8FD%FnBi@S;j2N0esCT_l7aJX+~KXS zGYJXbSt{&)6sfPm$I%v#5@wKk5l*`tzIvDy@DCw*82l`G`DT&c zi2QqSzM+^W;8(*L-wY$$X1|ZnONKg|&ysou`S0OBgFi>D8o}Jl{20lNNceVOevX8m zalQtBAKZ>3BWM^ww;A~#;dfzs)Xn8fibHLk4y?na_dgH}g3BS8&z}lgY@c zZkTI^KF`=5VBR@1!M&`NX5<;2c?JpJ)cgUA5o2NOmpjULc-!XKFEVyyc|+y!_R0AM za_q;w35mVq7r=v%Q$vUK$KwsN%U2SI^~Yt!^Qo0*d;Sb1VDpA`z+t>x?(Td7d^5SK z$z|;s>|=+X{T6A*bS#)}e_nSqvye0+!Mf74&c*&c#?kGI{4AL7cRp?LDv*2x3Gcu? zYejq$H1-P=Hs2m;Q{fCi`~XV8nf%1(B~Kc>();G_Wm7lPH<)i^1aBJr}BIe?C?Z$uSHT4+MdXLyK){@YqqklA1)nFN%e-^DAh{y66K&n)q2*}(t@YYH05%h` zmd4xrD9_Lc^TIqs8=v9suaLTsRNCU(mFLEAcIaJfE^6pjQKs!f`$gNX9<0(1HsJA< z$}NL4XJn?u|B8ijW$-=HU|k~*Tx!>W{1|sQ?HG`RcPf| z+{VbJ*<-X(hcr9Jwpr8%oeV2XhSs&Q2Tt=GOtVU-*~zqFU1|1OY4&VsY%gQW;f@9i z$zVSj_6ZsGOBw79&w@^dU74}FT-L@k>ra~9R~u_%n$@Wdn`xU#TbLbfl#{k?r?fOr z*fjm0wryu8kipV~F2WbXcPW2;8~A(hpTh4%ej8YRqsi|F^krA#n9CK*{``CJ#q4+& z({IZEAUjaaH4D60R}B4YG54;tt`&D>iX`=~-fV5D<$SFk8r{YIO@42hgIU+JqXtI~ z=uRX31;x?br1sX-^ly<|fUkmo8-A9&)o9+1BpdzN;4{eUk(@yC6kNZN9rk~ydkMa? zAJ#Wr-VL%M3XUR)dhjb$r|lI@<*V`G=m(MfC)lNgB$DSS=K&=0Ti&}jeHoH3z!&O$ z{TAiv!PMd3m1n*R-U=TJUx!YV)GLtu07*7@F}O2aN9|zSdF11fjD(M)Cw~S068MkY zy&TEiNFF8E5U}l;0i<5ZeLsMN5lLSK?gjoJ{9*WIM?577#(F32OjR$FC1pY&~{=MQkn;I?FeW}h_XJuxMVr`dj_2Twl>67q}A!$^d z^!4B^x_3n~Uf(-8E8AWt^+wfi)4vJ1T%OXhBb9xSJYl2S8<%HgBgs{s{-jExVta1? z=mf?3UP3g}@Dp(4(O;7qhkpq!Yl8a;f0)s~bI`wy$&UP7d9(|7qssNKk|cGit~PCR zk?Z%AbJ0m~nS)L`vI0CtdE^Wwe2-i@zQs|sr3UY3NcvL32jF+=^Nzos-PE>+)I9Do zOjG>}l=f5jqv#v>50F$*at^s_1oxokzNdc~H8~yVIQpZ6zkmfUV$>Ez^smTX;P0kh z&^aiQ-@yNh&S3DZGSUe+s#*Z_b0VbCKT8Jg!*Z zz&j5{FQfmzjO00Z2F~As=qNag{ky2oM8y&Po2$k8L=e0TegUqnc+!83HEkSg*E;y; z;Xi>t4F4WFAJ-=l-}N4()p?QSaIN`+vTqWc^*-=WH2((vA$$Ne??GF>N^SFK-8ZQ7 zB2wpruL1MdZs}FY(%YMSTY=qpa5cqW^0o`WH1X>T2LlZlfmA$Kk7~RaeS% z;JNVG3Icfdj>obemVE;Nv+bbDEuKf z&nEwf@{GoPelq$2xc=38H+>enPpZubUP{eV)ch9enN7{lgFgya?}iEg72PxIym0b- z+0S_2u{Pk#Ty}1kU-q(Mr_Zx)&*hn`J((Bo5FUfiXFoHF{Y(QAp6SuAA-@Ir2udrb zv>TPT{!S#{(yvbLmvk58d`oi)*Eu!TmyvSzQj@WfpD0d0qc}Q~)Htc1CUps^_mL`= z>|WtlQl>t?u3&BXlFljjis&b?0e!L$%;eCbRxD&A@{`nU2=+FV)H8~+a*&LoEseBm z7yOs-YbjwTd9%n>sSRD+JbuGq3)(nx3DPRowP?G|ZMx&H%Z;^$a}eC6phKyCJDdArpIVM{nzidR zV{tnAVR$bjhrri?PlNN|G3-JACeu&fMe3839HHcTB(rs8j_jl@HODb^j)*{|mfc>*M|jiGCA*)YmokblZBp zi}yP9%!cdR%Smne^cm{@4Sn4kf4gl8sg~b|>UCnOwMB*&WsAUe-Ur%Ch(vzL%b>8-d=Lo!wcl0>E z{r@2cFXZoxJIWk9mcLUu2Rh)x9dwSpMepR>-t)cG=iT()uI`r3hF;a%uhVaw@v`25 zw5)pB$KiE-SBL)lXZ7RT*YWN9u_L{uAJq%`|A>C<;XYt}t>I~HW$ikljkTL=w+U^m z-C4Vb^UJmSg*Mh6!u#6B+N0{ZtoFQ6tM#omFeYSus`U!Js#On630)^tI&i4aaG{Yx z>gTt5-~^#bLQ_bu9ym>CrqCR&)l+SC=&N@5z%@eaL#*_)&=#TXA>JjlSExnkfY9Mk zPdx-5!$wx zQ@_CbM0cO$(`!qoIIloY<>$D*Sa0Mk`D)kI?W>QftiH2QZrv001#<2wR3wzB+kw1N zZ3wq>&FYJpWgfBJVR)sxANOfK>Bmr3-&rWPVQ_tcoO=ot z2_;f7+*iM1B^s`ZjHIgD>Yb zLhHHSDYO!qmMwY><#HWxy}zMR&XTWPR@c}tqG6QK7@<2GCN?xTj1bw>@H|n|JL=Rm zri!_q9?~q4jcS-HG{0eyTrU+`A@l@zZNmo6o5J&2(%-DJmFpcLNqG&s8(tFHC*>Wi zn>aA1;fT=jfjM;(8%{Nx<9snZpVIU<>ogi<&6XOYdT#72l-pP!*F77H8WTd5LOmP% zHP&$+6rTH${$`yaT;CAVO`Jyyjcpv?cu(Ebh7paEh3=PrnA$M0aR%q9;d!E_zgb86 zPp@ZN()P-Et`Pm#_=wN~p~c{}jmtQ13eRgvf3wb3uHRhVOG5i7Z)M|Zp>^T8BW-*e z*=C__;GKv3{ZToe5NehDtxc&^cGGY<4^541lC>WBZ9?OO zMuwCkeNNNJ)I6>ywBywBrU62!)S9MAavqvGE9bMw#|e!LDWz!*v`}b?(DJ5LO>2av3C$FmBQ#HFq0kZ`o4&s3>834B+l6*D?QLplI?!}j z=vdRqrn5~KgwlijL7fJ58Ps)9kN>6@gGl~e`4f%Fzc>F$Y_9KJ+O#mP5ayZtxz-`sy&|DAZ;dw;I%<8!afy;5*8H)$dT z`33nJS;DwieC-PPt(m<(`{*0LoGNC8G*@VTcz!cE6^q^#ca%95OW&oO6&>&s9dy>d zMQ_8~-t)cG=iT()uI`pL32p6gy`#f<_ghHIdP!(s*mv#y_s{Cbx3A;d_hUzTYd;?R zAJUIU%nXxuvYlL~hg0lSII4;?1}7)9FClboQtHR*+!b7-t>Z)ag!I4>7Yx{No1Xa z+@K)nc`3EKq#g*mR;&(W?Mc2Q=>B9_QMiFlY?QCI0~R+V_UfK9N}8eG`I7!4&n@CwIFiIXQWM zFh$U~M5fY%pG0G%ndM7@8a+ zXpGchSTI6Ulf#lDlB0}UeJ)w4cb3!<$pOh!@;X5`NN%aWps-egMoI2F^}c#fEnAS* z(B{=NDO=E3(kBa=6qIWH1x=OKP7h`Ynjz&*rdCseYV}Jfs9Dn6Q)dT{1PcVs3l^#$ zLP1M|6~X*qk)UP4N=aWWXcfK*pBA(s*d+Nibz`tO*cQn8j1R)wwAX?i!S3LtV1uAN z!OM(>8|)2Qw7&(t6zmHQ2GR$?{@{>~o}dGGFVxf{lJ~fdesENBpCDEJ7ak6Z$$KQ& zmrM&fB)Rt_&yjbPq^gA-lv>+VExA3lCD@)kAxQ7KDS6nYCO0HE+54)0Nb(+$`<@bX zA~=&=lw2z4q~v@gxq!UKlQWZZs8xG=wZT&UypmS30#o(Zz z^Fgbmzbxnio)~u-x5m^&C3UMHwRv=aHpV{`m7B`3+htSRr1QSSJFC5-ob)$B)z-LA6L>e zZ?&cdYo+YCrpoBI>I~Jinyxy3wcMJXI)7`r*Ypz0GJ@2LWVO!Fnw~X9HHqX&LB%zt zLC@q7LGhaMnjpDfP$j8*WiH4FB)2Aa2-=q1ncSG%ENEA9OHDy?z1BH-Fu5Z6gw{EE zCb>AdOj{&#dR}s&pzP#D8Kt?}URgPgC1+@FBrgO9lT+xcXpNiHIg^$(Wmi(?%tcuV zwkAh13c10?q|TYMvgWKw>U=vDbV*hx2Qd24WIS1}RwtIxGg+iInOvTXCA%}eor9yv zE{uLGX_8Sar$_bq>Q?NkXZ6YIvw~WJUg`-|P+<_S-d}x4&`z=S)zvNGOxasC^1r>i z8j(Lnc2{@g-(lY0t+iXm

    Z!_@l`!_|uieM!yf7bNx4VSHXmTNRu!5E4{Sl$uUQ0 zUPuc=daG=S&~l+wA%5%invnEZAJWr8TSD3%(k`LB9nLN9LI>VL?e%M~*Ws`p?dNtn zCUi19pY1>wLP}c_Yl5`AnodGpgt`j#5GoXkTe;q=rd%lKaISp|HNKfH^$enI-ayR8ZYjSg6%>9Mwn&;(3%$0fhd0kD9yrR55re|I_1!`)S?|Q=Ruh z-is#4doAyerhndF^8RXSV{Xhh^|7p2mT8P#8@tvt#cqz>YzDboXzWu~>yu`2%`QiGW(vv!_YXqFiLRkFscH=E6Nv&XcUL*}SC zVa}NIrqyv}ZbDJ~HnIL<`Db6(6FV1o1ISZX7 z&T?m!v&LEPJS}_2?anS|uhSy?$HUGs=cIGix!|OA9jKaFC96i&H29pVd6y&;s^lqA zHLgmY*j1CNri2o|YKrKphF3MKYHrnZk&Kg+IilfJH7B-IO%#b}BsNk?P*p3uyebeL zuab4Ms!NqTy{mdu6$ z;KmL*!@$Fk4@PG&_ig09ja6}S6~cQ^x2|wohfbI38K57ie&rPO3V>f4oE*6=p-ep$nJ zn#&9J6r3_W#J+mDl_p|3J7dgE##HVRdih^Q&U@0^FLX%gsF3WZD$hV2b-a+c?zO}C zmFM4qTHhu8pFma8$K~rS?zQidJlo`&xJgORPL$cX*sL{f*|4%<6|02S2(9Nz_PJ&K z%KBA2A+)w)19+4C?sMZ$l=af1VusLc&?6#UP}WJ0ikTHlIM1t)kuN=0dah!w&34kUZAiixEg^r(neG;F}>X1-X;Zgbp;IzTL~tm$jC=<=K6^ zm*p?@I$fLVc6{U0{$P4bB{A!qc=Gt^?#c7 zJ^C*r=RN725R#Rx?|Grtch|papUmj&cc7eiN&o*RuN_}?{F2O(9(7BbOQ)7jFP&97 zH$J6we(54sj=N+O45RQ-(Q*p*7$>qNvXfO~wE4I(iE;lja^I7l{60y@?lmz*Xqxd7 zGoki$|1J8F((%Sg%y|cz_b%!G3|eTSa#nJ>zfqswW{4SYW}B5}o9y>mWq&t7_H$EY z|F&NCYbV`KZrmO0-s#SASGZf~ujzB% z=Iyh;{YXqrOiyeDjp?)Bwztpb_CreEB&mva^w}(_I}*G5ENefcbxRZbK!tslN$S?b z+CDSd4@%wy+RL&sa%ak$9rdp!P%Z7D`!)=JpvRsf!Xz z`xLbwB}>p&w5E?d6B6?ii~2;{4@zFDDAA=)R8nUp#uObdI-Z!Tykw4QgC-Tptd%-8 z7VR$DotUM(WJ01jF%>ktXt$&ePE0IXTeLROth{8X)N2&zY?16<5{-#rMe~d1OZmb} zN)w|JwV;-w`I@)nSW&ZRH0u#RT5>YsgU%NS4()&XD5nmi% zmgowa(OY)^+B>}uv>%C1@y((wC_c9L0ZF~kd&?U~{7igVNg6b$x9q%2j`d#t#!+&z zdZHe_{R8*l9QllZ~3iL($ag}8;8_tY{@D`S0C>!t5eCE-q*cx#P5#} zDp{}S>fOC%4wfwMUHryTGNoi%$xP6k-o?i4o!#+>*TthE7j*Uf-m)SWp6GbQdtQCK zBwNwd&4sd?F5J`cC>ehB?)V8sSC1&%BdO~;9#;>G-xMDW3JTZp9MxT*VQqg=em|Hi zi?1x!C~aAHW=%8E_FoZ2^ZsSzz9&7|0TjtTuSoWUMXQWgv<7NV_ur!L6s>;;diq_` z|1Wpn0T;#f{X07|yHo`i!~wR!E(C!S2-uBS0BM5aMzISjcEwI?LB-y% zV=t&dLlg-rDzOl|qDGCC^6ojq3dzr3`M;OE-{-yD+_PuTEpzKR_YUs&{1uU$3CSl! zk!5C`-03ZT_arC6Ipjuvf-0q6i%iL_-B;9~X!Zr7E#x*{CVEGk)6MA4^dLHwUQF+x z&(n8_cDH0)nE+-eGm%-&az8^cazSF-!rOYCDYEtZK}i$lfn;_2eG z;yiJ&_&G&8dO7+yc2;dsZE*~8424f2kd$_gevSdE1*!#(A&wF7DFl+@>*%l23BfT~ zQmZL0o4Ahq__2a>`&wpRHH!Lgm5Q;}P@qm!enN-G3Mdp)NjYv0kvQKd2!f}^3H zQ<1ZuBjqSjz7~S^g`QKsrfBVJ?FVJ45VX~LPDymX_Nn%^@`Mnyuk@Uf+`Y7A+Hz%% z5VVi=oRZwSwIx~~g+Nk*w1$doZKxufP%ofD zASvw}UMMoOeu@l26+neRQd}L*C=!L>&{@wZ5=n}UR;36Nf&*yAL@9L@>Id-95U;8 zqHmlv?iw%oYWZr1rJBz0DFo7jshZXf8S->_y2Ct80DKC8l=0Ab%VUM0@zrzkSd!vH z>Ie~nCP>f8Lr97rsl!7E8eY%IJ!)&S5dx{rMjuFum&Qj<34zp0=>tjO)hlHWg`jDs z=VT8_icDiKD-?ppNzciM?$=mqY-D?dplPV*WP3@<7Im;JOO~bCMWPfqA&``nYIoUW z*gg{bs>h-cHS(IkHEJ}SFI3bXf81*b!kSs`(C<{`b1x^UWt{t;KFXJ_R zWxR}67XTFkN!f3|LuRGvEVGhXsdoVt0`@e@wo=pDw$ipzy%eYrNQ%8W$hKVLWLs`q zt{x9m2&A?-YK3iq5bU${oNWO~8Ka(PyGsc6C3?=5*gkcv?NWVEC)M#JrN8ZXeNac# z@g&9HcCbFEz3X^#d-7Mi+xiPZ?WN~z{Yi>*T~JHv_&?lj4^z(8PS#DSFto`ptp${m zASxC7pyHcik=#&-YIlkvpOo5*L~@QMyjZQWDX=L}YwIZabXL0)>ZSGpzqDLD7f+s~ z<8-9{vD{c<@6)(6(t>H+G>YYBa5E?|w~$*%Y(7oC59fxH+{s)r$vui2MRL#NW|6jl z4_6hwy_OP6krl((7ua92FTva3VeHc~ZW$@NhFe1zoXyvWBqYXeNw%!qg0>lBzC5DQajF0L4wAv8Q~!EcCGE&+4P0hFV(n>3heDh-kLpqfj=q(dne z{JW|TXULgQowx>EL#iuh&NZR}ISbB;>c&}fa;gWX3MkFDXluHRsf=Qz_ELK?;|@{>N+NZax>E+y*3#CLp|p+Eo2-HM()MHx_)2{#Q)!?y zh^&O}((aU*G*sG?GM5gMMp07ElryC)IWx|TYRpMFDP_eq;W(-Zr{ENnHAj{oWy860 zu9Pk3&bd=Et`*msl5=giHk6WU$F-wWoG;grvg0~)ohdcfl?$LWTz_r=rNwy!y-uNC z*HR*eWdOm#ls2ZOP?UkHHfl+9uKoP0qEGE-=X$cBdVJ_#{5*Z^P2#|M--p)wjQvy8 z_uIK1|96Z*{aAkt#{bv)JyC8fHz&bLE|c4n;3Rh?=R#xhX)O1a`^x?0!SXP|Im!DH z`5;V-BJz0oNck9&I+2`7XUP{3ZmE2wJe#D?BB{ReO<#gB2|MI_3C)wAke`)bB+n|6 zUz3-S@8$BxB)DSf7xK5H4Knim6DdzP+bs%8A(8tlOyx3#6gX0QIoS+SazxjV)Mg4^ z9;Ik)yG8DyXs7T~DCCp3+ky~ z-!;m~ma>(QXlg69I+2HvFvnIy=2rO^Sf9>Pf3ga|2AQJ`lA;Z=KpWH;ZBP@mK^)p3YqUW&XoF;E zgXCy~6ljB#XoFN}gY3};snG^$&<1JI205Y)YWn}I?ffb>)jy(A{h#7dQDuN~t;d%_ z+=w&*FRB(z3NRa1vj*^c{hCR@i+kX2_em*62MFbit|l2MU9P<*; zWdsBQQC`(OOm#wDhrAco4F30i5EmgO<0E>&{ti?OehY7j-SHRv5~>zshSYWj>aYFX ze=mGidz2u$0Q~Ns@bD}DEBL$rE8@FIry+fUbQ#iOr0~0c4@3+~sD6Mn6(oolBnKZy zq69<(@<2481VHN%a671tRXg=KRU(V3`&2DT2elEx+h@jMTkOrYr zBHi8H4JzFtAp(K|B1kvV4H5!^bfbVGEggR6=yhGseb4y4-*-Ph-e31@Y@6q?&UM6E z=UV%*uVcm;{6_kLZvMjk`0#J`=QoficSCmK1I%^r!U;Q>IpC5^fucUa-gcR{W8`m+ zvsyILm-%18TRP)V`}9Hw@7>0gTd=}RrdOs~nfEe7h5~u??(S?{K~um0-$8ug`o6y)VI;+ZMdhNVnFWvahYaq*tUO z62n2Lb#XpwC|eOi#1$gRebYGnt&I9@($CvPsWbNtgNM#>2|tk@A{q6`3=Ao}iVl9g z#yNwZ!})+aE`y**Dn#PZ3i)o;L%h;~GfN{kI`PeE=pO3czCyMYTQo!!H=C%u(24() zJf^ns3R^i;|ACU!)ZwY}fRc2#8B99$FD=a=cu>koxNM zVg2nZX9Wi6CojG2xlaKP!Sj%8^e%ara3KuEayE>zB2$bt`rP+5P1-ciQ4tQ(Y`Gh; z=})g9^~ISQg?SbFcQd~nJvvK5Kj*MxXi2><@N!^jwV|Dn!-MHmSR$?Pr4RetV4kPC zr{}ggpB}`VjZ2z|X}(vl=5fyD#Y?UW`9;)Jwr}+*6I7;K%7Zm?srS_6q-EQ5R6Q6y zNM(1Lly6)bED2#&{id_Rx0J&az%<{?@VwTg=iYs{(KdQ`5*q~1EPieN?x7#)w1eb~ zf5HWFLyEJnyUzC-pUJ;Y<9=1@W71jRXMY1PEM-*(jY?Z)1$<{W70N83mhC0_jL_6t zeP}g%#@z(Z&h*FqS;_pSHw4UN)NdIaLKh!S&PD{NtN8QJHpw2}m35BW=ayiuvpyqs zor+S0wwv0AXEso#)eur45&g0Q>YsC^Z+={)$n)G4Bbs7(T;O;}N}j@k!|dJBeO3`2 zYCLNHjij{8lr(~3(vEN}8Rw!I!<&_)*_azGP*;F0+UaWbS@+DG zvqD8uvps3leJMP2Pgz}oegk$M9~ka(Zvz?U2=G8p?EW% zSK&o8PG{Z(+iFS5-_N7?@}8Z(rbNO^=7LdtT)Lto&6O&7$3#;ex5k)f58YlS#Wwn@ znKdgkCfOPGO87A`lxzl6ynTPGo_7nJ7;J9gfA!%zp7*Ws!vywk&x^B(kiIIk?ilC3 z_bL!%JMX+<*c8xITU2L|Cqd3wLNi7}Cql3Ye)%j+zgMYkR^~|$6MD7i-SVa#`4-b8 zCz>oGi10(CA;|^2v8CnU=Vyt9pU9o@GyEh$8B&+HhjJr+NWgcMn`9GeJ;!+iLL+!9 zpqAx_!xY{4?L&9GTJM%r6JEU6vJiTz{OfJ8`UPXRHWb3Q<69oe*LP5_v_#|(vW&@b zG1T7hfbT$_!nHz@|R!9L#~T# zw}$(^Jo9XmJ`Ueho%zY&oc_Dz@{r{H^oqbIPW%y2BX(bZ7|F`I|LcH5wudR_GDivG zQqB>d5W)y)2;tC~W{b3qEAj8h8Pa>2#t&avGgp9@v%4xYhX@)!8g+x=tSis)s3A{{ z%f`5hY}@4d(EO#b4zhDT@dVU5k97K0{3O+nX$;#2Bb|dKqSb-_)Lz~&fm#t?fG=dx}nTiZ;KRv8>l`_{N zPhGhm)p^1p&37^2!2j)LPbh!cjf0_aT@pSoI>rWpyMF{Ys{&JclxYO!u7`E5cghMgXSTuItUh^>NCYmy77>N$BNxO$zEP0xEUk+t(IpH-;Sh8LpUt3T%opW%{2A z1iO6jY(hU8t&uKbi%BE&jUL12aLjuBg7F5yWT4v|d)OoaV=hyp*`=`aW3s)*8+H+{ zZ^>#0!nzaXCF)b^!&hi7u)Hvs{z?yjSU`W4`+}qCZp(vGa0C7#x2yD1Jf;UF)S4Wj zT)D(omhNvc-_v*XG$Qpfw6d8!?PR@KO`*k1kRNY9n(77om9LHk*0HNT1qUWP5h(?$ zxF2fD+7KjAOl*i&7!Z^_%3OT;85tMRn!@_>{mq{tX_t3`onlZr1fBh4CubF$U*^6B zz9DqCh5526`!by?$stjF@6(!x>UZ&Xi?~Eye7KqN!AQcX(d)9hWY)u2ZdUC<8WH)H z+HeBM^(b z^X;Amtn z6)~P!4F)~yfkw_T%&p}7{%nj-Ph@oT6a@HMI(9q_XK7cv!0?!pn=mB^aGdf$Q(1E;^9(1 zH^QGYgY?vYnkG89vL~EGm>?Il{pj#+Il;?fHw%1*)j1A2n?v$jq2iv`-dw%SoJd$? z`1RRn#(5MMHd5$L74@EK{Zo1(~awc=S9e= zS&P)xAr}MI!+jJa^p^8yS9uu0jpEbqueQk3x&>^L*bkCG;n#i%o^SZAq=)!%<@p;_PRsH%N)?9v=FMKDa^rTH@lJ_m+jvgVw_` z^wWl0!@ZlN*qgImBE>%*+z~W5m35Dm&5aTB-)rYce`YB_Eb>vtnPtoHGiA$!=^^*a za!j+4?3bVvSCTKMsL;*wj>PvLt78J~rsh-;(MH$rJW z=Q1qM#KylBi>RgAntI|YLGpSsw}L%-ebq{eT`xo=+DAM52g67D(Lt+GVee8BtB0LO z9B_&ETA%A;xLq@|Xde(?{1$V$f&Kt|=k^oVb|Do|&<$dRjN0>NbXNZ55?!v1LtlCB zO0bSle!q81Fx?w}%e`IS`^niu$hkd#G zJW0KINGl`P#z=oCOgm1@dHdcRs&Oh-WP~J#=p%?lMZ40yI^#y+19|%-j_vTLmXlQ3 zwMede*A7g@bn0&!4)JlaFZkfc;JtVupm$H=ISeh4ydg#HupLBZ!&y=)wMa{&z6>!JotI5X4WUvLW4&6_mj?Iy{p7b$h8UImbt{S72#m|-xwr`|F z)!};`YE5eyrXC7nVqY{|h3I?Vlpc5sm5L_6l7!jdiJ6d8j~9;h&(7!6kItU0Z+bQy z)>-$0Exgy*vzVH+TCFPi+|2oU22F-NMu-qXz@kb3{k}KF?))u$QvagmY^wKn6>Uj$ z38{_3+ou+SUSElpj~d7k;(8MyE6)}&d_Ru)GyAD0RGccWUI=Z4 zT_vB?+_rI7K=!HX=8GK07V7TQZ&@6jCM3XT<=CfMAFobx!g_jR+%D8#e=5`#84)S3 z=t8lc{*9V-eyY8@p;YG0u&s`Eb=j`Hlhf>{ThYdPtBUTbMoJJRY`vJ#zR z7$rZqJ6GS4$X^*cF`N~xDP8kfOsv$YIy8SSvh!pw|9J<|egnjMyQRIP(MIh`c<#D4 z#b<;Syf9jVsV>EX(~G|J4w5IoQf4s7t0JWi@w!MRyD9%2g}|UL<F$9jR;8*_Oxy7BKQz6l@IvZ;5UH}3hac*caAK1*}>_`E}~E;W%EAl9NpZJtr)-jfllIZDv|D=n#L^bdASl#m5j|T_c zNOaxx`chZlBb!*li}OrRb2XwWlPq&~_w6}*{4yN^*O$O)d+@$qyYjw>=!azYDuibu zDSOtErnoYc^5l^pYb3)Bu7wtG{@DI3#OEOq9z*QFZUcsJ0dI60R1fgi%X0Q`$a84K z7hEBoQ8T=Q$WphyQ4rbWeSz)e&kuu)tCnma*YBf+qU=In^oH^l_+QphzOmez*Rtv__+4{q%Xl|n|Erl;PQ_1C zP@IBL+APXJ`}jGBhU|9MoQ-(Us{5N1ONWzZsm9HHhKen@^U6R4Bo$&xclT?cz7r?LV`a3+kUc8kTBYv?^@(-5_YM5I{@|1rRruP5-8u%s^zs}FRZ)EC6a1?d|-`Vx<@{i zr&dZDFJ3X!qrH8&YX98nOMrCgX9c!EYjroxOTG@LZv>u2h7qm`bnO_8_)W%D8SlHi zf&AQeXwc_F4Ag||Z)o|6W+vH~V7i<06UQJm3 z%rMj8sGrHdv$~9^u>bU;VlW|(`4-y~t|MD2I9uC+netUn$zTTH?T*xLT;*Q>9Lto6mqB-pGDKf$#2D?sO3y>J8;j zZ)7>G=%s$2LGKQ~b`Y%z->v#4Mb2PgS$y&_l$dl|TPAa5DUu;+B={68VM28{CAi?z zeZ(>~<@Wk}s&-uQg88?VcanV*VY+c?>gId`iEQ^zuh(u0idG2L|1|eK{*?2EO~8lW z0_^WmlKs5h_w$ll{GL*Slg-BTOYhHM0ps4s1PgH{9xLN{tZR-1W-V`S6S)?3CFOp* zZ>zs>THMcX9-(!#cmN2j54p&@>Qp z&0TX9+z*#l${?b+00&oCt9uVZR`y(jjSknGEH;-HA|jeo>(~kz-@zQDlV_j0Ey&w0 zv{Tv~I-b1EVtrbSxGh+w7I8nT0dmlEu>3{-h}GL$>}z8oTFW_q>(+fYzj_8cbV!KjNBYm4lO!D{JrKU`gD<|ou`>Dbjk9zD~I=z zwBa414t6^)QqOG<(Hlk;#`MKW4Xo<8?r9~u&8#&&nhbB*eIpejBUBxt`h%W}2`MPpe&QKiK42+4i%ktwMSCmRzN8*7OTQy_@phizSUF zDW5wqlS*T8i1fS>FB;0W*3?jHS)y0wFxL7m*eQkWgN^Xoi*e`4W~70ew`2))={dab zP>1y-(^)xLrBDFPG2D5s8kFL_nIo0@v|#665c?aYIoWgdTDvBkQ5w zzQ=OQ8{{L;>aV9xSQ+eRnaHrNMZWWHg6^Icu?eiKb|^zQXaZxi@lzxkw8tNlOX|Vs zmHJYx1*=qxD;+i~&NWG#luGUK2qILw)e8XpHFyPA`#s}MCwMDf>L?#WjgDAEc=H~}KwsiB4x8$qPuI~g7I^1|L(PADsptNyrnzr0<~{Q*8>;z?}$3}hjY`9 zc`m-}Zt!_H&2bzqz3e_HIGnVYBW_~{BY9yqC_LXhlOpO~W;{K+Ax%$HNzmSwGFnx# z;5Pl*D(t9VbV2-ucKPw})zvE*)6w16S?Vt}6kCnbNg{JMkb*s`i>2L3sq$&5gA@4> zuMg=aMDn{0Wh$8wTY7sN^L8UHH1Yz7?`U&F8PEHD6}hZ&)lwguq;hS9rdU)Qezs@q zAYDGlxr%{A8&6mblpSv&4!J)Cq$r%Lyl3aJei-Lr+p=jgP;;zv2wU~C+01QCZt>L` zbv!XH1pE7X48Aq&=&HCq7c{#sZ9{MF*kY!qTvcp|VBQey< zu7muG2Jayss-j%)sp;n9AC4IVUy+(}yvM#>7hRk3YPaGC4;K^iyq9+^EJn`7BI1K1 zyp#@|yk&CxV;T-F^+G%!C{^W+oN0*-Z>eBNJz3qfgV&FU7g*P2eY>+5F|RB3O86vR z@RIEIuqRPbi*A-_{?8zb8_yDQD#XA0% ze6_RE*T}23$SZd5u8x-OP92TkK)KoUqn2meV`&p&`#YfrwPwlDlOG&x7-z}?P5PDE zEW8R;=NSe2ij@5W248pc<1?+NvLqxU_pL`Cz5H<-nxy!sw``E*$gS4r*iv>D9Q!GU zGcs!PE8)U{^XC1Nla~gj;PJDIeHH9B!!zktQy#ka3*>&rDrvsZu;+9m7IdpuVV=7> zz|>H^3GfTsijQCYVCP{B1W618B})|zhjE4iPE#65W&BgMH61Y{L`UO3>t+*tb9aCC z+jvk5G9xxRiVGq2Xy*Uq#xA?CTkMyxf#7O(kPZIEPjwT0WS?C$kdLuPEF zeYO`ukkj}h8g)D3jw8I5(hrn#hvddudbE9ab++b4CJ4z3C|D}NMPD-rxl8!lQ`N^$ zzbxq`?;+J(*H_DYy}NXB_FgsKe0}la3p%+Pu)%r&*#xtg*P_q1yKD4UMBzyJvYU8m zes@8FPv51j9M_*7Y=gdi(^KJfSLq9%e>?WNvo7hH&$2afMN*Dfyky+^O}Xb`v|Tia zaeGF({yK>;+U{$Q(VOqi6fr4-O}C`E1%vYtH}eG*CQIF)$<}#T^=x16+V_%wWW`|? zFYLWts)I}`DkVB}?gteXM6mVGzdam@nMvIF!B(@5@3KBhAtbsroYQ_3HIeY++irHR zP$~DfMk8(ArBI!nrf!nxvPHGaG_g@4dHK|kpsHhVM`-|)FT zE=@NE@oHXEvQqky98wEqGcIDWKNRc~lqI!h13vLg`-HC$<>GjlZzxeecxx%JK2=nH zCV9YPS0iKAiHljdyr17I?Z;)6Pa|XV$xYp=hd<2GC#Gw8S1U(?YIRb*dc=jnx%+G7 z8r${S+1EpEdT+%GE50~){1#kt`k?WtsoceOWz-HoJnox>%khHA3Y)FvPOo-YIC3>% z>}%0$)aU8JUhyg&#lGFyBT`ce-JIRdwbUto&JDjG)FI!sO03?So*0I593;f7t(ku( z`~-D1@aAEA&^LN;V&<0Sr`QmsaKy?~XgH|4VIgx+CaFjGKK}BOM7{s1Ls{qBFAb&n zitk&bVpH298J_`!imRz=*PoG?Pv4#^c&gN-41=dI-Qs!>Gjzwhn?;&Dqdmqh z5P$Y9Xrd6JF}*xp)HZX#pQbGG0k-Yz zoS9qN7knJY%bBH;w!AUAZ#WUFQ)%l?<7PE__ehml&6@`Jb={BJKl^oGXN7aqO*qHa zSu7!uc|4WZ=hWEnN3wERD=Med9dC%aS|o3AE7A*9DqJe`H3C~GW!a7&SBhI&{4_ON zOl0dFyN=LNp*p%Y?4sdXO3_PwNJyc?)W)^br|IiAKA}W9vyW`h8LL=!&wX~6qK5Um zYaY+x7rB z{Md11`(h3?>C@_2ePge~QPwqBg#3VK~%S1*G~ zZ=Rm@UmS=meKuZ`(EXgXrp$cc`0e%AdaO!c)PB0E+3pLicbtA-ogQSX6Ucw!x!vV$ z`Z{3mr&V%1^j=#2&z(0%aJQCR*_9nXvgwljA5#r_Ny#DuyYrJE@t-H;bN5Jj2_k88 zr-dDD%6`_(_dFf-ClxjgrVl#ssA9DjLf7ymLU@Y3Pi4K?l2qkxe2PtQe4-w33HQ8_`Fx7hny&*(gwbzt6NWbY1R;^Bmq zFq{oXY?l>^`PrEZtyK5PYw;|3@3(mpar)C<;TH)qAiPXk#sp*VZeq+mpV)RI7H!e^ zJ+tw`*&g$kvd<`J6$nZo4A<%3!n0?4#xBR7JNPOYdX6!k#M}icL&JHyr^2L9!g5Vh zL44G8btXVV)M~1m`SgJKoO;T(JKafu+4lE|j*;Y3p_rJTzLj=jG=(J5E#pI0!YpiF zVn#oe-Bmr8RuAT##Kb;o&58PGJdNlNo-a4?eC^WES6)*~H$V=275J4>jXm}I+Wygm zd*#dneeNQDW#if>hczC}0ll&DQU&$xNDhaj*qhnPTg`#IlF-q$5e|Ulnsa+AWYQ=^?A(vRia8 z9@$NLo=0kW5cl#W!fArRHgwhuiOFxvwq7eR+E>Ky|TRl35!6^~DM50>t2_ z>O+(3G~sUh?+bs3&Npm+X}BaiJr&uVpC&UoZFl(nPH)Hd0PmZC4Q6^_Jza~F%-yB1 zVHKA=F2|prxm3M1`1j|vhbzXmO(IWOFTyN11s6TinFj6Sa+6w(T*E8kn<#klD16fJhYaPu@`Oz(~k+S+`=3?f{?EbGu?tXy< z<6H8J`(cjgmAI2jN~|hUGTRd(wuY2TVhzbFi-%nKM5I&ScAm+4^jnoU8m`Xi9Fa@( z2#LD%7J|>5!Q(ZCkdv6$8ap{Vni$ypy0kO2BqxEw;4pR&`>$&e5kX}SdlNx96K4Zs z17`z4B^N_yj6hvZR#4W&*38+Q9ST80#l*--{vJm}+}+;5$jZc--O$9$!d8@Hy{3VK z-NIOuLk%tmlC!^UVs3HA)6qo9Q(oD~)5-{K%poo&;x6QFV{ZdY!|rZlZR;fDF3MqG zY-ea91YBdpf*kC>RGh6uIiLbyek2IYAx0wNXlyFD%NaOYS=gF6iSn`kSzBKD_Z0sODk6w6>tD?L%XR-E`J>^+M*sNJ z-o?@Smp6@#1Wl|>Y)ovOodDaxzic-)5^}b1wl)#_^+0Y~JO940w!k=0$lAcxOq9c& z-`K>|z{T2`L+rkzi4)NOmwD{JI{sduwT0O4i(exM{?Dkul@So7&UTK!2Uaq1_Z!~9ai4D(Ot|D_***!;&4{}ur52KImxK);*-C<)#Ey-H;}JK!^~ z|K}LMRu}n4U?O4QY$66k3Ys4T=7+$QK`0>@@CV`tA%#F75kV}?Up?jQj4ez({{Qs+ z7tQ}|TmTD@llwn=#Kz`tr^v|(N!S^=U?S$OgqVwqg|QGs3IVx^0)zPx5D5rBO!6j_ z{}u|2;s+xExdZ|#0l$6gmzn?G7h@Y+!3-^1m7FU;6&Rc=rDbFOvTYbFlw+ zlK;rd|8>`Y-Sr=N;6GCSZ*=|FUH_2>{v+l8M%RDluHV}}P&5Es^Pj3i?0>2jpd=FI za06|k~nJ4AZF~ z`&@<0vqQh1C(jOlzWMg?bz6DhvCi^nI%q(}y>eq&JP>Jn-MjMc-1@~$m$|e(lAo^9 z8teykpdb0osa~|ZLRCe3_<<+Uf-JQLb5Dr%H*Zt6y$hU^ncrwOIGQVLo`V{C8w8X` z6z#-7>7%sq_UNOM*xtzjUAU)=Ua_bkun_oOD&tCM+2Cc&aQ^hZOl6QCnPUq^&8Wd-cgbS*u z8!AS0BnNUy&p*GF7ECH5sHMKMe5=8ObSC=xagpa-$A@MGlciiggaB~BwJqQBu_vXcOVEAO zKhkxWusu>Ni>|)Z-K)B6R+@{xx8iBEGNr2s>>V<+JnO1huOi^=4 zAqi(CKZ}~cZq$J5#y&oYk?yq=(-&qv4^R!#bB|vI$~@!I9xk_kr{prF#4q$lV8mq! z#!OpH$tOEe2wLzCWHqB(Z)Bi++ndqfpT)cvMmdw`TAI({W@`-|fZA-!vF-fpWD>hgC~ZLD=#Gz*^a^lArfBDIo%rL6y2BHf??qURwanAB7MYEOg)7-`zUl1SrZK-J^# z0cKn5IIDhv)WG0-Xj?IZC%U@E;}f$_(UpWoR&^#B1D79#3Lh9tD-}LCs?+%tlc_d` zsk8Fx!+*4Nsh`U=BqwWJ8_h4@xw)E8*(#(?V`X4N)=a2QzhdBH9mrpN8PVK6N|0;_ zC2LL|@34esfJi!wU~5hL!@FyicI&h$5nvP^ z_xzQ~Y0b6dT}QJy*_5zBd!Y}F2PjIj1(uZX;wlFE*<0EHybk9CnqF6tJzEfpXi=$R z8kyCc3}AK;wQaPix`{BW>`$V2JP^Q;x_PU{|w3iHGw zQ5_pBscleq5`_h>+7S8;5wT`w_e+Iy7i+`ZHYujtlif+#=J9Kz_crjwTHfpvur2U< zhYD_>>pR@`>GT$uJMxG}`}Wy{AS&bAM0%<$A=mw4BR?5hUnTiPJestc3&hhK|m-sL#G0wEj)~C8p`t~Cvzoo|w3}HG`GulKvkTT$m z8EEG*$%LP!dmVw0x|Wd~(|O+c@U{V`cTDwpy-fIH#-<2;DOt{Zs-8Ql#-MbDP@qZ3 z83w4C1_(kJ6oIBIXLC$mr>c8SVoO%cjoIafZn7c}eDs$boiqqcX53tzra^RDcs-Ch&F7jKJlmbO*)SWm9Ds z39Uo;kmR+DII7AJLkTd1;Zpcp$psGon5H|%1kiu(Dz;=B0Lx0es&O`9;xcg8+$atL zVPK3vWT|w$JqbuYn)A4pFCBF_IFsV5a1%2tYmvK?%>6g!+E*ad&#%TX(c1tvFmr}c zwS^cCfrRKRB7tT`WK2`1{trP*hLiA9$$gGA#g;odLm*2Acm$Kw&vd_m26Kl@fd}+C z;kHub8Ig)z%ceu18PpS{TaD>KiY>?L;>|D6S_gGq*=mf(*NyZ|c=BXz1(l%p zUFI5$B)qo`03lgm{JUa^r0Qbvzi38y#%~rw2vvicyI|_iH~;GHA8%0vAy;iL0fc{# z31~JI{?319WGF`Uq;ckI51FjoKJ~}K~ZWa+C5Ngzp`6;!+s^NwqJ}_ZJs2ejjM|G*_i~P>@O8`kXKP5=S(LbYYk+sxlTS3cA#Htcc1k4a$sANrm26k!Nc0J;C@zN-pgB! zEw4s+oM=U|_TigNveY&wch;HooHiME#==>Z+Mtn5!s%8mcjon3o!a2NO+2wy>3xQ@ zStakFzRh#>t!n$@CgZhxKQ}min}2RVeVYpR$r~0Zk3$jjssK?wqEKBezuA6+SewKteF!GA@ zOU@Ch6Nskj)%vbhHAXf})Jf!#MPLGqb~sOWy>*{>T=*3bz;~=N;UAeSBFm&SITID1 zF5hz&daKjk*u|g@^lC9SDa#|vjt67nN~*Q1QJoS0pP_OJfUwMJ!o(^qual8USYA(h zJP?5#s)X%8cMtD;AOb^wMIgaRcw)PetO$LaMbQ?I4iMXe`X-5a5ee}(OCbfSrZ1C< z^MNnB_fd_5R5JzwHX39UDUL2H!niTkq)P+MnBm_m-TC`2k2NiVg!x)DQ7Ei#Cr@3f zyX&FmKMRSAzgrAJs%CX|$!Y*XAQ6Gp#l^ob`)vo0^7ez3<+W+CYD)&2h%f+%frpT7 zPRm0=dol8_rm6n_+)##HXZm#`c@sR&rf}BeL0(T}{IwE@lIqpAu1WRh9K2AIe-#dP zeO7%wd7abHL_aSg8sin(e>6+Yfn<#ciGNfK5yRyA|3HPfLq6r*CFb7a3kG)WjS%Kx z@sHj^Nx(04g%gEB%!k8~mA4OiqJ148vg6gT_5_&>-%l6iKAkS9tSDUVXc#|@A-(qbr*j|b-{lKxD<=5RN}|r%Ep$TUS7glTwY*g(PctIoxI?kVmv|vC+o0Y5W|E~&F~t9 z_4-=HD4~|VjCEjsF{f*zFT=3rSm$n6kUstQfEUHwyNv}5VN*rIyKQ0s`YfD*rF|WA z(6r*VwOenEVF+EEWDW3lI8V`L&l1!EJ}W(oVhIPBg7gAIN|+Lesl$j&zA+R<%)KC) z67FQ5&|T&Mkb|=+(c2qm1)2jHf~~Zqzvk{LR?|M4HH>J3S1|$bq5X&#fR7FrchEqh+umbxk;w|Rld$W8b2l=EVf(L@{8R(%Nb^)aYB6XgPx zNLa@PDz!1z{q2**t9#dVn`Gp*oj%n?AUA|`OWmDvy-DrnX}l-Lr!ppLj##JLCfteG z=5E(UQ*JPdwXyBjm4B<5$UP;Nn-uGy-)GgE=k<=X+u%>qKYci}!JEW%8lksAf9iat zjI*?S_j`?LUss6wp!2rfvA^GD8k+^(lfUw!DZ*Q-0FyPHwh~nl32@6ajTO-&;}5&3 zIp#1p2g{=<47k(}%wu-hTg{v9e_OmDgT@AR5OkNa{zoLrZ3w-xlA?&{**;7@p+cnN^M1cMT(Xh@cej@@K^!49xV*F_!zMoBxk$v9m@ z2xkK@dEPV*oy7Dg3d3>!LQM{qz`rJ&$~M098_*pC z6&OZimytZsyKE{#95+@Zh0I8{sJ>Q1H3yNE-@m*4k~vg1wo}dfY!a`GIcFkO53rPQ zWSTF=;^-}(m87adA2}YAE0826VCjq9!)L|I>F>9g8~vz=cn7#5Fmf8P0MMvv#;FKf zDc5dUjrC(8^_uDLZ?+S9hYPR6RF2Zr@}F-FHm$O0KyJKFbU9L9d zaBgW$B!KFB%0^uSab-0RB@#}7`LkN6^G~$j)TMeXCNsXxZ z!cvz5r^gTLx5vF8+R=)KviV;&l1PwY67PO#JBAx67KC~QE zouQxS(2gjsB6v0r(T?J^=PGFaR7E%f2S*u0wiXQg9uQ?vFyUq@AT#=zHTp z6~L5mw^+CKAd|$o3_Q;8F6!4Pia;)6Ovj*}=3tqFh;b#^EBIcEk*3I{b{exJ9uiZ4 z!7=58V}KNJU5Fu+9H^Iot2;Wh2)S!6P|HzS{}`aQ`XP8oe-fSoR6Ia!5n^}+a!BtG z&LhQvX>LhBg=6kM0Ne|dIGy^&AUQ%6{%XcKtE+7gOf zVxC2yY&k<}c$qIkvY!+<8t^m%^F?tL(I&J()R}yWS>&6$)QR(rKd~Lf=;nv`s$a~V zmH5$NiNZ7bHaO$dwfj|%9=}+KP@g<6w7dv0+?16c4}ABlHH~$|PLUX*k=;5ZvgjP5 z!;~RnK}!o&R2R4koDsCDjxtT?+kFrGRXWIzGS(Q;lQsR?{E2p3n^5PE^!3PEd`H=c zW^b@WDxwI24N+081}GLzdx9h@pm1n+z@)ZON|2I632*LL|1}h;*}QYgqiB2jHR~4{ z4y#ViR7nqC{FB>mWy4!Hz4+B$eI0FM2$!+HCeZSw>MU~BQ#;bip1*xgXfkTTp3}Cu zx9VJ_p~zZ$@cv6*%DU>xnHElWhP_$c$>5{SGpwz*-5bhF@K)nR{oicz{8dR@!yFRu zrM7Il7nZ-eJ;CgGv2d2FHUc;+&}~_9$G4m3uhqHZq;|}bHb+$?oor!Ik!1tpm2CQ=e!ypr+`s+h=T;Ra;5PFaMx0zH&_ebM{wlQTgQu zLQd)Dc9$kcP0SRgnk@mgtM5`zIWbKKW90AVb4;_-_IDG==ikjZ^etvN;NZb7qf#SN z%(>3YoI)oPevA2C6rHptXPM$mw%w$CMiJHE){Nq}+>S^nMmsJXs!!THqm3#j zZ)AL`e4>UI5J4n|^Ul1Ez@P^}EO?xTkQid|7kkI>^Tz-hRGF*{`$n0szrloYe$24B zL)<%npI~l%mkPiz79QQ8iV8O?FE7lg1Evm117tw&HCrG74D$HLtaO_F<|Y_a z$f9ZkhJkGTItd}?OtU~tXiH%BX{PqoYv~LZ`EMIUc9fmBF|Lew0XLe>;Y|hTP0Z9C zD;PjDUPYctiX}S;eEhYqV+I>E^#;)87ajQxSCQfRQv1N6L*MV_E5N^E0F>0;u`&j2 zF^=&s81=r`P^ZEi8C>h0L~T;`DqmoX=udc8T%VAn#8(s3xoj!{{(YuW!cjI*oUQ2$ z#q8Eu0OkRZ)M?fV15QZzZX3uAN+}p`-nj^XXu`FUMIY}oeM|suMhDc!y({+pL;#$b zR9akro1-`iIGYr9+4B0^A`GO(l|1L@eyJfilEmTVr)W#OlY4g{^ezZ|wJ~5hEVQ3| z&b$1cccOcU?BCZy;ygrktOj`slIAYkSK_Lu{B9OLyRCf@1qz& zT|bQz&Nh#iPrf=ceV>glbXuJ(+=!SDI6|OJkkaGxHz_7jZ6{Hu;x*VAuGb!%es-!( z4s7_t?V6*PYRc*S3hVaiMp;($*@xRa)!CT!FCbc_Mj4Xzm8^rB%w4Ppb0)NAC?*Vl z)dJ+M%~7MQ!uo1tO&>+mQ?QncbR1f3L#>$Vu6&J!(MU7v#-6b@N`ON}ZN@%G)SfKf@vjrVHgVL|#T2&-!hJ1gWAd*Z*B-@i0w4tA^Hm7O=B6w*Xbd99SfZd*e!K^PoFn-@Hj} z0R4vH<=(m-o7zC6_k|>x1-aT_x6P=wWUm8hcQ&@!+v4+LX{`D9j_OAbVflx|z}62t zu&zEp*Ec@fCy~3>&{VlkF|$B)9OAc0>Dw;2f3acC?f8-SCjIGdlrl{28UO}Iyh_G$ zffOP3f91bv*RW#sJM=vaA8!>7W4$Y2q~A++AIR?^T=n_+r_k~zsO7N*)J9(Sp z;(1eJ{CO~1ucz-3l@LfZ;L0NH6`p!CB_;L+~|2RVr z>6-wK&yi87I0JDV&Nep&RWsV~;amPXJOHrJeJ#`*$Y;Q=tbvITi%fX>sB9wUv``t= zOg{yH4Kv0b470h;)FewIIRzY+25>fSeg=q*bVG=5K!t1~-0p@LXTC*xb|t1`Qr30r zABc}k7&<_kJOHU4i+B;!dB+$ki{U*$WmWiO@quy|fMi#sky?70(7DCabNB0R6tQ1z zC0K3@U6w$~1{A2DiPbmki9YzYO0M^|uI?HLeYMRvkxLd~>t;slSEY4++7%zfIFx{xWc!^Ce83nAhlHUKqTXDQP1=3QrwhSYI?R{E<3v>gZ)1Y*Ty@IAUZ7 zATOpuv|k;iO*Q}_I_O5JC-kkp4^>ZgsR=2#yQk6VjPT4DO}XT6^?uVC(Wn6xc@Mab zr0Mb;YuD%3tq9W7`||4!}Bt7#^DQ<3<2WXokG_E;=)BUtaa)O&kB zlPJDi*3(iW)4Kz>Y*-!j= z7RsN0d^^?M(ZrOT1cZ4f6bbzM`vpeB*%5F!6wZ#h_qPzq{_Bd}_8%D-3A|T|dHstF z4npC`PzVsV3<3cI@5}ysUkC(&#*)E72o&&k@4xB6;V>i=ONIc0z}R{Sz$9E55{7LD z0)|FouMYtS!GO1Z|7~6b9D>B@ivYo}`=X&>7`AO_7zhEu8V?PFLUH=S5OAEna1;vL zUNqnqobiw#2)6&wNZd7}kuVUpZGa4lD}$qO$3q}+)`CQXaP&|h7>*tag!A0cClF&7zD`DfAcdS1F{QSh8tI4 z5E57*wjLS`$I5*$2#piZfDDepSqtD)?6rU)2y8q6gCRf=Va*FfF3xx`5DJVHe_$ZB zuyYWQ!LYFekioHW1CSwb=YS%y^AZe$fpFIc17qhZpa;Xwb3g{i#!f(n0Ac$S216pT zeFcNz#61{zlxUp3a2Ns$ufQ-A6es=wuYj?iFB$^H&V4W%0>`lp4ZsWb^9Aq^=Xs#v zKoVj-OEdz4s|SEF&Ugqw5vMQm596VrxOzaMWA{bk`U=257#0oz|7igX!;UL7U>wf+ z&-qk06)O#i$>x26bNV}_Ph`X z3L86tAOK_UQNRub#pYa?T?>gF;}A5!;;?LkpwZZv4NL(fA(kE#hy?6s2?aE9^>BR( z1@IZ$_rQu#IDHYgaR5c2K{)fGpg6GsMZs~N8-TFbdp86I?3mbbj{xStkpUQn?JEQl z3d6Po0niPcz9<|VhagZmdol!xVGUS*22c(2kx0zzZ_W=vp+GqPLjf-wy+2?C03|qc z0I-YWdo zKn~)L_Xj%w{(`Ib2Ri_MilYblgB<`K;OhOs4j@i(_5NT7fCspGf3O4Kf4F*oumiv$ z96g{W!Ik~N4glM6_5NT7z%6j~{$K~d$8q)kUUe~P<=^w)Ro zuYu+}>wykCykc)jOXnQD+DAw0LPwr+Iu1HgS5#bT;@$=wxp#IPbmSxQj)RWeV>=Ey zQa5%SbmW<};@;4a`LK>#&iQzs_sW3WWA`w$bD<;kZ^uDL=58u3&-}d&I#U039NObr zw2h9;Pj)VJq?YVB=*aUy#of@6`HfF;xz6<*JLi{r|5Mz@Ht5JRddES>4IOzd>0Iat z_bV>XguQLiHs}06N1kIl7dpW6JSrj=I`YiF9wU#B*w#9ZJjZr!>&PP|;#x-@9}(9& z4)A=QmFrx<^QpHw4m!Z|OqwGXI`Vwl$AFH^X>}ZQfamjkU%8p5>1}9_JQsHybY%Xj zDzIuPq0iGY=`H}YlwLkFu0M8G+$3DRG z13aHOfIe>P$V;G#d!asmf#yB0H{iyukC!Ja#U4KJ&_T z4DkE~p1)9^zrgbs>hruhl+P{z82|?+oj> z;Q7p5cO3c^>hpOQ)4AwZ;Q0&n`3pSHThcxTc>V&AEi9`3v>=3p{^;=P&Sl)_K%%QJ=rS^A~uYm-N^l?pLVKU*P$?|ETi=&+|4Pap+g5 z&+{SzxzGWgzp^%<&JR3)f#>snzjL7jJb!`bFYx>Yp1;8JEc~i-Il=Q2JU_wn6FkpC zG907F$E?L!ugeLZ&-%KKgAVZg1kdyGsrLt-pWykdovCvH&rk4t)|_-Mbb#k4cz%NC zCwP8>=O=i6g6CNP*yjwM&wIbp2A-eb`3at%sLxOEd{%7sanY~9^AkKj!SfS5Kf&`8 zJU_wn6ZQECo@X&rYr}l|37((e`3at%;Q6dOtZNFMXH_cV&>rCViTeBm&rk6D1kX?K z`~=TW@cabNPw@N%&rk6D1kX?KeAZUfbq3F8ZDYqZKThy`)&qAg`W1LS>p(jf;~YFc z!Sh)cS^ERePt@mmDS}++Kz%;zLHfAR0iK`Wc^3Bd{!pKv;Q6fks&fI)Pw@N%&u5Lz zy1z`YVOu|6y}|P=xV^@vyi8c0iI`(9O9s3 zor6#P_6E=2;Q6dmt!o9I&-$T`gAVZg4W8#q4D1j63Ot`RS$!_h0iM6X^L)k8`vcG4 z;CapixzGWg=S?Rjjm&u1NS=RyZ~{szypn6CE+ zp1;BKH+cRA&)?wr8$5r5=NEXM|01Y!&H_Me>wa~iKEJ^83p~#PKpdmnBa3xA4m`iW z^9wxBLPqSb`Eh~g7kHize6T<00M9S*`~uG}@caVLvmmq21@-xS|FQP_EM~_x=m5{N zAh>hE^9wwmHLi6o;Q596`~uG}@caVLFYr7c_w~7e=NIbpS-)F4!1D_{zfhmgx0by> zvf#(-^KHqiJal!KoJioy63p}51&emhx;Q0-n-{ARt zANpy3)0R2sltkI<|9+=_gXcGRo)45i?=QQ#QJ>%7`3;`mE4y=k{cU)T0iNHe&*yuq zPkQJ4!1MT$Bd+_^d^cPB1J7^p{07hSF*o+Nw9%Y1cz&X63Q5@pX9^iRCu$B#r?c;Q4&>Smy_x-{AQTp64S^><{AuJio#78$5r&^L#{J$DQvqS8WgG z+n<&3X^8nwy>nZ~eACcz-5%p#QgPsUzE(vXbb#misuj7=0iHkL`GfiP2Rwhk^9MZ7 z$GLre;Q534JkAivMSHC5p0Slaw2rL@Jb%FR`3}6=4LpxA3F6Qm;Q9DR^fAz{!1D+7 z`S=yo{=oBm-HbTs0M8%r`~lBnc!OhLe1PZky?E&W&mZvo0nZ=s`~lA&@H{3xI2Y)^ z`|}4pj}bxd4?K_Y2jbALFyB7k{@3*b&*SujINYzm^9MYSBUJAXJdYy^;xNv^^9MYC z!1D(@f57txJdbl!pC5Q0GYiB)2YCK~=MQ-PU_IP;idFl9=MQ)uQ8#UVu4&x3prd)7IOyp5JaN#`JWm{SG|$J#rrV==o;c`O**(`F_u{$+&GRvfz;V$Y zE90kqo98j#fsU2kIlnV~qt35+p8cUcn&*jwj;_xWhxTZm$0G$gn&%&0DmAvcK2IEU zG|v+U9nJH^K}Yj^j6XiN?_B$EwXS{hJh>R>&GW?7eK*^nqj{b<=xCnDmo;c{}`aGs9(9t|k9CS3#69*k#pC=AFn&*jwj^=qxv7n=Qo;c`e zo{!1a=YBf(m$hd9*ajWV^W;KD^E|#x(9t|k9CUPjo;c`eo+l1Ex;{@Fbb#l9V_m<% z2isalZirG2-q&$A6W!1E0}kE2na3wRz^HpD>(cs{;} zD+4z0d;`xn@Ot-$jQJm0|c z4Lsk#^9?-T!1M7ftMdcTW9x}Hj1Ta91J7fQhW(*mb$z~#XKS4^c)o$>8+g8f=Novw zf#=)G?iuId^!mK9f#(}|9tW}32A*%=d7Q?Oi}3-TZ{T^H7JGl-`S@p7dw}N~cpkGg zjt3l^XQJdgQj9RvPwK}xqr>}QeN?J+*7tBxH!hd*47+dAM6mpJGE&v)>A z2hVr#dKAw-I13cfs^Bp|jQJ?SN`3|1XyTv{i z=m5`m@O%f)ckp}%&v)=VX7ZoUFIKi^#%i?@>hpbNe4g8P@I2=4pO5hohw%ZPkC$>? zKk$5f@;h$P_HkUa2Y9}N=dsM~V}R%5xm@Q0p2Ht5hN{p3o{yhu9|QdgJdd$+=Yr?( zhl^=H+5wX1)xG~_xaa+d$o|hNg+z;~Xz1|OE8{EeL&&N-{t^s%sf4J=c&tnmc{q;CM z!1FkZcP@Aif4G#j&;gzw;Q0ZbAK>}1u93_A>HyEjcfYPFcn*KK?Eug7XBwaPmo|Ur z`KsC+_4%2Y3#Dxa4Adtc?FSM&EZ2@caPJ;SZN-8nnmC?)0lGU3SKvAP;WC8>9jMRY50_l%0MFqMmt6EK@ErbdnPP07!yhhj&2#v}C2koD zGmg@q*Kq`Yxa77D_`_uiwC`6h@Erbd$%PKo=kSM1?xHRCCiuf;8+3r@`6H|vgXIO6 z>o@D$>-vG`@Q2IPaQ7?t!zHfy0e`r}_4t54T>e7_{R%wKzhm_^SQ$Up89dLwV<8th zz;pP+WqKU#f%+W&aLMiGl39mb?Y1(0w1MaOx2@I&p2Ht*{(-A=!SfgDbNIt$e~Y#` zXVmBLhf5rEpgxB`Ts}{M4%FxHhf6N{)ynwM0iM6WbNIt0cNq&AtM%Vva}4kt{&0zF ze!w3tacB?l9R6_0MSFnfFYp}xaCrr^obz0R?63Mgc%DCx>wXHJ!yhikg$~r`@Q2G^ zsi9w?K8HVCa?!6)pTi$6xwv1UK8HVCa+kiAeg%KHZ0q|j{NWO}T>B&cjGDS^ZMRwT zv_7-KA1?dr_JBWJ;-CXOhd*3i87_Tot^s%sf4Ia!2Y3#Dxa2m^^Fdf&7w{bZa2x#L zvaS0S{NWO}^r30DjKOL*@ccx54u813a_#W}f4IbX; zbNIvMbux6IK8HVCa-jn}&mRSMe*w?o50_WlXb{%~35fpHF=!yhiW7$4v{ z{Na*|@d2L0A1+HydVIhiE^*x+`9ts;)9{B&Znwu9JcmDAa=Sg|zcbfo2Kd8e=}foB z8$6%+-QHif2mIl3j2`E2@ErbdS;hk$cz-_sn_K4xp2Ht5$AFHN@fqjvhs(C^SLFql z=Y#$q^6U@wIsD-ghkk|n{0*MJ!E^Y-rA9{Na*|_5jb{;5q!^ zvOnkm&*2Z3rC`tjp2Ht*{;;z9BzT@bl0_WaW39!fU*$f&K6k<&F8>`29jMRY50_l% zKz$B>xa3L)+525z?!5=Ph z%|ZCXB@XQYp2Ht5xzK_6cKE|(SuS*-K8HVCa{KwJyx?-bpLK5Q{T}{s*&lSEK8HVC zmJ&n9%I-Or+#~8-);ah*H^Cn++t9DT^9%L)1)jqnZi7EuwqbmL=kSM1F8URCKL3xs zK8wO1Zo9zq`p@>ceyGpk50^NM57g%ucwSy`c^SHg3)Q~hIsDA?zskeZ(7#?^*Q|EvOly3-k-xCF1hGecz=Gc z?9MsQyPY~`@Erbd8~ow24LVSt-{3j?;j%xp2Y7y?K8HWtc7x~ehf5rEfaf=Oe&hW) z{NZwpelCGOTt3C?`UC!OiR=3n{NWPUbV1hd*5Q2OZ$~1D-$NIsD-^_`_uzbf7+m zKU{Kqd_3Se{Na+@_p1jyhd*3CBSpVLeGY%PQ_`_}G1s5GNM_W2jpTi$6`-2Yfyu9G% zxan(sTyPLPf7Y5k&tdR~%QlP;@caSK;SZPnp+{4xNAo;!(6O>R{bl9~mj04l=xClN4m!F% z&!_)rkLG#e&>m~eo`(FUd7f=(kLG#e&>lVCzQZ3b+n}R)o;c`eo+l3ds_XN_p*@=C zi9>rd&ttIw9sT}1anR8`PaJeK&l3k7&GW=TN7v`Eg@BH(&l3k7>)iT`g>bdTLi0TP zgO28T;-I7J^H^CxNAo;!(9t|k9NMGn^Ta_%^E`3T(L9g+26S|No;c{}`aE&a(L7Ha zbTrQs2OVq8KKGZd&$A8p-R61XaNlj7Cl2?ko^MYa?pIx($I=A+Xr3nyI-2K+gO28T z;-I5>o;c{}`h15!T()(;imB)N{G7P%S23VOT=%OOBO4u81hLI-#bf4JnLJ-~DL!^NVf$45Tk?`r^_ z=Yw&?K?isaf4H0rbb#mZhl{Ncbb#mZhf6MWfam#utM!8C`LGCa=vUx*J__kv@H`(s zAPzdZK9AiJbb#ksD2-!42Y8;vu$>E@XW=H|paVRIKir;$ZrC4mfamasi{%t_fah7T z(#HkQ;SZN%pgq9zycowZ&>rA*gLT~$RB^T`hp2Ht5xfma) z&u8uG^1dgxHM9qK4u81hqCLQK_`@X^?E#*{A1=4u)&YOG#C3bXA1-mN1O9M{Yo5a& zE^*x+fJqp2Ht57({!3=kSM1 zE_8tB@P|t-+5_|L2Y3#DxS$(4P@k7)+_X7(4u81Bp*_HJ_`~Hf0^iRz5Kz)9I=kSNixu9Qx=LdKWf4Dq$;(i65AE?ja510L6oUiPj>ymS>>jIv` zA1;r@Xb;rq@P|t-`W5Q)*wGYg^Z5w2p*_HJ_`~f7cn*KK#NmF0`W*gn$%PKgx5FPU zxfth|Z-+lzN|NqZ@P|uWw+H;;64yG)GcNZq_`_ve>wrI8N~Z2t@P|uWw+H;;64%cq z@P|uW_bd3rB@Q~kbNIuh^h0}q=P&Ra{&3kJ+5T~$RB^NqSpTi$6)1uG; zp2Ht5xy_IAjGOkrd^`N%@^>A}J$Cv~p4+Prf#>jt%l^=>z;pP+B^T|nGJdpy=kSNi zwDO{Da@V=_=)Lk>QhLF2_`_v?Xb;rq@P|uo-*@2;m#J{*0MFqMmt3?5cn*KKQ&*2Z3T->j~bNIvMl>^!X^*Q|El8g4hd^`N% zl8g3OYxe2m;5q!^@|pxXz;pP+B^NqSpTi$6xy!YmF__#MgWx&*;qqz+I>2-I!zC9w zz;pP+B^T`hp2Ht5xjjDM50_U|{agZnxWu&%_`@Zx?^p1LOWe{%=~wWF%Qol$&&vxg zZGPu|zqUF2;qsSFJ4u813c7_h{9R6_0g%0ri4W7dvE`NuH_CS3O zf4JmA2kLY9!zC9wFyH2-I z!zC9w)|!3pFDv6ewxK=n{`?J|!yhh7A)o_1hd*3$p#waJKU{L513ZU6T$XAy&*2Z3 zxW4bgA1-mN1O9M{YYxI6E^*zj;18GOCD4KTeEwr|eU^tmT=oYYsL$aKm)vd-_`~h+ zhs!qTKz$B>xa9V83H;#_*F1+mT;iYuJcmDAmhnIb=G);9mt5$;e0zDuWlX~#F5933 zJcmDAmL5R|cz%KB7v|gH50_)0J+QtV{&2~~_yEu050}5#?EBRPp2Ht5xfmbdIsD<0 zi}nD|%QJ4;7xV4#hf5sBIqGxx!zCB(f%^Oc&*2Z3C20NJexW{xKU{L51NAxl;gSm- z;5q!^l8b%?p2Ht5f4_=;1)fihUH4+}9R6@Q2Ka&c9R6@w>WB6~eSU%G@Q2I(paVR= zz;pP+Wq%kS;5q!^vShLESMY~RT=y&Z!zHfAIsD-g*X;p+xWsk8fhl{sFVDCcGb_8NJ#ww8J;3uD^*Q|EatyQw=G$-ZygcLPoL6?|oTuKZ za|X}h510L+Jy4&+A1=9Q57g)Ihl`yr#yNNnf4JmgoP+1^hf6Nn13WJ;xVg^h_v>|r zKU|jc_xON6T;f^>{NWPU_g(nIC9c~8{&4xUpzl`?cwU}y>3{Ht%Qomheg1&w@Q2I( zpabvE;SaaNA1>R_9^g6r;gZ|qWB$`|eJ+MSTymiUJcmDAKI`c5@t{73KU{K`b57r# zXRhkI;5q!^vOnkm&!3gubKKn9>$u=K{NeH$3;Gp!4u81h_BemmT0G}BeXY(9JcmEr z4u808>*uSulXiar&*2Z3{XqwK4u80O-m~SpfamasOD=SP=kSNi zCrP+pp*}CqxVc}gjQ`kH<0G#~ac@U`4u7~D1LFfchd#g(L7HabaZ{5IOtdzKmD|M zo^9w?&GW>eU-kR*e3H4GbH>8>@zhx8`S#>ONAo;!XpiQ3;?N!|>+{4xNAo;!(9t|k9CY-2dpZ&;g#qA1=Aw9vgTLf4JmA$I9;X-F#eMeHZ?4`D7kCz;pP+B^Nrt zbNIt07dpUm_`~Is{vIFjhf7?K5BS3+4m!Yd_`@X^I>2-I!^MUGI@X#!V;cT&*@p1} zp2Ht5xjoL|50|(e=Notqf4JBwpkIOK`D6IC7EdnP13b^{Fmllz;CU+V&IQlQ3vR|% z__1;!f0B#+K?isaf4F?k4jte*{NZ9zfqn&^!yhiW&;g$359L1V&2LYcSs|*EK+W4u7~D13Fg5&$*yJkGWj+KlsBXx5r0$!Htge-O_>j9R6@Q z26Ui4pJ$czeh>p4Y(smXK96whl;N^l`y+_`}7@2kil#!yhiW z7$2z5;SZPGzF*}d&(;B+!yhj8L(l=9=L0hw13FNj!yhikg%0pMAC&ZQQJ=#f?il}^ z>Zjm&7Oo?%`2l~p90NMQbNIu>(h1`OJcmDAa?u_ujlrVn5pBy^Lf6i z>kOX5A1)SF(1H3K{&2~K4)8oLcKiHLpXY@m;xIl?pXWsra?!6)pXa3ma=Tw;^19+O zIgD+sBNLQ}>+z9^GsLxyOz0r4b!76P7T3J~#$+famas%WpDI;SZNwvQ_`@X^?E#*{AMSuZT(&_6cn*KKq(TSk^8-9DFSr=* z%sqB}_L=`hUhhrthf6609pE|q;gSm-;5q!^l8g2L&kyjtJmYe|hd*4lVSIq+@P|t- z#yRS9_`{`nF+RZa13WL!xX}il!yhhjXb;rqjtOC0(Ycn*KKSVKYwcn*KK Date: Wed, 19 Jun 2019 16:34:54 -0700 Subject: [PATCH 53/62] Add opt-reorder knob. --- src/compiler/compiler_main.cpp | 6 ++++++ src/compiler/lib/Eqs.cpp | 23 +++++++++++++++++++++++ src/compiler/lib/Settings.hpp | 1 + src/compiler/lib/Solution.cpp | 2 +- src/compiler/lib/YaskKernel.cpp | 7 ------- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 54be64ec..4b41f184 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -172,6 +172,8 @@ void usage(const string& cmd, " the memory layout used by YASK must have that same dimension in unit stride.\n" " [-no]-opt-comb\n" " Do [not] combine commutative operations (default=" << settings._doComb << ").\n" + " [-no]-opt-reorder\n" + " Do [not] reorder commutative operations (default=" << settings._doReorder << ").\n" " [-no]-opt-cse\n" " Do [not] eliminate common subexpressions (default=" << settings._doCse << ").\n" " [-no]-opt-pair\n" @@ -228,6 +230,10 @@ void parseOpts(int argc, const char* argv[], settings._doComb = true; else if (opt == "-no-opt-comb") settings._doComb = false; + else if (opt == "-opt-reorder") + settings._doReorder = true; + else if (opt == "-no-opt-reorder") + settings._doReorder = false; else if (opt == "-opt-cse") settings._doCse = true; else if (opt == "-no-opt-cse") diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index 0ce6cca7..a9d806e6 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -1441,6 +1441,29 @@ namespace yask { printStats(os, odescr); else os << " No changes " << odescr << '.' << endl; + + delete optimizer; + optimizer = 0; + } + + // Reordering. TODO: make this an optimizer. + if (settings._doReorder) { + + // Create vector info for this eqBundle. + // The visitor is accepted at all nodes in the cluster AST; + // for each var access node in the AST, the vectors + // needed are determined and saved in the visitor. + VecInfoVisitor vv(*_dims); + visitEqs(&vv); + + // Reorder some equations based on vector info. + ExprReorderVisitor erv(vv); + visitEqs(&erv); + + // Get new stats. + string odescr = "after applying reordering to " + + descr + " equation-bundle(s)"; + printStats(os, odescr); } // Final stats per equation bundle. diff --git a/src/compiler/lib/Settings.hpp b/src/compiler/lib/Settings.hpp index a9f9880d..22145318 100644 --- a/src/compiler/lib/Settings.hpp +++ b/src/compiler/lib/Settings.hpp @@ -57,6 +57,7 @@ namespace yask { bool _doComb = true; // combine commutative operations. bool _doPairs = true; // find equation pairs. bool _doOptCluster = true; // apply optimizations also to cluster. + bool _doReorder = false; // reorder commutative operations. string _eqBundleTargets; // how to bundle equations. string _varRegex; // vars to update. bool _findDeps = true; diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 17c74a38..244552d5 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -91,7 +91,7 @@ namespace yask { else return 2; } - if (target == "knl") { + else if (target == "knl") { if (level == 1) return 1; else diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 8e5d95b0..66a4042e 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -702,13 +702,6 @@ namespace yask { VecInfoVisitor vv(_dims); vceq->visitEqs(&vv); - // Reorder some equations based on vector info. - // TODO: make a knob to control this. - if (false) { - ExprReorderVisitor erv(vv); - vceq->visitEqs(&erv); - } - // Collect stats. CounterVisitor cv; vceq->visitEqs(&cv); From 0fd8c7626772b3019afd6c32cd71ef0807f5e40b Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 20 Jun 2019 08:49:45 -0700 Subject: [PATCH 54/62] Fix ISA-flag var when using Intel compiler. --- src/kernel/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/kernel/Makefile b/src/kernel/Makefile index b20d8677..545e3c59 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -343,7 +343,7 @@ endif # TODO: make check for Intel compiler more robust. ifneq ($(filter %icpc %icc,$(notdir $(YK_CXX))),) # Intel compiler - YK_CXXFLAGS += $(ISA) -debug extended -restrict -ansi-alias -fno-alias + YK_CXXFLAGS += $(ICC_ISA) -debug extended -restrict -ansi-alias -fno-alias YK_CXXFLAGS += -fimf-use-svml=true -fimf-precision=low -fast-transcendentals \ -no-prec-sqrt -no-prec-div -fp-model fast=2 -fno-protect-parens -ftz \ -fma -fimf-domain-exclusion=none -qopt-assume-safe-padding @@ -796,7 +796,6 @@ realclean: clean echo-settings: @echo "Build environment for" $(YK_EXEC) on `date`; \ - $(YK_CXX) --version; \ echo TARGET=$(TARGET); \ echo BLOCK_LOOP_CODE="\"$(BLOCK_LOOP_CODE)\""; \ echo BLOCK_LOOP_INNER_MODS="\"$(BLOCK_LOOP_INNER_MODS)\""; \ @@ -857,7 +856,6 @@ echo-settings: echo arch=$(arch); \ echo cluster=$(cluster); \ echo fold=$(fold); \ - echo host=`hostname`; \ echo omp_block_schedule=$(omp_block_schedule); \ echo omp_misc_schedule=$(omp_misc_schedule); \ echo omp_region_schedule=$(omp_region_schedule); \ @@ -867,6 +865,9 @@ echo-settings: echo real_bytes=$(real_bytes); \ echo stencil=$(stencil); \ echo streaming_stores=$(streaming_stores) + git status + uname -a + $(YK_CXX) --version # Print stats on inner SIMD loops from asm file. # Compile with 'EXTRA_YK_CXXFLAGS=-Fa CXX_PREFIX=' to make asm file. From def6a899942660ff350d67a1140203196a1fe68a Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 20 Jun 2019 14:42:28 -0700 Subject: [PATCH 55/62] Change BBs from Tuples to Indices. --- src/kernel/lib/alloc.cpp | 11 ++--- src/kernel/lib/context.cpp | 72 ++++++++++++++++----------------- src/kernel/lib/context.hpp | 30 +++++++++++--- src/kernel/lib/indices.hpp | 44 +++++++++++++------- src/kernel/lib/settings.hpp | 2 + src/kernel/lib/setup.cpp | 37 ++++++++--------- src/kernel/lib/soln_apis.cpp | 13 +++--- src/kernel/lib/stencil_calc.cpp | 61 +++++++++++++--------------- 8 files changed, 150 insertions(+), 120 deletions(-) diff --git a/src/kernel/lib/alloc.cpp b/src/kernel/lib/alloc.cpp index c30dd68e..52c4e135 100644 --- a/src/kernel/lib/alloc.cpp +++ b/src/kernel/lib/alloc.cpp @@ -449,7 +449,8 @@ namespace yask { IdxTuple copy_end = gb.get_allocs(); // one past last! // Adjust along domain dims in this var. - for (auto& dim : domain_dims.getDims()) { + DOMAIN_VAR_LOOP(i, j) { + auto& dim = domain_dims.getDim(j); auto& dname = dim.getName(); if (gp->is_dim_used(dname)) { @@ -482,8 +483,8 @@ namespace yask { idx_t ext_end = ROUND_UP(first_inner_idx[dname] + max(min_ext, neigh_halo_sizes[dname]), dims->_fold_pts[dname]); - mpi_interior.bb_begin[dname] = - max(mpi_interior.bb_begin[dname], ext_end); + mpi_interior.bb_begin[j] = + max(mpi_interior.bb_begin[j], ext_end); } // Neighbor is to the right. @@ -497,8 +498,8 @@ namespace yask { idx_t ext_begin = ROUND_DOWN(last_inner_idx[dname] + 1 - max(min_ext, neigh_halo_sizes[dname]), dims->_fold_pts[dname]); - mpi_interior.bb_end[dname] = - min(mpi_interior.bb_end[dname], ext_begin); + mpi_interior.bb_end[j] = + min(mpi_interior.bb_end[j], ext_begin); } // Else, this neighbor is in same posn as I am in this dim, diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 2136f904..16022a5b 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -52,10 +52,10 @@ namespace yask { // Based on rank bounding box, not extended // BB because we don't use wave-fronts in the ref code. IdxTuple begin(stencil_dims); - begin.setVals(rank_bb.bb_begin, false); + begin.setVals(rank_bb.bb_begin_tuple(domain_dims), false); // 'false' because dims aren't same. begin[step_dim] = begin_t; IdxTuple end(stencil_dims); - end.setVals(rank_bb.bb_end, false); + end.setVals(rank_bb.bb_end_tuple(domain_dims), false); end[step_dim] = end_t; TRACE_MSG("run_ref: [" << begin.makeDimValStr() << " ... " << @@ -155,8 +155,8 @@ namespace yask { // Scan through n-D space. TRACE_MSG("run_ref: step " << start_t << " in bundle '" << sg->get_name() << "': [" << - misc_idxs.begin.makeValStr(nsdims) << - " ... " << misc_idxs.end.makeValStr(nsdims) << ")"); + misc_idxs.begin.makeValStr() << + " ... " << misc_idxs.end.makeValStr() << ")"); #include "yask_misc_loops.hpp" #undef misc_fn } // needed bundles. @@ -211,10 +211,10 @@ namespace yask { // Based on overall bounding box, which includes // any needed extensions for wave-fronts. IdxTuple begin(stencil_dims); - begin.setVals(ext_bb.bb_begin, false); + begin.setVals(ext_bb.bb_begin_tuple(domain_dims), false); begin[step_posn] = begin_t; IdxTuple end(stencil_dims); - end.setVals(ext_bb.bb_end, false); + end.setVals(ext_bb.bb_end_tuple(domain_dims), false); end[step_posn] = end_t; IdxTuple stride(stencil_dims); stride.setVals(opts->_region_sizes, false); // stride by region sizes. @@ -576,10 +576,10 @@ namespace yask { const ScanIndices& rank_idxs) { STATE_VARS(this); TRACE_MSG("calc_region: region [" << - rank_idxs.start.makeValStr(nsdims) << " ... " << - rank_idxs.stop.makeValStr(nsdims) << ") within rank [" << - rank_idxs.begin.makeValStr(nsdims) << " ... " << - rank_idxs.end.makeValStr(nsdims) << ")" ); + rank_idxs.start.makeValStr() << " ... " << + rank_idxs.stop.makeValStr() << ") within rank [" << + rank_idxs.begin.makeValStr() << " ... " << + rank_idxs.end.makeValStr() << ")" ); // Track time (use "else" to avoid double-counting). if (!do_mpi_interior && (do_mpi_left || do_mpi_right)) @@ -785,11 +785,11 @@ namespace yask { auto* bp = sel_bp.get(); int region_thread_idx = omp_get_thread_num(); TRACE_MSG("calc_block: phase " << phase << ", block [" << - region_idxs.start.makeValStr(nsdims) << " ... " << - region_idxs.stop.makeValStr(nsdims) << + region_idxs.start.makeValStr() << " ... " << + region_idxs.stop.makeValStr() << ") within region [" << - region_idxs.begin.makeValStr(nsdims) << " ... " << - region_idxs.end.makeValStr(nsdims) << + region_idxs.begin.makeValStr() << " ... " << + region_idxs.end.makeValStr() << ") by region thread " << region_thread_idx); #ifdef OVERLAP_WITH_BLOCKS @@ -932,8 +932,8 @@ namespace yask { } TRACE_MSG("calc_block: phase " << phase << ", adjusted block [" << - adj_block_idxs.begin.makeValStr(nsdims) << " ... " << - adj_block_idxs.end.makeValStr(nsdims) << + adj_block_idxs.begin.makeValStr() << " ... " << + adj_block_idxs.end.makeValStr() << ") with mini-block stride " << adj_block_idxs.stride.makeValStr(nsdims)); @@ -987,12 +987,12 @@ namespace yask { TRACE_MSG("calc_mini_block: phase " << phase << ", shape " << shape << ", mini-block [" << - adj_block_idxs.start.makeValStr(nsdims) << " ... " << - adj_block_idxs.stop.makeValStr(nsdims) << ") within base-block [" << - base_block_idxs.begin.makeValStr(nsdims) << " ... " << - base_block_idxs.end.makeValStr(nsdims) << ") within base-region [" << - base_region_idxs.begin.makeValStr(nsdims) << " ... " << - base_region_idxs.end.makeValStr(nsdims) << + adj_block_idxs.start.makeValStr() << " ... " << + adj_block_idxs.stop.makeValStr() << ") within base-block [" << + base_block_idxs.begin.makeValStr() << " ... " << + base_block_idxs.end.makeValStr() << ") within base-region [" << + base_region_idxs.begin.makeValStr() << " ... " << + base_region_idxs.end.makeValStr() << ") by region thread " << region_thread_idx); // Promote forward progress in MPI when calc'ing interior @@ -1293,10 +1293,10 @@ namespace yask { idxs.end[i] = rstop; } TRACE_MSG("shift_region: updated span: [" << - idxs.begin.makeValStr(nsdims) << " ... " << - idxs.end.makeValStr(nsdims) << ") within region base [" << - base_start.makeValStr(nsdims) << " ... " << - base_stop.makeValStr(nsdims) << ") shifted " << + idxs.begin.makeValStr() << " ... " << + idxs.end.makeValStr() << ") within region base [" << + base_start.makeValStr() << " ... " << + base_stop.makeValStr() << ") shifted " << shift_num << " time(s) is " << (ok ? "not " : "") << "empty"); return ok; @@ -1458,17 +1458,17 @@ namespace yask { TRACE_MSG("shift_mini_block: phase " << phase << "/" << nphases << ", shape " << shape << "/" << nshapes << ", updated span: [" << - idxs.begin.makeValStr(nsdims) << " ... " << - idxs.end.makeValStr(nsdims) << ") from original mini-block [" << - mb_base_start.makeValStr(nsdims) << " ... " << - mb_base_stop.makeValStr(nsdims) << ") shifted " << + idxs.begin.makeValStr() << " ... " << + idxs.end.makeValStr() << ") from original mini-block [" << + mb_base_start.makeValStr() << " ... " << + mb_base_stop.makeValStr() << ") shifted " << mb_shift_num << " time(s) within adj-block base [" << - adj_block_base_start.makeValStr(nsdims) << " ... " << - adj_block_base_stop.makeValStr(nsdims) << ") and actual block base [" << - block_base_start.makeValStr(nsdims) << " ... " << - block_base_stop.makeValStr(nsdims) << ") and region base [" << - region_base_start.makeValStr(nsdims) << " ... " << - region_base_stop.makeValStr(nsdims) << ") is " << + adj_block_base_start.makeValStr() << " ... " << + adj_block_base_stop.makeValStr() << ") and actual block base [" << + block_base_start.makeValStr() << " ... " << + block_base_stop.makeValStr() << ") and region base [" << + region_base_start.makeValStr() << " ... " << + region_base_stop.makeValStr() << ") is " << (ok ? "not " : "") << "empty"); return ok; } diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index c03af3dc..4e72855d 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -31,18 +31,38 @@ namespace yask { struct BoundingBox { // Boundaries around all points. - IdxTuple bb_begin; // first indices. - IdxTuple bb_end; // one past last indices. - idx_t bb_num_points=1; // valid points within the box. + Indices bb_begin; // first indices. + Indices bb_end; // one past last indices. + + // Number of valid points within the box. + idx_t bb_num_points=0; // Following values are calculated from the above ones. - IdxTuple bb_len; // size in each dim. - idx_t bb_size=1; // points in the entire box; bb_size >= bb_num_points. + Indices bb_len; // size in each dim. + idx_t bb_size=0; // points in the entire box; bb_size >= bb_num_points. bool bb_is_full=false; // all points in box are valid (bb_size == bb_num_points). bool bb_is_aligned=false; // starting points are vector-aligned in all dims. bool bb_is_cluster_mult=false; // num points are cluster multiples in all dims. bool bb_valid=false; // lengths and sizes have been calculated. + // Make Tuples. + IdxTuple bb_begin_tuple(const IdxTuple& ddims) const { + return bb_begin.makeTuple(ddims); + } + IdxTuple bb_end_tuple(const IdxTuple& ddims) const { + return bb_end.makeTuple(ddims); + } + IdxTuple bb_len_tuple(const IdxTuple& ddims) const { + return bb_len.makeTuple(ddims); + } + std::string make_range_string(const IdxTuple& ddims) const { + return bb_begin_tuple(ddims).makeDimValStr() + + " ... " + bb_end_tuple(ddims).subElements(1).makeDimValStr(); + } + std::string make_len_string(const IdxTuple& ddims) const { + return bb_len_tuple(ddims).makeDimValStr(" * "); + } + // Calc values and set valid to true. // If 'force_full', set 'bb_num_points' as well as 'bb_size'. void update_bb(const std::string& name, diff --git a/src/kernel/lib/indices.hpp b/src/kernel/lib/indices.hpp index f7c38deb..7edae7af 100644 --- a/src/kernel/lib/indices.hpp +++ b/src/kernel/lib/indices.hpp @@ -295,18 +295,38 @@ namespace yask { return res; } - // Make string like "x=4, y=8". - std::string makeDimValStr(const VarDimNames& names, - std::string separator=", ", - std::string infix="=", - std::string prefix="", - std::string suffix="") const { + // Make a Tuple w/given names. + IdxTuple makeTuple(const VarDimNames& names) const { assert((int)names.size() == _ndims); // Make a Tuple from names. IdxTuple tmp; for (int i = 0; i < int(names.size()); i++) tmp.addDimBack(names[i], _idxs[i]); + return tmp; + } + + // Make a Tuple w/o useful names. + IdxTuple makeTuple() const { + IdxTuple tmp; + for (int i = 0; i < _ndims; i++) + tmp.addDimBack(std::string("d") + std::to_string(i), _idxs[i]); + return tmp; + } + + // Make a Tuple w/names from another Tuple. + IdxTuple makeTuple(const IdxTuple& names) const { + auto tmp = names.getDimNames(); + return makeTuple(tmp); + } + + // Make string like "x=4, y=8". + std::string makeDimValStr(const VarDimNames& names, + std::string separator=", ", + std::string infix="=", + std::string prefix="", + std::string suffix="") const { + auto tmp = makeTuple(names); return tmp.makeDimValStr(separator, infix, prefix, suffix); } std::string makeDimValStr(const IdxTuple& names, // ignore values. @@ -314,21 +334,17 @@ namespace yask { std::string infix="=", std::string prefix="", std::string suffix="") const { - auto tmp = names.getDimNames(); - return makeDimValStr(tmp, separator, infix, prefix, suffix); + auto tmp = makeTuple(names); + return tmp.makeDimValStr(separator, infix, prefix, suffix); } // Make string like "4, 3, 2". - std::string makeValStr(int nvals, - std::string separator=", ", + std::string makeValStr(std::string separator=", ", std::string prefix="", std::string suffix="") const { - assert(nvals == _ndims); // Make a Tuple w/o useful names. - IdxTuple tmp; - for (int i = 0; i < nvals; i++) - tmp.addDimBack(std::string(1, '0' + char(i)), _idxs[i]); + auto tmp = makeTuple(); return tmp.makeValStr(separator, prefix, suffix); } }; diff --git a/src/kernel/lib/settings.hpp b/src/kernel/lib/settings.hpp index fcc10557..c8ef6ad2 100644 --- a/src/kernel/lib/settings.hpp +++ b/src/kernel/lib/settings.hpp @@ -640,6 +640,8 @@ namespace yask { _state(state) {} KernelStateBase(KernelEnvPtr& env, KernelSettingsPtr& settings); + KernelStateBase(KernelStateBase* p) : + _state(p->_state) { } virtual ~KernelStateBase() {} // Access to state. diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index d5f760b9..361abfa6 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -773,9 +773,8 @@ namespace yask { bbtimer.start(); // Rank BB is based only on rank offsets and rank domain sizes. - rank_bb.bb_begin = dims->_domain_dims; - rank_domain_offsets.setTupleVals(rank_bb.bb_begin); - rank_bb.bb_end = rank_bb.bb_begin.addElements(opts->_rank_sizes, false); + rank_bb.bb_begin = rank_domain_offsets; + rank_bb.bb_end = rank_bb.bb_begin_tuple(domain_dims).addElements(opts->_rank_sizes, false); rank_bb.update_bb("rank", this, true, true); // BB may be extended for wave-fronts. @@ -890,19 +889,17 @@ namespace yask { auto& cur_bb_list = bb_lists[start]; // Begin and end of this slice. - // These tuples contain domain dims. - IdxTuple slice_begin(_bundle_bb.bb_begin); - slice_begin[odim] += start * len_per_thr; - IdxTuple slice_end(_bundle_bb.bb_end); - slice_end[odim] = min(slice_end[odim], slice_begin[odim] + len_per_thr); - if (slice_end[odim] <= slice_begin[odim]) + // These Indices contain domain dims. + Indices islice_begin(_bundle_bb.bb_begin); + islice_begin[odim] += start * len_per_thr; + Indices islice_end(_bundle_bb.bb_end); + islice_end[odim] = min(islice_end[odim], islice_begin[odim] + len_per_thr); + if (islice_end[odim] <= islice_begin[odim]) return; // from lambda. - Indices islice_begin(slice_begin); - Indices islice_end(slice_end); // Construct len of slice in all dims. - IdxTuple slice_len = slice_end.subElements(slice_begin); - Indices islice_len(slice_len); + Indices islice_len = islice_end.subElements(islice_begin); + auto slice_len = islice_len.makeTuple(domain_dims); // Visit all points in slice, looking for a new // valid beginning point, 'ib*pt'. @@ -936,9 +933,8 @@ namespace yask { // Scan from 'ib*pt' to end of this slice // looking for end of rect. - IdxTuple bdpt(domain_dims); - ibdpt.setTupleVals(bdpt); - IdxTuple scan_len = slice_end.subElements(bdpt); + auto iscan_len = islice_end.subElements(ibdpt); + auto scan_len = iscan_len.makeTuple(domain_dims); // End point to be found, 'ie*pt'. Indices iespt(stencil_dims); // stencil dims. @@ -1010,8 +1006,8 @@ namespace yask { // 'scan_len' now contains sizes of the new BB. BoundingBox new_bb; - new_bb.bb_begin = bdpt; - new_bb.bb_end = bdpt.addElements(scan_len); + new_bb.bb_begin = ibdpt; + new_bb.bb_end = ibdpt.addElements(iscan_len); new_bb.update_bb("sub-bb", _context, true); cur_bb_list.push_back(new_bb); @@ -1142,9 +1138,10 @@ namespace yask { // Lengths are cluster-length multiples? bb_is_cluster_mult = true; - for (auto& dim : domain_dims.getDims()) { + DOMAIN_VAR_LOOP(i, j) { + auto& dim = domain_dims.getDim(j); auto& dname = dim.getName(); - if (bb_len[dname] % dims->_cluster_pts[dname] != 0) { + if (bb_len[j] % dims->_cluster_pts[dname] != 0) { if (bb_is_full && bb_is_aligned) if (print_info && bb_is_aligned) DEBUG_MSG("Note: '" << name << "' domain" diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 4d61608e..056ac52c 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -48,8 +48,8 @@ namespace yask { GET_SOLN_API(get_rank_domain_size, opts->_rank_sizes[dim], false, true, false, false) GET_SOLN_API(get_region_size, opts->_region_sizes[dim], true, true, false, false) GET_SOLN_API(get_block_size, opts->_block_sizes[dim], true, true, false, false) - GET_SOLN_API(get_first_rank_domain_index, rank_bb.bb_begin[dim], false, true, false, true) - GET_SOLN_API(get_last_rank_domain_index, rank_bb.bb_end[dim] - 1, false, true, false, true) + GET_SOLN_API(get_first_rank_domain_index, rank_bb.bb_begin_tuple(domain_dims)[dim], false, true, false, true) + GET_SOLN_API(get_last_rank_domain_index, rank_bb.bb_end_tuple(domain_dims)[dim] - 1, false, true, false, true) GET_SOLN_API(get_min_pad_size, opts->_min_pad_sizes[dim], false, true, false, false) GET_SOLN_API(get_rank_index, opts->_rank_indices[dim], false, true, false, true) #undef GET_SOLN_API @@ -224,8 +224,7 @@ namespace yask { " wave-front-shift-amounts: " << wf_shift_pts.makeDimValStr() << endl << " left-wave-front-exts: " << left_wf_exts.makeDimValStr() << endl << " right-wave-front-exts: " << right_wf_exts.makeDimValStr() << endl << - " ext-local-domain: " << ext_bb.bb_begin.makeDimValStr() << - " ... " << ext_bb.bb_end.subElements(1).makeDimValStr() << endl << + " ext-local-domain: " << ext_bb.make_range_string(domain_dims) << endl << " temporal-block-angles: " << tb_angles.makeDimValStr() << endl << " num-temporal-block-shifts: " << num_tb_shifts << endl << " temporal-block-long-base: " << tb_widths.makeDimValStr(" * ") << endl << @@ -269,15 +268,13 @@ namespace yask { " stencil-name: " << get_name() << endl << " stencil-description: " << get_description() << endl << " element-size: " << makeByteStr(get_element_bytes()) << endl << - " local-domain: " << rank_bb.bb_begin.makeDimValStr() << - " ... " << rank_bb.bb_end.subElements(1).makeDimValStr()); + " local-domain: " << rank_bb.make_range_string(domain_dims)); #ifdef USE_MPI DEBUG_MSG(" num-ranks: " << opts->_num_ranks.makeDimValStr(" * ") << endl << " rank-indices: " << opts->_rank_indices.makeDimValStr() << endl << " local-domain-offsets: " << rank_domain_offsets.makeDimValStr(dims->_domain_dims)); if (opts->overlap_comms) - DEBUG_MSG(" mpi-interior: " << mpi_interior.bb_begin.makeDimValStr() << - " ... " << mpi_interior.bb_end.subElements(1).makeDimValStr()); + DEBUG_MSG(" mpi-interior: " << mpi_interior.make_range_string(domain_dims)); #endif DEBUG_MSG( " vector-len: " << VLEN << endl << " extra-padding: " << opts->_extra_pad_sizes.removeDim(step_posn).makeDimValStr() << endl << diff --git a/src/kernel/lib/stencil_calc.cpp b/src/kernel/lib/stencil_calc.cpp index acb651c3..7bebc36a 100644 --- a/src/kernel/lib/stencil_calc.cpp +++ b/src/kernel/lib/stencil_calc.cpp @@ -42,9 +42,9 @@ namespace yask { const ScanIndices& mini_block_idxs) { STATE_VARS(this); TRACE_MSG("calc_mini_block('" << get_name() << "'): [" << - mini_block_idxs.begin.makeValStr(nsdims) << " ... " << - mini_block_idxs.end.makeValStr(nsdims) << ") by " << - mini_block_idxs.stride.makeValStr(nsdims) << + mini_block_idxs.begin.makeValStr() << " ... " << + mini_block_idxs.end.makeValStr() << ") by " << + mini_block_idxs.stride.makeValStr() << " by region thread " << region_thread_idx); assert(!is_scratch()); @@ -113,8 +113,8 @@ namespace yask { TRACE_MSG("calc_mini_block('" << get_name() << "'): after trimming for BB " << bbn << ": [" << - mb_idxs.begin.makeValStr(nsdims) << - " ... " << mb_idxs.end.makeValStr(nsdims) << ")"); + mb_idxs.begin.makeValStr() << + " ... " << mb_idxs.end.makeValStr() << ")"); // Get the bundles that need to be processed in // this block. This will be any prerequisite scratch-var @@ -165,9 +165,9 @@ namespace yask { TRACE_MSG("calc_mini_block('" << get_name() << "'): " << " for reqd bundle '" << sg->get_name() << "': [" << - adj_mb_idxs.begin.makeValStr(nsdims) << " ... " << - adj_mb_idxs.end.makeValStr(nsdims) << ") by " << - adj_mb_idxs.stride.makeValStr(nsdims) << + adj_mb_idxs.begin.makeValStr() << " ... " << + adj_mb_idxs.end.makeValStr() << ") by " << + adj_mb_idxs.stride.makeValStr() << " by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -214,8 +214,8 @@ namespace yask { const ScanIndices& mini_block_idxs) { STATE_VARS(this); TRACE_MSG("calc_sub_block_scalar for bundle '" << get_name() << "': [" << - mini_block_idxs.start.makeValStr(nsdims) << - " ... " << mini_block_idxs.stop.makeValStr(nsdims) << + mini_block_idxs.start.makeValStr() << + " ... " << mini_block_idxs.stop.makeValStr() << ") by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -252,8 +252,8 @@ namespace yask { const ScanIndices& mini_block_idxs) { STATE_VARS(this); TRACE_MSG("calc_sub_block_vec for bundle '" << get_name() << "': [" << - mini_block_idxs.start.makeValStr(nsdims) << - " ... " << mini_block_idxs.stop.makeValStr(nsdims) << + mini_block_idxs.start.makeValStr() << + " ... " << mini_block_idxs.stop.makeValStr() << ") by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -494,11 +494,11 @@ namespace yask { // the inner one. if (do_vectors) { TRACE_MSG("calc_sub_block_vec: using vector code for [" << - sub_block_vidxs.begin.makeValStr(nsdims) << - " ... " << sub_block_vidxs.end.makeValStr(nsdims) << + sub_block_vidxs.begin.makeValStr() << + " ... " << sub_block_vidxs.end.makeValStr() << ") *not* within full vector-clusters at [" << - sub_block_fcidxs.begin.makeValStr(nsdims) << - " ... " << sub_block_fcidxs.end.makeValStr(nsdims) << + sub_block_fcidxs.begin.makeValStr() << + " ... " << sub_block_fcidxs.end.makeValStr() << ") by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -578,11 +578,11 @@ namespace yask { misc_idxs.align.setFromConst(1); TRACE_MSG("calc_sub_block_vec: using scalar code for [" << - misc_idxs.begin.makeValStr(nsdims) << " ... " << - misc_idxs.end.makeValStr(nsdims) << + misc_idxs.begin.makeValStr() << " ... " << + misc_idxs.end.makeValStr() << ") *not* within vectors at [" << - sub_block_vidxs.begin.makeValStr(nsdims) << " ... " << - sub_block_vidxs.end.makeValStr(nsdims) << + sub_block_vidxs.begin.makeValStr() << " ... " << + sub_block_vidxs.end.makeValStr() << ") by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -622,8 +622,8 @@ namespace yask { const ScanIndices& loop_idxs) { STATE_VARS(this); TRACE_MSG("calc_loop_of_clusters: local vector-indices [" << - loop_idxs.start.makeValStr(nsdims) << - " ... " << loop_idxs.stop.makeValStr(nsdims) << + loop_idxs.start.makeValStr() << + " ... " << loop_idxs.stop.makeValStr() << ") by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -656,8 +656,8 @@ namespace yask { idx_t write_mask) { STATE_VARS(this); TRACE_MSG("calc_loop_of_vectors: local vector-indices [" << - loop_idxs.start.makeValStr(nsdims) << - " ... " << loop_idxs.stop.makeValStr(nsdims) << + loop_idxs.start.makeValStr() << + " ... " << loop_idxs.stop.makeValStr() << ") w/write-mask = 0x" << hex << write_mask << dec << " by region thread " << region_thread_idx << " and block thread " << block_thread_idx); @@ -802,8 +802,7 @@ namespace yask { DEBUG_MSG("Pack '" << get_name() << "':\n" << " num bundles: " << size() << endl << - " pack scope: " << _pack_bb.bb_begin.makeDimValStr() << - " ... " << _pack_bb.bb_end.subElements(1).makeDimValStr()); + " pack scope: " << _pack_bb.make_range_string(domain_dims)); // Bundles. for (auto* sg : *this) { @@ -844,9 +843,8 @@ namespace yask { if (bb.bb_size) { DEBUG_MSG(" valid points in bundle: " << makeNumStr(bb.bb_num_points)); if (bb.bb_num_points) { - DEBUG_MSG(" bundle scope: " << bb.bb_begin.makeDimValStr() << - " ... " << bb.bb_end.subElements(1).makeDimValStr() << endl << - " bundle bounding-box size: " << bb.bb_len.makeDimValStr(" * ")); + DEBUG_MSG(" bundle scope: " << bb.make_range_string(domain_dims) << + "\n bundle bounding-box size: " << bb.make_len_string(domain_dims)); } } DEBUG_MSG(" num full rectangles in box: " << sg->getBBs().size()); @@ -856,9 +854,8 @@ namespace yask { DEBUG_MSG(" Rectangle " << ri << ":\n" " num points in rect: " << makeNumStr(rbb.bb_num_points)); if (rbb.bb_num_points) { - DEBUG_MSG(" rect scope: " << rbb.bb_begin.makeDimValStr() << - " ... " << rbb.bb_end.subElements(1).makeDimValStr() << endl << - " rect size: " << rbb.bb_len.makeDimValStr(" * ")); + DEBUG_MSG(" rect scope: " << rbb.make_range_string(domain_dims) << + "\n rect size: " << rbb.make_len_string(domain_dims)); } } } From 7c04841c0f220fc3ef4ac6d706879973a8406b35 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 20 Jun 2019 15:51:13 -0700 Subject: [PATCH 56/62] Unroll prefetches. --- src/compiler/lib/Cpp.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index dc3e456f..a3168fe1 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -298,35 +298,34 @@ namespace yask { if (left.length() == 0) left = "0"; string right = _dims.makeNormStr(_ptrOfsHi[ptr], idim); - // Start loop of prefetches. - os << "\n // For pointer '" << ptr << "'\n" - "#pragma unroll\n" << - _linePrefix << " for (int ofs = "; - - // First offset. + // Loop bounds. + string start, stop; + // If fetching ahead, only need to get those following // the previous one. if (ahead) - os << "(PFD_L" << level << "*" << imult << ")" << right; + start = "(PFD_L" + to_string(level) + "*" + imult + ")" + right; // If fetching first time, need to fetch across whole range; // starting at left edge. else - os << left; - - // End of offsets. - os << "; ofs < "; - + start = left; + start = "(" + start + ")"; + // If fetching again, stop before next one. if (ahead) - os << "((PFD_L" << level << "+1)*" << imult << ")" << right; + stop = "((PFD_L" + to_string(level) + "+1)*" + imult + ")" + right; // If fetching first time, stop where next "ahead" one ends. else - os << "(PFD_L" << level << "*" << imult << ")" << right; + stop = "(PFD_L" + to_string(level) + "*" + imult + ")" + right; + stop = "(" + stop + ")"; - // Finish loop header. - os << "; ofs++) {\n"; + // Start loop of prefetches. + os << "\n // For pointer '" << ptr << "'\n" + "#pragma unroll(" << stop << " - " << start << ")\n" << + _linePrefix << " for (int ofs = " << start << + "; ofs < " << stop << "; ofs++) {\n"; // Need to print prefetch for every unique var-point read. set done; From b97d52dc85427353bc3550f5b240f8075ddbf152 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Thu, 20 Jun 2019 17:10:55 -0700 Subject: [PATCH 57/62] Fix tuner bug. --- utils/bin/yask_tuner.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/bin/yask_tuner.pl b/utils/bin/yask_tuner.pl index d2f2b7cf..a0c71ce7 100755 --- a/utils/bin/yask_tuner.pl +++ b/utils/bin/yask_tuner.pl @@ -1036,7 +1036,7 @@ ($$$$) # vars to create. my $order = join(',', @dims); # e.g., '2, 1'. - my $outerMods = $reqdMods; + my $outerMods = ''; my $innerMods = ''; # path gene? @@ -1044,7 +1044,7 @@ ($$$$) if (exists $h->{$pathKey}) { my $path = readHash($h, $pathKey, 1); my $pathStr = @pathNames[$path]; # e.g., 'grouped'. - $outerMods = "$pathStr $outerMods"; + $outerMods = $pathStr; } my $loopVars = " ".$makePrefix."_LOOP_ORDER='$order'"; From 722ece819559845da03ea26801f1cbc535f0a03a Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 21 Jun 2019 10:14:06 -0700 Subject: [PATCH 58/62] Fix bug in bounding-box calculation. --- src/kernel/lib/alloc.cpp | 3 +-- src/kernel/lib/context.cpp | 2 +- src/kernel/lib/setup.cpp | 38 ++++++++++++++++----------------- src/kernel/lib/stencil_calc.cpp | 4 ++-- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/kernel/lib/alloc.cpp b/src/kernel/lib/alloc.cpp index 52c4e135..724ff925 100644 --- a/src/kernel/lib/alloc.cpp +++ b/src/kernel/lib/alloc.cpp @@ -635,8 +635,7 @@ namespace yask { // Finalize interior BB if there are multiple ranks and overlap enabled. if (env->num_ranks > 1 && opts->overlap_comms) { mpi_interior.update_bb("interior", this, true); - TRACE_MSG("MPI interior BB: [" << mpi_interior.bb_begin.makeDimValStr() << - " ... " << mpi_interior.bb_end.makeDimValStr() << ")"); + TRACE_MSG("MPI interior BB: [" << mpi_interior.make_range_string(domain_dims) << "]"); } // At this point, we have all the buffers configured. diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 16022a5b..3532384e 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -935,7 +935,7 @@ namespace yask { adj_block_idxs.begin.makeValStr() << " ... " << adj_block_idxs.end.makeValStr() << ") with mini-block stride " << - adj_block_idxs.stride.makeValStr(nsdims)); + adj_block_idxs.stride.makeValStr()); // Loop thru shapes. for (idx_t shape = 0; shape < nshapes; shape++) { diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index 361abfa6..4f76a643 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -857,8 +857,7 @@ namespace yask { // If there is no condition, just add full BB to list. if (!is_sub_domain_expr()) { - TRACE_MSG("adding 1 sub-BB: [" << _bundle_bb.bb_begin.makeDimValStr() << - " ... " << _bundle_bb.bb_end.makeDimValStr() << ")"); + TRACE_MSG("adding 1 sub-BB: [" << _bundle_bb.make_range_string(domain_dims) << "]"); _bb_list.push_back(_bundle_bb); return; } @@ -904,6 +903,7 @@ namespace yask { // Visit all points in slice, looking for a new // valid beginning point, 'ib*pt'. Indices ibspt(stencil_dims); // in stencil dims. + ibspt[step_posn] = 0; Indices ibdpt(domain_dims); // in domain dims. slice_len.visitAllPoints ([&](const IdxTuple& ofs, size_t idx) { @@ -911,10 +911,9 @@ namespace yask { // Find global point from 'ofs' in domain // and stencil dims. Indices iofs(ofs); - ibdpt = islice_begin.addElements(iofs); // domain tuple. - DOMAIN_VAR_LOOP(i, j) { - ibspt[i] = ibdpt[j]; // stencil tuple. - } + ibdpt = islice_begin.addElements(iofs); // domain indices. + DOMAIN_VAR_LOOP(i, j) + ibspt[i] = ibdpt[j]; // stencil indices. // Valid point must be in sub-domain and // not seen before in this slice. @@ -938,6 +937,7 @@ namespace yask { // End point to be found, 'ie*pt'. Indices iespt(stencil_dims); // stencil dims. + iespt[step_posn] = 0; Indices iedpt(domain_dims); // domain dims. // Repeat scan until no adjustment is made. @@ -946,20 +946,19 @@ namespace yask { do_scan = false; TRACE_MSG("scanning " << scan_len.makeDimValStr(" * ") << - " starting at " << bdpt.makeDimValStr()); + " starting at " << ibdpt.makeDimValStr(domain_dims)); scan_len.visitAllPoints ([&](const IdxTuple& eofs, size_t eidx) { // Make sure scan_len range is observed. - for (int i = 0; i < nddims; i++) - assert(eofs[i] < scan_len[i]); + DOMAIN_VAR_LOOP(i, j) + assert(eofs[j] < scan_len[j]); // Find global point from 'eofs'. Indices ieofs(eofs); iedpt = ibdpt.addElements(ieofs); // domain tuple. - DOMAIN_VAR_LOOP(i, j) { + DOMAIN_VAR_LOOP(i, j) iespt[i] = iedpt[j]; // stencil tuple. - } // Valid point must be in sub-domain and // not seen before in this slice. @@ -979,18 +978,18 @@ namespace yask { // Adjust 1st dim that is beyond its starting pt. // This will reduce the range of the scan. - for (int i = 0; i < nddims; i++) { + DOMAIN_VAR_LOOP(i, j) { // Beyond starting point in this dim? - if (iedpt[i] > ibdpt[i]) { - scan_len[i] = iedpt[i] - ibdpt[i]; + if (iedpt[j] > ibdpt[j]) { + scan_len[j] = iedpt[j] - ibdpt[j]; // restart scan for // remaining dims. // TODO: be smarter // about where to // restart scan. - if (i < nddims - 1) + if (j < nddims - 1) do_scan = true; return false; // stop this scan. @@ -1002,7 +1001,8 @@ namespace yask { }); // Looking for invalid point. } // while scan is adjusted. TRACE_MSG("found BB " << scan_len.makeDimValStr(" * ") << - " starting at " << bdpt.makeDimValStr()); + " starting at " << ibdpt.makeDimValStr(domain_dims)); + iscan_len.setFromTuple(scan_len); // 'scan_len' now contains sizes of the new BB. BoundingBox new_bb; @@ -1033,8 +1033,7 @@ namespace yask { // BBs in slice 'n'. for (auto& bbn : cur_bb_list) { - TRACE_MSG(" sub-BB: [" << bbn.bb_begin.makeDimValStr() << - " ... " << bbn.bb_end.makeDimValStr() << ")"); + TRACE_MSG(" sub-BB: [" << bbn.make_range_string(domain_dims) << "]"); // Don't bother with empty BB. if (bbn.bb_size == 0) @@ -1075,8 +1074,7 @@ namespace yask { // Merge by just increasing the size of 'bb'. bb.bb_end[odim] = bbn.bb_end[odim]; - TRACE_MSG(" merging to form [" << bb.bb_begin.makeDimValStr() << - " ... " << bb.bb_end.makeDimValStr() << ")"); + TRACE_MSG(" merging to form [" << bb.make_range_string(domain_dims) << "]"); bb.update_bb("sub-bb", _context, true); break; } diff --git a/src/kernel/lib/stencil_calc.cpp b/src/kernel/lib/stencil_calc.cpp index 7bebc36a..736d2a82 100644 --- a/src/kernel/lib/stencil_calc.cpp +++ b/src/kernel/lib/stencil_calc.cpp @@ -467,8 +467,8 @@ namespace yask { // Full rectilinear polytope of aligned clusters: use optimized code. if (do_clusters) { TRACE_MSG("calc_sub_block_vec: using cluster code for [" << - sub_block_fcidxs.begin.makeValStr(nsdims) << - " ... " << sub_block_fcidxs.end.makeValStr(nsdims) << + sub_block_fcidxs.begin.makeValStr() << + " ... " << sub_block_fcidxs.end.makeValStr() << ") by region thread " << region_thread_idx << " and block thread " << block_thread_idx); From 5560fac937e43df463e65a386fe11d4f24bc1021 Mon Sep 17 00:00:00 2001 From: chuckyount Date: Fri, 21 Jun 2019 11:30:15 -0700 Subject: [PATCH 59/62] update tutorial --- docs/YASK-tutorial.pdf | Bin 1599058 -> 1626596 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/YASK-tutorial.pdf b/docs/YASK-tutorial.pdf index c513909cf036370cd7e39a874096263a3355600b..6f7d2d233a7b01fa32abf86ed5b82a4cc4b2496f 100644 GIT binary patch delta 401746 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 _5v>jvGUl~AaJ|h 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%0DygcChTh4e22Jm03wlc?i% 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

    ?0%+!-bi22U>*ZP4CqaBOWXQ%(CjtzqMx(2sCv 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 Date: Fri, 21 Jun 2019 11:32:45 -0700 Subject: [PATCH 60/62] Change YASK acronym expansion to Yet Another Stencil Kit. --- Makefile | 2 +- README.md | 6 +-- YASK-LICENSE.md | 2 +- docs/api/doxygen_config.txt | 2 +- docs/api/mainpage.txt | 50 +++++++++++-------- include/aux/Soln.hpp | 2 +- include/aux/yc_node_api.hpp | 2 +- include/aux/yc_solution_api.hpp | 2 +- include/aux/yk_solution_api.hpp | 2 +- include/aux/yk_var_api.hpp | 2 +- include/yask_common_api.hpp | 2 +- include/yask_compiler_api.hpp | 2 +- include/yask_kernel_api.hpp | 2 +- setup.py | 2 +- src/common/combo.cpp | 2 +- src/common/combo.hpp | 2 +- src/common/common.mk | 2 +- src/common/common_utils.cpp | 2 +- src/common/common_utils.hpp | 2 +- src/common/fd_coeff2.cpp | 2 +- src/common/idiv.hpp | 2 +- src/common/output.cpp | 2 +- src/common/swig/yask_common_api.i | 2 +- src/common/tests/tuple_test.cpp | 2 +- src/common/tuple.cpp | 2 +- src/common/tuple.hpp | 2 +- src/common/yask_assert.hpp | 2 +- src/compiler/Makefile | 2 +- src/compiler/compiler_main.cpp | 4 +- src/compiler/lib/Cpp.cpp | 2 +- src/compiler/lib/Cpp.hpp | 2 +- src/compiler/lib/CppIntrin.cpp | 2 +- src/compiler/lib/CppIntrin.hpp | 2 +- src/compiler/lib/Eqs.cpp | 2 +- src/compiler/lib/Eqs.hpp | 2 +- src/compiler/lib/Expr.cpp | 2 +- src/compiler/lib/Expr.hpp | 2 +- src/compiler/lib/ExprUtils.cpp | 2 +- src/compiler/lib/ExprUtils.hpp | 2 +- src/compiler/lib/Parse.hpp | 2 +- src/compiler/lib/Print.cpp | 2 +- src/compiler/lib/Print.hpp | 2 +- src/compiler/lib/Settings.cpp | 2 +- src/compiler/lib/Settings.hpp | 2 +- src/compiler/lib/Solution.cpp | 2 +- src/compiler/lib/Solution.hpp | 2 +- src/compiler/lib/Var.cpp | 2 +- src/compiler/lib/Var.hpp | 2 +- src/compiler/lib/Vec.cpp | 2 +- src/compiler/lib/Vec.hpp | 2 +- src/compiler/lib/Visitor.hpp | 2 +- src/compiler/lib/YaskKernel.cpp | 2 +- src/compiler/swig/yask_compiler_api.i | 2 +- .../yask_compiler_api_exception_test.cpp | 2 +- .../tests/yask_compiler_api_exception_test.py | 2 +- src/compiler/tests/yask_compiler_api_test.cpp | 2 +- src/compiler/tests/yask_compiler_api_test.py | 2 +- src/contrib/coefficients/Makefile | 2 +- src/contrib/coefficients/fd_coeff.cpp | 2 +- src/contrib/coefficients/fd_coeff.hpp | 2 +- src/contrib/coefficients/fd_coeff_test.cpp | 2 +- src/kernel/Makefile | 2 +- src/kernel/lib/alloc.cpp | 2 +- src/kernel/lib/auto_tuner.cpp | 2 +- src/kernel/lib/auto_tuner.hpp | 2 +- src/kernel/lib/cache_model.hpp | 2 +- src/kernel/lib/context.cpp | 2 +- src/kernel/lib/context.hpp | 2 +- src/kernel/lib/factory.cpp | 2 +- src/kernel/lib/generic_var.cpp | 2 +- src/kernel/lib/generic_var.hpp | 2 +- src/kernel/lib/indices.hpp | 2 +- src/kernel/lib/new_var.cpp | 2 +- src/kernel/lib/realv.hpp | 2 +- src/kernel/lib/settings.cpp | 2 +- src/kernel/lib/settings.hpp | 2 +- src/kernel/lib/setup.cpp | 2 +- src/kernel/lib/soln_apis.cpp | 2 +- src/kernel/lib/stencil_calc.cpp | 2 +- src/kernel/lib/stencil_calc.hpp | 2 +- src/kernel/lib/utils.cpp | 2 +- src/kernel/lib/utils.hpp | 2 +- src/kernel/lib/yask.hpp | 2 +- src/kernel/lib/yask_stencil.hpp | 2 +- src/kernel/lib/yk_var.cpp | 2 +- src/kernel/lib/yk_var.hpp | 2 +- src/kernel/lib/yk_var_apis.cpp | 2 +- src/kernel/swig/yask_kernel_api.i | 2 +- src/kernel/tests/var_test.cpp | 2 +- .../tests/yask_kernel_api_exception_test.cpp | 2 +- .../tests/yask_kernel_api_exception_test.py | 2 +- src/kernel/tests/yask_kernel_api_test.cpp | 2 +- src/kernel/tests/yask_kernel_api_test.py | 2 +- src/kernel/yask.sh | 2 +- src/kernel/yask_main.cpp | 4 +- src/stencils/AwpStencil.cpp | 2 +- .../ElasticStencil/Elastic2Stencil.hpp | 2 +- .../ElasticStencil/ElasticStencil.hpp | 2 +- src/stencils/FSGElastic2Stencil.cpp | 2 +- src/stencils/FSGElasticStencil.cpp | 2 +- src/stencils/Iso3dfdStencil.cpp | 2 +- src/stencils/SSGElastic2Stencil.cpp | 2 +- src/stencils/SSGElasticStencil.cpp | 2 +- src/stencils/SimpleStencils.cpp | 2 +- src/stencils/TTIStencil.cpp | 2 +- src/stencils/TestStencils.cpp | 2 +- utils/bin/analyze_trace.pl | 2 +- utils/bin/convert_v2_stencil.pl | 2 +- utils/bin/gen_layouts.pl | 2 +- utils/bin/gen_loops.pl | 2 +- utils/bin/view_asm.pl | 2 +- utils/bin/yask_log_to_csv.pl | 2 +- utils/bin/yask_tuner.pl | 2 +- utils/bin/yask_tuner_summary.csh | 2 +- utils/lib/CmdLine.pm | 2 +- utils/lib/YaskUtils.pm | 2 +- 116 files changed, 149 insertions(+), 139 deletions(-) diff --git a/Makefile b/Makefile index 3ff7b81d..a3044cdb 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index a359a9bf..397f060e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# YASK--Yet Another Stencil Kernel +# YASK--Yet Another Stencil Kit * New YASK users may want to start with the [YASK tutorial](docs/YASK-tutorial.pdf). * Users with existing YASK-based code may want to jump to the [backward-compatibility notices](#backward-compatibility-notices). @@ -40,14 +40,14 @@ YASK contains a domain-specific compiler to convert stencil-equation specificati the Intel C++ compiler. Older Gnu C++ compilers can produce kernels that run many times slower. -* Gnu C++ compiler, g++ (4.9.0 or later; 8.2.0 or later recommended). +* Gnu C++ compiler, g++ (4.9.0 or later; 9.1.0 or later recommended). Even when using Intel compilers, they rely on functionality provided by a g++ installation. * Linux libraries `librt` and `libnuma`. * Perl (5.010 or later). * Awk. * Gnu make. * Bash shell. -* Numactl. +* Numactl utility. * Optional utilities and their purposes: * The `indent` or `gindent` utility, used automatically during the build process to make the generated code easier for humans to read. diff --git a/YASK-LICENSE.md b/YASK-LICENSE.md index aff26b8b..cc631848 100644 --- a/YASK-LICENSE.md +++ b/YASK-LICENSE.md @@ -1,4 +1,4 @@ -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/docs/api/doxygen_config.txt b/docs/api/doxygen_config.txt index 6bd9ee97..1577ab9f 100644 --- a/docs/api/doxygen_config.txt +++ b/docs/api/doxygen_config.txt @@ -44,7 +44,7 @@ PROJECT_NUMBER = # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "Yet Another Stencil Kernel: a software framework for creating HPC stencil code. Copyright 2014-2019 Intel Corporation." +PROJECT_BRIEF = "Yet Another Stencil Kit: a software framework for creating HPC stencil code. Copyright 2014-2019 Intel Corporation." # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 diff --git a/docs/api/mainpage.txt b/docs/api/mainpage.txt index 9547a5df..107c1bc9 100644 --- a/docs/api/mainpage.txt +++ b/docs/api/mainpage.txt @@ -1,4 +1,3 @@ - // This file contains text for the main page of the API docs generated by Doxygen. // See http://www.stack.nl/~dimitri/doxygen. // The 'yask' namespace enables automatic link creation w/o 'yask::' prefixes. @@ -60,16 +59,15 @@ utility, `bin/yask_compiler.exe`. -# Create a custom application that defines stencils. - This approach is typically taken when a 3rd-party front-end tool will be creating stencils automatically from some other existing format or description. - - In this case, you don't use the provided \ref yc_solution_base class or overload yc_solution_base::define(), + - In this case, you aren't required to use the provided \ref yc_solution_base class or overload yc_solution_base::define(), but equations may be expressed in the same way, because both techniques use the YASK compiler API. - The output from the custom application may be written to any file that is then specified via `YK_CODE_FILE=`filename when running `make` to build the kernel library. - See `src/compiler/tests/yask_compiler_api_test.cpp` for an example stencil definition in C++ or - `bin/yask_compiler_api_test.py` for an example stencil definition in Python. + `src/compiler/tests/yask_compiler_api_test.py` for an example stencil definition in Python. In either case, the resulting generated code should written to the C++ stencil-code file to be compiled into the kernel library. -`src/kernel/gen/yask_stencil_code.hpp`. @subsection yk_intro Create a Stencil Kernel Library and Stencil-based Application @@ -82,28 +80,31 @@ Once the stencil-code file is created, it must be compiled into a YASK kernel li the `Makefile`; you'll just need to specify the filename via `YK_CODE_FILE=`filename as described above. You'll also still need to specify the target architecture and give a descriptive name to the stencil. - Example: `make stencil=my-stencil arch=hsw kernel-only`. + Example: `make stencil=my-stencil arch=hsw kernel-only YK_CODE_FILE=my_stencil_code.hpp`. If `make` is invoked as in one of the above examples, it will create the kernel library -in `lib/libyask_kernel.`stencil.arch`.so`, where *stencil* and *arch* match the corresponding +as `lib/libyask_kernel.`stencil.arch`.so`, where *stencil* and *arch* match the corresponding variables provided during `make`. +(If you want the file named differently, you can override stencil with `YK_STENCIL=`stencil_name<\em> +and/or arch with `YK_ARCH=`arch_name<\em>.) To use the kernel library, an executable must be created from it. This may be done in one of the following ways: -# The default YASK kernel executable will automatically be created - in `bin/yask_kernel.`stencil.arch`.exe` when `make` is invoked as in the above examples. + as `bin/yask_kernel.`stencil.arch`.exe` when `make` is invoked as in the above examples. - This application may be run via `bin/yask.sh` to obtain a performance measurement of the kernel. -# You can also create your own stencil application using the YASK stencil kernel API. - This approach would be taken to integrate the kernel into a larger application that would inject real-world initial-state data into the YASK variables and extract the final-state data for analysis or further processing. - See `src/kernel/tests/yask_kernel_api_test.cpp` for an example kernel usage in C++ or - `bin/yask_kernel_api_test.py` for an example kernel usage in Python. + `src/kernel/tests/yask_kernel_api_test.py` for an example kernel usage in Python. - See \ref sec_yk for documentation on the kernel API. -@note Anytime you want to change the name or any compile-time properties of the kernel, be sure to run -`make clean` to force the removal of all kernel-specific intermediate code. -Otherwise, you will likely see some unexpected errors when building the new kernel. +@note Anytime you want to change any compile-time properties of the kernel +(like vector-folding or prefetching), be sure to run `make clean` to force +the removal of all kernel-specific intermediate code. Otherwise, you will +likely see some unexpected errors when building the new kernel. @section sec_yc YASK Stencil Compiler API @@ -117,13 +118,19 @@ this distinguishes them from the 'yk_'-prefixed types used in the "YASK kernel" The types, classes, and functions are listed in \ref yc. @subsection yc_usage Typical Program Flow using the Compiler API -- Create a yc_factory. This is the "bootstrap" object that will be used to create others. -- Create a yc_solution object via yc_factory::new_solution(). - Alternatively, if using the provided YASK compiler utility, derive a new class from - \ref yc_solution_base. -- Create index variable for solution domain dimensions via yc_node_factory::new_domain_index() and - via yc_node_factory::new_step_index() for the step dimension (often "t" for time). -- Create one or more \ref yc_var objects via yc_solution::new_var() as needed by +- If using the provided YASK stencil compiler utility, `bin/yask_compiler.exe`: + - Extend the provided base class \ref yc_solution_base + (or \ref yc_solution_with_radius_base). + - Create index variables for solution domain dimensions via yc_node_factory::new_domain_index() and + via yc_node_factory::new_step_index() for the step dimension (e.g., "t" for time). + - Create an instance of the class to make it visible to the compiler utility. + - See the examples in `src/stencils` showing how to define solutions from these base classes. +- If writing your own YASK compiler: + - Create a yc_factory. This is the "bootstrap" object that will be used to create others. + - Create a yc_solution object via yc_factory::new_solution(). + - Create index variablse for solution domain dimensions via yc_node_factory::new_domain_index() and + via yc_node_factory::new_step_index() for the step dimension (e.g., "t" for time). + - Create one or more \ref yc_var objects via yc_solution::new_var() as needed by the stencil(s) being implemented. Calls to yc_solution::new_var() specify the name and dimensions of each var. Vars may be read-only (constants) or read-write. @@ -153,13 +160,16 @@ The types, classes, and functions are listed in \ref yc. in the `src/stencils` directory. - Specify the number of bytes in a floating-point element via yc_solution::set_element_bytes(). This should be 4 or 8. - If you are using the provided YASK compiler utility, this controlled via the + If you are using the provided YASK compiler utility, this is controlled via the `real_bytes=`4|8 `make` parameter. - Optionally specify the vector-folding and/or vector-clustering via yc_solution::set_fold_len() and/or yc_solution::set_cluster_mult(). If you are using the provided YASK compiler utility, these are controlled via the `fold=`fold-spec and `cluster=`cluster-spec `make` parameters. -- Format the equations for additional processing via yc_solution::format(). +- Set the target architecture via yc_solution::set_target(). + If you are using the provided YASK compiler utility, this is controlled via the + `arch=`arch-name `make` parameter. +- Write the solution code file via yc_solution::output_solution(). If you are using the provided YASK compiler utility, this call will be done for you with the proper parameters based on the target architecture. diff --git a/include/aux/Soln.hpp b/include/aux/Soln.hpp index 4ee004c7..499ac829 100644 --- a/include/aux/Soln.hpp +++ b/include/aux/Soln.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/aux/yc_node_api.hpp b/include/aux/yc_node_api.hpp index 80dd4191..62ea498e 100644 --- a/include/aux/yc_node_api.hpp +++ b/include/aux/yc_node_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/aux/yc_solution_api.hpp b/include/aux/yc_solution_api.hpp index ec1b3e0c..1a5fd690 100644 --- a/include/aux/yc_solution_api.hpp +++ b/include/aux/yc_solution_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/aux/yk_solution_api.hpp b/include/aux/yk_solution_api.hpp index 60a99e36..f6fd4d0d 100644 --- a/include/aux/yk_solution_api.hpp +++ b/include/aux/yk_solution_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/aux/yk_var_api.hpp b/include/aux/yk_var_api.hpp index 892dd198..b924b43b 100644 --- a/include/aux/yk_var_api.hpp +++ b/include/aux/yk_var_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/yask_common_api.hpp b/include/yask_common_api.hpp index 64f10775..1448fda8 100644 --- a/include/yask_common_api.hpp +++ b/include/yask_common_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/yask_compiler_api.hpp b/include/yask_compiler_api.hpp index d3eae862..a7c33f1f 100644 --- a/include/yask_compiler_api.hpp +++ b/include/yask_compiler_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/yask_kernel_api.hpp b/include/yask_kernel_api.hpp index 89e1f80f..5b1cd250 100644 --- a/include/yask_kernel_api.hpp +++ b/include/yask_kernel_api.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/setup.py b/setup.py index b7ec0195..80173131 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def run(self): setup( name='yask', version='v3', - description='YASK--Yet Another Stencil Kernel', + description='YASK--Yet Another Stencil Kit', url='https://github.com/intel/yask', author='Intel Corporation', license='MIT', diff --git a/src/common/combo.cpp b/src/common/combo.cpp index 9ec2327f..7f4caf76 100644 --- a/src/common/combo.cpp +++ b/src/common/combo.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/combo.hpp b/src/common/combo.hpp index 57c20272..3561220c 100644 --- a/src/common/combo.hpp +++ b/src/common/combo.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/common.mk b/src/common/common.mk index 4bacd955..61aa983e 100644 --- a/src/common/common.mk +++ b/src/common/common.mk @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/common_utils.cpp b/src/common/common_utils.cpp index 0e1e2b50..063a5abe 100644 --- a/src/common/common_utils.cpp +++ b/src/common/common_utils.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/common_utils.hpp b/src/common/common_utils.hpp index fc4fa07c..b096c363 100644 --- a/src/common/common_utils.hpp +++ b/src/common/common_utils.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/fd_coeff2.cpp b/src/common/fd_coeff2.cpp index e93a76b4..52b29dc4 100644 --- a/src/common/fd_coeff2.cpp +++ b/src/common/fd_coeff2.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/idiv.hpp b/src/common/idiv.hpp index 060bf94a..9d4c431b 100644 --- a/src/common/idiv.hpp +++ b/src/common/idiv.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/output.cpp b/src/common/output.cpp index c7a22336..f398cff4 100644 --- a/src/common/output.cpp +++ b/src/common/output.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/swig/yask_common_api.i b/src/common/swig/yask_common_api.i index 0014d9cd..07fb788f 100644 --- a/src/common/swig/yask_common_api.i +++ b/src/common/swig/yask_common_api.i @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/tests/tuple_test.cpp b/src/common/tests/tuple_test.cpp index cb5567b9..8558ca39 100644 --- a/src/common/tests/tuple_test.cpp +++ b/src/common/tests/tuple_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/tuple.cpp b/src/common/tuple.cpp index 0c10cb2c..471fcff8 100644 --- a/src/common/tuple.cpp +++ b/src/common/tuple.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/tuple.hpp b/src/common/tuple.hpp index d5f5ff51..72e386a6 100644 --- a/src/common/tuple.hpp +++ b/src/common/tuple.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/common/yask_assert.hpp b/src/common/yask_assert.hpp index 3920e83f..d1c7284a 100644 --- a/src/common/yask_assert.hpp +++ b/src/common/yask_assert.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/Makefile b/src/compiler/Makefile index 14287e26..75aa3bcd 100644 --- a/src/compiler/Makefile +++ b/src/compiler/Makefile @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/compiler_main.cpp b/src/compiler/compiler_main.cpp index 4b41f184..36d7755d 100644 --- a/src/compiler/compiler_main.cpp +++ b/src/compiler/compiler_main.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy @@ -370,7 +370,7 @@ void parseOpts(int argc, const char* argv[], // Main program. int main(int argc, const char* argv[]) { - cout << "YASK -- Yet Another Stencil Kernel\n" + cout << "YASK -- Yet Another Stencil Kit\n" "YASK Stencil Compiler Utility\n" "Copyright (c) 2014-2019, Intel Corporation.\n" "Version: " << yask_get_version_string() << endl; diff --git a/src/compiler/lib/Cpp.cpp b/src/compiler/lib/Cpp.cpp index a3168fe1..b76d5c1e 100644 --- a/src/compiler/lib/Cpp.cpp +++ b/src/compiler/lib/Cpp.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Cpp.hpp b/src/compiler/lib/Cpp.hpp index c73e2844..d4491ab5 100644 --- a/src/compiler/lib/Cpp.hpp +++ b/src/compiler/lib/Cpp.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/CppIntrin.cpp b/src/compiler/lib/CppIntrin.cpp index d2f79c4a..68039327 100644 --- a/src/compiler/lib/CppIntrin.cpp +++ b/src/compiler/lib/CppIntrin.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/CppIntrin.hpp b/src/compiler/lib/CppIntrin.hpp index f6827658..60202df0 100644 --- a/src/compiler/lib/CppIntrin.hpp +++ b/src/compiler/lib/CppIntrin.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Eqs.cpp b/src/compiler/lib/Eqs.cpp index a9d806e6..a393fe7b 100644 --- a/src/compiler/lib/Eqs.cpp +++ b/src/compiler/lib/Eqs.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Eqs.hpp b/src/compiler/lib/Eqs.hpp index 477b1f32..3e76167f 100644 --- a/src/compiler/lib/Eqs.hpp +++ b/src/compiler/lib/Eqs.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Expr.cpp b/src/compiler/lib/Expr.cpp index e9c0509f..a4d79fc8 100644 --- a/src/compiler/lib/Expr.cpp +++ b/src/compiler/lib/Expr.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Expr.hpp b/src/compiler/lib/Expr.hpp index 202221ef..f2a6f6a9 100644 --- a/src/compiler/lib/Expr.hpp +++ b/src/compiler/lib/Expr.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/ExprUtils.cpp b/src/compiler/lib/ExprUtils.cpp index 3f3405f3..0bb8a3de 100644 --- a/src/compiler/lib/ExprUtils.cpp +++ b/src/compiler/lib/ExprUtils.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/ExprUtils.hpp b/src/compiler/lib/ExprUtils.hpp index 2148efc7..e740553e 100644 --- a/src/compiler/lib/ExprUtils.hpp +++ b/src/compiler/lib/ExprUtils.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Parse.hpp b/src/compiler/lib/Parse.hpp index 721fa87c..c18d3e39 100644 --- a/src/compiler/lib/Parse.hpp +++ b/src/compiler/lib/Parse.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Print.cpp b/src/compiler/lib/Print.cpp index bea476cc..e076796a 100644 --- a/src/compiler/lib/Print.cpp +++ b/src/compiler/lib/Print.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Print.hpp b/src/compiler/lib/Print.hpp index 3c413f34..c000b0d9 100644 --- a/src/compiler/lib/Print.hpp +++ b/src/compiler/lib/Print.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Settings.cpp b/src/compiler/lib/Settings.cpp index fdc01760..6b7560ea 100644 --- a/src/compiler/lib/Settings.cpp +++ b/src/compiler/lib/Settings.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Settings.hpp b/src/compiler/lib/Settings.hpp index 22145318..fcb43159 100644 --- a/src/compiler/lib/Settings.hpp +++ b/src/compiler/lib/Settings.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Solution.cpp b/src/compiler/lib/Solution.cpp index 244552d5..78ea9c38 100644 --- a/src/compiler/lib/Solution.cpp +++ b/src/compiler/lib/Solution.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Solution.hpp b/src/compiler/lib/Solution.hpp index 279d8c3c..5502e4bc 100644 --- a/src/compiler/lib/Solution.hpp +++ b/src/compiler/lib/Solution.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Var.cpp b/src/compiler/lib/Var.cpp index 2aefd5ac..574790dc 100644 --- a/src/compiler/lib/Var.cpp +++ b/src/compiler/lib/Var.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Var.hpp b/src/compiler/lib/Var.hpp index facc25db..2a652c20 100644 --- a/src/compiler/lib/Var.hpp +++ b/src/compiler/lib/Var.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Vec.cpp b/src/compiler/lib/Vec.cpp index e63308f2..0bc2c37c 100644 --- a/src/compiler/lib/Vec.cpp +++ b/src/compiler/lib/Vec.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Vec.hpp b/src/compiler/lib/Vec.hpp index 855b3d6c..69de8e19 100644 --- a/src/compiler/lib/Vec.hpp +++ b/src/compiler/lib/Vec.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/Visitor.hpp b/src/compiler/lib/Visitor.hpp index 690c1bfe..c02a0ce0 100644 --- a/src/compiler/lib/Visitor.hpp +++ b/src/compiler/lib/Visitor.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/lib/YaskKernel.cpp b/src/compiler/lib/YaskKernel.cpp index 66a4042e..0b4b8ee0 100644 --- a/src/compiler/lib/YaskKernel.cpp +++ b/src/compiler/lib/YaskKernel.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/swig/yask_compiler_api.i b/src/compiler/swig/yask_compiler_api.i index 72b7fc9c..bbcd5b62 100644 --- a/src/compiler/swig/yask_compiler_api.i +++ b/src/compiler/swig/yask_compiler_api.i @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/tests/yask_compiler_api_exception_test.cpp b/src/compiler/tests/yask_compiler_api_exception_test.cpp index c0bcf528..7ca9c2f0 100644 --- a/src/compiler/tests/yask_compiler_api_exception_test.cpp +++ b/src/compiler/tests/yask_compiler_api_exception_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/tests/yask_compiler_api_exception_test.py b/src/compiler/tests/yask_compiler_api_exception_test.py index 94b9751f..419a26ab 100755 --- a/src/compiler/tests/yask_compiler_api_exception_test.py +++ b/src/compiler/tests/yask_compiler_api_exception_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/tests/yask_compiler_api_test.cpp b/src/compiler/tests/yask_compiler_api_test.cpp index 4d96cb51..e4d43d90 100644 --- a/src/compiler/tests/yask_compiler_api_test.cpp +++ b/src/compiler/tests/yask_compiler_api_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/compiler/tests/yask_compiler_api_test.py b/src/compiler/tests/yask_compiler_api_test.py index f83c2582..51b2c14f 100755 --- a/src/compiler/tests/yask_compiler_api_test.py +++ b/src/compiler/tests/yask_compiler_api_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/contrib/coefficients/Makefile b/src/contrib/coefficients/Makefile index c66afc76..ffe3932c 100644 --- a/src/contrib/coefficients/Makefile +++ b/src/contrib/coefficients/Makefile @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## ## Permission is hereby granted, free of charge, to any person obtaining a copy ## of this software and associated documentation files (the "Software"), to diff --git a/src/contrib/coefficients/fd_coeff.cpp b/src/contrib/coefficients/fd_coeff.cpp index d969b5c6..5d94ab42 100644 --- a/src/contrib/coefficients/fd_coeff.cpp +++ b/src/contrib/coefficients/fd_coeff.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/contrib/coefficients/fd_coeff.hpp b/src/contrib/coefficients/fd_coeff.hpp index 47cedf98..ddff31b9 100644 --- a/src/contrib/coefficients/fd_coeff.hpp +++ b/src/contrib/coefficients/fd_coeff.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/contrib/coefficients/fd_coeff_test.cpp b/src/contrib/coefficients/fd_coeff_test.cpp index 797ee79e..45e2ba88 100644 --- a/src/contrib/coefficients/fd_coeff_test.cpp +++ b/src/contrib/coefficients/fd_coeff_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 545e3c59..eb729ee4 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/alloc.cpp b/src/kernel/lib/alloc.cpp index 724ff925..cd4aeaae 100644 --- a/src/kernel/lib/alloc.cpp +++ b/src/kernel/lib/alloc.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/auto_tuner.cpp b/src/kernel/lib/auto_tuner.cpp index f4ff1938..8f4356ae 100644 --- a/src/kernel/lib/auto_tuner.cpp +++ b/src/kernel/lib/auto_tuner.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/auto_tuner.hpp b/src/kernel/lib/auto_tuner.hpp index 9dd3a7ed..2c28169b 100644 --- a/src/kernel/lib/auto_tuner.hpp +++ b/src/kernel/lib/auto_tuner.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/cache_model.hpp b/src/kernel/lib/cache_model.hpp index f2788442..3be45bc2 100644 --- a/src/kernel/lib/cache_model.hpp +++ b/src/kernel/lib/cache_model.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 3532384e..707f3fc3 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 4e72855d..0d95ea61 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/factory.cpp b/src/kernel/lib/factory.cpp index 6fcf2079..a4ede07c 100644 --- a/src/kernel/lib/factory.cpp +++ b/src/kernel/lib/factory.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/generic_var.cpp b/src/kernel/lib/generic_var.cpp index 8b7dea8e..f5500c8d 100644 --- a/src/kernel/lib/generic_var.cpp +++ b/src/kernel/lib/generic_var.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/generic_var.hpp b/src/kernel/lib/generic_var.hpp index 0c956301..cc3e7657 100644 --- a/src/kernel/lib/generic_var.hpp +++ b/src/kernel/lib/generic_var.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/indices.hpp b/src/kernel/lib/indices.hpp index 7edae7af..57714eec 100644 --- a/src/kernel/lib/indices.hpp +++ b/src/kernel/lib/indices.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/new_var.cpp b/src/kernel/lib/new_var.cpp index 9264e41a..8df11d52 100644 --- a/src/kernel/lib/new_var.cpp +++ b/src/kernel/lib/new_var.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/realv.hpp b/src/kernel/lib/realv.hpp index 765bf55b..911c2b65 100644 --- a/src/kernel/lib/realv.hpp +++ b/src/kernel/lib/realv.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/settings.cpp b/src/kernel/lib/settings.cpp index afbf7acc..148eda9c 100644 --- a/src/kernel/lib/settings.cpp +++ b/src/kernel/lib/settings.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/settings.hpp b/src/kernel/lib/settings.hpp index c8ef6ad2..7e2c3bb2 100644 --- a/src/kernel/lib/settings.hpp +++ b/src/kernel/lib/settings.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/setup.cpp b/src/kernel/lib/setup.cpp index 4f76a643..7ba01872 100644 --- a/src/kernel/lib/setup.cpp +++ b/src/kernel/lib/setup.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index 056ac52c..d7d8d334 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/stencil_calc.cpp b/src/kernel/lib/stencil_calc.cpp index 736d2a82..a03c36c1 100644 --- a/src/kernel/lib/stencil_calc.cpp +++ b/src/kernel/lib/stencil_calc.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/stencil_calc.hpp b/src/kernel/lib/stencil_calc.hpp index 6745b9aa..7e5b08fa 100644 --- a/src/kernel/lib/stencil_calc.hpp +++ b/src/kernel/lib/stencil_calc.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/utils.cpp b/src/kernel/lib/utils.cpp index e21514e6..ec16749d 100644 --- a/src/kernel/lib/utils.cpp +++ b/src/kernel/lib/utils.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/utils.hpp b/src/kernel/lib/utils.hpp index 370fed1c..cd04516f 100644 --- a/src/kernel/lib/utils.hpp +++ b/src/kernel/lib/utils.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/yask.hpp b/src/kernel/lib/yask.hpp index 5cb66293..1a4a8a7f 100644 --- a/src/kernel/lib/yask.hpp +++ b/src/kernel/lib/yask.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/yask_stencil.hpp b/src/kernel/lib/yask_stencil.hpp index 2c1edc98..09cab826 100644 --- a/src/kernel/lib/yask_stencil.hpp +++ b/src/kernel/lib/yask_stencil.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/yk_var.cpp b/src/kernel/lib/yk_var.cpp index 13166cc9..22bef855 100644 --- a/src/kernel/lib/yk_var.cpp +++ b/src/kernel/lib/yk_var.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/yk_var.hpp b/src/kernel/lib/yk_var.hpp index 1cdf6384..e0b538f4 100644 --- a/src/kernel/lib/yk_var.hpp +++ b/src/kernel/lib/yk_var.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/lib/yk_var_apis.cpp b/src/kernel/lib/yk_var_apis.cpp index b36cfaf1..fa383381 100644 --- a/src/kernel/lib/yk_var_apis.cpp +++ b/src/kernel/lib/yk_var_apis.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/swig/yask_kernel_api.i b/src/kernel/swig/yask_kernel_api.i index cff20a5e..1c4b3bb8 100644 --- a/src/kernel/swig/yask_kernel_api.i +++ b/src/kernel/swig/yask_kernel_api.i @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/tests/var_test.cpp b/src/kernel/tests/var_test.cpp index acd46291..9641e621 100644 --- a/src/kernel/tests/var_test.cpp +++ b/src/kernel/tests/var_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/tests/yask_kernel_api_exception_test.cpp b/src/kernel/tests/yask_kernel_api_exception_test.cpp index 05c8f1da..60e310a2 100644 --- a/src/kernel/tests/yask_kernel_api_exception_test.cpp +++ b/src/kernel/tests/yask_kernel_api_exception_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/tests/yask_kernel_api_exception_test.py b/src/kernel/tests/yask_kernel_api_exception_test.py index d5e33de5..520952a3 100755 --- a/src/kernel/tests/yask_kernel_api_exception_test.py +++ b/src/kernel/tests/yask_kernel_api_exception_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/tests/yask_kernel_api_test.cpp b/src/kernel/tests/yask_kernel_api_test.cpp index 22c0ab72..238ec951 100644 --- a/src/kernel/tests/yask_kernel_api_test.cpp +++ b/src/kernel/tests/yask_kernel_api_test.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/tests/yask_kernel_api_test.py b/src/kernel/tests/yask_kernel_api_test.py index 4e20add8..479275ea 100755 --- a/src/kernel/tests/yask_kernel_api_test.py +++ b/src/kernel/tests/yask_kernel_api_test.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/yask.sh b/src/kernel/yask.sh index 770a8400..f726e897 100755 --- a/src/kernel/yask.sh +++ b/src/kernel/yask.sh @@ -1,7 +1,7 @@ #!/bin/bash ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/kernel/yask_main.cpp b/src/kernel/yask_main.cpp index a5c679af..2d942080 100644 --- a/src/kernel/yask_main.cpp +++ b/src/kernel/yask_main.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy @@ -198,7 +198,7 @@ struct MySettings { // See https://en.wikipedia.org/wiki/Box-drawing_character. os << " \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n" - " \u2502 Y.A.S.K. \u2500\u2500 Yet Another Stencil Kernel \u2502\n" + " \u2502 Y.A.S.K. \u2500\u2500 Yet Another Stencil Kit \u2502\n" " \u2502 https://github.com/intel/yask \u2502\n" " \u2502 Copyright (c) 2014-2019, Intel Corporation \u2502\n" " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n" diff --git a/src/stencils/AwpStencil.cpp b/src/stencils/AwpStencil.cpp index e76c4130..8c0706ab 100644 --- a/src/stencils/AwpStencil.cpp +++ b/src/stencils/AwpStencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/ElasticStencil/Elastic2Stencil.hpp b/src/stencils/ElasticStencil/Elastic2Stencil.hpp index ddb57353..e3004363 100644 --- a/src/stencils/ElasticStencil/Elastic2Stencil.hpp +++ b/src/stencils/ElasticStencil/Elastic2Stencil.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/ElasticStencil/ElasticStencil.hpp b/src/stencils/ElasticStencil/ElasticStencil.hpp index acca1cc1..eb58d204 100644 --- a/src/stencils/ElasticStencil/ElasticStencil.hpp +++ b/src/stencils/ElasticStencil/ElasticStencil.hpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/FSGElastic2Stencil.cpp b/src/stencils/FSGElastic2Stencil.cpp index 8f1c1a8b..fbe2060d 100644 --- a/src/stencils/FSGElastic2Stencil.cpp +++ b/src/stencils/FSGElastic2Stencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/FSGElasticStencil.cpp b/src/stencils/FSGElasticStencil.cpp index d1eb6236..6a2caaeb 100644 --- a/src/stencils/FSGElasticStencil.cpp +++ b/src/stencils/FSGElasticStencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/Iso3dfdStencil.cpp b/src/stencils/Iso3dfdStencil.cpp index c9507aae..6bfc1763 100644 --- a/src/stencils/Iso3dfdStencil.cpp +++ b/src/stencils/Iso3dfdStencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/SSGElastic2Stencil.cpp b/src/stencils/SSGElastic2Stencil.cpp index 5291c006..9a7dd0a7 100644 --- a/src/stencils/SSGElastic2Stencil.cpp +++ b/src/stencils/SSGElastic2Stencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/SSGElasticStencil.cpp b/src/stencils/SSGElasticStencil.cpp index 356428b5..9f40b12b 100644 --- a/src/stencils/SSGElasticStencil.cpp +++ b/src/stencils/SSGElasticStencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/SimpleStencils.cpp b/src/stencils/SimpleStencils.cpp index 76fab546..b1b20edc 100644 --- a/src/stencils/SimpleStencils.cpp +++ b/src/stencils/SimpleStencils.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/TTIStencil.cpp b/src/stencils/TTIStencil.cpp index 916fa69f..9fa11a84 100644 --- a/src/stencils/TTIStencil.cpp +++ b/src/stencils/TTIStencil.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/stencils/TestStencils.cpp b/src/stencils/TestStencils.cpp index 609ce104..648147e8 100644 --- a/src/stencils/TestStencils.cpp +++ b/src/stencils/TestStencils.cpp @@ -1,6 +1,6 @@ /***************************************************************************** -YASK: Yet Another Stencil Kernel +YASK: Yet Another Stencil Kit Copyright (c) 2014-2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/analyze_trace.pl b/utils/bin/analyze_trace.pl index ba671725..6e5ce984 100755 --- a/utils/bin/analyze_trace.pl +++ b/utils/bin/analyze_trace.pl @@ -1,7 +1,7 @@ #!/usr/bin/env perl ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/convert_v2_stencil.pl b/utils/bin/convert_v2_stencil.pl index a71743a8..705ceb57 100755 --- a/utils/bin/convert_v2_stencil.pl +++ b/utils/bin/convert_v2_stencil.pl @@ -2,7 +2,7 @@ #-*-Perl-*- This line forces emacs to use Perl mode. ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/gen_layouts.pl b/utils/bin/gen_layouts.pl index 62441ff6..baeaf266 100755 --- a/utils/bin/gen_layouts.pl +++ b/utils/bin/gen_layouts.pl @@ -1,7 +1,7 @@ #!/usr/bin/env perl ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/gen_loops.pl b/utils/bin/gen_loops.pl index b7801b2c..fe10000f 100755 --- a/utils/bin/gen_loops.pl +++ b/utils/bin/gen_loops.pl @@ -2,7 +2,7 @@ #-*-Perl-*- This line forces emacs to use Perl mode. ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/view_asm.pl b/utils/bin/view_asm.pl index 0e59d06b..98f7d5e5 100755 --- a/utils/bin/view_asm.pl +++ b/utils/bin/view_asm.pl @@ -1,7 +1,7 @@ #!/usr/bin/env perl ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/yask_log_to_csv.pl b/utils/bin/yask_log_to_csv.pl index 16a5138d..bd5922ba 100755 --- a/utils/bin/yask_log_to_csv.pl +++ b/utils/bin/yask_log_to_csv.pl @@ -1,7 +1,7 @@ #!/usr/bin/env perl ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/yask_tuner.pl b/utils/bin/yask_tuner.pl index a0c71ce7..3b6bbc79 100755 --- a/utils/bin/yask_tuner.pl +++ b/utils/bin/yask_tuner.pl @@ -1,7 +1,7 @@ #!/usr/bin/env perl ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/bin/yask_tuner_summary.csh b/utils/bin/yask_tuner_summary.csh index 9207aae1..86467dc7 100755 --- a/utils/bin/yask_tuner_summary.csh +++ b/utils/bin/yask_tuner_summary.csh @@ -1,7 +1,7 @@ #!/bin/csh -f ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/lib/CmdLine.pm b/utils/lib/CmdLine.pm index 6120bc8d..2c739c10 100644 --- a/utils/lib/CmdLine.pm +++ b/utils/lib/CmdLine.pm @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/utils/lib/YaskUtils.pm b/utils/lib/YaskUtils.pm index 103b6e10..7bbfb218 100644 --- a/utils/lib/YaskUtils.pm +++ b/utils/lib/YaskUtils.pm @@ -1,5 +1,5 @@ ############################################################################## -## YASK: Yet Another Stencil Kernel +## YASK: Yet Another Stencil Kit ## Copyright (c) 2014-2019, Intel Corporation ## ## Permission is hereby granted, free of charge, to any person obtaining a copy From 0078fba3571dc28f4b8f7dbcb36a2d79d6809a5b Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 21 Jun 2019 13:38:45 -0700 Subject: [PATCH 61/62] Fix bug during throwing exception for unprepared solution. --- src/kernel/lib/auto_tuner.cpp | 2 +- src/kernel/lib/context.cpp | 2 +- src/kernel/lib/context.hpp | 13 +++++++++++++ src/kernel/lib/soln_apis.cpp | 6 +++--- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/kernel/lib/auto_tuner.cpp b/src/kernel/lib/auto_tuner.cpp index 8f4356ae..f8fca528 100644 --- a/src/kernel/lib/auto_tuner.cpp +++ b/src/kernel/lib/auto_tuner.cpp @@ -82,7 +82,7 @@ namespace yask { // Will alter data in vars. void StencilContext::run_auto_tuner_now(bool verbose) { STATE_VARS(this); - if (!rank_bb.bb_valid) + if (!is_prepared()) THROW_YASK_EXCEPTION("Error: run_auto_tuner_now() called without calling prepare_solution() first"); DEBUG_MSG("Auto-tuning..."); diff --git a/src/kernel/lib/context.cpp b/src/kernel/lib/context.cpp index 707f3fc3..32e395df 100644 --- a/src/kernel/lib/context.cpp +++ b/src/kernel/lib/context.cpp @@ -224,7 +224,7 @@ namespace yask { begin.makeDimValStr() << " ... " << end.makeDimValStr() << ") by " << stride.makeDimValStr()); - if (!rank_bb.bb_valid) + if (!is_prepared()) THROW_YASK_EXCEPTION("Error: run_solution() called without calling prepare_solution() first"); if (ext_bb.bb_size < 1) { TRACE_MSG("nothing to do in solution"); diff --git a/src/kernel/lib/context.hpp b/src/kernel/lib/context.hpp index 0d95ea61..23f88c9b 100644 --- a/src/kernel/lib/context.hpp +++ b/src/kernel/lib/context.hpp @@ -45,6 +45,11 @@ namespace yask { bool bb_is_cluster_mult=false; // num points are cluster multiples in all dims. bool bb_valid=false; // lengths and sizes have been calculated. + BoundingBox() : + bb_begin(NUM_DOMAIN_DIMS), + bb_end(NUM_DOMAIN_DIMS), + bb_len(NUM_DOMAIN_DIMS) { } + // Make Tuples. IdxTuple bb_begin_tuple(const IdxTuple& ddims) const { return bb_begin.makeTuple(ddims); @@ -325,6 +330,14 @@ namespace yask { get_stats(); } + // Ready? + bool is_prepared() const { + return rank_bb.bb_valid; + } + void set_prepared(bool prep) { + rank_bb.bb_valid = prep; + } + // Modify settings in shared state and auto-tuner. void set_settings(KernelSettingsPtr opts) { _state->_opts = opts; diff --git a/src/kernel/lib/soln_apis.cpp b/src/kernel/lib/soln_apis.cpp index d7d8d334..9ecf3e1b 100644 --- a/src/kernel/lib/soln_apis.cpp +++ b/src/kernel/lib/soln_apis.cpp @@ -37,8 +37,8 @@ namespace yask { #define GET_SOLN_API(api_name, expr, step_ok, domain_ok, misc_ok, prep_req) \ idx_t StencilContext::api_name(const string& dim) const { \ STATE_VARS(this); \ - if (prep_req && !rank_bb.bb_valid) \ - THROW_YASK_EXCEPTION("Error: '" #api_name \ + if (prep_req && !is_prepared()) \ + THROW_YASK_EXCEPTION("Error: '" #api_name \ "()' called before calling 'prepare_solution()'"); \ dims->checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ return expr; \ @@ -63,7 +63,7 @@ namespace yask { dims->checkDimType(dim, #api_name, step_ok, domain_ok, misc_ok); \ expr; \ update_var_info(false); \ - if (reset_prep) rank_bb.bb_valid = ext_bb.bb_valid = false; \ + if (reset_prep) set_prepared(false); \ } SET_SOLN_API(set_rank_index, opts->_rank_indices[dim] = n; opts->find_loc = false, false, true, false, true) From 90745b2c5fe0f8a3423cabe7705fc07029a89870 Mon Sep 17 00:00:00 2001 From: "chuck.yount" Date: Fri, 21 Jun 2019 15:03:01 -0700 Subject: [PATCH 62/62] Fix typo in API doc. --- docs/api/mainpage.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/mainpage.txt b/docs/api/mainpage.txt index 107c1bc9..2f442300 100644 --- a/docs/api/mainpage.txt +++ b/docs/api/mainpage.txt @@ -85,8 +85,8 @@ Once the stencil-code file is created, it must be compiled into a YASK kernel li If `make` is invoked as in one of the above examples, it will create the kernel library as `lib/libyask_kernel.`stencil.arch`.so`, where *stencil* and *arch* match the corresponding variables provided during `make`. -(If you want the file named differently, you can override stencil with `YK_STENCIL=`stencil_name<\em> -and/or arch with `YK_ARCH=`arch_name<\em>.) +(If you want the file named differently, you can override stencil with +`YK_STENCIL=`stencil_name and/or arch with `YK_ARCH=`arch_name.) To use the kernel library, an executable must be created from it. This may be done in one of the following ways:

    JAgbvqHC?cT{1# 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

    wZP55 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 z zmOtEMQ1_dFGg?T}MiMp6hqt0uywWoPX%w=ay=kUoK}V)33|dGs833$vG^D#O${-q) z6V>X}iUASAwlvNFIt=dtcr0}JoEnLKj!dVU8;xpWfDzXXC$KQWhWd6}5Ej_VT%?+* zKVO<-8_McVyr_M~W1?PX+EBrun#iO>t58Yp`e(v^9b`NLrEQnMNxwjBGdQy17UmS@ zL|{uD<$z%foVRX}QvWB@#wj@)!=^3GKuih*HmhR0Rn+er|(~g z$14e=VP;_+C6qTdbmp*OjKydIqkOk$^J;R!pQdoV4fD`YAlg68KJ}mpYxM-WeXRlh zV~-Mnc>c9O+F7o+)xx-^pY$p+tr==grLN5IBS6k!(?uK5<$y_8X#ejkF`ZL5t~%4Y zT^=?3q8NUVeRdOY{x(L3x>%u%QMOh-a&N%tVeeuT=i|20y>QLAqra`!woZymhoJ?9 z3zi`KJowCi?Gpy%W|&8M*9?%W$c2HvIj#@%xYh+eA)no0vJGIr}Pb_h84$mb^|+Oi#6?m?O{Ewf_Pwu9MLRup8%Y`U7_wuC=g^An~U{=U2oC zEEf5cQ)6g~lrP%w4j0@wM^zOhkpa#Dwaas#%BHjO0X)_p%vu#$kr6hk)W8*N*>3yz(**=t zRJ#(*jD~^((OMnK);Ef?!AyIGGhFa_Yz{>$vYG6~Uklm$tePj2n?Vgi2L4@vU7s@h zpSNA-@oO(%&(X1| zWH$X{OO%NRj=_aC(|SGwJ#Sc;;(##`eQnh5Iq?1ceT3`TpU4w#q@5-Fe=&T26_INE z{8AJ~W(JMLhDS`(3mGCU5o3w*NrX6fc`Kr&`50V>+0OcFgs@N)*?h}oThuqMc$?Rn zdvaXQh9Y~y+{;MtW!*8EeRPof2L6sUUaXT5>keSXqq`P0L)#%}F>LeUQ^U2wbCH-2 z5BM2BXEp1&HJ@ugZ-TE@?^j(T(;4>Pva{)(G=93CH|D;t>uR!s(5X+GoBPuyFtm8} z)HBSLNP`%T5QnI-vAohqu@i3-x&cfP4rtrcgn4tuAT7QrhJ6KltFR_}Hq{i$M#dZh zhfz+$g|UKd!?Pq?o}_Xj(D@Q?6dpJJ*%0l#k*<;0#ihEs2G`!S?WLx0wi>iue}M%0 zKtW^Vv)#NzWDFn+?`$(oM|X_KIF#2TgI8m-InfT5e<;Fu%Zy-9Y@p^!jDTT)=FDPb z+v1ovb#bw%;UH|zHN-L%nusVw#=~z)=eHWnS|-BN#|wknF`?1Ma#f96`T2B~iK(L@ zA+17G0l6M7_1a1_Xl6%0Dsg}X^jua;6{22M`R})qm$OfZD4%ww{{wpePLh1;6vI1i zdE(z$3(L5Lsm4R0KacPJfu-bv;BDZP%bYm(w0%pE_0hjuT%un>GxICq&>UfON1n&U zG(IVUiY~Wb-l*TwVwB)whw?+>6tR2)`G2ynDSSjO%X(5kt2-tu^kG$Et$yE7l%gAqyqAtzdA2VAdUrQhhRf-ZZ$~VB*VwvnuA=XassR=J$N-A#eocZM`n&@{1ybv629J0LSbVRQCCHYEM z-w0s0d~JAzwL|TU6os6V8f+3uogn99ED~*7)fFQcme0-iU6E-$q`#GCn`*cf_YBZ4 zzL-XRi^?h3(f-EHTBk8nR1an<=7OJzu8+1asGjLG0dY=$lN}THugSkA?#gKZeIPjs zE6OHoBFDcbz9wjTbZHdV?3I5GFYWLjY!2s`ajy;0S0^``78 zELElzhPpd<;+_oAQ75?77N>@%=C`b&cn-JE+4{0cSLy?6QMndvksy*CpC}X--_$G6 zfM)E!y&6RJ7&gH{_cRcqNMH(ilqBAUX_g^B?NpgXJ=^}{RX=YgNN`6y>M2S*N)|7b zHRU;oDYpS!6H`O`{h6D^H(|Q})7Gw~(WYb&%+8mcvnVgz2exwr-gcuCpD1Sd`Xf99 zJe@v@REbhd=dMr`aIaRs}hJiv|j!R%%5l}NlM#HYN>%euI= zq&5uodo2NKFPQ`vxv?-8T6{@3YP`I#SPCjC>G#@DaZ`g{vexi$*l^U|4ra1ij5wbS zk%h~RD$F>0_lvxahun|XgKVCImwko1TQwh-lXV?|?BPme#(x}*!ugW_Th^S*%oPxh37Rm+$;f)+h&$?f$;QihNj1nx^m|GWzS4w4RwvEzH3rL2l?lHPWW zXr(ll;?D^0*b-vA%I`ZtzgVLAEmkc?%Bp5u*w==RAj?2ilcZN;CiaaMDaw>sld2u5<41bbL*G5KB~Fa1OoGP^<{ddBy8)*&!9YgMI#> zSa`%4`m@j4{TwSmu5@BxdtiD8XD6Y}{Z;yba%_`2% zZULlU9S<9KhgT1=Zw`bwS0$dA^BPEQaxNf^n*{@R1xE)b5<8(``pULg%?AU>L7Q#3 z_$__9)pdfmehZ#m_CUV2LDGH!rT5M*C^!EPLfZ2{_;+Y3>(9$}+Vf6?4``~U178*I z87>vD3k&oNl0aH)=!nrAfk^IL`Jgj61@6WFvR+n?Q~UN$~F z+@jn~UNPU1TyLO?4byLRB~hi!U%S7$MM_1SgJuH%LYYBjql_S8cPn?Zc7wVb z0x<&rK~ck?AS)o{5M*JuQ3A*xy&cWNVI$xp;35!8u@X>cs3>?$9i^;?R^#g97)kL+ z4}P%y5Vusbl(W>etegs-;>sJ&3;Ln@;~=y+#2#)OR)8b}kE$oX$GB&^$2x>ExB*TU znSd|_pNpG;(N}A{W`Sb1` zI%da&@rn6)s{@`hZ@+cG!4rZ!XeFeachaCKVAOtx*Ef7L=eSmH$AhDhA%*!Af!&8F;xSk z++T#H;k`P&=S53g;a+c?Dzo>%E2)(iJ6m;loeyTucBM?UuD<=b+@9s?t)F_9k^BhH z^ly*zDtej<_kwqAFyKl*y!D!w0i2!-^k$IW-1%DuAB=67^m8B5+23P<&i>o+P7Y7^_0mpTig*`vh5D-X_7P_#P;P4y?CoJyn*BUXo)mPO)DE&XM%I{v!`TOZH zFVws>ulgD6zkrjuIhEGuzDt0zwza_owD#3avBsQ{NX7K(>+9dwNFR`Q1_UTnRUC)uT0bry>>%U5wLx-j$B!3$dqVBG-(0(*|q*Fi6ix|e1B() zcf=YfIHNr-b@B#|rBlBuiUzmX&0X2KHXRh$jkQOj?>$h1}YX`5j8+W1p=ouweMgD`q?{3kJRO7bdCkv{or^K^?1<>NQ~R z+yVNkr$f9}b!A=EE44;0z2qFd#$mLNM6KiEZB=fdg^MbvEOTUUn68DY{4j@K=Sp;Q z%oiImzR7|SzUY^(x@@c+c;5R#N&8+2|3L}g&zz^>3^-xN?HK!e(XoFgTk<}}Pc3)7 z?CWVIndZgOx%-r)_^Kd6c1@{){6X0v_v%`#FJ155sAJ=8too|j-$#~%6~B7@uOs}w zn`>8+t8X=?>BY^WF_Vc@)QS@FU#Z0R#vn#izcs!32&1G544W~#E?Z>Z3y+&IyI8Zp zniQtk?V)IGM?o2Q7RG`~KYA+?=FMr4ffd)UQz~HKJeOLuk0s*^abMU0@m~Ya4CK#l zC}W;_PxCB$8olSHSB`fbTd{g31!^uVGPFW6l?lpxYwz)8{Ir}arSjG|9)fUk`h5HA|-Vx3xWOGzPRxnbq2z-k*haR3V(osQY(MH?a;eHJdv# z`XCqUto8tKw#=FRJhpaG-x&=e{;)$S5pb~lyEFZ6UpA`0RevDKHz_1E+?=yd%{$1~ zSw4EcUEk?8FT3I3w)`*aJ`lH=nB>+%WZw4gn*OYrhFg1Q*{J;~;RcGc?mcNq`|pOE zw@4h`Gm_EfQ;t-hB`fBZS#^Xn0%t}A6pdtl2cw1QWW<8p+8my1M+tlB)jE(3BCO%r7m_KK}6Hgmy+gY8_7TH%Os=gL4 z#kd+?tf_hfpNcP+GV%2ukz~p)f3za&WW=FOWkscK7;y~1#BD*9;|nOEBy5C12Mv}{ zEocJ!>EfBxH|dF;VzPR7n9wUAhRmGsXqqLeATXFCQ$;YU!!=mAS9k(zM=HwRJUG%q zx9A_2<(AqFeZ4KBD!#}Hd*Q}rBPwx6v+=hD_zXk_H6f-|mhSX1bYQy{Yoyj8_5Y_hej67k{ zl<)dC?{ymQbrbJ(Fz>ampUu$wLeiU${QZNkEaUQZi*0FkySQzfz$%4Tllc9m?1JQtZ(;?Il*Q=&Oy+W9i7xM zWz-oE6kl2rr4nE~mp*{_p7GCx5Vus7!;(|6-g1JWm@_dHJzo+;RW=dWGNJ-VchQ@n zehj-f5rxM8+vP%R)Ps~zLb>abvQ|crnEs9rRbT}`3S;HK8HYBpg3$glFilnu8&yJS zX_qF9VI?V5kZnmVRibB!qp8q3ZHg$^Zpo}E{xZ|?Cj+^p*9eJ7T(Vo6H~Bo!Wh_?T zIV{<{h%^yseB~GmG?|Ar!&rjqsTZ?jo4%#;#88oODCQ=gJR&(HiJS41ZKw3mzxd_$ zy~b0ro!mp@qR@@Z?AAcwO-gG=e#ghD`_KkG!3tVC`G|UU{T)91D}xdydWdG6yEgxLpg5Xxa7egCA3K8@KYfmwQGOH6M31<%a>5>J zk+>B$sj)c2DD6l%8-q#`#-1jVvWS{tvv^jxiHDfDa=dtiOg_4oOkbpXiiR2%P)jiW zJG!Rtv>JyQw3zdB78WL>7=pT#H-(^aNdMrr$$h;g^-7K9wDM0=aWU%Y2rR7JaK$C| z{MN$>aKvPv#i`b`&aF9Xe(vEQI1)3yMN1apQhX)|B?|1Cdu1QBqi?6%}a|R5eb<;Iy8R$Wmjv^6$lwN2lVfs$-@gpLrYSKJ*dzI&vJo z(dTd~Un6^J?9xwM6ZZDw6ys${XZsgmXdU~Yk4Ifm7ZYchZ@ac>>^QP~o6bu^7sv0< zx5KuJ(MM=DCp4$X)gBtx*wx;{JXIo&=82!p6Z}ruAbe@^ZrPjJ*Uf@y4tzv)tb)u^ z?gfINBJTOjKm&&=ZkW8rDIH<|b$thv0MGm!SP{>J9H?%x>LCPDvd*Dco3>vxutxcR zXb`u^w8efPE309Kz$(jO24#^+^a&Tzkje-%U1hl=J4GJ!-^59_eb@J=QC3e1DG~Ef zCcXya^hd@iwo&N!SegxPd}Vvb#;gWw$h_g>4=J&&FL(-6GM=mI- z)uY*M;!Ug9hZvJ7Q}oo4NmGbK9WwC#0L3#TM zjLc4BKaN;SV_!$}VzrpV!6SoQ$Fk_xvi!~zjxeR9 zi=O&jL>EnCQvf8d8zgb;i{{0xraiFIaj3&pO=(hZQqOQ5;6OOA z^%3=8g!r2K@HY99^dK&CQCGdKG&56o;U{=6MDl|2ggdRXyx1b;tDOOyJ{GYbyem?_ zt|svmg+~mjVSzU9_164KZwP4{*6xU_&}&w48sHwjcY-*!*qwU#BIYD%fHN%Jp-Aa= z?easR&tfIx4GVvryWRahgT>bhx zNh?3;Nt(7!jkZpXHnAAV+wpM|*R-d+3gtk_hmQ9ha zR>@PQMa^`4L(Q~K#WYgIv|PnBQ)L&YXsB8yo=7HsBZ-VJnXEO5%v`$*IPU5sq^0ZERwAW!OyP+z(#VWghRd!=kcB@n)i})dq56x)glRfPcHsy#Hoq&s{*?mI*QY5T-bzBQ}*)DeT9I#7MUy*iL9}-CfrZ+ z>~2#%EsZ~#Y%hebwuA&Qq_%MX5cA#--X?!=vB=n}mP0A)Q>%5euYw4?`4;K`-IsxBZ?*7L<c@r?BME$}=>_ z?3;k(BzvO%FPtMv&vgAfjU!Ia>~|4|smxpKcKM5`R*uB=UQ{t$vnVS$3*v$F)Tbqa z3S_Uuc{3!<9}D5_lY+))n#>ECcSb(TEL@?{7B@?7r(S>k8O?=i8ExtR4fq=UTduZ+ zd5JzVZC$ee8+K;)vgGUPZ}unX6!k@qz8X07*QV2&uYRLGdxgoa@vr2+^0V1{8<={; zvtO=KFM50xMAI?WgY`QraA$?CGJKWU(-YPQ^*1ZfXZfzutrdFHRo093Co3c?NN2^a zvaOYC)92RdD*|iPFgK|ll<)Ad2gx2-?{w88QcVb{ZZ}+PM6J7PlO(TV6?C z8Q;082RF9vo?6>JF*-3Gz1quI>5L-3|mEE!wC*vL3eEJxJD5A9mh6;7Ph*u0_0AJ_1p;46gIM zaY-g5FXO#2NyY~+YrF|bCaEvg1mhLA6Q3~Ov2sT`_njZPy_r5zCU-Wjo?g8={6D&I zuEo7sKjN9UgszIb@f3H2Zhm%TRd3Qi(RE~0Z`nNYcH}s05$;%v=W8#AqIUG9AyJGJt)zh`?%^BMOw_hauTG(_frNe>!l z9wXh?bk5>g&oV5|z!;a_H+2R-CG*T@nJaKxq_K}{?c3hi+z>cdJyr5dzD{I0_&PAL z__6qL&5rNw!#fu>kLcP}v2v#ojF0bQJC`?)zxJ=%zgwTP__4cXw2p6#lkc2I;ttEoVA4W2XJ^x=HPOY~edz{UYFd z{_yPM+w1Vm*tx;{3h^%N7bmntvW;>V_SE~v^NRMK^)BVd!Sy!;_;CM#@+>A-Cg5IZJtf3h#w z7rhVBH@+{@SGmvgl1(-ySOD8NN#nF+k#x{PKk50whfkti9um-`o)(kxWf`4DCy3BXe#U^a&p-oIvDO&!eVBV5*>hR>&Wh&ZefaMZ5GD^HFI&wgq zpJd)*_UxmG@MP@Ihu^{C2Or+TM4n;>_eUlVdm8uNxCg>Jt@(F8XZ3+BEmiY6ZWeZ= z6pvcseJMUZ^SuFc#Wbwe_e}3cOD@77k4vL(V>x>72BV=UwM6^<(`lV`7X7I;&wp%U zD@J;&_^eI#K&taZjWx&aF!V8MTF!EP;2mtwGo8cIi)CLAA-9>>ERR|E`oIc9`abxE zo(f0$Ff60Jda_Dgb$j|)EHeSKy@qS8r^>JDBIR+wCC?S`U$CY)Nv55bkl+StS)V-cf75m~SVcSuSmOIY=mcYK?jlajGuORjoS=iX{!Ml}u$BU&t zHX2z;_^a&la(rfG>qo>XVbk@-?!h7)rBPFQG{rQkjCEp*lCbXyu{^pIyL+g&u%Q2e zlS+y?1z#VQg^BM}PG&ME_Ho;!kPB=pja8HadXV$7)B``ZUZG7o+O_t5y)9JHM2 zU8_mWNvP{6i+l?%+Vk`sE#VO_Y|n)__etJKu4|M@g-L~k&E=hC$@Lq;OG1k18r~+^ z43Bdom#M_T>uXb1zxYnEnKtn@@nI(iRtHe+jLwWsLdD&Hr^zs{gO-CE zMU9lpXT8xv%O)IL8FB3r>;=%v4)tv4!=&WHQe+k^voYirth4WORYt|_B5d;39kR{K zQ>UUEja1rUR&IVsen>4dLPJ6+RU<8v&~8P}d)&-O($04yJ+{@TG}ITeF>!7_D-Zc9 zV=c236aB}A8K(cVi!015iMqmk8pqjp@ouwm(Sxk25ov=Cyp!9&(#79OA@K3!B}QBA z7P?tj#6-j<@@rN6eQxY#7ZciI9A77|tmni>zcA&q>`RW1y-| zXbH(Ram~1KnaDNOtk%o#fDeq9M+l|gi+JO)#BGePAeqnJsR<)h__aM#DG1u%ZLZukV>We^%RT|$tDcZ{UfY7115W#+3JHMHOQ4g z$vgjU?WStpt-cXgcnkK8)a1s0)i?RY3MFUK!V38{T5Et1mdh2t_513Q$!Qqu&My#@ z&2g1E+iowz3w`HSG6>-z4X8e1h3yl|5Ur>G(Z#>l}Ha^rfgb1M!WGQF6g zAQyd~O($LbitUvE#hB5!o$FB$^e89<-#OX?kpDCwIz%~`rV+#13F-krheWdvKoh14 z%;56OBsdk;I2D?)peXeE^dPR{2;` z7%hY;lty{f@)YJZe?<60Socb)8IbA!1BG#o);czYTZQ&E06QE8_l{NVP z0KPy$zbYdLE@7^Z#GL>}Lfk2}1F(0JP|3d90B_j$Z^4`9r&eXyg73*g#>jgd*~1x; zcfbSgh-|N`ooz-2Kb#S$3vmx#qfilwW}A`0_SI)&yfGC&Io()?-geWp{TE-A`|Yg$ zJQ4h6_K6e#0Ru#7_?G7g2xI20!1P!1V~aspv1?7v%~RoN0$;@^EALy19xv6uNt zQBsPOBb7*XQU`n2n6x5oNfK5tJxM<@m<-2HokXUSIb=RrOw!0IvVm+vZT6!MC&_to zmE6MM@1YhArV%uX7NkW{-B?l-M<0z^JS(|AW$x$AuiJGD!IE;s>Fb5XEQp{tUUngJp5!LvJIU{p`I4KG?&-7Y z(_29DJ#Rsqam0lrzeG~y{7sZIH%ZRiWI1zFsd$7`Jf~DVQYxNHDxO;^PCyF)d3QIHu>#~uCjs`)iP(SrT1)=r zQ8bjoT&%80k#Om2Ii!z7*q?2mh2(tjtcC4KcI?G?GE(}AMEjdE5{MBBNEq&Hh>S#3 z#uq!MML>V@5Ars7htwl)krqZh%s%zAt`F0WG@16JBiL9ri_I5z#9fgo?qPhLV5Axo zjY-C2V~X*WF%@I&a$|+D(pY7zHr5zxjdkJ=K?M_<(1k~E;Wcg=w~X7y9pkQ%Y1}h0 z?3rJhL(O64aC3zDf7tsDI4P>E-&57ole%Z9zV}vj5yW8_1{h!%h9T!+2m&Guc?3a% z1cxjmq97uRtc!slA~{J0k(`5RU3LBTbJbOrWsT_Px)>LcCA@S0-P6;x!FAvJp1=3r z@6o@mDbBy@hI7t6sX{LeJQ-LPcq(upa4>Kva5!)za5Qi%a6E7#a3*jza4zs(;Df+N zf%Ab+1D^#x4_pX*8TdMw6ig1L1XF{7U@({#Ob=EH)(h4THVEbh8wT@&je_~X#=(MM zlVHDAKpwa9GbeuR9_&yhoS_G#nHQuf++ab6cRXL4SbhP$BCk;PR)Zf2nd8}dEtdzM7v zGl{!NCLT;YNOt0PiQjSD#u*ERb;iQ+&AHT%sjkjjIGUNyzPlyo?)#}DXWj2o56--Q zPdCGN_k{1h1-`o%e0Oj7?qc}vKJeXr;k*06clU?y9su7xFmR2%_Mo7}o_aVu^-Or` z+37ZW>IZqAN2uh-Nc4YBg8y6OR4$=ZaFf8z6!1}ik5$3PEX=$CX5JJt?~R%FMT{~a zlKJ^l{b^W*-ALDW3#od%{{O8O|8sqe=nl6Kf~F8O#Rmx|LZ0c6XC=tff;>Zzr+_>q zQ1>Kic5JMs{ppNAGBHDW_N@)~#e)L#?6Ypp_o_ ziI0ELias+HX9jRidu$tMX_&{%&saiV^7kUfrtPxN+{B+ZnRbT1@5Rv{_0>0zG3`12 zz8s?`m}O>}PnjE;x{bfPV~C-Dx5#{)|0c(1rrFiJz|{Nr`)$RM<~#hogXPrK%#S;^ z8v5$R^n9~g+|jxpj`4g|d>Ov%isOyX%|(o`KlYivWIRJue#UhECh{CUH81G>*cnGm zmb-C*k>8ka>;2dnJVQfsp+_8TAJb0pxYl!=TtQvURE{~!1?D2pDCaSK5!3H7XPC3& z`s{2@U}T1VDk_eeXAVSWXqugkyg0gRvcxz7^O?D3fpMY&p=&13og+P;smv;7MjYQb zI%Y(Ft5?X+xMF;1n);#$f0N_r?{J2}dO-U7Wd)s9bFBXc|6hOKsgO6#qj|SkK^lVd$#&7sQH zTx%{>wdPs#shahOwUlnOmRlQn9Glo~===Lk9#Oy83Jpbj)O{J~%a6WN&{qI`rK7J( z=u4q58-2Oxs|xz6YW>3c1yzsrxB)$Gr^eP!?zctEig6#<7Grxewga)96M4Fh?SlSa z6W%&8i}wg6u*EC2x&hPgQ^~=b2^`7*ehbg45B7S+_IhKF^~ox-I>XZC;T)H;qUUHU zT7Fi=e(&gh+?mFDjHEG*!4GuLpxLY^3plG>Myoj=*hahQ0A~cx(aZEY=LBcyJvz@> z!Pj(&t{DlOUs{G^RO1Y@j*)8=aE{sD=xp@hEOQ{o*CYQn&t!{fvIf=SZ7nOCx7k*0 z-qyC*dRukalA3H!b9kF$akgdE)0$(|XRB#i4Paq&EzY^Dh8E{sR-VNi#g}Anp&K5SwVBN+s!O!$ItpK`LMn-xGJ;<3}HcPRDt;VCq z7UMbNtZ~t_IO8ueZ!@Q}t=(b1WWHx!_9^sB-)`S4zK?v@65NFRgdPcZ zB+O1&p0F?B^@LCTroWoMslS(hoPVx=wf~U+4gcqfiHRABEff1DPDq@exIXb%;@gQ| zCZ#52CACc&m^3A6LDHtAQ%Pr%zD-U~u9IAtJUF>5`SIj!$uA_IOTLsMQtGF4P8pUm zBV|d-u9TNkK1jKe>ZInSc1s<}5!|xWJ*lsyp66(_N}wRnGcYDFC$N&E)ZYX?3nm1s zbHrI3EDg>Jt_>auz8SobmYkNE);g_!+N89H(>A7^NP8#kYmPj#)7zKlV9a~wlHR5j zVB5GH(Ynn1%hCw86-X^0wSd&}AlX2&fn57Gum8z5~wNLwInfwc7??SQlc($0gl z2htu$dk@k9NCzMtJV+ssLLh}6q$7}yKstJmA|ORTiabasAf148@*tgobOzGdgLDDX z1xObU(iKQoAYDDkO+an}a+3$?2BaI1ZXTpNknTXbdypPLdI0I+L3#q|38be7DF#vu zq}YS>0n!IZ9}m(GNIxL`JV*(U5+EfWAVG7$9Rj z$XFm_fsFMaOsZ>84qN<2blf!ysurURJ{WV#2r2gp4@?(rb^0=XB+y&hyH zkeNVcdXQN_W&xSyLGA}~Kal%9$OAwg0P=tbnFC}FkU1V?E|9rE=6aBMK;{9N=RqC< z@(_@RJji??^MTCwAPayj0J6Y?JObnqAdh&EM}a&Fp}Ja*#l&c2iXf`FOa<+WFL@yK=yf%{Xq5u+3!IP0675UfCo7U^LqHCB zki$R@13BzLjsQ6Vkdq$d z6p&LuPI-{iKu!ZW4a6inT8+`!s)1}Z2ia;pWUCF3t>$vJI*jsBu_-{sra3A$tx>UQ zi;7JLRBQ@SvFU<}O;=QGx}#!qGb%PcIp1AMy-^(+jOviC%&ez0%Ag!7ptjVNifJ(2 zL6c|(&80_a8R{d*@v(59~?9Xi9XP>uCoapqJ?lI!ov2OS;VYx?^M*IYwk0 z%XO6@n&GcN#bKqcHAE?^Kv^9}Sp&-2ILbOu)`Oy3+<+GK-lo{z=Gfkr*xuH-o_C;) zov}7{#g2M5wzns?w>P%8FRqRKXyZVvjf1hH4#oBkV=tn2j$R>r#&Pml1NiR={yQ+% z+DTxiqVr5c9kQY}IEMVzIM%l$=vy-D+ayYbz6Gr^j)&5$dt!A$%bLYn7lPJFXr0Yt z$;DNcYSG?!Me-PU^;rX>l;fbB07X|S=U7KPS41{OHAGhtBh|tl(K@28{g`HRU5_?9 zqx!QbO3N}iPd8UaYxm{UbkiZ9IgdZp;_1dk;~FKH6Yxp!AZLw__`FGGnTPt4@jAED z)+~wE=gaB4j04Bejxe;p5Pq*1DSHnup%hXiEv)yZ)T_Ak~a4-tI=#yn>o&q~n_SbMaLDetK?wj4{{P&45QG4>G$XR=~Mk-w7v(^ z_hcA`m+Vzvy!%f!aEUS=v($~Ol zv~Fd~o`DKv&1kLMisT%Qy1L^JG?z=yA9@$z8>_N@hPrY>8oR7&>pU=8vBgjF#T;@N2{Q&Hm5|c zSs541mT~lXW(m``;5u3bb&}Z)*Q`wAlo^bp57aALU$HV%bdNxLu0Z@-*LF?Tm=V@U zK3aPblUGzJ_b`)lTfcQbub)I-KM!z=tJwD@TWi?grdS(Tw^Mn|Y~oe7g*|A{I>eqV zExIncM>RbKqtbV)`>pY;g~V%f8jnYNBGcN+8tSw5vBylrxK~ld6{yI{DaCe6d2OG! zd$1jY?Iz}rkFxRO(*~81{--&na5a8pbj>{RzkI#igs+>!=O3~3RaBGD_*d<983oLA0mu+Neh5?>0`b2IC4y0hm1WQ>T;%5GqxB@J=D2OP2}}B&qJNSf4?;5K))-f z1NrY6_A@0OY9ar9!5AF%B<0ll{CAhpIl7L@sqEirnUNRuEKC0nh_1C%NATK-tO5h8 zz{hQsv4mD}yqO4{PlnE?K<87fJ**V^%`9?qFz9-UWu^as9aQuQU-u>dmLpTC~S#E)hJ~UD7VEOQv%Ac zILfV{jKEn*k*8$grE;kNeF(HG(U!vbHqLRxVBTh9WFf8lVmMm$bFL75f)+h1j5>rq zZH!moNH^O52(+a~Ezyc@HLPt9pW_mVDm<=a?k5|zCrCbDZ~e{zeT1)@uN#{Q{d}^4 z=acn&X$?F*P#CosPr{1yz+KvTaWo%W;pUK6wHTFU5qdyd!=n+z( z1EGV6XN=G%q3aZRGfCe#%d`yrOd!1misNWLD&dcgJ=?}n6Q~Fuef6|XjLxDB#jnIG;#KjQ^vMM2mx(e-Cd(9=Dg!bo(`34=BrO?|LQ1J*maHYS zWo=nU)|EN3o~$n$$XwY_=E+7fUv`q6Wf$31-Xy!p?y`rxS@x8-$X>FyES7y_U)fLg zm(%4va)!KD-X~|uS@M24TRtG?$S34d`J`MXpOVYvX1PUfmD}X=@&);#d`bRNzAS$w zUy=VMKa+owpUXeX3-Sy3rTj{MtxV-p3Cgb$RYz5%I;qa8i|VRwQr%Q{)kEE^da7Gg zFV$NWt3Il)>Zkgv5;aLpR#Vheb(fl^%G85uuKJmpr`D?tYNL8uZBm=n7PVDvQwP-{ zbyyuyr_^cn0)J1bx7F{|JL+9^M*Uu$RewV5Tr`cQqOK33=LDt1-7ntg*^ z-M-Pzuxr?vc1=6Wu4QN2we31~T|39FZ#T5_>}GazmSJTvN=#s@bB|yR5x*Aa=tgPF zn$$=(mPOQF4v@D~v3yX@ry+8MTume7cDaW}%U9)_G*NydzoUCplBz2C-2*EjEeGVvE=+wu$XxhuA50iD$%a@vPV*_KJOCzc?Tcim$}i z;v4a;_=~tGz7vP1aa*5m^H_E5wCV5mIlgH%=c~YK|r{#0=C zDt|5?mcNh-*RX5SMHPh4v z>JBwpjZyci`_xP|OFga@szqwCTB4p%OVyKVnR-U;w(nDW)Ft)3x~%@HuBfZ(n!0Y2 zZP=#mvlDE;ooFZ7$#!GA;3tv}+huo{d%HUv9%Ni-99#XFp;;99JrdI$;f{p28XFo< zcq5pmgbuQOpKedKr?HheXy2oc2*dNSiPx3JPy#yY|-Q;JB^&lm( zbvj5%eCAqJsFi$u4I9JJIgL+evm`-cAl* zAv3(n?#KI6JV*A&kppn#Kpc4$M-IY~JVTb^SgN>RD-(WoCA`%LHHN*_I5m;uFdhl} zs_9hm&b9KmWR)H{w=$fM9m{PQ_5^#PK414NCbJx;@_G8K{&;32gZ*hyB(`&p=ux;w z$+SzOloOzwjH4U_<#-(B6ey>olz-HB`4}ff$GDnlmDqCg_}NUZf&gB1d%9GSq?#t zk^Q29XipiU3rExiQK>}g7W%g^BRTbX{I*ePG{=s-i(2QbuSfr{f9bGCl(Xxi{kG&B zWm1&FQqs1EdCmTT^{A?<$}6FvYRD@=%PJAFO42pH*vKmJ$U;I;3g-hh1vulVLTTa# zQG<`EDYD2xgzxg`8?g^=ESgYt(M&X_8lshGO*KVZ(T-~Ith!Qd(OvYQx}vAJh3bi7 z&LtWkUR46|C%4lKJh_##6ml)sVmsZ-?Zs=p*e%BVt3)+rC0iTCHgr9O+0SjFDjel( zqZ?G3Dx?gKSV~xfhV$we<6I9fqB7TX6OB|i*$o(#+%z}cklcF6uwCgoM%b4UH3#abWc=M z_e8aHPgGm?M0IsfR8RLr4It~LkhMwMAaPCEM-|V#uBY;+8H{K}ZN1iTj)nU3ihPk* zRF?Z3uanMLf0nRV)>7wjoY6TtqZHLRkINL9Ed5%d7A1;&kxxmYsc6bMT?^5Y^`VVu z!}`#kwKgbj65UuUZWcFlYrRBo_7o#nj|Jp8Mz9SRr5v4Ui!h3{jJ*~b0je=?3^*H>r?$CTS>29NwZdXOW-d^&)*??3Dr_Pz9<_5=2M z`fd2h@MZdo8+3!lAh(iR$tZD!D~wy+u9d40ZWQ=jUxLu90Zi#!Vai`{$Zk;8}t+RG=>#UvJ zI{Pecon_9gQ=)F2l632otXpR-;MQ3SxOKLY+&b$5x6Z9`>tyNHnO6~sWusc7CANVo zo<3O_twy3EXWyqQH9A9KzD{9pVRDXg7fUxwW=Gd^631@MD4CR8Z8VQcLtFj^Hc$*Z*+nMBWj9s6?I?g5+9Is;cXS=H_ zXh|H^Zsrl}5Ifj@Jf)su$*xc@mOf3cjFQg3IT^Dq@Vk2;Uh0B51IkOn!6 zohPZpS?;W$q2Ref{Y6JMn&bM-B}vTjLY7*Q>`NABoc(!5n){jHem>S+AzPA{Xe4A@ zMONXXYsebR&$_ZMnVik$!FHR-iU@IDq&|^@TK$En#fsFC9sbN_>X{hzr}IT7wa|G0 z_r!SsuPM$0*m^A!%h>v@5Ukfa6JYDNR;*<`STEM|2so=_>&ICgrR%JY?cPqYlLTjV zyGiQ2juiC9;mqzJg*gUaLN4p&D)v@duC+MwzCv}>b#aFc}?02ZWebzop9qe=VAF0s(!2XDe?DO_{>SBLt ze@0#HKihw%?)I1VSJcD)#=b~B?eFdHso1`1U!^|wb%&_0<8%Df-$`$~{=2UU2&`77cQ=LXR8BPtl!^v{8+0WK->d>7|j#HmXorX?Bn&{*^ zjcJn8#A!}Cn&lX^LgsWWD&5WTGN;dC)Spu3A?e64>ueQSm9_N-*4zYHAlYWiRNDJ%r}>DhL3RBsqVYkDULGg@{}u56$_j|&0Xw1+-io@_ z-+3=xd0@V;6l<98>%<1;^;WTs<*YqzC9zBFV=f=i+=M@@%z6DnYQsKnDYaG0)pF{< zo?{IaBF^gs&o`R$`zxG%YyWpA`@a+_wFAuAGP@G{l6%;fRHhl==7aWkJmQBCxs4X1 zd1QBrJ9%W2Ib$@%G%*c29C=nu|1_Qje@&6hD*C_3bBiK6%Wd3N=0BX}8t!AA)*|V$ z-$;|yWHnxEHDpa*mCa>yUTZC7OS0v!vSWkS5EI<;PSeKaqc?yX6=13!0@X-*msc zstkI7W3~P?k0o15yI8Viw1;D|d2|#tiRaZR^#Z+s==WFlGHjP4 zJOl1*;B`${*9O+L59>Ms>pFl{oQ74L&M{vK>yTcp0;|==YIP9v{olx)NDZcIw2Bd} zQJ}Ixv|HCGm^TMmM~BP1dF}sPF5z|h6nlzh%!$gp2KBsqBVzBQ*AXmLB#+ejqOdox z{#FUE2%p4tbFYR!tIxxl`!VNbAkU7MU}ThgP~EDkI5M^m+b5`w{fhk`xO4A^)_qc> zP6s}wG9Sx0w$~hN53Y3$%WyXJ0N2XjSfKCzEU)b8I|5oqE$UvxQt#lpeNG(BM=S#) z7ui!emHSm`DmOaPO#21sv~ZyA^UQyl!;iWrd`Z)&9a}ipJs2r+1^YI z!e58K;jtXydFTD4u}*TV?pTv&qiu3cc+4&s<5<)bCx^e{(ak_jab}!UrbMMOJ5DP5 zqW44H5hs;>kcz%XuQ*OB`?Qv`9e%2XqKL%2F+ zhHG&DS>ayc-joyW6YfLx!~MejST=*gC6pT;5*|)@;gR7{)HFOgJerz^$A-sJi}3jH z1Zo+c94^C~G=4hC)nebGEyP~7T{-eC`6;!Om)J)21V09oojSZ^UwG|^UwH5^UwHL^UpZ1`Dc8p z`Da|v{4>7P{4>7N{4>7R{4>7Q{4*|V{ux&^|BS1ef5tVNf+_1iIMR%qnn}Q&0cXdpV8FJ z#5*He#~*24_9dX=R8BLF@G(U3dB?Q6a~0ZnOg6hdoG?wPkHeLLDF( zb$}F96H-x4r~-RX4^dEkSmf4rU%M|y=L7A5bhG_{y@6wNZ6_wfPE0|)aw?A?C32;g z*KL^Fs>*p=8e5?ZUIE2+A6^~(?0&5KE5a*T_x0)x^IVQom4Bm}@hYkriLnaXT|7ta zQT_H9dn_f}rFJQ$hF67Gqq3F35!1WOp^rG{NZ_2~6F%-w_UDvjU$DQX6#FmsWlDGa zoLeZ)Et1K0f=(KRol1_R%8uhyrRq*L=MY((L)4{OP6H>GYCCyO0o8SyaV(zetaR2; zp0mx_Mg`6eXD2mro^|$6GiRT3h*~&Dom14-dDVH9ikx3NuTv-I4d=Ji#d*tlmu_;- zI`30Y=X2+C&TlR_Ur;~i8|PaZ;9PVrbCz?JbzWb`s?B-dVxH?#&iMSu?-F_aJkGvj zky=E_`f4GiaHjS>$0k?RRSL3o+)8QocRV+Rxw)8IWz4NA=5_<-mWjF5!QAR%ZuKy? z2AEsE)5>Ybvnq57c_uxa9@Nsg#kqxAIlZ0U)Y|Fq44^j7AZHM@bA~uWsJ(NXXWId@ z?S$EO#%#M{w%st>TQJ*xm~DT|b|7Y3g4qtm6|+&gCarY|T1(Jc16pfBYkkn#1Zb_F z=emIsp^Hh-#pGBfSN_|}2apr&RgB^pV%7Kk)4I6cv z{WkMvINOAi^dh2m9k)^VQuq??+0!j$F}*WKDiwZ6SMMTs6CPsBABmz6IoXJusv~l0 z=(yZ=qqsP0ypFSQTn3J-i{o0NH*MGbkvIz#cmZ!z6*H@kndKs*(XkpKR&#J(W^@Fv zMMsc>mK&qxB8;GOtm4=@78xIo@?<@DvW!P{iSvN!$O9TOPr}p)Jem5V=4T-OEsx&x zeZ75S|I^%?LF?nLoT%uR=*W+1JvkE1A+AnEOjj8(T?f{JBXkSm;Q`K_&I%groMXLv z9Crmr zuFb_-Gaiq&cI=r(OkZDrOvm*{OW*%M0+n<1KiK;Y z@TiLJ@0q*1A=xC8Z8LK>L=3$brB~@S0@9?35L)O(KvbHD2#7!w6fqP55djscDyXQ) z>#MwqsDOwV>;(m)pdi9`=C?Ot6F{;2{od#M{?9)9o4Ir6PP=E?x#ygrS$sdOBMtvN z9Q-+WhE|YiWof>Dnp$LIXd}%n zn?svvZZV@)MI+h3D&fmS74Xlm!S1>$jnv=LPX8zQ6OF0~DuLCYH*C|`T2WPGwNxEd zpT;FKB1J}_1~dxwqOoX*8cw5-;juSUv(zjag$!T41&!2MH0C~|o}sbmusY1z(D?HM zOH=37d3HUm@`9|bF0D(mcDk;v%i8O9x*fYg_tkw_2YP2qSx5c2ew=mE>-BopS#Q-_ zSr>goA7MA@ul3igt63kgZWv*DpzX~%iqYDsCe7GYZKEF-kzV)0l8-qNB}I0poqRgA z+SWYZ&OG09h~;Cp>_Iyk6DQ*Cblm6g_A^514rd}ZFaAwV{F|KkH|53W6uaPwwJ#u@ zHKE17xuPw2%JPd&PkfB(_&CwK3w?ztiH<98p;ypCa~z(n z`KD&Z%@D@Tt1xc<_O7%b-|1CQ)yIL4DZL|s6V#)B2wIWvxL1%yq((c@D(34v!`FG& zA9^}6-)#y$Pfu^B^?ji$d^*Da+J%wK>ZH6h zY$uKXn7jh3&?d`6E2vE#3$2ODYl9Q-EyK+UWMbwpIr2buAe+XGoInoN80qwGP3|7# z9)sKq(TuW`_7^LHD`+*hF}RWT1lxk!Xr?(GJk1h<=Yr>0B4!bRStKdcHPnsyFqZ@{ zmjp4FgfN##nm?Xlisp~aEDV{Y6gfdoWJNIMraEm~gjy?=TG)dY_T|-Ml~a$mDW3gb zQjd*JJ(BUJtK_|D4oi?lSxeTPO`~<=YNDW{To`Q--iZ(3Ck_+I`QKV`*Q z$yNocfz{qhw}x8dtSQ$0)=KLs%d9nx?AL!N^{ee;hMJ<~+-w@5g3WB|O~KAK(Nbuo z{T5;#N6g5xdk}IWD&!r6AIf#&7qC!4I$l0in zLkRgbD&#Oi&PRoOXF|g9Q6b+WBq1s!8zDR@U&(SzJv z&4~(gv8nVsO4qmNh5i%#UQ^CPhQj|r?qMNtd>J^tN#OWaMJYRj<9ic$Mgzd{&6U43 z9N*r~UU7I77wuiN<~NYAD;E{!V*A)Wod2QnLTTmzf0u#3%fa9My)T9Tzw&pJF3aCF zoZYV2_4Wp5cQp3Cy63In|Tj3_>p}M z?mhNQyi;?c!3AFH`*_OeH>XF1Sls5l*ac2&By2qF=hlk~bMb!GTf7FlAesF>yA-E2 z!9GSkm)R$1Cgk=HW^S`j((L52f1>%uZJ(wY#bf_Mb4HB)E0woUnA5l!7xvJo9Um@4 zqcDxWG!vMUphN!{mv%YrXiw-&RUOt)HB^mQQ`JN@Va-)X)seMOomFSnQgu~bSu52`^>qhnd>4|9qQk2n!+;YV8p&=w)Ig+f~tMq3m`TNFcElt5dQ0*|;n zc*GUKBfb_q;;P`tR0EH=I(Wo2z@4cD9&v5(i0h!94N%YPP|rrFXA{)3CFWDY7p+O#sHO{-wEt&V4myJlx`PgSgAV$D4*G%)`lC+_MxPjtJ~0w~VifwsX!MC&&?m;A zPmD#M7)O0#2)jd#Qlr@X@r<$&&v#DyPn#t}`bJbin4f3#eLmqazT10*5 zUi6_%^r8FFhvuUXJ%~Q^2x#k3(AIL$)=JRUD$v$i(AG1ctqq{9O`xqUpsj7-&Ax!O z;bAk**~e)w#OyP)JK*+Nv;McwhiR=5cF`Kx6ON%3c%g7yI1YA2^2s7YsyH5!NC}Wc z65xR*L3-GSx9x|FT>x^!5`0gMHyOs8OpeHqD4W{8DB8Xx+P)Opz6{#F9Qt5o$QEA% z+2Xq3d)9+&aecIC1IQL%2Oelsv}JR&Wedm_r>Vnv-=I36RXU zy`I{}e4%M^CH)1o9ShoyLv6jF?Re030;oC>R4qW&NuX*Us9J)m71~0hEo@NrRiNsk zpyXnpLirfk5UIv>L5yOqts!PIvJ%dj8dnd)J0HgvwJOcxm6n0SZ=JbJXj;eU?<|v zJ=vT^>?B0Oa_v4uW}E$H2NCM|J@C!yGWurFTk2rP+Qrz7c3Ha~8*MkR zd$8$wtL0q1q622Fh41W4b}`zE_BMMPtxaFBU!b+=OZH2&Hhr1avxQi$yz`Zn`U8~l z4m_0u|76s|e5d;@EjdOxnUot7wxk)`?8Le|c@%PTNP)z4ZVe71kB^au(Tn4#Bd7ge za) zM3;lv$f&DvbU#vhb4EQ^FQ9FPp{#dB)uB7;mT{pbL0BsZWM62}kU6Kp!ie-|>nQTd z)eGeuM|JIm+Kr_8nQzd{iI@A{YtZ{KZ>J0SdeR=MCCgn`9YQH*f@|?f!I}g&qQryp zN*sAN26y3py3+!G{cX_-0X4Xve326?BEB^gx}I{`a?#srNbk$ELvQj$Qi=G+Q|Kh8 zb|3wf+EMSh@E-qaO*u0X*(F%+_ivw5!ow&JQkTYJl}&q{QF64rMUIhUJ<&ik6pckw(Ngph{lox~A%=+& zVw4ywZWXtQ$>L6Nx0oSjiTlJ{ale=^9uy13B9SGQh-G5ASSePC)nbiUC!P||h>c>i z*eaeA+r*3FW$~(bP5evzTf8a$Bir5ekL9y`EXJZ`1uJAFTgfceDrOa9aaI|t4D-5L zx>~Y$Pr4_aC3yOI`msdM0M7s>JQs*0InCaWf9i`lHYm?P$}8X{9WRf-F{>|@ilwZ9cvL*ft`jT73f53OCLUvr#N*;|)>u3to?uPHTCtWj6;FyMSu?R- ztY^)|2C;#)5Szp%)>3Q{TUaactaz5S7SD_4SsU?!c!8yf9byN&Uc4e+VQs}uv6HnE zyTmTmUc4?|XE%s9#2c)G*e!Omj^Zux7V9MTh&`;c*emw3F5*4$9=lQO6Z=?KaX=hk z-NZq0kaZV_#bMS%92G}dPjO5fV>gKt;som@eh@#fo5e|Sk{JtyKIY*AJVEhG%(>X> z%(pb0qR4oEPW{`x)xFi6_89XkbD1;G@hy#d6(1a9Mn;PdiusViVujm$pXDy2SD(zh z?vPu$m0P=Qci5fmF6>Tmn{(~ByNJ7VgsV)u)%up*d5`D+QC%+ci=UDIM|IBs>vpMM{FC{A)Jpk(z3{tm-LJrJApHhk<~Q?yX1 zJqr^{Sc3TyoVOZ`Ze`0?BGH__RTfwYSRGgcSQA(a zSQ}UeSRdFC*u&r-JV$XHtxg?Vd3mev=(YD>D_0X>>x;_xr!7{xi{L!1-#a;ZG#}3= z@o9V(pT{5MS$sKP&7U%7{qY@qmpKiPAK-`0X@Ru5ImORfmKAG>$mxStDXW5YEm2tm z8VOp{2+)PbuyiZK8Xh_S(3+0(5f@rZtd-UpYrVC_+HSpKy>7i_y=NV?vaK(yqgIaf zvvtnpc6nVsmvW`Jin+?TD!Hn;>bM%Zn!D0m9b8>qy>wDLat}|}tj&Ucr18$pHp18y+cs~Y9 z0!sl)1Iqx*0?Pr*11kV40xJP41FHb90bUEN3akdK4y*yJ39JRI4XgvK3#ml0@xDR3fLOh2ABqH3+w>w29oQGx z57-|#5SRfR1RM+;3LFL;0UQY&1-u0~7B~)gD{wsUHsBq=iNHy~$-p~-Q-RZf(}DK@ zX8>md?*q;O&IQf`W&-aAJ^-8#TmXC!xCri^FFz5kg1cwX2E ze~$kLC+tW6N%q?oE=>*}`49U)_GkN#_&@P~>i^9Dx&I6QTmHBGd;IVC_xj)UzvqA7 zzt6uvFYJK-1OGuM>_h*d-^_vY7?yg`JTQ(;zzM-~*nGB#En}cno+PcmkLM`~mnQ@T5WiXy7ftF~G6F zall)FSY| zGLpmXJAtEsV~s^Pdl~Rv;A{#XfjA=&X9VI5LYzT}Gswg#AYE*}YsN)n^YZ0u$)Pp} zPJ|V=C*Yp|oQ#k)z)1+12Q>Ej^4pTb$}#j3i`ZR@S`*ThEN2+QC7JG;GogWbXIXm_$Z+gMeXX$)W!JXr8QV~HQ)3khHlhBfZF9v!0yx*AR2k;i zOZ77Ss9vsD=#~00y-Gi>SL-MA8ogGp(@*NB^waF`vbQ9d+em`Z-|*WmZ#jrF0U9Fe z35;M7I~pjt9O!UKBUc%D_e{!<=q$*5{FW69i}rPm(DrU6=14 zLVyGf9^4_pCAb9-9-KylySoPnZowS_1aI7>f#5E|-L;|7MjGkM^Sm=tGxK|I-MMew z|9;i0KE2MjcU5=Q*>!rKb=F>s|E_(7zG;MTC+dQ(MZ%v^G%q6$QOv0+qG%j#>iXS>nj03Y=Mxvw~ksv|!myLul(i_}?M?6R& zi+&m|^=M8zT}&9rip{EZSUbXDo-XVPunU_xGGOs@8MV~PZR|Y3!Fol+3-MVX^k zAnetI)W6goo11=c7;jq)o_36W9L_Cu>360$F;w#+S^~{&VR((aA6__p?(=tpI3Rq` zOhNGTXB_EG^|t?U^J1*ePD0XNLM}gKKlVOk+yAiHkRLK1dmppy4{nwryAd3CTyu)! zhd2!gZ#MJC-Un|#9W*nL-6T!V5dtggO{I2~FD$%ta^gD&>n^ms#p}Q+^XsqC zSPZ5+r?hL0r`!zjJ6C2gaP2-aFDZTgu$PE6c;_7G`$dG7a5!w2`YwDlA!-+=MV&P< zPR@kxGRW`8CNM+5f!4mEP=BdHSU{TaPmT1J<^cFrc1eiRACZ%J1hS8{O*&Q;c4Tuy zt<_2#wM{VV?B|SN|;O z%zGTX@y^fr#Q^>QQxeu#FDyR%(;CfMK5}@`8dO=rbU54^*&%IMUVdcV+FF@sbEMPS zSSfJ``rt7FA8guLp1M17muA%Vm?U#!SOs`Y@g7w^AKpv~Lls+7I{-Ixey*+YKQJ;A zDW1}}s&w%o*iF~3DW~#uit9>2 zSbn|S0(^f(Dy%gzoeuL~o&U@LM)3YQJ{f%VRag>>`_IsG9lcVS!zmbnuyow)_HkSf zbMz%gL$+t zD2*|7ms#-!^$K;HS?R)3u!b(TB!))Mj3c*r%tvRTBZB9shQ{_xg>`$Y;%X)23+{~M zU#Zn6>OOA4M?VG1l*;PjNmSHkvY)4cyrP;%`QZ^cw}hL<-+9^4kFb&>^I2V}%HcoK zvJtF*a&n5*&48>MTPHr7m3lF%tyYnLxtx6o{ptOgMIDPILWL%`uy)3{L6SvdWTwEn zMJG?QY+!~F+N@KN^W{1FmxljWj;eAwRNDKqoqFbsd4rUl#zfh3;=6U`Ql-HcwzAY2 zOlYmQ6sXL-Y<`9n$_8zPHF-;bO5I5gsiBQa1#28Q(nrG3j-}%3a>OG>nBQ4%4``w?TvMHBAdX$CR30>vd}NzR1`tybDWrfkN;>k{7AXP^ zI^QN40@c3RI9cT52K>ZjyJ1uf{k&k#FtCyoEjZk<>~z|@TG18pI`gP^$Z@6SIw<^_ z>5gVMZRd7u^@GwvLW$lU{|zUZN8n?Y+7i;895&hM4fk$Lj@@g+cJzT_Hw4xkuglu&!lcGwyIc7AlT|6)h~ zfG&aBqkxL^@hZkPH}!xgS<@LmzhlLX6E?V4fzA3N!`DLKZoHllXT0yRrCF5lW?$fD ze~It+hg@A%=J+|gOS4bBbE4d;!5aPB!-o6<{#%C>iT$}fvw z%x{fLGCX}^Fo0+dk)Kelj>Z9BKem}etlNsdVwMvmhlabP0Zmf^8ZjPXd1@kmy57&6-u)FSFC>?#f< z`8NG+g35l!ZikQWEg!Zgnj?bao9BWdM3Xy7+dE0YSrk3b^R%%&qPJPySLkAGa)8n5jDk;Q&kI(W=k5*r!)IflgY?3#^iPQ{W(@no zO5@4dSxkcbTCqENU5rC?F!=+_OM}<@h-0H%L{y2`oQvP_s+AH3%&;n&ifhB6*s*F_ zF&eL!>W4=Aov9&Gz~~)ev4Tzd{%p24b?+O~Gph<$8}jag%F!h*`&+v|ZG7Co+c4jt z>2i})9y`V!*FbiB?a0TT&@a6~xgojXD#Sb45rtp>*|^@-B+uo`OACYf$gD6j9jiU6 zV9WGmbL8$>b3F{FN`fvjBXi1TkJ_LV1-{II2f`uTT?%NiD)=23LpKoj`TmEfi>j;d zleMAA`Zr&-Z}Q(pzFmGx|3s{)s1vF*NOmCf_@b>oJHdCI!OScvkMmDC>0L_dgh;rQ zU9zdDc~vb%lh%F<__+8OdL8PR?g&_3u(`LnMmsy9KQ_ZIN5YP{(9=H-*MH$cuFa~o z|A+W$FP-R`IiUvBiBZ?;mts)VfZ5-2LWgB_m3m&l2C2Hao*v%nHqaAG;R`;9$io`UPKQ(#*@V`I-zP&3f9CFb8*z^3n z)###FTWZK~lu_vkhhX+Mqe(Jd0RPAVU24;CVrP&>-~)a|(Ps_ z!8N3ZGeuOz2c$MfI;lv0(T&J`1-++DkrWmly1=(s(dwR$Z}H9c%^q|x&DQH+?O@&M zoSIL5SoK{UboiC4*I^)%PniWhzIblmBmcD6vAEO8_Nfi@N#Q5Olv98gB4`eCrkL4_ z3rfyZ#$xV$ zLG7POX|9v_*+%A_k+yOkgK4{jx=gWg><{7we5%oZk3D zKYR{t&zGBRTgd&{EPnE@b9R~@-sRtu?i@dvFfbUYi}Hd+LlVbT@7H*|-;;T}gDDBU0X$8(F50aO`* zasp4NSe{)^`^AXq4mJNMQQ)FWBK)oZY>Vkl78-R znd{Lc{cKijEZ$0e8ME~`r_4}L{Y~ZZ%J~=TzA++5bEHwiT=IOi&3$aU8Ew_8=g=FX z?Q2_11w{9Ee*&%?*YMMje91jucn<&6z|cl{j=+(oAxokXs8)L;+#{f1fw{cHxpDX? znlYPkJzqbM8bM=z*-o%P%7=K1e8$c`@Kexy;fImL%21bT7h{(|S5a4E7i*V67ed$O zbMQyD>ku3#1`|MC>+T|01ZtIlTqnx*zg7Xf zbJ@_J*~5zUWi9DYbHDd7y}njE0b5n8Ajb7oQ61J;0RvPiJOhE)I7_I&QYN=?3;=g2 zlczvmM}96+v&^mp#b9D7J?FT0DBv_MY`~E7!MoLDuA21V{h+)8aW$i#4$~V5N3gr&__NDNzoZT_(0ttRVo{0QW0+ zfu|KNm8cNooHsd(Il#1?G-M7E^+jMKybArSva2(p5nrQdQ4W#h>)#;dcGTB#QQI+q2=3MPnL_Q4o$ zm+t#-31E%)?)R8?v9NI%?sF+B)FYwAs=Kj)_Q#v)*QrjiOef*<(R4 z$x+EMaxmz=tBT``L&dG~a`N)>-sCOj0Vi80uO}gsd6QFZsJ_Xb@uYT~csm?_>B$HQA+-2?(H zxsdeU&}&Jp0JFl|@(gFVKF$j_)5D?W9#3EvtGlY)@?^NTu6u`#e8j{2^X*GjBFTOy ztC(4AL@R4Lj+dkS6dQoLbg;a_2oP`zw(eGybl^O z$7xhS))ci}w69z+1>ZbT=qe~1Zw`QrnsN@&Vt1$fs8;x7`dqF0ecS8T2oj(2-ZCp; z$BW4!P=yK;_claE;-xaGM&hyP7?c24E6 z>_tfR8@}ZYC+sypPg$UHj{;pdXcTVMH&a^gOjC@&z5%05{dDI10b$*4Oi@7H!PYw9 z{g8JOkjv~O1*!_DN`(>tPJciR02E1X>A>CnCYXp`Q*5$Z0=8Sm`MtuU!)vr&)jJYU zY9H7*bHVHZ;@|lmkD*s~+#9y;KpfLKO2>GT{IRh3&-0GOXw5${aI7C|CKLdyc&H~} z;s;a+U@-!-0yrct&JZh^qU{0b&BeUi%ML0=mhc*Fyb>JX2gnXt~Bv#;IWuz<`Q zi75y$$4Rl|%Lv}C6=4Iz99QR9!Pn2bwZKNTn?u=qaX>C7 zgq%@xr1QL!=sY#W*hwynu&jho3ojF=xL#8=xl-=5sFQZRc%^DogMe`)X?EEAdPwm& zX*u~OIWEa>7-6?W6_}+u&QzvarB}1S?36N>qAsr`@9_NKgnhfotpA;=>004nyL`M? zDz$}UWY+HwE~X%bInGlxgVcs-4yipKxf)<$&xe>z0dA!^GBXxYHn(Wtu8_PwEttWS zyZ>u=;*e6bIQSt8^TI`7@NPz|vXzWrP(W+W+3$ps>u1kEtq7wH ze}Ld%^vQdz{MhF~m_ML=0E;1={%Ms;U$R1bvR&Vk_oBtyRDjfHarRuU8A7YIqGVN@ zk~?qJ4m^#^YATT0X+P2XYMsm8FgqxGR>?J1IZZyzP%F#>g{3b5#xKU5Zw`)mg)cXu z6U{rf`Zq%Y?IhBNaAh>5mer6eHpM+F9R~nbO2cSw{V0W}eL2wV>6a{MdM7qj6R%Vv z6`Pl|&dS`wOMb4+l*Q-7`Td^|Czt3%$!5hv=RyEUYopzqxx-0@opk{5A|#o7vBRw* zJi?v_hHxnr-S_M4g_rR=N-q1ZweV?-Q}iT$k!rr$8!?nI56t*F*UyTkq!NUgOB6D( zHkJk95v_rOJ-;%0b{M&AYk<4qq1kvGTKAJOAKR6Gb(r{Ma7NzrH(|_ATZDmG3NnRp zrS1XP+m>?!f-Pf9dg}(H>DV6jyh~&1?^u+%3g*`+_YaH)b{!v=D>q@Fe8$aa*4N{NeF<(PLr%lx5xpWiFz7PWd~e1w-_$lA z3O>Jh`pcY8 z3?9$*UeTvphjnsZ77qz!(`%&BPmoXVSPSbzYDGJ~k_UUJG(WY6aD>ulo7X!uJ{_It zsok5Y`Gl1|mX_+9S{t%2Ve|9S;8j`-x92S0!+gx;n#_m&T=xEutkB#Xr8{e6-5p{; z;_tZX1oSKxt2!B&Wakjg{MMf}OjFs^y2jOwoH$dK32Fdzew|DHh_k#6IIzA!&d+OJ z@qGE?ZI;QwvlvoH(;%r4{~#|KY0E}|vp7B;ZYxUA634`krf?D*f08^Q)2L+^V_VfI z**IU%-ashbIG@qqH2$$;WzeB~czY51zVJd4U@BM@R|*ojxNA?0KVevn7c`&CGZ%a# z*mc}&ektvc>8{}6X6mD4W_mBC=2Kbv_(ipDqCn{5+Cqzev+(ka!5lL==n+`@SX=t& zT{o-e;K0>DLbH6ysdz$Gbe%kS-J_;>l3jFt6Mu4dlfKkOy-Yr3>o>p5rEr2pb85K3 z-e8frx z7rASxwY8P5F3&)0tZ%p)P|}tV6;G&&u3xM9)Rzj6&nWRWJbyuH(Y33Z;K)plo%IAq z!+!eGrQ!)v(Y3gmPkbq8VaCAPnvJWWPVt0P&8MNXA^;w}>pH!93x7pljVwa-y|9W- z?YZ4)lP^u9PJr2C^7}@XIuMOqen+Edg|^9Q%wy?=?6I1X6hGcPwLNgRvKipy0MP86 zh%x+n=km~cyU&7x!~6zwB;tGMcjS?E?S^33I>AZdxsQW(tg30@|DK&1VbBWQq* zSPCSGDv2WrNqW(k^<3)BGLDFK4IrgrY?u{PkH^bg!@`w0T*t!8o&2?#wrK6=RUY~z zykfSfR#-2ZspyZlGFU=!*E5qV3C-KercFimc$%li?#6wBhbc3<79LtyqQ5*rHW>i%xLdh^a)%~WQg2cax({90bLU!yr-w`2Pvur zGaeK9%#f*=KW#E*ac|YHZ#(w$3>*#%Wz4GlKo8F^I}omS6XfwjVe`amIrCiL@>)`# zkB>dv{;?dTUC8l;S?|wZVt`<0+iLs(Miuc zn0>+w^B$kVbqX{D|8V}{+*TLzwyR$KK zsb*7TrX~ z({d$gyYtm>3zG+sS$EcDHcg{W%MQ?BGh3?hd$vHcN)O}^<2P2qEkEzuytk3TWV2kA z-RVA{+3XvN#{v5xZj#((Gm$#2N*;UPeb{F>ESyZkD;Y z?OJJ4&&RF=KMxVuAuwdxbQ3d_&^?wDSg^+hpABI*05kfDZD)W@EL;G?CR$sY8vc$F ztFfK6l;5l_P>bywdfS#p_fQREH*ynT=Vsd9kHZbCza5tF`#&zDRGz$AzH%~bf}OV7L*tTdp6dF&9e@|oqC(m1 zq4T1!_~|Fizt38MIcrWUTf$sOqP6h0 zvl0)Z?w{<#pbDlt!C!*eto{at%t;<7gqd7~S0yJ#$1l z@s5!<^-Npe+@+kNG>4V@)Xic)Ym(!!npIks3Q_Ag@4tYMTIrWOO1-~wQCeu`jrGxW zb|Ag!Cw{zZE|>0oUnj*l-{$B?JTK@7Li1ZyFl5c~4?fQ#P%=0%YG8u_VE-4mvAL%2uC0VsTpDI`XV033bVY4S1i;Ls(W#vbP|9|;{> zxc5t1xgQ;Qkk?s>CS8gZ)R^D2$K(ehlVp~5Y4+RluiU`Eh93i$;7!?u7s|h<&(MX? zCVpR@MZ9AX33*%9iK2M*<<uXnd-Ub#*=uH)Xn<^IUqRk3uf`gX}*j)+DUl{*HT1D zKzQ@}$tImA$r^S+!FoZ*Ywj;-ZjMC6 zFEGfky7fF?r$i}nh@;0?Rls=*29wct+<@mtx_S<8?FN^8Yk6{Q!P1SZvW>!GjjQsF zV^quZKkN#ceFX3R3<&7^{Dzs>(Gj_#cwI6IH&+CwlkS|K|XvS6Rb+s57zdN<;GACD&Glj2Ho?fvYsaxUC zZ=(ChM%f!W38wTWldsZ0tPuqHjU^g#T|%gat-3#Gr3KU_959X8P%EqTd3)mUbg7+v z6hfTnb~zKmv!-%-72D0hhiNE|?Tf^)Ve>u|=Y4ReO$HwZz9aIuI9=9sZ209y@Q6;! zEyHCy`OCN8kzd!eK1P9K&dBrv1A1cBgNw)_T_wwS84lOcKvWybXz~ zs2P${!yqkB&>Mr0u`_vCK;});xwl}|`Zg4${RwwNVzwx#amHvvPcq?nkxK=ev`l<#z{Z8kALR1JC_^&9;|GHNp$toJr?+Z!De_U z!@0I7>z}%$48eRvy+f3&Dci>U<48^wr1Qg0OyO!`S&Re8&MWU_pl{2eF*b9qe(h!K71TFiK`T@S==hO`N+ig`&}^YmGAH?zvy zg>}810FFCDg(t#9c;5~jZ~rgqBYvo|sfH@X6xatn146lJ=KQRFbZPVh+MH^lIuNI#ci-)?5 zNYpvXUO{Uv2m94dJWGsA05~nA+CLPYoR8La4a&m7U2Iu)kvlf7FgLqR!M^o6rP#u} zzARj_5SmKiGRx>FzI+hp2qa^U%F3mq*R~)ju6jcq7+=UZ8olQWiK`=4Pa5%Jl=O;Zkr%5y^d z@A`@I5E_P6_;8E5)SC$*xHVa;#{6x4&hAmW#{?t=a9uVYJo`Sb^ow6kU1tZt_nNIX z$#Pf+Z$LkJS5W;ncn;8-Bt#Fe5H~RY?xp(hI<)J{JLDdtSJB^992ufR+rFYlhd4R% zMu)xmfr)E`vw}#(PGk_qyP@cbwia4(hG`pY*yDbSas180h~a_2{kPAV$OEQ(56T(U z1NrqQ5#Lt<8}*u>9@E`b7qN1C5N?@BcOKd5adzL5hKlpOlxaX4{_C>p95lGKJZxJr zc&(*`gR+Un_bM#!ZETkcUs3WxY)`6=th#&!XBl^WVB;ia0wtilzVmez0`bE7AJzpA z%hco3Zlzn6u08#fU!rjc1-K!DYBn5u0i7)e^{l8#Rv~jc_nx& zXki2gmD$k{gdOpZEpKB^ryebz^HRQ?h+nZEl`heRNtL^5|3+5%8fNME3B5N6cZ-r7 zXM^4np%?u5yXL1A%q{n~O~K7%y(g6RGCrRJ)xSPq_MiR@M=@g8z)D9hR}+QDdbHT5 zGn$HCj#r@Jl&y(+U+-(FRRcG1Qd}RR!>v_iCJpbBLXSmYIukEIK zkKbl%XqL$wsBdi)m?~&P`HYt=35^93CCc$;RKCcFks-PLn-jwD4~M8QM6u z;(#2UnWQ0b8O6A(0MNjcgydlilvr~;iPZ=>LB)ZmB*W4bVqR|yLbbl)wxeclrk)Ad z?2w$%w<9_9XnLYF{;o0-d_Z=8A^5Wv*B`BIL)eqTAEhm@LDQ&0!yn6sl0qct<=n-@ zS5aR~l#Qx0B+{UsFRx{~+9MUF{f8NagZ(z>HJ^-*5qWE1SSGVi!~KyKCVh1^TZ`J~ zwm?rFO(7DdoEZFx|17uN#ax2W7VqiR{l>&bNarU6U*!8u z7rqw*l36Ewz8|*obs`r^=DLYyk(a~;KL?p^){9o@*TcotPS`HIxvH8hHLm9u63@D{ z#~Phuw2wPCiA@^0%mqyv>*SV2C&!mXzYFV)p!g*(k30tKfRvk`K0HKRi+s&;@3#W_ z8&0zBEMXrNw0odGPx3FcTgQf%i@r^Dm#gCj!#?Yl82xfy2{q?_;|6_oz7{p*?R&0v z`>uAKubvMsv-`$92<}Dmo);UmjmRgyu0ie`u;(etLM3Yxt`vIx<7MfjSg*9lccn?9 z)`;c<-JgP2-;%twW}MTKA=L@f2_kL|OXU}VCZ6UOi z|J9fIA)GI?i`HNr(Rad4VXsBuE2yL`_f7D|E1huls?_O0XWu3o6+pu#=l%EvA8x~A zKXx)m7)nE34cg!RsjJa*{=DoZplp0mgA~s4$riyF?XB*&g?~Y^Xmy|C$EN=+`~xA8 z3b)A8B0~6ESa7|A<3UN^nTnw4!(KIR%_%J;I|Z<0KcaU_BvgR^Q!Mc5F>}EK=U&Np zUG`Wo0`zSGE&M-V>{7p4!}Jwj2vga*jYtb&oAIk2Qgrz@Cw%tGm;D-D&8WTEd>g+J zuuKHQ5Xt-JKOxU1ib136g5r}n5;(#2r{D^%4y@|7-tAGlW7hL#m&}LQfN#fT3~fh5 z`a}gxCaz}DmC;kl9Ic#L=Nr)|7D9a6zlpHMJstalxyb(&>B~=aq~ZSt$9@`!I1(>o z^Z6G0Gq$VE+7CWm5lQA!1+2re9z<4g@t5+&1Jo^}P#w}tSIYYSZkv+Bd399>rU!nze5S^zNHP~a=^b4GXyCm;< zREBa_6U>RRKA-JRA=*^we}x!l+v6O12{j? zZEC3Xz*OJ0mQ?^ih-*wqkOlOD4MTYQ$-ldk3|EO(3weHj%x` zxM%km;d#jaOTaR?CGJVADWoqR%|Rquj@zg=nvPY$KG~y5 z+SDgK3K4WmA{QQ?P@E1>G4-j2ee*{d{-44LC4OgfjH;dA^gLYsfnV|!7AN9UANp&Y zA#Z9ch5)WpO<=*#7m!a zEm35Dpr24lm5cQde+2#)?7yuTx`SPuFfuCX+UBEP&4`38C71ZgGE1AV5&H~XSwn=r&+Sjb zvdrjCxR;uQ+|oz2hJ2I%0zSo443>fK*_K51F475_c^B{KH-|KYb#}xKBUUmqJHBuk zI#2Z=83Un7^NjINUY&&2bEr~w0^>#Z8XIFRRYp9vee&w2B!IQg@G0g|4MlVQOk zqz?@KrvrWRd>%OaPk}Dnd|JVO1MYO&iE^X9qQ)|DzQ*PVlREL>(~b$A{Rcd;QNV+V zqT9wutePA7kx`7SWz8j9e>*V8sjw&!y{pZ9EJDBLgB~dg*8izgikxcg_&kNtQyCrq1&Cku6;iSy#Vo#a&m$*1a?Ha-3F7-1;7}&9Dlk*=AHc}Bf9n=p zLL#|Jd4#OO8{R55^FNi8$c|?6{wpGKfaqG_g2Ly8YqA z_wK00t?CCa$ntPqkqLkO)`NJx-uvCdPQfRZ?}n(u`}2Q-;Iz28Sxfz~a1Ci7C)&g4 zOVPTn3Fb2rm|-@;fxrHqOHk86=i=?AZB>7q^+U=ul`m5N?wIl1repY< z2j?zsSp1({IGcGeMc4!1&H$At=AF}EoP}Mn{xBS0z21;-W88iUf}k@(#&g!y*ZQeSw4g5=Fum zqgRwR)@Pz)*yE7JER{R+VcRH^#>I3yi*zfyG^-lw0xK!NxP3eF+y%&2I2RhNDQ`aS z>=E7q7=h?bsQG>23-5-GDJeFXdax|&%e&7ftUkLZ@Z#B`l;d)`d+VVNo!Y8@cbDMB z#ng|>a<2cDYU*X=-UC{sJPy{JB zb#${CVkD}{_Z-hC2^6p?$YOl&*WQa3{plmjG8!|1nh8H&9$t^ejP1nV#e7iOoYRxn zwjVI}J|%6ZerbSlH-nS&M4UqGlDvyEZlm=s5 zNKg3?KDt8ozi_xTiK*`u-9FjR?{uuF?@yoo^cY1)Y#9IruxCL0}qj2{J`P3j;Uau(j6Z z?(tS1CsA@V*{f3&piaH=Bd|48qfNUZO5>*Hh+dPW`iNL_b*Rin+YQ48VmwAZcWg97 zp7IwoNx$}qXdavNi4Ytc|E5N(H2TfWtZn)izW#oRMgXWj6aDL$^{@?Mw7?EWw$Eh;5(zfVrIv((*vF8zQYl58hW2`mnGiTGJh?LU!cE^H9GlVoE zQ#(^kOl@4Fi?zHj+?4G(o5uDu!5DYWLRt71IllbukkTe0Xfy*Rv^TT=UYFnBZFcva zh-Q|5*PWFSsCa4AS@z04r=jj)2PX$goN}JVD+J2Y+AST_h%N7-U#p4mu-zic^z6?R z+Ez3;r>|NVVsgKT%ofVemASeM_a{H6S3cN(^C)DLn7wSe@4nQay0=bDW-4OEm21_` z5PhH3z}i(?9j33l=;8u_Rgc{Jw092N`#9eS2E0GM$jK@BqXshfZ(!g_ddR`?7iUd( zV5tg~*3wl~y!bp63YI`=Mo45A5XDyqE*nd?I?dx!-Vm8gKos?;dZzt(x3; zrk#rFKdtU^jqah>G{w950GhOp?Mycf2r!vRd)K5j-%b1pq${fK#Y;(}e&VUUCZAjD zS@O{q4DXEDa-bM>>;IXY_=ttkyf5BxVp1SQe>{5&#*g8qIP2W zALjm8K>cVJ|J3+7Kv%t!jLc3{&Zi~n#H0EVQ@L=r#Gb!QH}O3bX&(7=7l^4@mHOtn)Igh`Kpi=XzI5lBET ziQDG3zvnDD9ZHqmZrd@kg{nq4eqTE(TBEf3L4J?3>)Bf;wV-i&h`kC>i`B_l0=M~j z3NkC5c%YX#BB{RLt&&^Q+;!2(84i_os+eeDug#i3<|mJqV1Fmk&EF37UGo-k5H_>} zeGp;PBkUaUkl9{1SUz`(J?%SpUVFpG;maU0bT{OgdwH{smkURtc%7R})5%sRWHwK~ z+%V*B$LRo1@b%Jtz`pUtqd*gl5`}p3jK9I%R_61^$wf_#jJ(_qfZk1STF0M{A$D@y zC%tZA?cfuj?m+M9LA`@wwQS~b@V?Xv0p*)ky>5~Je!NSU=rv?&z{$_Mcq7_Vb!PK` z+$1gG(zNNW-~Nmp zB?8JJnS+Q7mt8|wzZJ_?dRKD0C!8Ln5RT99?9N(9a})9DXV2RN{I#BI0l6i| zY8XW`b4aJWQ`0(Wm%bhh!kXLdmUnaG8{8M;TYx^Fny^+8T0C`Fkep$O;L3fh<3v0k z>S_0sXOmAH^wGyL>wF!YfzCvtSeE&YSn77CHM1bk?Yec`V15zYs_V#Pf4RE4DG)CT zC=yWqhY_SP>t<{5uKJj#-Sn*8rQJ-pJ_(L?pZ0K1Io0;g*7j12B;O@F3kN9DFHmn4 zhabyJUHhsCYRz<1?p;SL5K0|Ot1QwI!>LgTqq@yiZXBq=obeyEdROR;4RAShC5J%y zzW{jcUH1V4_no8nhFgz?aJ5YuA%CeWii_E8^9vMw8#C)lMs7nT&+!H%PpNF5Sr7Sc z>qVD_VQ50uY@zd*7Gm3IqdqjF%6lxe(>&wO=0d$Koh>ygCCyE&W07**mi?0D!fkD| zX=KrhUyv=And82AC+II5b*=*VSN!r)uS#xtt}G^seyLG?$G9MeZ`-kOjFYMV?4I8> z-yY-S#zjpG^zCmmE)1`*3EjxA1nKrz1N<6*9Xht|rRGc;b;+C$)Pgwerp3sMrDEPGCPs?SpCzwvpuOs8(lwzjO_v308eO}cS;XUpcm}L$W#Rjo zx@Xw#j3GV`i#b{>$?@AeTk~HNjM>N3b^&pB5ZiCpv{ihqsmtD5Bh1;z1Q!$lZHw#1 zH0SKiPBa^P%7}LYF_~gxIZH^+q`btc4@3= z)s}cPe`cgnW`MYK;e z<$fW5V9-x`?fFMauZ=zzt2pKI&Yj{V@vEC6i7`0B;ss;Rjid_ppq3jL?HJHB4x6Ew zu5feOmx_8eW;snmj)W&A+(>T&(v+guBFC9^E5~>%I;@y-lfBzOW`dezo@E1o;+v}L zCwuGWPt)$TXXN0~TFLK>86W@gk8A#&Y^|oFol6m7uOcPqavY;{5j*dDNqP_UoWF#4 zf=?g)TGk{lbN}*S)ExEoRkjQ0-6KT!W``SPyHs zGLW(VY*JdDN9)l*@ozH;iSN{ZikadX^8pFwHrQamf@b&N)J$W3GRPk^LSM>{RnHf; z-V@l2eXSsxyUcG|+p=>xHby*Y%s{fJ-ar>z?26=)loXT1JGKmlg5EQt&NZ(Q|1a9! z0w}KUSr<(pKmq}R>!2ZMaCdjtpo0W=cL)&NgS)#kxD4*@!QI^lfAjmFbM86!)w#Fs zdsVmU>#lFQ*RH*5YVTFuYwg{=puO$Ux+EA-QP`zEqh0nUu}AfH7ru4nB6`$5-8KD- z$&aV-`Svw>j(E^O>yP%pIqhMA$b&dB`0g^3)xN9mCM(AM1zDR;H7-b&jmgGIcrG;# zNVJXB|EcW4V_SYS1v+d0X#AHFQ@tH(@l+L9>*;yy4p)-KS`nc}7G+|qoz-jveV?)) zN9U6j@cuJN87keZU9eK2e8zvl(v6a8i~v}#+Hx*-0?@45B-n7YuT?EMPaeEDi3!Ku zm)W$cHLjK}+qAT1otuqId8OBuzB6uS3` zN*FwlWPn$Bx|)UR)0$g|?3Lf7Io#>lQG@^?@*jg6-YL9(YSDx>(2%FJfa57cMQ51f zZWf7C{F!Me>DFOS&id`Ng7NBRGxC(dxOCZh{i9yl`S+@4L#@r)>LUQ{dHvPeRVe`= zts4EiS>T+eW>vzimZt3uQQmjcb^bfu9zVVMz1hR1u!hpd=m&_-l%gSqH0dM2>JwF4F8z+{JX4wgzIzecQ)JVO8LYTxkD0CL zz|)KUyLM82=y%=A5(o~fMU0d6$KOluuM z#&xx~+kSPNuW{ekHT#PEcv5KPjGtTjQ4tAMrI7_oqffR7KHuj0$*k$7`|+*Ir~ZpV zx2BuwN3<@V{FlN87-t-p+h?#2cNv?xI6l(L) zRealyyx$0hJ;;3Oo0WL9Cww;^O|cN38BDuLj5y(8{5=LDE;$a;M= z-RyyUG01r>fe!vNwB%Uz$}b`o=4o3Eu^ z23lANx?;u}N{ed2+aC!-8|+NgiacAY$yZW*1o-`FdtMG>A)kE0m^Nc?>h`o%X=7c9XH_ zx8K?gm@Aq50mwsFlMGNUFT^afj1l|pP~0Pg`#Zq?BmB0a7cX5UKf(I#gG5vuq3<~- z53lwr4!&hu*`DGfWZKN`2N3{qk%9ZOh&`u#|I>v}y1&XLoEI9f8xFz@_OIHqgm8mH zZMUy3NG7~v_W1`LDMj;oBFsKl_Bl5Zar|Cvb7!~B97{93-djxQ_%uRm+f~to+-QV& z)|t_S~iy-(DYXV9SQTWultLvJq38A7n6<2z!H#O=Kv2&ilaBo@sKX2WX| z`jOj{$;0sEFZ#KT%4h9D&;}d{1%hSl@xbBdo5RpcaF5yN9dsnx;lgkm|6O-mSdoM< zR{3f^#6Fdg!_@Nc=VL_b7_j1vqP)Oq^XtfcKT-n|Y1S>xN*=97rElb>CI9c>TME^? zF~D&#A{kAf+#AMl+zoBM>RlPG$f>CX0R9HaAIQ^SSPh^!@gM148I8_}?#I;$KDH;f=^p!Hi^o1(trQf= zZ1pvB&&21LbH=`MTew;z2*7+2V}MX|SNFqHtDNuqd?vPKRe1dZ%kpICY38YO24C;$ zN*Jnm!W5|z*7RUDKHFd}cJp*ra<3344?ccIz(@}#KYvto^!Bz91bR>N`$tD_Y?DJE zA!g+qD__K~u4A9Qz6uZzO-P6fM8k`9bTZgu*!2HfBDJAT7ZMekInZwx0BG-uTGN*} zugL?Q9$4{kFGr0xhScpDupB}lja<5fJHI{AD5`8SADcly~{T+Pyk*Lr164zwQ zH92tIh@EHv!wucHQzbc|IXM`*Xf?a7V4!w%W2Sf%VPI`F%&iK#R!Etk}uWv*3P1I#_#PtbGX zhVi|Y%LDkFxScq?4)3snja*3x04Q_8FKlt^MAtOE|F?PI+twzdG8mT{7*Vc+hg@nU zPE=NnZ>iX+g*oM~UJmPdb$8k3-KN7*c@$F}wy;hz5K+E_ZM>Uge>KASVEl7#?I6bK zGdKa76x;Kz5sMcp*z>{?hXoB&lg|*}J`6L;zv5E*M#Ks94-p&fL^E9te0(qxO=T#s zeFv0YCsr>Yrg|g3DPunGXX3;@@4{;$8O1i|2&p3wU4o1jn{!9RVDXPS+P=^ujK;7d^V!f%+78A&_k#Hrq{fD2pmvvQCwFHUfvRCb zDZKKtPfq=Rs5|zRDC#EI`Ly=`cv`S#>;#B9op?j=+&-Sfd4GuBYJ_Ifc|!I7{>S=T zTP`--nSNQX-)dF&S_nJWx-Ms%_-~bCIop8N|EyL@rm_PpV#F$*W5P5-;v;L74pk0q zqX{!x5DARU-g3?!F;=&zjH7lQi0F>?x#r$_+n1Zn|RLbwf5VIxUV^aSj zgZnq5(jJfM9#1^_LG}l3DnAtI?12A!?LHLIr&xr~FaR{KvH7j?n*&8l2Djd8|}>TWl7t=R&(QWmkJh~!7=;4V59+~ zBUeCZz(G~p1a2fdYPoIF@fx95G)j6D!)2oG2~<_+yZ@hzdbxTGHIn}ml&X@77i4CS zDUNQ@Z?SwMYq5}jL}4kZV~vy;a;ecJakt*Q6?6N{Up_M`v9$`awPx##(SOP)8DY|K z_LNYQiTs>FvrMVhfc9_NUI(l$**&^Hw`2%XYemLn64$0Z^(#ST(i& z=2}pud?-)#7CD5n&{)EomzPeHq_XQ!sw1B;QsTg+Mqf0%tJ?e@#;8AM+4($FhbYo5 z0skvnoR0rz*u04tRiB%v_cL^Q>}jUi{|Aqi9^M-5;4(d|vC>>kHP*5)6Sb*wnp8D0 zP^p>ve;N-*e~-%^{I6AhErXN#S+~uN(L2v-oF|fRs(Upw*FO>-5EHnnn4_oPux@2k2omkY=?s;anA}Bg`JpLF^Zg; zh?Hf)k~d$Z_BhTu3Z6CKFiI)QvLtUXLVd`l6uzoX{-B|ffdiCONmAw1#4D=X#vXh} zZx_pLl)S+XT_ekh5m%DTqsmvpoGu>ycD@$TNU~tM<56l(Gsl`>kt)VEmYdkGER$DU zpgBAJ!-BeOf#Kj5$>YUeuOs{ajH+s69u2GLx|h-_IPaEJ^3Ej`wOswLjT%|z^2FT( zBHp))kV@CL&WBwHsn5<5R@7VQCazyr5DMaVg`8dLI8@SN@`}AlMWEx4_%RnJ~&9|p#nH554 z&tJm6q&$cNCNOGiM9GUQj6ve^|F7}ISJkW8SJ^9AtT9+YRR`OQH+oc@*v2ooZCxm%u3ql30&m_?#8WfS47Pg$mlj=}y{0-gI8FlcekEvkm0gt}rlP zA!?^Ro3yn?YRxsuTfXnW=fhJMm+6+aeVg^`fPX@>6_{IAxV`hOz$J1isYr{=O`A#3 z#T{oKri^6%riY0QtybUtIu0pd1V(CObfD{n1CbjEUU0fUTMC^DQwY`2_wk#8+TpUU7)vb(?mt6IuGvkJ&xlBQ0roCtq2pZ>J#7a#5DI7n3&HY)#1yf^4cfB%CxrhT)#qtPxE8)`4z!?+Yk0_OOen(LdDQ)h zZRmZFQ=9EuBIJ~jZtdLTqlCKp>AF@5N><6}Z&~Bp*VP2JCv6%Ksjg}@w!S311U91y1KHf;NabBV6kPwR#yQ_VbD_Wue!k*-Vcg5VBupE-1~unQ4* zh{Cq*5yv}&g=HS|q8fvo51$yvnw<-M_d&P$6_nO|=EqVK&elYk;(VEXFbi4GGx#?b zjq$zUWUY4sy=^)j$~!H}KUvO*ty_1oLvs_Jsc`-ilw)QDgD)ukq?}~sV}zmqgo%+L zVVS)=T&z9g%Kopi{TXh!(LsfyaZ#;3ZAWoEEk`OMGPei-1=qHBz`KWK1M6ER#(Hlz7*wF?i$r?}4f{suBCCN0@ zajU!&j~MtM+Y7zYi3`VPn2uh#CcKXBs!Ias`n)}X%>d?#U#lI*Syy`#stObGeek|R zQII>r-0yvq;aqlJ9JNxc>z}VtZfZ9|?(RS*TPKlZqR5^|+~`lZAH`lAmELq_1#oUB zpfuN4{$?Wdm1|0X@^N4EE&U)1U6hd)s zHSfxP%#)_V(ldW`F7bMA3usSS0<5WyA(sBVaT9YY_gF0SUo8zztNeEy&-OSUZA!nW zD7~r93SiyJhGtSvu~2vvicZ8Iq@eRnJ9$q!c@I1B4LR}kI`N6-N*v4*e0}^S?=5J$ z7q2*)uJ!7fo>Av3HG*?^LT0U-9~jPR7yBxAu>Sl1ROy}OYw#S-{T4qhC)!?(^Lq6@ ztSSury(W7wHl7MyXUk=b>`xb0VV{W~YrZtFw1K7~70x2vY0kk0RL}{5aq)JbJ55Pi z?IEB=exPqcf;bvSJgJ{S+_aBDOrrW6bV(aOTQ)Uxd36BO02TxS#hARLZ3Q^TB}{9d z)~SMx4$_e;Z6f4zaOksfpyG zU+H(>UK*WfgCu%h?>mYt`AtKj6mW0Dk2ayJ%NzZ-X zbSn0=AH!4%LvZ2n)Kv8_Qxo>Wrbk2{GHx&d6A=a@6MkV5aiQtIAVFLR1toFe8&Tms zQQMPRmo5wJDd08=Onc zoncIG6g<(7(|Y{p;18tsYCXC2E10=W=dn!mvfe<%3wRUjW^tpm{nh1BRN6#-cOZ|2 zb|OmNv_dA=h}S;Ce!MmRP?<#V*ZgSbs)n9Sd&u@Ej)30Y+ ze%WvaTlSZ7oZhMa<{qX)WXKm)>-Ex$(EMEzzBMBK+7c*FF1@d?|O zb!&0AT@%kFUScG8&d?@=-gM$UF&AjMmG+)olu`pZia)6tH)#WUr;MtOil$w2)V$wI zSv=FK+NO7;eR&x;HDT8ugEespb4E>Gq@MSVcTQp!ufH{^aF%KN#@%${9L{?gM#=8J zMWtYM)vJ^VNp3}D-)|hwY-B!RJNHqrp%F-6cx(NDLvW6s>6NnW3K$p+BgnlUc3a*} zE+2KvA9V}yYAk+cIEufkI;i}caC)~XoJCJFAbwc2`GVuT{vN0n`{G-;lJd0H%J7Nw z_t&~fA;tG->R&$K(AFL-DPh9(!5kryk@eNmkV)74qE-IjjD^EPMRhmGi#Y0Ap+ssVj> zK34~K)?0B;Qd9PDw(lf=dBZ07*ssW!Ez=a?!Wm-)Hbyqh6FL7UpB6U~uk~-A=1;2Z zM(I{UyX{{=Gs`fIb0?~+8!bJnu&xX%uy*Z&9Hg&Vg5iShOjHcme0CbB@2)krxhnlI zE5uM8T#*RZez7l^`8c(>xnCq9zt(mEU7pWQQ?DEpHBo2?Rpnu$rLt>@RUHKTv{LVd z3=&=h$o_pCJ7fgjcX5M(;MsWQa5j)W?_U=xVtruH1h#wGcvK;nO%B07h6VA~U0`+6 zp;maoF&@j+-5{79PLLL@3(GV3rR#lLWACw35YYc!jI|BFow#cPYl5+_$TDcgve-@c z$EY}x5Q!sd$xX^Br4hYD`=S-g2BBWbc{8=sId4SOwaIhiED-ekuwenzv2oL}Y4TKW zfa6G|Ys6>zGrid7g2p^2 z6lsF^l`s1_mDWY+IU5FS(i#$n6jbdBgu>DFE5t#B#D2ZI`kDHpXcx8kv!ww`=!(mf zB6}LH8fd)xzy4%X+rsRUZyXA^V6qWnqW+3DCJW}21_-W>{KVYkE-W33WkKMoRm`$3 z=^KoNOKnKN4(LazJ5!oKQV@7eS8Pe%-@azM1V2JEyhMlF!mK7VtqaoG7GgpgIM>c1()5S2ak5MPs_KPnm&Vf;8 zxzxs(_!>jqsBfn`Cw zbFoG6SF^&IOSp?Cj)*#~g-VE!>hCV^yz+lVL)-J{EUWi8BQN+Pbc!Ilh5RiN?q2m2 zZ_6-RS)Ru@0~=8^3^eb>|IkVitXd7anci^dhPMmcXaR3}bO? zzfcg55nm}{EU&IExJ&3MQ6#Q+@fGYkQKQPd-5+EowcDTL0jOaxC6B4Y_)E33s zGgD;FP#EJ^&d7P!Ny0Q)gs7JUs+UmHl0(~H8j~rgHCZ%OMtQNtRDHXe69zBEq<&#- ze8;`u-u+rNp`nTmTE!f7veZ|<#2LjhF>FXWc-1zeX$?&U$vcs@24)&GZZ)#7-j|J0 z*&{o}T8^oX@`^Y6mX>*@>#*q3KM_kJ=~|u5dAe&5ran8}1-efJo^&i%h*P0yT^)+f ze&#+jpT#$YwUE(J7HJ8p6g#<19?6h#oz!oM&&+E))Jv6~vA=~IH@M;Zp1oQ3aUWL; z{`4oEvEP<WDQ|bV{(Wx1-g%b|TX#yA_-1*h_;&f=nxQR7`UHtRSZx#8jojs%?Pyx9cpIK=f9gfzGw*!-TSBA3 z{sq!QU^!Pua-;G7l}j7Ivaf1Gqjvro-v?mXW4pmo9S#|LHgRD(@3u8cx~OcUwH$$V zps5~#ytLsw@tluk87^EEJ%Gw-iMxS@s}RXo=HnsCi+fFmSJJGZ*P)JGq`x1*Ayo#p zSCL*UPcgRpJb!;ew}nizE&_Pd$`8T314&}xSydL( zl-9uI1{Dushc4yPYttQt&nzTng2qT!A zIl{9C;pYa0XwNaS={Tt~l;ZSRTl~hSu+cD@`!OXKsj)5QdfVcmyOQ^<6t%D2qV`et zMxABWx9{C;B^tk6JJGI6(@p!%;e@W=6g=7*HiLzMr1J-5H)@6z(Ec#w^M@#pCN+Al z^SZs*-bG*)s~OkhHN)1kyr*#TN3@sXokyvc_;`;PXe}5%(dc;aYtn0y?0nu0m8N?1 zywT6F%xua*RX!z!xZPU~kHqr4{Uf+5*>=(MKc>fgk1@S} zZ;)?c+m!7IM{9Aq<*t7ImKw;%zc?uMatIK5P~^ zXuG+)Wvt-v;||4e#U91x=$ZU<`Qkz4$jIZ z;Nuy}nM%&aYj%U^x-2G+ETznono?!s zOvRQ{nUG+~#hOE!8lJ+p5Uo?MOT-5Nz5ufOMTsN%bNa;*#Iw|@B!b1VG%)fQ#DU6j zxeO9O^>Z;G^r2si2IB*Y_(P(i!6k)XFMfZx)f9FRc4wo_5f-LkqcrgCCcQjQx@27&gmHc{uQtM)k?0$=DCZ%5R>DbORzrKD6P5sAkvb$wc7-$5D=NNa#0_5AVG; zxc<)5{-9wvkM3iI6H=g%w#(VyVpj=4-mvHG85k;n;f$4Y7zQiqU9Y zJjtBgTUiMlwq+ui8fe&UXwt=V?vT0Or;a*z1NXsIzA9}TwPNJ?<>ibJC$WOQOiXYf zg_pSdg2AgXugbD#uA?2+(d_H#j0$igRgKdI#tn+Y&lpsZJS++=lRJ4&pyt~T!y@9N z5-5#{%lqonJ#D*_H{a_lH+uv~5tqkQgHtJ~aKseIUtH zqe1f7ueUWdqd!HWT#}lCHkwN6H($>zh5(o9edBH(31q{weVTBlt1voXw6_clo@f=Y zLG12!1rqfllGBnWU65av_Lw}$U+IOSa#dox%Zb*V;XNdl)n^Nd8>4uEbcW~81+Z^b z1$Pa>z1xWfR>|tP;n%}I_mNQh2IC}?6e)jG_HEB+-|i84s*Y8xOWll65yL#L5KA}^ zy!p8&{Z4Thy^@g030_pu=oKJPcpLW$zkB2NQN!&(-9aQWt>$9v{@O-=Q@ zpL|>Ootqy)VRS36x%+v{iRpB^c>t5<4Oj8R`I`6|^uPvWEsDC~L>52b!Z++l$#ErV zjx$3v37#?IW^*V*lsll+5|lgS(2}sG4rgkKayHB;MqqvHP*ErwQDG?Sn+bTPU&|o! z=Ld&8UQ&1=-|iDY;61`@x6;hB=f=#xtPkAJ=x2_B4!O$GX1+j$@n8?lLr)b=%`Cr3 z$tgccjM5&dos4p1=x4o_NM8F-h7=!F;5tdC(kseY}slINoF5krV60kyD){ zu(B%KSiL9@Yx1zNAOT9|pn?n)IjD?5B>*af2Tl`={_GqP)GuvBL&EAsMxjuVf{O8t z8=qf7JvV^X)R|iyiF=jag}aWcXX&Z?{x354Ja|#gXM?g@`qym!Y3-ShbH}&V3ERW00S`gT)=0j0r&c7#$fqZG^8-h~6N5608n8O0;R_k6L{P0n zMPZNl2Pq-^H0(BvwjMCb{0E-DvSpUl?&=Hr9h$lU-|Ji8wGEt+8>Wx&ts>{x{)$7L z0H~9vqO$Amhi-teHlIJB!Q%su;qAw94B<~`l^DYm@%x*YeS~sIM(HJpfd;E((sG~NVn{ja2YNwvJT9;Ki^FE#JfCP|}8V?&vxBa#DPn_iD zS7tkOJVCNnCG>NY=FjOm-$dw>lxTqCNh+GqcZqVZyx4$p=3dA<^|^5ii1K1~OQ zSE-vj^>iF7ikg0h0tJE=Twa8#D79s1{XIoaX#RvnoLrUfxWKU%p;0k=OEG)$AJ<`0 zDo=m5p#Sv1V`|o^B&S~(p;LAUSP@5S);-G^cBopB2zBV-l~vn8lk}CNd{N7|(Quds z4oUe^P`)IPy!aMiu8KG2gg_S=1(kszuNyf6I$_BTE#D34XOd#)Pn~$KZr3LjO7pUG zqG~m=8-MHAhW^F+5_V)cWr{v&YLi|1D83qtek=F*t+d2eoPlQBLkVvo9M@xNm1<6I zJ(%}x@}9gf_)JLWeik)5QLhDuN+2W?TS&nZx8U&z9CBXtMC$8%(_Vb+Ia*mnG9mcF zdIZSN5<2?A_kl^|RxuvGFqm}W`jMhHVv@XbNRkho=^zWU;RVA<{CJ9rO*~rY*^Q6L z>D$4lK`tc)(NP``^kHz>x)@Jek$~`sSGfROmddSa-4H7uvW|CwssFO=4c%mV8EJ|K zI7s#=(1WS?`xGseO4Y38?6qm@pP~tm$qrZm4SEi@DcgrM~jImE-K5qnzyPWPt~E^PhQ#o zJ(#kGR4x!6VMDcLNzIu8llw3ce^GmH-Xo!Ae+{Sm`U_f?H-s*NF4t_QagbiRmP({M z7dj0Z&nqtKTURG4`#X1Whru5Q+{WWW8xKgXezD4~(>JP)rGZcLulQ(-)Ij=nr_XbB z^3jE4;!K~T+ta^29_<9_j&$O6TvaecnS1V4hU8*R&0?&9b$nfOI}L03Y!-4 z=F!yAAdp-O)2L)k-hfvm$Gx^Mpv1e1i6J3)`OcP=Ly${Dc;I;k42g0YR z015a@5(Yz2MRKOd{2~4XW{-c_Y(KFk>%&HC-V%E2^?KqQT zQ4s=rgorsgu{Lqob*M=0^b`(qI){X5K4i`(RG$E_Ho5HLZx7n(F{At1*J;fKjHa9x=MKz)fMxE;*myVU6dZ{J=(w_7;d2g#d~9 z!$GR|9^(pW>%4Ik=AdhvcgdU40P)Jc!UkiWeD1}r*rc|cGf6;#g8$KFH1|&R+*V1? zEE%eP&!=jzO7}dYXB;@vr{-Y# z7>>Kv&w0!Ew4?>aw%`O0j&+CApCY*H>iyct;O3c8mkCdSP_q7NDmE%nM}o($dC1wH zcMdye+^5k6na_~BCw`}{m*Ex7unf;;d(ZFV)`5GOv@0v1khQ2audtf3;%zG4G!3ek ziz%i{h%Y8UfnrgD;nKi{!NBh?4>s%=#+hrY$S>3ik%M&;2fCeUhka9<4h)5(8D+bB zzlRSY5BASTme=fy_W^}}83|)BsP5Pl$y~A900&PZgp`I)rk?`Md@T9dS+-bJPSkk8 z@3?VQ9Bg#CZj`UJ*VHP{YKMayZioNMu8=O#(Gu6Vif+A_CW-7s?K!xz1)SKddE23q zvCc;H{hv8WVGIy+2f zmTUYf@%n(^5inPay>*Yvv+B;pk-^)sr#7?jJQHEJ$rW>Ne&FKXk>?N)U&=0spj_{*)D+pc=#SUr731lL9@F%t^8gQt4HdB3eh@xW z`_z-I`EKdFalJGb_pI31uwZ6CDc~hDrBys&o@!NdFs8nMz?XDRmSm3v$x^X;8tMtM+32pNNx02tjyZ)T>#(I}^oyqK*-gVy6jAQ|W_K6eTz&dp$FR|u9hNz>Ks`L|-$8<8~@I32|Jgo$6 zW{w?oh(@20!?D%b5qDUXmxjWNJWCSJQ@c88<%xzS@+rNXd7TT(aGOElo;LzE>LQ+y zmz<+K5iv5-<&*f(F|8sP(-tuWxKi1B@4j#bAQ|PD`*ePj(YfF`P~19b8y8LuTC31n zj9oGCYkkD`W(fMcxjn|P8uCZ-yTXa*7};>r-b=9iou|zHU0-DeF_2AwpS$`Ogl!_`X z`EV>?(r@L?>%#Y~s91ORZ`78OJx}<0ANA?xT5KpeXfg1imwq%FJEgCKJa*Bav(@w& z$1$??^$U7+rxPp7X?==;9^?97EXSlfulGwM4%;%lN}e;TycYD4z~(PstILo&4Eoca zND=ZFwbR047xt2^_}Pj3B&=Jxv!sz%G97Ja#`^l!BnTtjZ_Do7f6#t%w|$TG1Bn^I zv15+`t%D)0F}v)A)`x9*j&FGL*=hma<^GlrG~ji}+zVcc?lAb0v;~sUJI-=`Rsi?Y z>x`7@^oE`CylG09-<4eCH!6eGf_afXQ8M4fQ#`$nC(!G};)~pmIvFn*%-4)Ze#1JT zVOS)fG^5_z1Re(1(}Q8m zwbIfymr|EY%0nZ&n%P+&yL9za)5_$YN8qnBG>_I2tNC0o`t#N7U+RhG?8!~}l8zx| z1Y*~0;}OAc>T9>EWg}Q_psiB34fsc%mq2_j9ws(j=~qwG{bxfmuBTPWhm_`JFS7y0 znRQ+pk!;kz-UE|;I!!0SP%M4X!D8_nMdkz8p*Rwt@)df z8P4~Bs=*cx?5rZil<#Me?|2mKrg!omEOlg(2nk)mMluxB%^R6BZH6a*okNyuJR|50 z(i8IN$GLTFO*3q=LGm0S&iVjzs@AwwDF)6~Cx%*tza;oW@E|nSA+4gkl6h``9BBUV zfWX|Oy=xgaZLPuceLgd$^D*Mw0xv4x z%*5+YUN9AVwpUVhK?-{+W-M>e!OgH|9yCiQj3z|tTp0>mgW-knZq5rQwvgX9PX(cqxTiDFTxngg1Xgz#}3bJEMtUc^kQE@x8rfxx9eGr8Q|M z!9ceilObc({ItEsv%O%AW`1PJ)5yD`onw9iN?xGkE~NgxKlA3!WATLAayydG)Vi$( zZN8s?zz9lepd?KnN<#l3Hc)~GB~O~pstUD%^DP9XP)UNyeYrD7WrZ`xSy_z*uR^uU zs#|USasP-`t4&)jl$2>hNkeJ@_GQa_E`h*+mecl_YU0x9L_PMZo2BJcWFrWB6#{)n zfS_Xp>O);T-*)rOdP+yVNT_-s_vwwk7?)h#`Y_C5cJqLP~yrp&gX1Gs!(DX{^m|7oe z{847*)lom(j|%zL3lXwRh$L=MUxc7pCdgGQdKA}&Xn9)YS`}**M@fE~L&_kf`Hdfl zA4-!05-|-QRh&_DRAQSYa{?D*SzuU@9|hBY)}@n2)y21<#s9q&xD+m)V=1x_3KF^h zeTE~~ld_4wrDM4&SJyDV+DkF7mDV(?Wr=aGX=%MhYFQ!2Yf(`jT12iP#vLAdSH{OQ z26Y1AxFs!5@JN=%>! z)ao&kCQ}`2Ls?Dz%(pa69_uS!sIQ?GI>-`A^bAkyhDM;ry9Yx3Rfy_vWyT1W#&Tcd)v<` zctZFbp8N@g3BxaWA$zu-bL1TdkN=k3Y>Ji=j=q_t{=rK!*G;E8|84%7Y7|j-inMpJ zfCbUJ-*T|s@bTlhbbib$INex3&>8QY^lhwrXAPW--W$Y`bQLt*4rzVkUw?c>lc_!6QV$BhuO5$i@uHDtG9L ztvMp6K`8YE+_N_CW_^%08~s+1f331G5qb51bM{WO?_e`Vd_JT$+L?{}?L}^8Anpjj?~2n61CWv$xG1{wsOR*z zujxr&-?={(2R5!RqpqR2A#_eacV4@L+eAK^dM?gR^K1d$?-KTvl%q>4%j{A|w&OKNFh$XmEYQ2Lmfqavq9J()tiIu6Nx;F0k3 z5t%cZn@v?^r}vAlF7hKljdIo}yalV?Nxd;ZUc;HAUU_x4eO7C=$RoEOL6w0U$XEP} z=!kSKSb47J$iQw{<949^vtsnG@w_7?MK@VKc*N+k0qWe>lGjkJOhpBfiMS)FS%18D zYSk?7EPmm2GFp@em2EmDW*{hX@4Y9F;Z}~!|9o2ugHo(9OY2mLUm%`SKTuk8F;KEl z99#cB{5hHSSGOn|+A9yDa_P4cDXOPRk7#EuW!}q5#Q$v;~U8Yq<}+fa4s)AdA8n zY;Z^E!-l(`mS9m?pam(LTKFtkd>gYc`a>OE ziG>208}k+-wuM_~@80yviG1u9Kbv=m$j%}=R`~>^6Pk~7`RuR0v)-TFFx48~N=hrw zj^v$NrdQPtzkc-pqE0Rx!t~*1XvnXS6Dl&YTG9Dm*&)Rt!%ZZ$sAMEGG}&Ziuwnj9 zpB3GMT6$(Q+ zP+{I@Ma&}@F(DMpz&{*X9Jv{3mfR>A&G=e^8FKaJ{;nI;1M{#zDszFag1?uRdP$c^#172 z9ip?Jf|k_nvbIpHV}O=o986$m{>P7W?=0ZHA7b{(EFp+=eR1PSM#BHJ^^D9dBr)vo z-bMAbMqidD;8I_Q8-6vLR@YyTk@(7A-!C2>DIn0nqnhf+2e48#ng-IA<$S&%9`;Jf3(d^i$COqGgel;~Y8A>6oWer<0EhUYy%#JhUn8+Z zzN`AA{G>btl32{k5A{y*PDwY3Zjg{+d2)DiU^-#COV}7#+*b5y<0CTu_7_8OkLHQy zBJN~pdL`3PK`5o~4&zxf2Y>M_+gTYe(J_O$#1gj6vpvB3tIvmCeHwfcoIku~CV=P@*Z#?veK{@m z>G#Wr1NA2prZsDJ}*2Vh2@ry9S-df7@*Bb`^3^ za0{(NW`=f~X*)vuQqsl?e~`4-%WYXQtl|RuWt~F>IMb1+ZBxbC3y>K_4{~M=ati&_i9zca`1wo}e(5ROf6j#0LD>u8 z`?h_b9I^iY@bs2JaWzfDFdhN{f;)>l!Gb#kcL*BXCAhl<3GVK}HMl!0&f*r_T^EPl zm+SuO`Toqz>FMt2sj03r(t>UAN|yBhgZuvn{zmX0cJ3`@a2Z|xPv<(jTEcMBe-~%RWWlwSYyL# zeKdagEci7+{D@a(@|)0EMD170t;^{PQLoSu5FDi;!+PM*l8i_G)p@?Mt+G6ZU3l|{ zHk42dDwIoE90N%l|1T<@KI{?wF`r)TU;-YfA;N&i4p!CHNVYxGUj>3v1Y@SZDAF*) zZX#w_DWybyKr{S1T;Gk4%^iu#ne;X^1H=Qwbx#F?#+9ik9mKwEs0AnnpgsODzAkyD zc>BE9g9x!7E0ZiedN+_kqzq6F!1yl7W;0x7ZwLPKoJa8#1;JOr{a4LSMa;DXtpLE+ z?hxai1}urd))ta9&GszDg=p2qW*#+ps}XVTsB%hhx?V9}sMZ-1(R$*(l@a~{aPc@t zlgLntLTLuyNF!e4f4_Vnl9Zwv!F^_BSAu^Q8K6gcW~F#`aA;&-4Ro+?4@VHkW{Hgq(VPJ0`u3%rmuy9~l=id1+Vx*ZVR&ZWd4 zfM!Se^EG~YUPfLJqrzrXy0EAMfTrY9Qla+ctrrYi_yjZK3#;nGx^oAU;GHbf6?oK% z@8lKODk!G6fvQd7U)zHav8K#SMuT^mBDGx%QA=jMO)Kc^-|33zS5FrZ%_b#pzEJ$R z9=^;k_j5gNd6lYpimqAd^AG&bLimrD;LVQ;UTM%T`Ldz8OcCi!Z%nUD3e)eDsECw~N1kUM*kK1Gxi6G*WZ!((hI-a}NSkovzEH`LAtZNV zyLrGe;bStTVKaGL_Z$U$Wa&H$Al%2*eD8m!_(CUlA)c(aFM^P)C!4&ML*Eun--fE{ z%u~4M@;g!BY4ffpN-s1{eWW!BY6{&XSAA^FeryeX^o;LWG(`PX5${Bk;Dk@U>wATQ z?LkF*L1sl{MIjUsT^SJ_j!F1Hjeem-A{fov8p+#A@2I)OtP&asqJgVH$;RgWU{?`g zf(gXpB$Q|Fr#Hcr!sH~BWFDk9c_WmZFvDTzWMgCd+*PSWEjS|6NB>6~W&RB_iY-z*LUoWbno@Iw-h}o~#5>u z6{Iku*#D0b&lsn!Kl=Z${^Obv4Y05n#NZ?pVV-z2#svP?`Y9^)%9eCJK>6Os;jjJc zdO+cSaOVC;W7^&D9MGe&-#b3=(HNi2UpoMZ(Gh<=fb`y^*bRT@x0rT4@XYDI92osS zbX*Sq^p5~qTHGsbT^WyOI-#mmP5DQp>MG6NXS?cVHT$LprSKkAlN8a74V%3CA7fSM zn$mn}8}b<%7AYZ&fReG3pKekDW8uffclA^7=XQ6Jwr^FaDkVJ&hVN+t`jd`L(EcLz zOAuI~Nz~j}w(F$nq!|mER-p93Oty9cMYi0=tYIy$4EK)Hx;h>h*@{ zVsa>r+?ZlJRkg*oVaO|ux=X(!7!x$ML-a$*RgQIAe#Sn^+rHhKKIDrNR>nBxJmqYx z^36p#wLP_+Pl_qW|5q9OEcng^Ku?c3&dGdPA#*iuD3T5Yl9j8LW zcl%JsFlbfkVaSyD{IV#YIfb@Bjo(=9wm^Hmc?^gwsG5Q9K^RFA0NM}26QTKIKBEN> zi4vFlf}X4)b7WCB8esz%ZRup=BhxZ6HOTrD`VtETHq){Nvia)b>Y}BgB|%f4CJ{91 zj&2B|zQolX=>ZE}2>;i*IeH=h+kF{h7_+9eJOq!n$+RCtPi9bs5SC9#I}CroC}rtH z-XCZz#+X~}#u8Rg_bJpzE2?=-Edgt<_M2v)_-6`{<_<9X;8Blh@lAG5b)zSqo)d2s z(?g38-;$ca%DMw0ZKR0;Tg8nfX|uE4|GJ6yQvzle4eV=0FXSHSShn+CNvawChn;Nc zOeBmhv)U3hu4eOUN-`$NXRcy?U@?>T7_eH&fC*(bSKD_HT9-FKc~9K1XsQ$p@WsD{zA>*ciH)k1b|d_ zrU7OFpMFQ;EKdkqK+!rQ@wF#BgC+@B|B~(^a+`Mc(nd?KE(;sy!D!UM|67qIMvlis zc+bxU56cm2gbk#%o3IKlW#hIs1>!JUDD=5UE3VRJ6UU0y?4aU>n{E?OGmaTCNfG|U zQu>9OP-%kJY+BW4@}6mSNIPV5V6uNQzLF9hk8{U}Q;Os#Sq-|Dyt=mu%hvDpZ_1zU zKX~CrP(vtP@HY6RW9H{K890?tY*7HQ6!f!U+>(`9d z)1DX!6`q+GxH9?HK6AJjphicsNJO+433nfVrgVHthx_*i3c-5pLaz zcqV!LI{Z2`SniGmQW>MxcyMhr+|)m+EriKQ`{pez1$1?%n9hz6X88&|wX5d{rVAeF zN%FI_v9wKQ23Gn-%V-<-+< zEVAO%AqdBsv!%-rr5n)S97|b`Bw^`i!DHctZmV+DGG*(~A_45>eksY~-|W5gOj5$iZfe&oWal?=88naIoI$#apky;(I5TTEqOu_^g|XeenY%HovJPTHL(#L zrzhJL@wkiRiD>qP7t&O8s_h|k{KniC z$)oL|s+Ol&k!aUaor$3^iL$Huu6!E-Y88!vX`bO*St*mXSFm?QlK-g2;7l}7OOp6% zev@|cuqh@@ANgv+0Mrm=&EX}Ulfm{#t8a!2grHw^pG>+~m%kFe6|i?zp^FD7j$k0Q;+Bn!&xJ$`jpAQdV`ACJs8eg)2Jay{GYaR)zU`Pgqczr8#Y7^7+&KM~IIVy>6=BQ1%PVWE zJCoVyj@y;$s-&A1`GveI6r9_5fb+j)^q)m5ic7SoT+d#NEc`c@sp9%Bfh2oRW@GhN zX|-GaM8V)31};N=Ea2w}o#<^K@?M1xGSVg4V>HnpDFxHwIguOSm(p zJq72I_b`Lw8C0<@U7YVO`Lu_4qaOAy7rjb;_-BRX4Fv8^nGJ(FjFUP0Qz*+Pel|IL zar{4ub8eFx^yP94d3)kHEYlkBea40LT3ohD^PW zO$mU&;zorIA^w%V=rK}YnRNrSjcW#zIS-)`BSTRXazTOLNyer5{fK1{c9SADsqRx6| zE+{{HZrQW|drWNJ!>jzA_e5sdOSq|dMs#H4JX$wwc;qi+orl#0 zGWEiK&B;}}rfS`*l`e@FB~9+W90ai8MqR%ceBKl2#}(eA+A_cXx@$$HsFTv$#u z?gx>F69eT71f`28+47ayXuJtzu4IW9g5};jMXOAHUi>klQ7M8o=Y(&dg-BOG&vA+kS$oY_j6JX!${7FLP|a-TB*%Q zMr^_mTYaUNC0_%1-uVPjyB3yzF2~mCAalx%zylp9q+B?KHWg#_M0-fv$hp}@NOuF5 zJ>)f2JymVB&235H{gmM%VB!DafN)sw5>EdYr>@6^`vuTyLH69`!s$XxKt7x1$caJe zJicKP15I zNi0O!`1PODPS(`i6neB?&WoyLX#;kXJ70$igz(TS+84t$M_T_>M!)>@vs;dY{=a!Q zbT_*I`6b9F{SOh}3+LT>%iU}Gk&}V9W!ErV_Nu#LHiBCdjuzsDU&-=;1B65vD!X`G z7b^e3MPm-tc3~|k{$rUn??&d9^FZ2;uCj#ZM*6EpOY}zZ?U@ry?8ptrBApYS6V9F{ zoh?0GKkF9Q-duK?e_M1*{b)DEJ(999Fz*xS-BRWe?v0^#340=x=8aKwSHqS-tJ?Wv zn}tJaG&@(x5VN#r4#36g@@3%S&mSq5Qof?C~wKC&d6s8!2DKt?Mi!w+>=0vOK$Jq~5KJzMt7}l4rl_A&N>2|S- z^4|HAkXZqF&0yty;$#b1>}8KEPA;W!jqx`b=|8vtsYQ4ybtML^Yc0@TpHvq1cr)^UCv+oUfI|^!q5Kb`tMl z$9r3w*6&qMLtu)qI$zB8_b5xF8ETq96A7TfS}rx&Zn(Spn~namZ|GF4>g^a>r&KGf z0BZ>I6YU5Fgnz1+}c=$ z+u79;jb$pA`W5BU0if1Tkjt>tBW}%Zz>aPv8&?SCc%w3{tfP|mhuQe^JoF*~WHhzY zoZ{AgQ!;f+{mHU=Q7dA#mPw-@(L5gG?3cjKA}@?)YnG~N9X*z45Isxb*QojvJeBzH zSsjW{-jZP32pa2qy~BFr{G*zRbG!6#{PFGYHYnNFupmcKrm&|FFh0fyNBk;kScPvX zYbYt;(irkgvOb#VAR%B1W?xn6>=_x;3FT_gysVB}sBGBdDU|X#*E~ac0|)8w?GD!Z zw3jNvo#&@n?%(y5Az2w7lhzj%AMKWD2IWxME^3RExWklZxQjlR?;nlSHQKG7t~%+z zF9b&27p+ltyOd^qAHx?mrprKtN1QQ=X^mAT-PDDV-M`Q0%UlOmw)J~V(^{-Lf85dR z#5AY$zza&YbhlzYwmQ!VGgfxl2jrHHshvEF7x*W9#Aoy=I(#(R9pMRb*AO{d&Ad|U zkGXz{sYQ#0u_;<-y&jIMymobzAjhfRj{zkvv{Q#_r8uQ(mZh9ZOEpt`ydmC3iU+(@ zbwqYGK)rboX9%q?vJq~TLw>K#eBPdd)N%QgYjW=PL@$GHlM9Q|{b}}TAgIQ}eoH^) zDG{b!n>@7F1+_S$l`>Q#i?^~4_yZpIXKL(}=@hE-y~sLtw}Z4!&W0Azee5-%&&+2l z>ESlL2#4F*XF|hT0G&|J%#qkGv)j}xNGFU}KC2V~INoyl5U*O}nZ9PmUgf6urGuY`XF$(TKFJxI|> zL@UdxY#L2u=|9x^i^D4ao^ZjhdtMf3tPt*KU_OSlbL&+^rK7fR*vBkOJg*<*oWX&S zcbmXnT#WLu$&oRDGA5vhr5q|Z(|;}t`fmHdGM%>T>H;*QR8*C7r6cUcCKR6h{aAH9 zK#zKSc9vhhGHX-0$)wvsgFZ^6BtDp%&F*^PWFte9#(~OOcj;3(MnuUs193HiQn8wG zJaewhq=n!wm0z3E$Ur~Egrzd$T4(`gO)8W1wU*7~K0(y;3}6LK)U5b+SZwPXBTdxm zJzU=oPI}xqqZ{yxmIws&j(=)^bmMK4U-6jxshcRfk&6F7jv3FMcwr zu_>RL9@EGU2rzm*{C(?TF`~#Y;QcS6NOS!;nna}PFCn-vksr~%8uW7P-VBXWa(sK; z_xD8i-%^6Ukla!i;|DZ|W&r%N0Lya$`35yF68`z0p$aqbLy&W{efYKmI@)_Bs7&Y5 z{J7sq8}qFlwofWxBQrou3ga@}M^QTo@R9;04RDjn@q_psNMS<|o@cM^L?u{m-J!bJ zxgk%4&fL%PoHpy$O1G?RmJ}GaV}{y!rq8yoTn8!vO~30hd=lsgo5C`2ArM-35^NcQ z%~*^1$}6q(m^adigAx6RH58YC5LyMCz|MB15H~8YpB34Iv1A5(f=fkDYeCqh+a_^* znkgRO>CIojRP%%1KR*z8E&J-*@@tW??*Y0?xI>eJ(2ehifLV8ns%?`)E(Xz^Uzz9o zWs<5xE+2>o7@o7?0n>IH-y>`qt#RN8=%n4;9U-=x;ySdPuexdCVDh6G(GMn*&e|pV zYSPT{qnsf(6!}8B1m8FNeOVi!_%QD!Wkq^rM z9_p+!+R#>IDFO^Bz~F-8@p$Zq7nn4^4}NHw?9s%2<2X}1!s1g(#VgO*PThP!>OGQg zQ@WcQ(aq0D@M?ye=@!L+Zp8em-66)0MSXNEm#Ox4- z==Jxxm+^c{hE^5)3fevLVH=KrfZqtYY#R%_o5G%K(?!6IGMn>kMAamRwI#;TIW6<( zq6~wuTdlc#G(Uf-(=hY91gT@^m`GL z$Pl#E8Jk8TLKMRfrV@E4N=g#d1!@I%bUXc!QnUq4%lXP_#-h4Kv9}?uztHWMPS*?N z-%HSd>kOO&k_eZ3!|NQ5t`aaQ{)U)hb;9VGX}rtt`SsCPi{A`)G=B~GyS!>Onl4^6 zN6U3+DzgoaX9xxtP&UE60!7e)_C{+;HeF02g2we>vjUIO2bQVQUe zltt|%;Ey>zh!a7YZo?mrB9v0HJ(*K8k?zgh`ITd(mdn