#ifndef _verify_solution_hpp_ #define _verify_solution_hpp_ //@HEADER // ************************************************************************ // // MiniFE: Simple Finite Element Assembly and Solve // Copyright (2006-2013) Sandia Corporation // // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive // license for use of this work by or on behalf of the U.S. Government. // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA // // ************************************************************************ //@HEADER #include #include #include #include #include #include #include #include #ifdef HAVE_MPI #include #endif namespace miniFE { template struct err_info { Scalar err; Scalar computed; Scalar analytic; Scalar coords[3]; }; template int verify_solution(const simple_mesh_description& mesh, const VectorType& x, double tolerance, bool verify_whole_domain = false) { typedef typename VectorType::GlobalOrdinalType GlobalOrdinal; typedef typename VectorType::ScalarType Scalar; int global_nodes_x = mesh.global_box[0][1]+1; int global_nodes_y = mesh.global_box[1][1]+1; int global_nodes_z = mesh.global_box[2][1]+1; Box box; copy_box(mesh.local_box, box); //num-owned-nodes in each dimension is num-elems+1 //only if num-elems > 0 in that dimension *and* //we are at the high end of the global range in that dimension: if (box[0][1] > box[0][0] && box[0][1] == mesh.global_box[0][1]) ++box[0][1]; if (box[1][1] > box[1][0] && box[1][1] == mesh.global_box[1][1]) ++box[1][1]; if (box[2][1] > box[2][0] && box[2][1] == mesh.global_box[2][1]) ++box[2][1]; std::vector rows; std::vector row_coords; int roffset = 0; for(int iz=box[2][0]; iz(global_nodes_x, global_nodes_y, global_nodes_z, ix, iy, iz); Scalar x, y, z; get_coords(row_id, global_nodes_x, global_nodes_y, global_nodes_z, x, y, z); bool verify_this_point = false; if (verify_whole_domain) verify_this_point = true; else if (std::abs(x - 0.5) < 0.05 && std::abs(y - 0.5) < 0.05 && std::abs(z - 0.5) < 0.05) { verify_this_point = true; } if (verify_this_point) { rows.push_back(roffset); row_coords.push_back(x); row_coords.push_back(y); row_coords.push_back(z); } ++roffset; } } } int return_code = 0; const int num_terms = 300; err_info max_error; max_error.err = 0.0; for(size_t i=0; i max_error.err) { max_error.err = err; max_error.computed = computed_soln; max_error.analytic = analytic_soln; max_error.coords[0] = x; max_error.coords[1] = y; max_error.coords[2] = z; } } Scalar local_max_err = max_error.err; Scalar global_max_err = 0; #ifdef HAVE_MPI MPI_Allreduce(&local_max_err, &global_max_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); #else global_max_err = local_max_err; #endif if (local_max_err == global_max_err) { if (max_error.err > tolerance) { std::cout << "max absolute error is "< tolerance) { return_code = 1; } return return_code; } }//namespace miniFE #endif