| 106 | |
| 107 | template <typename F> |
| 108 | int test4 (std::string const& f, |
| 109 | std::map<std::string,double> const& constants, |
| 110 | Vector<std::string> const& variables, |
| 111 | F const& fb, Array<double,4> const& lo, Array<double,4> const& hi, |
| 112 | int N, double reltol, double abstol) |
| 113 | { |
| 114 | amrex::Print() << test_number++ << ". Testing \"" << f << "\" "; |
| 115 | |
| 116 | Parser parser(f); |
| 117 | for (auto const& kv : constants) { |
| 118 | parser.setConstant(kv.first, kv.second); |
| 119 | } |
| 120 | parser.registerVariables(variables); |
| 121 | auto const exe = parser.compile<4>(); |
| 122 | max_stack_size = std::max(max_stack_size, parser.maxStackSize()); |
| 123 | |
| 124 | GpuArray<double,4> dx{(hi[0]-lo[0]) / (N-1), |
| 125 | (hi[1]-lo[1]) / (N-1), |
| 126 | (hi[2]-lo[2]) / (N-1), |
| 127 | (hi[3]-lo[3]) / (N-1)}; |
| 128 | int nfail = 0; |
| 129 | for (int i = 0; i < N; ++i) { |
| 130 | for (int j = 0; j < N; ++j) { |
| 131 | for (int k = 0; k < N; ++k) { |
| 132 | for (int m = 0; m < N; ++m) { |
| 133 | double x = lo[0] + i*dx[0]; |
| 134 | double y = lo[1] + j*dx[1]; |
| 135 | double z = lo[2] + k*dx[2]; |
| 136 | double t = lo[3] + m*dx[3]; |
| 137 | double result = exe(x,y,z,t); |
| 138 | double benchmark = fb(x,y,z,t); |
| 139 | double abserror = std::abs(result-benchmark); |
| 140 | double relerror = abserror / (1.e-50 + std::max(std::abs(result),std::abs(benchmark))); |
| 141 | if (abserror > abstol && relerror > reltol) { |
| 142 | amrex::Print() << " f(" << x << "," << y << "," << z << "," << t << ") = " << result << ", " |
| 143 | << benchmark << "\n"; |
| 144 | ++nfail; |
| 145 | } |
| 146 | }}}} |
| 147 | if (nfail > 0) { |
| 148 | amrex::Print() << " failed " << nfail << " times\n"; |
| 149 | return 1; |
| 150 | } else { |
| 151 | amrex::Print() << " pass\n"; |
| 152 | return 0; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | int test_concurrent_parser_construction () |
| 157 | { |
no test coverage detected