Dear all, I have some problems with the signs of VectorTools::point_gradient. Here's an example:
I modified Step-4 of tutorial so that the mesh is a GridGenerator::hyperball with half of its boundary_id equal to one. After solving the problem, a function is called that prints VectorTools::point_gradient function versus a simple 1st order gradient at some points inside the mesh. The result is almost the same but there's sign difference at some points. For example: correct sign: -0.246203 -0.0555845 0.0532539 -0.246227 -0.0555722 0.0532624 wrong sign: -0.249757 -0.059087 0.0550266 -0.24978 -0.0590716 -0.0550173 correct sign: -0.246203 -0.0555845 -0.0532539 -0.246227 -0.0555722 -0.0532454 correct sign: -0.242905 -0.0526048 -0.0516154 -0.242929 -0.0525951 -0.0516075 wrong sign: -0.216536 -0.144069 0.0495166 -0.216534 -0.144071 -0.0495091 Can someone check this out? I attached the code. Best regards, Morad Biagooi -- The deal.II project is located at http://www.dealii.org/ For mailing list/forum options, see https://groups.google.com/d/forum/dealii?hl=en --- You received this message because you are subscribed to the Google Groups "deal.II User Group" group. To unsubscribe from this group and stop receiving emails from it, send an email to dealii+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
#include <deal.II/grid/tria.h> #include <deal.II/dofs/dof_handler.h> #include <deal.II/grid/grid_generator.h> #include <deal.II/grid/tria_accessor.h> #include <deal.II/grid/tria_iterator.h> #include <deal.II/dofs/dof_accessor.h> #include <deal.II/fe/fe_q.h> #include <deal.II/dofs/dof_tools.h> #include <deal.II/fe/fe_values.h> #include <deal.II/base/quadrature_lib.h> #include <deal.II/base/function.h> #include <deal.II/numerics/vector_tools.h> #include <deal.II/numerics/matrix_tools.h> #include <deal.II/lac/vector.h> #include <deal.II/lac/full_matrix.h> #include <deal.II/lac/sparse_matrix.h> #include <deal.II/lac/dynamic_sparsity_pattern.h> #include <deal.II/lac/solver_cg.h> #include <deal.II/lac/precondition.h> #include <deal.II/grid/manifold_lib.h> #include <deal.II/numerics/data_out.h> #include <fstream> #include <iostream> #include <deal.II/base/logstream.h> using namespace dealii; template <int dim> class Step4 { public: Step4 (); void run (); private: void make_grid (); void setup_system(); void assemble_system (); void solve (); void output_results () const; void calculate_field () const; Triangulation<dim> triangulation; FE_Q<dim> fe; DoFHandler<dim> dof_handler; SparsityPattern sparsity_pattern; SparseMatrix<double> system_matrix; Vector<double> solution; Vector<double> system_rhs; }; template <int dim> class RightHandSide : public Function<dim> { public: RightHandSide () : Function<dim>() {} virtual double value (const Point<dim> &p, const unsigned int component = 0) const; }; template <int dim> class BoundaryValues : public Function<dim> { public: BoundaryValues () : Function<dim>() {} virtual double value (const Point<dim> &p, const unsigned int component = 0) const; }; template <int dim> double RightHandSide<dim>::value (const Point<dim> &p, const unsigned int /*component*/) const { double return_value = 0.0; for (unsigned int i=0; i<dim; ++i) return_value += 4.0 * std::pow(p(i), 4.0); return return_value; } template <int dim> double BoundaryValues<dim>::value (const Point<dim> &p, const unsigned int /*component*/) const { return p.square(); } template <int dim> Step4<dim>::Step4 () : fe (1), dof_handler (triangulation) {} template <int dim> void Step4<dim>::make_grid () { if (dim==3) { const Point<3> center (0,0,0); const double radius = 1.0; GridGenerator::hyper_ball (triangulation, center, radius); static const SphericalManifold<3> manifold_description(center); triangulation.set_manifold (0, manifold_description); triangulation.refine_global(2); for (typename Triangulation<3,3>::active_cell_iterator cell=triangulation.begin_active(); cell!=triangulation.end(); ++cell) { for (unsigned int f=0; f<GeometryInfo<3>::faces_per_cell; ++f) { if (cell->face(f)->at_boundary()) { if (cell->face(f)->center()(0) < 0) cell->face(f)->set_boundary_id(1); } } } } std::cout << " Number of active cells: " << triangulation.n_active_cells() << std::endl << " Total number of cells: " << triangulation.n_cells() << std::endl; } template <int dim> void Step4<dim>::setup_system () { dof_handler.distribute_dofs (fe); std::cout << " Number of degrees of freedom: " << dof_handler.n_dofs() << std::endl; DynamicSparsityPattern dsp(dof_handler.n_dofs()); DoFTools::make_sparsity_pattern (dof_handler, dsp); sparsity_pattern.copy_from(dsp); system_matrix.reinit (sparsity_pattern); solution.reinit (dof_handler.n_dofs()); system_rhs.reinit (dof_handler.n_dofs()); } template <int dim> void Step4<dim>::assemble_system () { QGauss<dim> quadrature_formula(2); const RightHandSide<dim> right_hand_side; FEValues<dim> fe_values (fe, quadrature_formula, update_values | update_gradients | update_quadrature_points | update_JxW_values); const unsigned int dofs_per_cell = fe.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); FullMatrix<double> cell_matrix (dofs_per_cell, dofs_per_cell); Vector<double> cell_rhs (dofs_per_cell); std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell); typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active(), endc = dof_handler.end(); for (; cell!=endc; ++cell) { fe_values.reinit (cell); cell_matrix = 0; cell_rhs = 0; for (unsigned int q_index=0; q_index<n_q_points; ++q_index) for (unsigned int i=0; i<dofs_per_cell; ++i) { for (unsigned int j=0; j<dofs_per_cell; ++j) cell_matrix(i,j) += (fe_values.shape_grad (i, q_index) * fe_values.shape_grad (j, q_index) * fe_values.JxW (q_index)); cell_rhs(i) += (fe_values.shape_value (i, q_index) * right_hand_side.value (fe_values.quadrature_point (q_index)) * fe_values.JxW (q_index)); } cell->get_dof_indices (local_dof_indices); for (unsigned int i=0; i<dofs_per_cell; ++i) { for (unsigned int j=0; j<dofs_per_cell; ++j) system_matrix.add (local_dof_indices[i], local_dof_indices[j], cell_matrix(i,j)); system_rhs(local_dof_indices[i]) += cell_rhs(i); } } std::map<types::global_dof_index,double> boundary_values; VectorTools::interpolate_boundary_values (dof_handler, 0, BoundaryValues<dim>(), boundary_values); MatrixTools::apply_boundary_values (boundary_values, system_matrix, solution, system_rhs); } template <int dim> void Step4<dim>::solve () { SolverControl solver_control (1000, 1e-12); SolverCG<> solver (solver_control); solver.solve (system_matrix, solution, system_rhs, PreconditionIdentity()); std::cout << " " << solver_control.last_step() << " CG iterations needed to obtain convergence." << std::endl; } template <int dim> void Step4<dim>::output_results () const { DataOut<dim> data_out; data_out.attach_dof_handler (dof_handler); data_out.add_data_vector (solution, "solution"); data_out.build_patches (); std::ofstream output (dim == 2 ? "solution-2d.vtk" : "solution-3d.vtk"); data_out.write_vtk (output); } template <int dim> void Step4<dim>::run () { std::cout << "Solving problem in " << dim << " space dimensions." << std::endl; make_grid(); setup_system (); assemble_system (); solve (); output_results (); calculate_field (); } template <int dim> void Step4<dim>::calculate_field () const { const double dx = 0.1; const double dy = 0.1; const double dz = 0.1; for (double x = -1; x < 1; x+= dx) { for (double y = -1; y < 1; y+= dy) { for (double z = -1; z < 1; z+= dz) { if ((x*x + y*y + z*z) > .8) continue; dealii::Point<3> r (x,y,z); auto f_dr = VectorTools::point_gradient (dof_handler, solution,r); //------------------------------------ const double inc = 1e-3; auto rx = r + dealii::Point<3> (inc,0,0); auto ry = r + dealii::Point<3> (0,inc,0); auto rz = r + dealii::Point<3> (0,0,inc); auto f_r0 = VectorTools::point_value (dof_handler, solution,r); auto f_rx = VectorTools::point_value (dof_handler, solution,rx); auto f_ry = VectorTools::point_value (dof_handler, solution,ry); auto f_rz = VectorTools::point_value (dof_handler, solution,rz); auto f_dx = (f_rx - f_r0)/inc; auto f_dy = (f_ry - f_r0)/inc; auto f_dz = (f_rz - f_r0)/inc; auto f_dr_me = dealii::Point<3> (f_dx, f_dy, f_dz); //------------------------------------ if (f_dr[0]*f_dr_me[0] < 0 || f_dr[1]*f_dr_me[1] < 0 || f_dr[2]*f_dr_me[2] < 0 ) std::cout << "wrong sign:\n" << f_dr << "\n" << f_dr_me << "\n\n"; else { std::cout << "correct sign:\n " << f_dr << "\n" << f_dr_me << "\n\n"; } } } } } int main () { { Step4<3> laplace_problem_3d; laplace_problem_3d.run (); } return 0; }