Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * O
- *
- * Author: Gabriel Brandao de Miranda
- * Date: 20/04/19.
- */
- #include <deal.II/base/quadrature_lib.h>
- #include <deal.II/base/logstream.h>
- #include <deal.II/base/function.h>
- #include <deal.II/base/tensor_function.h>
- #include <deal.II/base/convergence_table.h>
- #include <deal.II/lac/full_matrix.h>
- #include <deal.II/lac/sparse_direct.h>
- #include <deal.II/lac/precondition.h>
- #include <deal.II/lac/solver_bicgstab.h>
- #include <deal.II/lac/solver_gmres.h>
- #include <deal.II/lac/precondition.h>
- #include <deal.II/grid/tria.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/grid/grid_tools.h>
- #include <deal.II/dofs/dof_handler.h>
- #include <deal.II/dofs/dof_renumbering.h>
- #include <deal.II/dofs/dof_accessor.h>
- #include <deal.II/dofs/dof_tools.h>
- #include <deal.II/fe/fe_dgq.h>
- #include <deal.II/fe/fe_system.h>
- #include <deal.II/fe/fe_values.h>
- #include <deal.II/fe/fe_raviart_thomas.h>
- #include <deal.II/fe/fe_dg_vector.h>
- #include <deal.II/fe/fe_face.h> // Para problema com multiplicador descontinuo
- #include <deal.II/fe/fe_trace.h> // Para problema com multiplicador continuo
- #include <deal.II/numerics/vector_tools.h>
- #include <deal.II/numerics/matrix_tools.h>
- #include <deal.II/numerics/data_out.h>
- #include <deal.II/numerics/data_out_faces.h>
- #include <fstream>
- #include <iostream>
- #include <cmath>
- #include <math.h>
- namespace PoissonProblem {
- using namespace dealii;
- const double epsilon = 1.0;
- const double coef_reat = 1.0;
- const double coef_conv = 0.0;
- template <int dim>
- class SourceTerm : public Function<dim> {
- public:
- SourceTerm() : Function<dim>() { }
- virtual double value(const Point<dim> &p, const unsigned int component = 0) const {
- double return_value = epsilon * dim * pow(M_PI,2) * exp( -dim * pow(M_PI,2) * this->get_time() );
- return_value -= coef_reat * dim * pow(M_PI,2) * exp( -dim * pow(M_PI,2) * this->get_time() );
- for (int i = 0; i < dim; ++i) {
- return_value *= sin(M_PI * p[i]);
- }
- for (unsigned int i = 0; i < dim; ++i) {
- double gradient = coef_conv * exp( -dim * this->get_time() * pow(M_PI,2) );
- for (unsigned int j = 0; j < dim; ++j) {
- if (i == j) {
- gradient *= cos(M_PI * p[j]);
- } else {
- gradient *= sin(M_PI * p[j]);
- }
- }
- return_value += gradient;
- }
- return return_value;
- }
- };
- template <int dim>
- class InitialCondition : public Function<dim> {
- public:
- InitialCondition() : Function<dim>() { }
- virtual double value(const Point<dim> &p, const unsigned int component = 0) const {
- double return_value = 1.0;
- for (int i = 0; i < dim; ++i) return_value *= sin(M_PI * p[i]);
- return return_value;
- }
- };
- template <int dim>
- class ExactSolution : public Function<dim> {
- public:
- ExactSolution() : Function<dim>() {
- }
- virtual double value(const Point<dim> &p, const unsigned int component = 0) const {
- double return_value = exp( -dim * pow(M_PI,2) * this->get_time() );
- for (int i = 0; i < dim; ++i) return_value *= sin(M_PI * p[i]);
- return return_value;
- }
- virtual Tensor<1, dim> gradient(const Point<dim> &p, const unsigned int component = 0) const {
- Tensor<1, dim> return_value;
- for (unsigned int i = 0; i < dim; ++i) {
- return_value[i] = M_PI * exp( -dim * this->get_time() *pow(M_PI,2) );
- for (unsigned int j = 0; j < dim; ++j) {
- if (i == j) {
- return_value[i] *= cos(M_PI * p[j]);
- } else {
- return_value[i] *= sin(M_PI * p[j]);
- }
- }
- }
- return return_value;
- }
- };
- template <int dim>
- class HybridPoissonProblem {
- public:
- HybridPoissonProblem(const unsigned int degree) :
- degree(degree), fe_local(degree), dof_handler_local(triangulation), fe(degree), dof_handler(triangulation) {
- }
- void run(const int refinements, ConvergenceTable &convergence_table, const double final_time ) {
- double current_time = 0.0;
- InitialCondition<dim> initial_condition;
- make_grid_and_dofs( refinements, current_time );
- VectorTools::interpolate( dof_handler_local, initial_condition, solution_local );
- // DataOut<dim> data_out;
- // data_out.attach_dof_handler( dof_handler_local );
- // data_out.add_data_vector( solution_local_last, "inicial" );
- // data_out.build_patches();
- // std::string file_name = "inicial.vtk";
- // std::ofstream output(file_name.c_str());
- // data_out.write_vtk(output);
- while( current_time < final_time ) {
- current_time += dt;
- assemble_system( true, current_time);
- change_boundary( current_time );
- solve();
- assemble_system( false, current_time );
- // solution_local_last = solution_local; /// Altera solucao por solucao anterior
- std::cout << " Current time: " << current_time << std::endl;
- system_rhs.reinit(dof_handler.n_dofs());
- system_matrix.reinit(sparsity_pattern);
- }
- ExactSolution<dim> solution_function;
- solution_function.set_time( current_time );
- output_results(refinements);
- compute_errors(convergence_table, current_time);
- }
- private:
- const unsigned int degree;
- const double epsilon = 1.0;
- double h_mesh;
- double dt;
- Triangulation<dim> triangulation;
- FE_DGQ<dim> fe_local;
- DoFHandler<dim> dof_handler_local;
- Vector<double> solution_local;
- Vector<double> solution_local_last;
- FE_FaceQ<dim> fe;
- DoFHandler<dim> dof_handler;
- Vector<double> solution;
- Vector<double> system_rhs;
- SparsityPattern sparsity_pattern;
- SparseMatrix<double> system_matrix;
- void change_boundary( const double current_time ){
- std::map<types::global_dof_index,double> dir_boundary_values;
- ExactSolution<dim> solution_function;
- solution_function.set_time( current_time );
- VectorTools::interpolate_boundary_values( dof_handler, 0, solution_function, dir_boundary_values);
- MatrixTools::apply_boundary_values(dir_boundary_values, system_matrix, solution, system_rhs);
- // std::map<types::boundary_id, const Function<dim> *> boundary_functions;
- // ExactSolution<dim> solution_function;
- // solution_function.set_time(current_time);
- // boundary_functions[0] = &solution_function;
- // VectorTools::project_boundary_values(dof_handler, boundary_functions, QGauss < dim - 1 > (fe.degree + 1), constraints);
- }
- void make_grid_and_dofs(int i, const double current_time ) {
- GridGenerator::hyper_cube(triangulation, 0, 1.0);
- triangulation.refine_global(i);
- h_mesh = GridTools::maximal_cell_diameter(triangulation);
- dt = std::pow( h_mesh, degree + 1 );
- dof_handler.distribute_dofs(fe);
- dof_handler_local.distribute_dofs(fe_local);
- std::cout << "Number of active cells: " << triangulation.n_active_cells() << std::endl
- << "Total number of cells: " << triangulation.n_cells() << std::endl
- << "Number of degrees of freedom for the multiplier: " << dof_handler.n_dofs() << std::endl << std::endl;
- solution.reinit(dof_handler.n_dofs());
- solution_local.reinit(dof_handler_local.n_dofs());
- solution_local_last.reinit(dof_handler_local.n_dofs());
- DynamicSparsityPattern dsp(dof_handler.n_dofs());
- DoFTools::make_sparsity_pattern( dof_handler, dsp );
- sparsity_pattern.copy_from(dsp);
- system_rhs.reinit(dof_handler.n_dofs());
- system_matrix.reinit(sparsity_pattern);
- // DoFTools::make_hanging_node_constraints(dof_handler, constraints);
- }
- void assemble_system(bool globalProblem , const double current_time) {
- QGauss < dim > quadrature_formula(degree + 2);
- QGauss < dim - 1 > face_quadrature_formula(degree + 2);
- FEValues<dim> fe_values_local(fe_local, quadrature_formula, update_values | update_gradients | update_quadrature_points | update_JxW_values);
- FEFaceValues<dim> fe_face_values(fe, face_quadrature_formula, update_values | update_normal_vectors | update_quadrature_points | update_JxW_values);
- FEFaceValues<dim> fe_face_values_local(fe_local, face_quadrature_formula, update_values | update_gradients | update_normal_vectors | update_quadrature_points | update_JxW_values);
- const unsigned int dofs_local_per_cell = fe_local.dofs_per_cell;
- const unsigned int n_q_points = quadrature_formula.size();
- const unsigned int n_face_q_points = face_quadrature_formula.size();
- std::vector<types::global_dof_index> dof_indices(fe.dofs_per_cell);
- FullMatrix<double> A_matrix(dofs_local_per_cell, dofs_local_per_cell);
- FullMatrix<double> B_matrix(dofs_local_per_cell, fe.dofs_per_cell);
- FullMatrix<double> BT_matrix(fe.dofs_per_cell, dofs_local_per_cell);
- FullMatrix<double> C_matrix(fe.dofs_per_cell, fe.dofs_per_cell);
- Vector<double> F_vector(dofs_local_per_cell);
- Vector<double> U_vector(dofs_local_per_cell);
- Vector<double> cell_vector(fe.dofs_per_cell);
- FullMatrix<double> aux_matrix(dofs_local_per_cell, fe.dofs_per_cell);
- Vector<double> aux_vector(dofs_local_per_cell);
- std::vector<double> mult_values(face_quadrature_formula.size());
- std::vector<double> st_values(n_q_points);
- std::vector<double> prev_solution( n_q_points );
- std::vector<double> boundary_values(n_face_q_points);
- for (const auto &cell : dof_handler.active_cell_iterators()) {
- Tensor<1, dim> b_velocity;
- for( int i = 0; i < dim; i++)
- b_velocity[i] = coef_conv;
- const double beta_stab = degree*degree*100/h_mesh ;
- typename DoFHandler<dim>::active_cell_iterator loc_cell(&triangulation, cell->level(), cell->index(), &dof_handler_local);
- fe_values_local.reinit(loc_cell);
- A_matrix = 0.;
- F_vector = 0.;
- B_matrix = 0.;
- BT_matrix = 0.;
- C_matrix = 0.;
- U_vector = 0.;
- SourceTerm<dim> source_term;
- source_term.set_time( current_time );
- source_term.value_list(fe_values_local.get_quadrature_points(), st_values);
- fe_values_local.get_function_values( solution_local , prev_solution );
- for (unsigned int q = 0; q < n_q_points; ++q) {
- const double JxW = fe_values_local.JxW(q);
- for (unsigned int i = 0; i < dofs_local_per_cell; ++i) {
- const double phi_i_u = fe_values_local.shape_value(i, q);
- const Tensor<1, dim> grad_phi_i_u = fe_values_local.shape_grad(i,q);
- for (unsigned int j = 0; j < dofs_local_per_cell; ++j) {
- const double phi_j_u = fe_values_local.shape_value(j, q);
- const Tensor<1, dim> grad_phi_j_u = fe_values_local.shape_grad(j, q);
- A_matrix(i, j) += ( dt*epsilon * grad_phi_j_u * grad_phi_i_u // < grad(u) , grad(v) >
- + dt*b_velocity*grad_phi_j_u * phi_i_u // < b*grad(u) , v >
- + coef_reat * phi_j_u * phi_i_u // < u , v > / dt
- ) * JxW ;
- }
- F_vector(i) += (dt*phi_i_u * st_values[q] + phi_i_u * prev_solution[q]/dt ) * JxW;
- }
- }
- /// Loop nas faces dos elementos
- for (unsigned int face_n = 0; face_n < GeometryInfo<dim>::faces_per_cell; ++face_n) {
- fe_face_values.reinit(cell, face_n);
- fe_face_values_local.reinit(loc_cell, face_n);
- for (unsigned int q = 0; q < n_face_q_points; ++q) {
- const double JxW = fe_face_values.JxW(q);
- const Tensor<1, dim> normal = fe_face_values.normal_vector(q);
- for (unsigned int i = 0; i < dofs_local_per_cell; ++i){
- const Tensor<1, dim> grad_phi_i_u = fe_face_values_local.shape_grad(i, q);
- const double phi_i_u = fe_face_values_local.shape_value(i,q);
- for (unsigned int j = 0; j < dofs_local_per_cell; ++j) {
- const Tensor<1, dim> grad_phi_j_u = fe_face_values_local.shape_grad(j, q);
- const double phi_j_u = fe_face_values_local.shape_value(j,q);
- A_matrix(i, j) += (- phi_j_u * grad_phi_i_u*normal
- - grad_phi_j_u*normal * phi_i_u
- + beta_stab * phi_j_u * phi_i_u
- + phi_j_u * fmax(-b_velocity * normal,0) * phi_i_u // <u,[b.n]-v>
- ) * dt * JxW ;
- }
- }
- }
- }
- if (globalProblem) {
- /// Loop nas faces dos elementos
- for (unsigned int face_n = 0; face_n < GeometryInfo<dim>::faces_per_cell; ++face_n) {
- fe_face_values.reinit(cell, face_n);
- fe_face_values_local.reinit(loc_cell, face_n);
- for (unsigned int q = 0; q < n_face_q_points; ++q) {
- const double JxW = fe_face_values.JxW(q);
- const Tensor<1, dim> normal = fe_face_values.normal_vector(q);
- for (unsigned int i = 0; i < dofs_local_per_cell; ++i) {
- const Tensor<1, dim> grad_phi_i_u = fe_face_values_local.shape_grad(i,q);
- const double phi_i_u = fe_face_values_local.shape_value(i,q);
- for (unsigned int j = 0; j < fe.dofs_per_cell; ++j) {
- const double phi_j_m = fe_face_values.shape_value(j, q);
- B_matrix(i, j) += ( phi_j_m * (grad_phi_i_u * normal)
- - beta_stab * phi_j_m * phi_i_u
- - phi_j_m * fmax(-b_velocity * normal,0) * phi_i_u // <lmbda,[b.n]-v>
- ) * dt * JxW;
- }
- }
- for (unsigned int j = 0; j < dofs_local_per_cell; ++j) {
- const Tensor<1, dim> grad_phi_j_u = fe_face_values_local.shape_grad(j,q);
- const double phi_j_u = fe_face_values_local.shape_value(j,q);
- for (unsigned int i = 0; i < fe.dofs_per_cell; ++i) {
- const double phi_i_m = fe_face_values.shape_value(i, q);
- BT_matrix(i, j) += ( phi_i_m * (grad_phi_j_u * normal)
- - beta_stab * phi_i_m * phi_j_u
- - phi_i_m * fmax(b_velocity * normal,0) * phi_j_u // <lmbda,[b.n]-v>
- ) * JxW;
- }
- }
- for (unsigned int i = 0; i < fe.dofs_per_cell; ++i) {
- const double phi_i_m = fe_face_values.shape_value(i, q);
- for (unsigned int j = 0; j < fe.dofs_per_cell; ++j) {
- const double phi_j_m = fe_face_values.shape_value(j, q);
- /// Negativo para facilitar a condensacao estatica
- C_matrix(i, j) -= ( beta_stab * phi_j_m * phi_i_m
- + phi_j_m * fmax(b_velocity * normal,0) * phi_i_m
- ) * JxW;
- }
- }
- }
- }
- } else {
- for (unsigned int face_n = 0; face_n < GeometryInfo<dim>::faces_per_cell; ++face_n) {
- fe_face_values.reinit(cell, face_n);
- fe_face_values_local.reinit(loc_cell, face_n);
- // solution_function.value_list(fe_face_values.get_quadrature_points(), mult_values); // Rotina0
- fe_face_values.get_function_values( solution, mult_values);
- for (unsigned int q = 0; q < n_face_q_points; ++q) {
- const double JxW = fe_face_values_local.JxW(q);
- const Tensor<1, dim> normal = fe_face_values_local.normal_vector(q);
- for (unsigned int i = 0; i < dofs_local_per_cell; ++i) {
- const Tensor<1, dim> grad_phi_i_u = fe_face_values_local.shape_grad(i,q);
- const double phi_i_u = fe_face_values_local.shape_value(i, q);
- F_vector(i) += (- grad_phi_i_u * normal
- + beta_stab * phi_i_u
- + fmax(-b_velocity * normal,0) * phi_i_u
- ) * dt * mult_values[q] * JxW;
- }
- }
- }
- }
- A_matrix.gauss_jordan(); // A = A^{-1}
- if (globalProblem) {
- A_matrix.vmult(aux_vector, F_vector, false); // A^{-1} * F
- BT_matrix.vmult(cell_vector, aux_vector, false); // B.T * A^{-1} * F
- A_matrix.mmult(aux_matrix, B_matrix, false); // A^{-1} * B
- BT_matrix.mmult(C_matrix, aux_matrix, true); // -C + B.T * A^{-1} * B
- cell->get_dof_indices(dof_indices);
- std::vector<types::global_dof_index> local_dof_indices(fe.dofs_per_cell);
- cell->get_dof_indices(local_dof_indices);
- for (unsigned int i = 0; i < fe.dofs_per_cell; ++i) {
- for (unsigned int j = 0; j < fe.dofs_per_cell; ++j) {
- system_matrix.add(local_dof_indices[i], local_dof_indices[j], C_matrix(i, j));
- }
- system_rhs(local_dof_indices[i]) += cell_vector(i);
- }
- } else {
- A_matrix.vmult(U_vector, F_vector, false); // A^{-1} * F
- loc_cell->set_dof_values(U_vector, solution_local);
- }
- }
- }
- void solve() {
- PreconditionJacobi<SparseMatrix<double> > precondition;
- precondition.initialize(system_matrix, .6);
- SolverControl solver_control( system_matrix.m()*10, 1e-11 * system_rhs.l2_norm() );
- SolverBicgstab solver(solver_control);
- solver.solve(system_matrix, solution, system_rhs, precondition);
- std::cout << std::endl << " Number of BiCGStab iterations: " << solver_control.last_step() << std::endl;
- }
- // void 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;
- // }
- void output_results(const unsigned int refinements) const {
- DataOut<dim> data_out;
- data_out.attach_dof_handler(dof_handler_local);
- data_out.add_data_vector(solution_local, "solution");
- data_out.build_patches();
- std::string file_name = "solution_" + dealii::Utilities::to_string(refinements, 0) + ".vtk";
- std::ofstream output(file_name.c_str());
- data_out.write_vtk(output);
- }
- void compute_errors(ConvergenceTable &convergence_table, const double current_time) const {
- ExactSolution<dim> exact_solution;
- exact_solution.set_time( current_time );
- Vector<double> cellwise_errors(triangulation.n_active_cells());
- QGauss<dim> quadrature_formula(degree + 2);
- Vector<double> elementwise_l2_errors;
- VectorTools::integrate_difference(dof_handler_local, solution_local, exact_solution, cellwise_errors, quadrature_formula, VectorTools::L2_norm );
- double L2_error = VectorTools::compute_global_error(triangulation, cellwise_errors, VectorTools::L2_norm);
- Vector<double> elementwise_h1_errors;
- VectorTools::integrate_difference(dof_handler_local, solution_local, exact_solution, cellwise_errors, quadrature_formula, VectorTools::H1_norm );
- double H1_error = VectorTools::compute_global_error(triangulation, cellwise_errors, VectorTools::H1_norm);
- convergence_table.add_value("cells", triangulation.n_active_cells());
- convergence_table.add_value("L2", L2_error);
- convergence_table.add_value("H1", H1_error);
- }
- };
- }
- int main() {
- using namespace dealii;
- using namespace PoissonProblem;
- const int dim = 2;
- const int degree = 1;
- const double final_time = 0.5;
- ConvergenceTable convergence_table;
- for (int refinement = 1; refinement < 5; ++refinement) {
- std::cout << " --- Refinement #" << refinement << " --- " << std::endl;
- HybridPoissonProblem<dim> hyb_poisson(degree);
- hyb_poisson.run( refinement, convergence_table, final_time );
- }
- convergence_table.set_precision("L2", 3);
- convergence_table.set_scientific("L2", true);
- convergence_table.evaluate_convergence_rates("L2", "cells", ConvergenceTable::reduction_rate_log2, dim);
- convergence_table.set_precision("H1", 3);
- convergence_table.set_scientific("H1", true);
- convergence_table.evaluate_convergence_rates("H1", "cells", ConvergenceTable::reduction_rate_log2, dim);
- convergence_table.write_text(std::cout);
- std::ofstream tex_output("taxas.tex");
- convergence_table.write_tex(tex_output);
- std::ofstream data_output("taxas.dat");
- convergence_table.write_text(data_output);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement