From: Daniel Arndt Date: Mon, 23 Apr 2018 21:56:36 +0000 (+0200) Subject: Apply indenting script X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F40%2Fhead;p=code-gallery.git Apply indenting script --- diff --git a/CeresFE/src/ceres.cc b/CeresFE/src/ceres.cc index 914cc4e..fbd6f5a 100644 --- a/CeresFE/src/ceres.cc +++ b/CeresFE/src/ceres.cc @@ -9,22 +9,22 @@ Summary of output files: One per run: -- initial_mesh.eps : Visualization of initially imported mesh -- physical_times.txt : Columns are (1) step number corresponding to other files, (2) physical times at the time when each calculation is run in sec, (3) number of the final plasticity iteration in each timestep. Written in do_elastic_steps() for elastic steps and do_flow_step() for viscous steps +- initial_mesh.eps : Visualization of initially imported mesh +- physical_times.txt : Columns are (1) step number corresponding to other files, (2) physical times at the time when each calculation is run in sec, (3) number of the final plasticity iteration in each timestep. Written in do_elastic_steps() for elastic steps and do_flow_step() for viscous steps One per time step: -- timeXX_elastic_displacements.txt : Vtk-readable file with columns (1) x, (2) y, (3) u_x, (4) u_y, (5) P. Written in output_results() function, which is run immediately after solve(). -- timeXX_baseviscosities.txt : Columns (1) cell x, (2) cell y, (3) base viscosity in Pa s. Written in solution_stresses(). -- timeXX_surface.txt : Surface (defined as where P=0 boundary condition is applied) vertices at the beginning of timestep, except for the final timestep. Written in write_vertices() function, which is called immediately after setup_dofs() except for the final iteration, when it is called after move_mesh() +- timeXX_elastic_displacements.txt : Vtk-readable file with columns (1) x, (2) y, (3) u_x, (4) u_y, (5) P. Written in output_results() function, which is run immediately after solve(). +- timeXX_baseviscosities.txt : Columns (1) cell x, (2) cell y, (3) base viscosity in Pa s. Written in solution_stresses(). +- timeXX_surface.txt : Surface (defined as where P=0 boundary condition is applied) vertices at the beginning of timestep, except for the final timestep. Written in write_vertices() function, which is called immediately after setup_dofs() except for the final iteration, when it is called after move_mesh() One per plasticity step: -- timeXX_flowYY.txt : Same as timeXX_elastic_displacements.txt above -- timeXX_principalstressesYY.txt : Columns with sigma1 and sigma3 at each cell. Same order as timeXX_baseviscosities.txt. Written in solution_stresses(). -- timeXX_stresstensorYY.txt : Columns with components 11, 22, 33, and 13 of stress tensor at each cell. Written in solution_stresses(). -- timeXX_failurelocationsYY.txt : Gives x,y coordinates of all cells where failure occurred. Written in solution_stresses(). -- timeXX_viscositiesregYY.txt : Gives smoothed and regularized (i.e., floor and ceiling-filtered) effective viscosities. Written at end of solution_stresses(). +- timeXX_flowYY.txt : Same as timeXX_elastic_displacements.txt above +- timeXX_principalstressesYY.txt : Columns with sigma1 and sigma3 at each cell. Same order as timeXX_baseviscosities.txt. Written in solution_stresses(). +- timeXX_stresstensorYY.txt : Columns with components 11, 22, 33, and 13 of stress tensor at each cell. Written in solution_stresses(). +- timeXX_failurelocationsYY.txt : Gives x,y coordinates of all cells where failure occurred. Written in solution_stresses(). +- timeXX_viscositiesregYY.txt : Gives smoothed and regularized (i.e., floor and ceiling-filtered) effective viscosities. Written at end of solution_stresses(). */ @@ -83,2040 +83,2137 @@ One per plasticity step: // As in all programs, the namespace dealii // is included: -namespace Step22 { +namespace Step22 +{ -using namespace dealii; -using namespace arma; + using namespace dealii; + using namespace arma; -template -struct InnerPreconditioner; + template + struct InnerPreconditioner; -template<> -struct InnerPreconditioner<2> { - typedef SparseDirectUMFPACK type; -}; + template<> + struct InnerPreconditioner<2> + { + typedef SparseDirectUMFPACK type; + }; -template<> -struct InnerPreconditioner<3> { - typedef SparseILU type; -}; + template<> + struct InnerPreconditioner<3> + { + typedef SparseILU type; + }; // Auxiliary functions -template -class AuxFunctions { -public: - Tensor<2, 2> get_rotation_matrix(const std::vector > &grad_u); -}; - -template -Tensor<2, 2> AuxFunctions::get_rotation_matrix( - const std::vector > &grad_u) { - const double curl = (grad_u[1][0] - grad_u[0][1]); - - const double angle = std::atan(curl); - - const double t[2][2] = { { cos(angle), sin(angle) }, { -sin(angle), cos( - angle) } }; - return Tensor<2, 2>(t); -} + template + class AuxFunctions + { + public: + Tensor<2, 2> get_rotation_matrix(const std::vector > &grad_u); + }; + + template + Tensor<2, 2> AuxFunctions::get_rotation_matrix( + const std::vector > &grad_u) + { + const double curl = (grad_u[1][0] - grad_u[0][1]); + + const double angle = std::atan(curl); + + const double t[2][2] = { { cos(angle), sin(angle) }, { + -sin(angle), cos( + angle) + } + }; + return Tensor<2, 2>(t); + } // Class for remembering material state/properties at each quadrature point -template -struct PointHistory { - SymmetricTensor<2, dim> old_stress; - double old_phiphi_stress; - double first_eta; - double new_eta; - double G; -}; + template + struct PointHistory + { + SymmetricTensor<2, dim> old_stress; + double old_phiphi_stress; + double first_eta; + double new_eta; + double G; + }; // Primary class of this problem -template -class StokesProblem { -public: - StokesProblem(const unsigned int degree); - void run(); - -private: - void setup_dofs(); - void assemble_system(); - void solve(); - void output_results() const; - void refine_mesh(); - void solution_stesses(); - void smooth_eta_field(std::vector failing_cells); - - void setup_initial_mesh(); - void do_elastic_steps(); - void do_flow_step(); - void update_time_interval(); - void initialize_eta_and_G(); - void move_mesh(); - void do_ellipse_fits(); - void append_physical_times(int max_plastic); - void write_vertices(unsigned char); - void write_mesh(); - void setup_quadrature_point_history(); - void update_quadrature_point_history(); - - const unsigned int degree; - - Triangulation triangulation; - const MappingQ1 mapping; - FESystem fe; - DoFHandler dof_handler; - unsigned int n_u = 0, n_p = 0; - unsigned int plastic_iteration = 0; - unsigned int last_max_plasticity = 0; - - QGauss quadrature_formula; - std::vector< std::vector > > quad_viscosities; // Indices for this object are [cell][q][q coords, eta] - std::vector cell_viscosities; // This vector is only used for output, not FE computations - std::vector > quadrature_point_history; - - ConstraintMatrix constraints; - - BlockSparsityPattern sparsity_pattern; - BlockSparseMatrix system_matrix; - - BlockVector solution; - BlockVector system_rhs; - - std::shared_ptr::type> A_preconditioner; - - ellipsoid_fit ellipsoid; -}; + template + class StokesProblem + { + public: + StokesProblem(const unsigned int degree); + void run(); + + private: + void setup_dofs(); + void assemble_system(); + void solve(); + void output_results() const; + void refine_mesh(); + void solution_stesses(); + void smooth_eta_field(std::vector failing_cells); + + void setup_initial_mesh(); + void do_elastic_steps(); + void do_flow_step(); + void update_time_interval(); + void initialize_eta_and_G(); + void move_mesh(); + void do_ellipse_fits(); + void append_physical_times(int max_plastic); + void write_vertices(unsigned char); + void write_mesh(); + void setup_quadrature_point_history(); + void update_quadrature_point_history(); + + const unsigned int degree; + + Triangulation triangulation; + const MappingQ1 mapping; + FESystem fe; + DoFHandler dof_handler; + unsigned int n_u = 0, n_p = 0; + unsigned int plastic_iteration = 0; + unsigned int last_max_plasticity = 0; + + QGauss quadrature_formula; + std::vector< std::vector > > quad_viscosities; // Indices for this object are [cell][q][q coords, eta] + std::vector cell_viscosities; // This vector is only used for output, not FE computations + std::vector > quadrature_point_history; + + ConstraintMatrix constraints; + + BlockSparsityPattern sparsity_pattern; + BlockSparseMatrix system_matrix; + + BlockVector solution; + BlockVector system_rhs; + + std::shared_ptr::type> A_preconditioner; + + ellipsoid_fit ellipsoid; + }; // Class for boundary conditions and rhs -template -class BoundaryValuesP: public Function { -public: - BoundaryValuesP() : - Function(dim + 1) { - } - - virtual double value(const Point &p, - const unsigned int component = 0) const; - - virtual void vector_value(const Point &p, Vector &value) const; -}; - -template -double BoundaryValuesP::value(const Point &p, - const unsigned int component) const { - Assert(component < this->n_components, - ExcIndexRange (component, 0, this->n_components)); - - Assert(p[0] >= -10, ExcLowerRange (p[0], 0)); //value of -10 is to permit some small numerical error moving nodes left of x=0; a << value is in fact sufficient - - return 0; -} - -template -void BoundaryValuesP::vector_value(const Point &p, - Vector &values) const { - for (unsigned int c = 0; c < this->n_components; ++c) - values(c) = BoundaryValuesP::value(p, c); -} - -template -class RightHandSide: public Function { -public: - RightHandSide () : Function(dim+1) {} + template + class BoundaryValuesP: public Function + { + public: + BoundaryValuesP() : + Function(dim + 1) + { + } + + virtual double value(const Point &p, + const unsigned int component = 0) const; + + virtual void vector_value(const Point &p, Vector &value) const; + }; + + template + double BoundaryValuesP::value(const Point &p, + const unsigned int component) const + { + Assert(component < this->n_components, + ExcIndexRange (component, 0, this->n_components)); + + Assert(p[0] >= -10, ExcLowerRange (p[0], 0)); //value of -10 is to permit some small numerical error moving nodes left of x=0; a << value is in fact sufficient + + return 0; + } + + template + void BoundaryValuesP::vector_value(const Point &p, + Vector &values) const + { + for (unsigned int c = 0; c < this->n_components; ++c) + values(c) = BoundaryValuesP::value(p, c); + } + + template + class RightHandSide: public Function + { + public: + RightHandSide () : Function(dim+1) {} using Function::value; using Function::vector_value; using Function::vector_value_list; - virtual double value(const Point &p, const unsigned int component, - A_Grav_namespace::AnalyticGravity *aGrav) const; - - virtual void vector_value(const Point &p, Vector &value, - A_Grav_namespace::AnalyticGravity *aGrav) const; - - virtual void vector_value_list(const std::vector > &points, - std::vector > &values, - A_Grav_namespace::AnalyticGravity *aGrav) const; - -}; - -template -double RightHandSide::value(const Point &p, - const unsigned int component, - A_Grav_namespace::AnalyticGravity *aGrav) const { - - std::vector temp_vector(2); - aGrav->get_gravity(p, temp_vector); - - if (component == 0) { - return temp_vector[0] + system_parameters::omegasquared * p[0]; // * 1.2805; - } else { - if (component == 1) - return temp_vector[1]; - else - return 0; - } -} - -template -void RightHandSide::vector_value(const Point &p, - Vector &values, - A_Grav_namespace::AnalyticGravity *aGrav) const { - for (unsigned int c = 0; c < this->n_components; ++c) - values(c) = RightHandSide::value(p, c, aGrav); -} - -template -void RightHandSide::vector_value_list( - const std::vector > &points, - std::vector > &values, - A_Grav_namespace::AnalyticGravity *aGrav) const { - // check whether component is in - // the valid range is up to the - // derived class - Assert(values.size() == points.size(), - ExcDimensionMismatch(values.size(), points.size())); - - for (unsigned int i = 0; i < points.size(); ++i) - this->vector_value(points[i], values[i], aGrav); -} + virtual double value(const Point &p, const unsigned int component, + A_Grav_namespace::AnalyticGravity *aGrav) const; + + virtual void vector_value(const Point &p, Vector &value, + A_Grav_namespace::AnalyticGravity *aGrav) const; + + virtual void vector_value_list(const std::vector > &points, + std::vector > &values, + A_Grav_namespace::AnalyticGravity *aGrav) const; + + }; + + template + double RightHandSide::value(const Point &p, + const unsigned int component, + A_Grav_namespace::AnalyticGravity *aGrav) const + { + + std::vector temp_vector(2); + aGrav->get_gravity(p, temp_vector); + + if (component == 0) + { + return temp_vector[0] + system_parameters::omegasquared * p[0]; // * 1.2805; + } + else + { + if (component == 1) + return temp_vector[1]; + else + return 0; + } + } + + template + void RightHandSide::vector_value(const Point &p, + Vector &values, + A_Grav_namespace::AnalyticGravity *aGrav) const + { + for (unsigned int c = 0; c < this->n_components; ++c) + values(c) = RightHandSide::value(p, c, aGrav); + } + + template + void RightHandSide::vector_value_list( + const std::vector > &points, + std::vector > &values, + A_Grav_namespace::AnalyticGravity *aGrav) const + { + // check whether component is in + // the valid range is up to the + // derived class + Assert(values.size() == points.size(), + ExcDimensionMismatch(values.size(), points.size())); + + for (unsigned int i = 0; i < points.size(); ++i) + this->vector_value(points[i], values[i], aGrav); + } // Class for linear solvers and preconditioners -template -class InverseMatrix: public Subscriptor { -public: - InverseMatrix(const Matrix &m, const Preconditioner &preconditioner); + template + class InverseMatrix: public Subscriptor + { + public: + InverseMatrix(const Matrix &m, const Preconditioner &preconditioner); - void vmult(Vector &dst, const Vector &src) const; + void vmult(Vector &dst, const Vector &src) const; -private: - const SmartPointer matrix; - const SmartPointer preconditioner; -}; + private: + const SmartPointer matrix; + const SmartPointer preconditioner; + }; -template -InverseMatrix::InverseMatrix(const Matrix &m, - const Preconditioner &preconditioner) : - matrix(&m), preconditioner(&preconditioner) { -} + template + InverseMatrix::InverseMatrix(const Matrix &m, + const Preconditioner &preconditioner) : + matrix(&m), preconditioner(&preconditioner) + { + } -template -void InverseMatrix::vmult(Vector &dst, - const Vector &src) const { - SolverControl solver_control(1000 * src.size(), 1e-9 * src.l2_norm()); + template + void InverseMatrix::vmult(Vector &dst, + const Vector &src) const + { + SolverControl solver_control(1000 * src.size(), 1e-9 * src.l2_norm()); - SolverCG<> cg(solver_control); + SolverCG<> cg(solver_control); - dst = 0; + dst = 0; - cg.solve(*matrix, dst, src, *preconditioner); -} + cg.solve(*matrix, dst, src, *preconditioner); + } // Class for the SchurComplement -template -class SchurComplement: public Subscriptor { -public: - SchurComplement(const BlockSparseMatrix &system_matrix, - const InverseMatrix, Preconditioner> &A_inverse); - - void vmult(Vector &dst, const Vector &src) const; - -private: - const SmartPointer > system_matrix; - const SmartPointer, Preconditioner> > A_inverse; - - mutable Vector tmp1, tmp2; -}; - -template -SchurComplement::SchurComplement( - const BlockSparseMatrix &system_matrix, - const InverseMatrix, Preconditioner> &A_inverse) : - system_matrix(&system_matrix), A_inverse(&A_inverse), tmp1( - system_matrix.block(0, 0).m()), tmp2( - system_matrix.block(0, 0).m()) { -} - -template -void SchurComplement::vmult(Vector &dst, - const Vector &src) const { - system_matrix->block(0, 1).vmult(tmp1, src); - A_inverse->vmult(tmp2, tmp1); - system_matrix->block(1, 0).vmult(dst, tmp2); -} + template + class SchurComplement: public Subscriptor + { + public: + SchurComplement(const BlockSparseMatrix &system_matrix, + const InverseMatrix, Preconditioner> &A_inverse); + + void vmult(Vector &dst, const Vector &src) const; + + private: + const SmartPointer > system_matrix; + const SmartPointer, Preconditioner> > A_inverse; + + mutable Vector tmp1, tmp2; + }; + + template + SchurComplement::SchurComplement( + const BlockSparseMatrix &system_matrix, + const InverseMatrix, Preconditioner> &A_inverse) : + system_matrix(&system_matrix), A_inverse(&A_inverse), tmp1( + system_matrix.block(0, 0).m()), tmp2( + system_matrix.block(0, 0).m()) + { + } + + template + void SchurComplement::vmult(Vector &dst, + const Vector &src) const + { + system_matrix->block(0, 1).vmult(tmp1, src); + A_inverse->vmult(tmp2, tmp1); + system_matrix->block(1, 0).vmult(dst, tmp2); + } // StokesProblem::StokesProblem -template -StokesProblem::StokesProblem(const unsigned int degree) : - degree(degree), - triangulation(Triangulation::maximum_smoothing), - mapping(), - fe(FE_Q(degree + 1), dim, FE_Q(degree), 1), - dof_handler(triangulation), - quadrature_formula(degree + 2), - ellipsoid(&triangulation) - {} + template + StokesProblem::StokesProblem(const unsigned int degree) : + degree(degree), + triangulation(Triangulation::maximum_smoothing), + mapping(), + fe(FE_Q(degree + 1), dim, FE_Q(degree), 1), + dof_handler(triangulation), + quadrature_formula(degree + 2), + ellipsoid(&triangulation) + {} // Set up dofs -template -void StokesProblem::setup_dofs() { - A_preconditioner.reset(); - system_matrix.clear(); + template + void StokesProblem::setup_dofs() + { + A_preconditioner.reset(); + system_matrix.clear(); - dof_handler.distribute_dofs(fe); - DoFRenumbering::Cuthill_McKee(dof_handler); + dof_handler.distribute_dofs(fe); + DoFRenumbering::Cuthill_McKee(dof_handler); - std::vector block_component(dim + 1, 0); - block_component[dim] = 1; - DoFRenumbering::component_wise(dof_handler, block_component); + std::vector block_component(dim + 1, 0); + block_component[dim] = 1; + DoFRenumbering::component_wise(dof_handler, block_component); //========================================Apply Boundary Conditions===================================== - { - constraints.clear(); - std::vector component_maskP(dim + 1, false); - component_maskP[dim] = true; - DoFTools::make_hanging_node_constraints(dof_handler, constraints); - VectorTools::interpolate_boundary_values(dof_handler, 1, - BoundaryValuesP(), constraints, component_maskP); - } - { - std::set no_normal_flux_boundaries; - no_normal_flux_boundaries.insert(99); - VectorTools::compute_no_normal_flux_constraints(dof_handler, 0, - no_normal_flux_boundaries, constraints); - } - - constraints.close(); - - std::vector dofs_per_block(2); - DoFTools::count_dofs_per_block(dof_handler, dofs_per_block, - block_component); - n_u = dofs_per_block[0]; - n_p = dofs_per_block[1]; - - std::cout << " Number of active cells: " << triangulation.n_active_cells() - << std::endl << " Number of degrees of freedom: " - << dof_handler.n_dofs() << " (" << n_u << '+' << n_p << ')' - << std::endl; - - { - BlockDynamicSparsityPattern csp(2, 2); - - csp.block(0, 0).reinit(n_u, n_u); - csp.block(1, 0).reinit(n_p, n_u); - csp.block(0, 1).reinit(n_u, n_p); - csp.block(1, 1).reinit(n_p, n_p); - - csp.collect_sizes(); - - DoFTools::make_sparsity_pattern(dof_handler, csp, constraints, false); - sparsity_pattern.copy_from(csp); - } - - system_matrix.reinit(sparsity_pattern); - - solution.reinit(2); - solution.block(0).reinit(n_u); - solution.block(1).reinit(n_p); - solution.collect_sizes(); - - system_rhs.reinit(2); - system_rhs.block(0).reinit(n_u); - system_rhs.block(1).reinit(n_p); - system_rhs.collect_sizes(); - -} + { + constraints.clear(); + std::vector component_maskP(dim + 1, false); + component_maskP[dim] = true; + DoFTools::make_hanging_node_constraints(dof_handler, constraints); + VectorTools::interpolate_boundary_values(dof_handler, 1, + BoundaryValuesP(), constraints, component_maskP); + } + { + std::set no_normal_flux_boundaries; + no_normal_flux_boundaries.insert(99); + VectorTools::compute_no_normal_flux_constraints(dof_handler, 0, + no_normal_flux_boundaries, constraints); + } + + constraints.close(); + + std::vector dofs_per_block(2); + DoFTools::count_dofs_per_block(dof_handler, dofs_per_block, + block_component); + n_u = dofs_per_block[0]; + n_p = dofs_per_block[1]; + + std::cout << " Number of active cells: " << triangulation.n_active_cells() + << std::endl << " Number of degrees of freedom: " + << dof_handler.n_dofs() << " (" << n_u << '+' << n_p << ')' + << std::endl; + + { + BlockDynamicSparsityPattern csp(2, 2); + + csp.block(0, 0).reinit(n_u, n_u); + csp.block(1, 0).reinit(n_p, n_u); + csp.block(0, 1).reinit(n_u, n_p); + csp.block(1, 1).reinit(n_p, n_p); + + csp.collect_sizes(); + + DoFTools::make_sparsity_pattern(dof_handler, csp, constraints, false); + sparsity_pattern.copy_from(csp); + } + + system_matrix.reinit(sparsity_pattern); + + solution.reinit(2); + solution.block(0).reinit(n_u); + solution.block(1).reinit(n_p); + solution.collect_sizes(); + + system_rhs.reinit(2); + system_rhs.block(0).reinit(n_u); + system_rhs.block(1).reinit(n_p); + system_rhs.collect_sizes(); + + } // Viscosity and Shear modulus functions -template -class Rheology { -public: - double get_eta(double &r, double &z); - double get_G(unsigned int mat_id); - -private: - std::vector get_manual_eta_profile(); - -}; - -template -std::vector Rheology::get_manual_eta_profile() -{ - vector etas; - - for(unsigned int i=0; i < system_parameters::sizeof_depths_eta; i++) - { - etas.push_back(system_parameters::depths_eta[i]); - etas.push_back(system_parameters::eta_kinks[i]); - } - return etas; -} - -template -double Rheology::get_eta(double &r, double &z) -{ - // compute local depth - double ecc = system_parameters::q_axes[0] / system_parameters::p_axes[0]; - double Rminusr = system_parameters::q_axes[0] - system_parameters::p_axes[0]; - double approx_a = std::sqrt(r * r + z * z * ecc * ecc); - double group1 = r * r + z * z - Rminusr * Rminusr; - - double a0 = approx_a; - double error = 10000; - // While loop finds the a axis of the "isodepth" ellipse for which the input point is on the surface. - // An "isodepth" ellipse is defined as one whose axes a,b are related to the global axes A, B by: A-h = B-h - - if ((r > system_parameters::q_axes[0] - system_parameters::depths_eta.back()) || - (z > system_parameters::p_axes[0] - system_parameters::depths_eta.back())) - { - - double eps = 10.0; - while (error >= eps) - { - double a02 = a0 * a0; - double a03 = a0 * a02; - double a04 = a0 * a03; - double fofa = a04 - (2 * Rminusr * a03) - (group1 * a02) - + (2 * r * r * Rminusr * a0) - (r * r * Rminusr * Rminusr); - double fprimeofa = 4 * a03 - (6 * Rminusr * a02) - (2 * group1 * a0) - + (2 * r * r * Rminusr); - double deltaa = -fofa / fprimeofa; - a0 += deltaa; - error = std::abs(deltaa); -// cout << "error = " << error << endl; - } - } - else - { - a0 = 0.0; - } - - double local_depth = system_parameters::q_axes[0] - a0; - if (local_depth < 0) - local_depth = 0; - - if (local_depth > system_parameters::depths_eta.back()) - { - if (system_parameters::eta_kinks.back() < system_parameters::eta_floor) - return system_parameters::eta_floor; - else if (system_parameters::eta_kinks.back() > system_parameters::eta_ceiling) - return system_parameters::eta_ceiling; - else - return system_parameters::eta_kinks.back(); - } - - std::vector viscosity_function = get_manual_eta_profile(); - - unsigned int n_visc_kinks = viscosity_function.size() / 2; - - //find the correct interval to do the interpolation in - int n_minus_one = -1; - for (unsigned int n = 1; n <= n_visc_kinks; n++) { - unsigned int ndeep = 2 * n - 2; - unsigned int nshallow = 2 * n; - if (local_depth >= viscosity_function[ndeep] && local_depth <= viscosity_function[nshallow]) - n_minus_one = ndeep; - } - - //find the viscosity interpolation - if (n_minus_one == -1) - return system_parameters::eta_ceiling; - else { - double visc_exponent = - (viscosity_function[n_minus_one] - - local_depth) - / (viscosity_function[n_minus_one] - - viscosity_function[n_minus_one + 2]); - double visc_base = viscosity_function[n_minus_one + 3] - / viscosity_function[n_minus_one + 1]; - // This is the true viscosity given the thermal profile - double true_eta = viscosity_function[n_minus_one + 1] * std::pow(visc_base, visc_exponent); - - // Implement latitude-dependence viscosity - if(system_parameters::lat_dependence) - { - double lat = 180 / PI * std::atan(z / r); - if(lat > 80) - lat = 80; - double T_eq = 155; - double T_surf = T_eq * std::sqrt( std::sqrt( std::cos( PI / 180 * lat ) ) ); - double taper_depth = 40000; - double surface_taper = (taper_depth - local_depth) / taper_depth; - if(surface_taper < 0) - surface_taper = 0; - double log_eta_contrast = surface_taper * system_parameters::eta_Ea * 52.5365 * (T_eq - T_surf) / T_eq / T_surf; - true_eta *= std::pow(10, log_eta_contrast); - } - - if(true_eta > system_parameters::eta_ceiling) - return system_parameters::eta_ceiling; - else - if(true_eta < system_parameters::eta_floor) - return system_parameters::eta_floor; - else - return true_eta; - } -} - - -template -double Rheology::get_G(unsigned int mat_id) -{ - return system_parameters::G[mat_id]; -} + template + class Rheology + { + public: + double get_eta(double &r, double &z); + double get_G(unsigned int mat_id); + + private: + std::vector get_manual_eta_profile(); + + }; + + template + std::vector Rheology::get_manual_eta_profile() + { + vector etas; + + for (unsigned int i=0; i < system_parameters::sizeof_depths_eta; i++) + { + etas.push_back(system_parameters::depths_eta[i]); + etas.push_back(system_parameters::eta_kinks[i]); + } + return etas; + } + + template + double Rheology::get_eta(double &r, double &z) + { + // compute local depth + double ecc = system_parameters::q_axes[0] / system_parameters::p_axes[0]; + double Rminusr = system_parameters::q_axes[0] - system_parameters::p_axes[0]; + double approx_a = std::sqrt(r * r + z * z * ecc * ecc); + double group1 = r * r + z * z - Rminusr * Rminusr; + + double a0 = approx_a; + double error = 10000; + // While loop finds the a axis of the "isodepth" ellipse for which the input point is on the surface. + // An "isodepth" ellipse is defined as one whose axes a,b are related to the global axes A, B by: A-h = B-h + + if ((r > system_parameters::q_axes[0] - system_parameters::depths_eta.back()) || + (z > system_parameters::p_axes[0] - system_parameters::depths_eta.back())) + { + + double eps = 10.0; + while (error >= eps) + { + double a02 = a0 * a0; + double a03 = a0 * a02; + double a04 = a0 * a03; + double fofa = a04 - (2 * Rminusr * a03) - (group1 * a02) + + (2 * r * r * Rminusr * a0) - (r * r * Rminusr * Rminusr); + double fprimeofa = 4 * a03 - (6 * Rminusr * a02) - (2 * group1 * a0) + + (2 * r * r * Rminusr); + double deltaa = -fofa / fprimeofa; + a0 += deltaa; + error = std::abs(deltaa); +// cout << "error = " << error << endl; + } + } + else + { + a0 = 0.0; + } + + double local_depth = system_parameters::q_axes[0] - a0; + if (local_depth < 0) + local_depth = 0; + + if (local_depth > system_parameters::depths_eta.back()) + { + if (system_parameters::eta_kinks.back() < system_parameters::eta_floor) + return system_parameters::eta_floor; + else if (system_parameters::eta_kinks.back() > system_parameters::eta_ceiling) + return system_parameters::eta_ceiling; + else + return system_parameters::eta_kinks.back(); + } + + std::vector viscosity_function = get_manual_eta_profile(); + + unsigned int n_visc_kinks = viscosity_function.size() / 2; + + //find the correct interval to do the interpolation in + int n_minus_one = -1; + for (unsigned int n = 1; n <= n_visc_kinks; n++) + { + unsigned int ndeep = 2 * n - 2; + unsigned int nshallow = 2 * n; + if (local_depth >= viscosity_function[ndeep] && local_depth <= viscosity_function[nshallow]) + n_minus_one = ndeep; + } + + //find the viscosity interpolation + if (n_minus_one == -1) + return system_parameters::eta_ceiling; + else + { + double visc_exponent = + (viscosity_function[n_minus_one] + - local_depth) + / (viscosity_function[n_minus_one] + - viscosity_function[n_minus_one + 2]); + double visc_base = viscosity_function[n_minus_one + 3] + / viscosity_function[n_minus_one + 1]; + // This is the true viscosity given the thermal profile + double true_eta = viscosity_function[n_minus_one + 1] * std::pow(visc_base, visc_exponent); + + // Implement latitude-dependence viscosity + if (system_parameters::lat_dependence) + { + double lat = 180 / PI * std::atan(z / r); + if (lat > 80) + lat = 80; + double T_eq = 155; + double T_surf = T_eq * std::sqrt( std::sqrt( std::cos( PI / 180 * lat ) ) ); + double taper_depth = 40000; + double surface_taper = (taper_depth - local_depth) / taper_depth; + if (surface_taper < 0) + surface_taper = 0; + double log_eta_contrast = surface_taper * system_parameters::eta_Ea * 52.5365 * (T_eq - T_surf) / T_eq / T_surf; + true_eta *= std::pow(10, log_eta_contrast); + } + + if (true_eta > system_parameters::eta_ceiling) + return system_parameters::eta_ceiling; + else if (true_eta < system_parameters::eta_floor) + return system_parameters::eta_floor; + else + return true_eta; + } + } + + + template + double Rheology::get_G(unsigned int mat_id) + { + return system_parameters::G[mat_id]; + } // Initialize the eta and G parts of the quadrature_point_history object -template -void StokesProblem::initialize_eta_and_G() { - FEValues fe_values(fe, quadrature_formula, update_quadrature_points); + template + void StokesProblem::initialize_eta_and_G() + { + FEValues fe_values(fe, quadrature_formula, update_quadrature_points); - const unsigned int n_q_points = quadrature_formula.size(); - Rheology rheology; + const unsigned int n_q_points = quadrature_formula.size(); + Rheology rheology; - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) { - PointHistory *local_quadrature_points_history = - reinterpret_cast *>(cell->user_pointer()); - Assert( - local_quadrature_points_history >= &quadrature_point_history.front(), - ExcInternalError()); - Assert( - local_quadrature_points_history < &quadrature_point_history.back(), - ExcInternalError()); - fe_values.reinit(cell); + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + { + PointHistory *local_quadrature_points_history = + reinterpret_cast *>(cell->user_pointer()); + Assert( + local_quadrature_points_history >= &quadrature_point_history.front(), + ExcInternalError()); + Assert( + local_quadrature_points_history < &quadrature_point_history.back(), + ExcInternalError()); + fe_values.reinit(cell); - for (unsigned int q = 0; q < n_q_points; ++q) { + for (unsigned int q = 0; q < n_q_points; ++q) + { - double r_value = fe_values.quadrature_point(q)[0]; - double z_value = fe_values.quadrature_point(q)[1]; + double r_value = fe_values.quadrature_point(q)[0]; + double z_value = fe_values.quadrature_point(q)[1]; - //defines local viscosity - double local_viscosity = 0; + //defines local viscosity + double local_viscosity = 0; - local_viscosity = rheology.get_eta(r_value, z_value); + local_viscosity = rheology.get_eta(r_value, z_value); - local_quadrature_points_history[q].first_eta = local_viscosity; - local_quadrature_points_history[q].new_eta = local_viscosity; + local_quadrature_points_history[q].first_eta = local_viscosity; + local_quadrature_points_history[q].new_eta = local_viscosity; - //defines local shear modulus - double local_G = 0; + //defines local shear modulus + double local_G = 0; - unsigned int mat_id = cell->material_id(); + unsigned int mat_id = cell->material_id(); - local_G = rheology.get_G(mat_id); - local_quadrature_points_history[q].G = local_G; + local_G = rheology.get_G(mat_id); + local_quadrature_points_history[q].G = local_G; - //initializes the phi-phi stress - local_quadrature_points_history[q].old_phiphi_stress = 0; - } - } -} + //initializes the phi-phi stress + local_quadrature_points_history[q].old_phiphi_stress = 0; + } + } + } //====================== ASSEMBLE THE SYSTEM ====================== -template -void StokesProblem::assemble_system() { - system_matrix = 0; - system_rhs = 0; - - FEValues fe_values(fe, quadrature_formula, - update_values | update_quadrature_points | update_JxW_values - | update_gradients); - - const unsigned int dofs_per_cell = fe.dofs_per_cell; - - const unsigned int n_q_points = quadrature_formula.size(); - - FullMatrix local_matrix(dofs_per_cell, dofs_per_cell); - Vector local_rhs(dofs_per_cell); - - std::vector local_dof_indices(dofs_per_cell); - - // runs the gravity script function - const RightHandSide right_hand_side; - - A_Grav_namespace::AnalyticGravity * aGrav = - new A_Grav_namespace::AnalyticGravity; - std::vector grav_parameters; - grav_parameters.push_back(system_parameters::q_axes[system_parameters::present_timestep * 2 + 0]); - grav_parameters.push_back(system_parameters::p_axes[system_parameters::present_timestep * 2 + 0]); - grav_parameters.push_back(system_parameters::q_axes[system_parameters::present_timestep * 2 + 1]); - grav_parameters.push_back(system_parameters::p_axes[system_parameters::present_timestep * 2 + 1]); - grav_parameters.push_back(system_parameters::rho[0]); - grav_parameters.push_back(system_parameters::rho[1]); - - std::cout << "Body parameters are: " ; - for(int i=0; i<6; i++) - std::cout << grav_parameters[i] << " "; - std::cout << endl; - - aGrav->setup_vars(grav_parameters); - - std::vector > rhs_values(n_q_points, - Vector(dim + 1)); - - const FEValuesExtractors::Vector velocities(0); - const FEValuesExtractors::Scalar pressure(dim); - - std::vector > phi_grads_u(dofs_per_cell); - std::vector div_phi_u(dofs_per_cell); - std::vector > phi_u(dofs_per_cell); - std::vector phi_p(dofs_per_cell); - - typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(), first_cell = dof_handler.begin_active(), - endc = dof_handler.end(); - - for (; cell != endc; ++cell) { - PointHistory *local_quadrature_points_history = - reinterpret_cast *>(cell->user_pointer()); - Assert( - local_quadrature_points_history >= &quadrature_point_history.front(), - ExcInternalError()); - Assert( - local_quadrature_points_history < &quadrature_point_history.back(), - ExcInternalError()); - - double cell_area = cell->measure(); - - if(cell_area<0) - append_physical_times(-1); // This writes final line to physical_times.txt if step terminates prematurely - AssertThrow(cell_area > 0 - , - ExcInternalError()); - - - unsigned int m_id = cell->material_id(); - - //initializes the rhs vector to the correct g values - fe_values.reinit(cell); - right_hand_side.vector_value_list(fe_values.get_quadrature_points(), - rhs_values, aGrav); - - std::vector > new_viscosities(quadrature_formula.size(), Vector(dim + 1)); - - // Finds vertices where the radius is zero DIM - bool is_singular = false; - unsigned int singular_vertex_id = 0; - for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) { - if (cell->face(f)->center()[0] == 0) { - is_singular = true; - singular_vertex_id = f; - } - } - - if (is_singular == false || system_parameters::cylindrical == false) { - local_matrix = 0; - local_rhs = 0; - - // ===== outputs the local gravity - std::vector > quad_points_list(n_q_points); - quad_points_list = fe_values.get_quadrature_points(); - - if (plastic_iteration - == (system_parameters::max_plastic_iterations - 1)) { - if (cell != first_cell) { - std::ofstream fout("gravity_field.txt", std::ios::app); - fout << quad_points_list[0] << " " << rhs_values[0]; - fout.close(); - } else { - std::ofstream fout("gravity_field.txt"); - fout << quad_points_list[0] << " " << rhs_values[0]; - fout.close(); - } - } - - for (unsigned int q = 0; q < n_q_points; ++q) { - SymmetricTensor<2, dim> &old_stress = - local_quadrature_points_history[q].old_stress; - double &local_old_phiphi_stress = - local_quadrature_points_history[q].old_phiphi_stress; - double r_value = fe_values.quadrature_point(q)[0]; - - // get local density based on mat id - double local_density = system_parameters::rho[m_id]; - - //defines local viscosities - double local_viscosity = 0; - if (plastic_iteration == 0) - local_viscosity = local_quadrature_points_history[q].first_eta; - else - local_viscosity = local_quadrature_points_history[q].new_eta; - - // Define the local viscoelastic constants - double local_eta_ve = 2 - / ((1 / local_viscosity) - + (1 / local_quadrature_points_history[q].G - / system_parameters::current_time_interval)); - double local_chi_ve = 1 - / (1 - + (local_quadrature_points_history[q].G - * system_parameters::current_time_interval - / local_viscosity)); - - for (unsigned int k = 0; k < dofs_per_cell; ++k) { - phi_grads_u[k] = fe_values[velocities].symmetric_gradient(k, - q); - div_phi_u[k] = (fe_values[velocities].divergence(k, q)); - phi_u[k] = (fe_values[velocities].value(k, q)); - if (system_parameters::cylindrical == true) { - div_phi_u[k] *= (r_value); - div_phi_u[k] += (phi_u[k][0]); - } - phi_p[k] = fe_values[pressure].value(k, q); - } - - for (unsigned int i = 0; i < dofs_per_cell; ++i) { - for (unsigned int j = 0; j <= i; ++j) { - if (system_parameters::cylindrical == true) { - local_matrix(i, j) += (phi_grads_u[i] - * phi_grads_u[j] * 2 * local_eta_ve - * r_value - + 2 * phi_u[i][0] * phi_u[j][0] - * local_eta_ve / r_value - - div_phi_u[i] * phi_p[j] - * system_parameters::pressure_scale - - phi_p[i] * div_phi_u[j] - * system_parameters::pressure_scale - + phi_p[i] * phi_p[j] * r_value - * system_parameters::pressure_scale) - * fe_values.JxW(q); - } else { - local_matrix(i, j) += (phi_grads_u[i] - * phi_grads_u[j] * 2 * local_eta_ve - - div_phi_u[i] * phi_p[j] - * system_parameters::pressure_scale - - phi_p[i] * div_phi_u[j] - * system_parameters::pressure_scale - + phi_p[i] * phi_p[j]) * fe_values.JxW(q); - } - } - if (system_parameters::cylindrical == true) { - const unsigned int component_i = - fe.system_to_component_index(i).first; - local_rhs(i) += (fe_values.shape_value(i, q) - * rhs_values[q](component_i) * r_value - * local_density - - local_chi_ve * phi_grads_u[i] * old_stress - * r_value - - local_chi_ve * phi_u[i][0] - * local_old_phiphi_stress) - * fe_values.JxW(q); - } else { - const unsigned int component_i = - fe.system_to_component_index(i).first; - local_rhs(i) += fe_values.shape_value(i, q) - * rhs_values[q](component_i) * fe_values.JxW(q) - * local_density; - } - } - } - } // end of non-singular - else { - local_matrix = 0; - local_rhs = 0; - - // ===== outputs the local gravity - std::vector > quad_points_list(n_q_points); - quad_points_list = fe_values.get_quadrature_points(); - - for (unsigned int q = 0; q < n_q_points; ++q) { - const SymmetricTensor<2, dim> &old_stress = - local_quadrature_points_history[q].old_stress; - double &local_old_phiphi_stress = - local_quadrature_points_history[q].old_phiphi_stress; - double r_value = fe_values.quadrature_point(q)[0]; + template + void StokesProblem::assemble_system() + { + system_matrix = 0; + system_rhs = 0; + + FEValues fe_values(fe, quadrature_formula, + update_values | update_quadrature_points | update_JxW_values + | update_gradients); + + const unsigned int dofs_per_cell = fe.dofs_per_cell; + + const unsigned int n_q_points = quadrature_formula.size(); + + FullMatrix local_matrix(dofs_per_cell, dofs_per_cell); + Vector local_rhs(dofs_per_cell); + + std::vector local_dof_indices(dofs_per_cell); + + // runs the gravity script function + const RightHandSide right_hand_side; + + A_Grav_namespace::AnalyticGravity *aGrav = + new A_Grav_namespace::AnalyticGravity; + std::vector grav_parameters; + grav_parameters.push_back(system_parameters::q_axes[system_parameters::present_timestep * 2 + 0]); + grav_parameters.push_back(system_parameters::p_axes[system_parameters::present_timestep * 2 + 0]); + grav_parameters.push_back(system_parameters::q_axes[system_parameters::present_timestep * 2 + 1]); + grav_parameters.push_back(system_parameters::p_axes[system_parameters::present_timestep * 2 + 1]); + grav_parameters.push_back(system_parameters::rho[0]); + grav_parameters.push_back(system_parameters::rho[1]); + + std::cout << "Body parameters are: " ; + for (int i=0; i<6; i++) + std::cout << grav_parameters[i] << " "; + std::cout << endl; + + aGrav->setup_vars(grav_parameters); + + std::vector > rhs_values(n_q_points, + Vector(dim + 1)); + + const FEValuesExtractors::Vector velocities(0); + const FEValuesExtractors::Scalar pressure(dim); + + std::vector > phi_grads_u(dofs_per_cell); + std::vector div_phi_u(dofs_per_cell); + std::vector > phi_u(dofs_per_cell); + std::vector phi_p(dofs_per_cell); + + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), first_cell = dof_handler.begin_active(), + endc = dof_handler.end(); + + for (; cell != endc; ++cell) + { + PointHistory *local_quadrature_points_history = + reinterpret_cast *>(cell->user_pointer()); + Assert( + local_quadrature_points_history >= &quadrature_point_history.front(), + ExcInternalError()); + Assert( + local_quadrature_points_history < &quadrature_point_history.back(), + ExcInternalError()); + + double cell_area = cell->measure(); + + if (cell_area<0) + append_physical_times(-1); // This writes final line to physical_times.txt if step terminates prematurely + AssertThrow(cell_area > 0 + , + ExcInternalError()); + + + unsigned int m_id = cell->material_id(); + + //initializes the rhs vector to the correct g values + fe_values.reinit(cell); + right_hand_side.vector_value_list(fe_values.get_quadrature_points(), + rhs_values, aGrav); + + std::vector > new_viscosities(quadrature_formula.size(), Vector(dim + 1)); + + // Finds vertices where the radius is zero DIM + bool is_singular = false; + unsigned int singular_vertex_id = 0; + for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) + { + if (cell->face(f)->center()[0] == 0) + { + is_singular = true; + singular_vertex_id = f; + } + } + + if (is_singular == false || system_parameters::cylindrical == false) + { + local_matrix = 0; + local_rhs = 0; + + // ===== outputs the local gravity + std::vector > quad_points_list(n_q_points); + quad_points_list = fe_values.get_quadrature_points(); + + if (plastic_iteration + == (system_parameters::max_plastic_iterations - 1)) + { + if (cell != first_cell) + { + std::ofstream fout("gravity_field.txt", std::ios::app); + fout << quad_points_list[0] << " " << rhs_values[0]; + fout.close(); + } + else + { + std::ofstream fout("gravity_field.txt"); + fout << quad_points_list[0] << " " << rhs_values[0]; + fout.close(); + } + } + + for (unsigned int q = 0; q < n_q_points; ++q) + { + SymmetricTensor<2, dim> &old_stress = + local_quadrature_points_history[q].old_stress; + double &local_old_phiphi_stress = + local_quadrature_points_history[q].old_phiphi_stress; + double r_value = fe_values.quadrature_point(q)[0]; + + // get local density based on mat id + double local_density = system_parameters::rho[m_id]; + + //defines local viscosities + double local_viscosity = 0; + if (plastic_iteration == 0) + local_viscosity = local_quadrature_points_history[q].first_eta; + else + local_viscosity = local_quadrature_points_history[q].new_eta; + + // Define the local viscoelastic constants + double local_eta_ve = 2 + / ((1 / local_viscosity) + + (1 / local_quadrature_points_history[q].G + / system_parameters::current_time_interval)); + double local_chi_ve = 1 + / (1 + + (local_quadrature_points_history[q].G + * system_parameters::current_time_interval + / local_viscosity)); + + for (unsigned int k = 0; k < dofs_per_cell; ++k) + { + phi_grads_u[k] = fe_values[velocities].symmetric_gradient(k, + q); + div_phi_u[k] = (fe_values[velocities].divergence(k, q)); + phi_u[k] = (fe_values[velocities].value(k, q)); + if (system_parameters::cylindrical == true) + { + div_phi_u[k] *= (r_value); + div_phi_u[k] += (phi_u[k][0]); + } + phi_p[k] = fe_values[pressure].value(k, q); + } + + for (unsigned int i = 0; i < dofs_per_cell; ++i) + { + for (unsigned int j = 0; j <= i; ++j) + { + if (system_parameters::cylindrical == true) + { + local_matrix(i, j) += (phi_grads_u[i] + * phi_grads_u[j] * 2 * local_eta_ve + * r_value + + 2 * phi_u[i][0] * phi_u[j][0] + * local_eta_ve / r_value + - div_phi_u[i] * phi_p[j] + * system_parameters::pressure_scale + - phi_p[i] * div_phi_u[j] + * system_parameters::pressure_scale + + phi_p[i] * phi_p[j] * r_value + * system_parameters::pressure_scale) + * fe_values.JxW(q); + } + else + { + local_matrix(i, j) += (phi_grads_u[i] + * phi_grads_u[j] * 2 * local_eta_ve + - div_phi_u[i] * phi_p[j] + * system_parameters::pressure_scale + - phi_p[i] * div_phi_u[j] + * system_parameters::pressure_scale + + phi_p[i] * phi_p[j]) * fe_values.JxW(q); + } + } + if (system_parameters::cylindrical == true) + { + const unsigned int component_i = + fe.system_to_component_index(i).first; + local_rhs(i) += (fe_values.shape_value(i, q) + * rhs_values[q](component_i) * r_value + * local_density + - local_chi_ve * phi_grads_u[i] * old_stress + * r_value + - local_chi_ve * phi_u[i][0] + * local_old_phiphi_stress) + * fe_values.JxW(q); + } + else + { + const unsigned int component_i = + fe.system_to_component_index(i).first; + local_rhs(i) += fe_values.shape_value(i, q) + * rhs_values[q](component_i) * fe_values.JxW(q) + * local_density; + } + } + } + } // end of non-singular + else + { + local_matrix = 0; + local_rhs = 0; + + // ===== outputs the local gravity + std::vector > quad_points_list(n_q_points); + quad_points_list = fe_values.get_quadrature_points(); + + for (unsigned int q = 0; q < n_q_points; ++q) + { + const SymmetricTensor<2, dim> &old_stress = + local_quadrature_points_history[q].old_stress; + double &local_old_phiphi_stress = + local_quadrature_points_history[q].old_phiphi_stress; + double r_value = fe_values.quadrature_point(q)[0]; double local_density = system_parameters::rho[m_id]; - //defines local viscosities - double local_viscosity = 0; - if (plastic_iteration == 0) - { - local_viscosity = local_quadrature_points_history[q].first_eta; - } - else - local_viscosity = local_quadrature_points_history[q].new_eta; - - // Define the local viscoelastic constants - double local_eta_ve = 2 - / ((1 / local_viscosity) - + (1 / local_quadrature_points_history[q].G - / system_parameters::current_time_interval)); - double local_chi_ve = 1 - / (1 - + (local_quadrature_points_history[q].G - * system_parameters::current_time_interval - / local_viscosity)); - - for (unsigned int k = 0; k < dofs_per_cell; ++k) { - phi_grads_u[k] = fe_values[velocities].symmetric_gradient(k, - q); - div_phi_u[k] = (fe_values[velocities].divergence(k, q)); - phi_u[k] = (fe_values[velocities].value(k, q)); - if (system_parameters::cylindrical == true) { - div_phi_u[k] *= (r_value); - div_phi_u[k] += (phi_u[k][0]); - } - phi_p[k] = fe_values[pressure].value(k, q); - } - - for (unsigned int i = 0; i < dofs_per_cell; ++i) { - for (unsigned int j = 0; j <= i; ++j) { - if (system_parameters::cylindrical == true) { - local_matrix(i, j) += (phi_grads_u[i] - * phi_grads_u[j] * 2 * local_eta_ve - * r_value - + 2 * phi_u[i][0] * phi_u[j][0] - * local_eta_ve / r_value - - div_phi_u[i] * phi_p[j] - * system_parameters::pressure_scale - - phi_p[i] * div_phi_u[j] - * system_parameters::pressure_scale - + phi_p[i] * phi_p[j] * r_value - * system_parameters::pressure_scale) - * fe_values.JxW(q); - } else { - local_matrix(i, j) += (phi_grads_u[i] - * phi_grads_u[j] * 2 * local_eta_ve - - div_phi_u[i] * phi_p[j] - * system_parameters::pressure_scale - - phi_p[i] * div_phi_u[j] - * system_parameters::pressure_scale - + phi_p[i] * phi_p[j]) * fe_values.JxW(q); - } - } - if (system_parameters::cylindrical == true) { - const unsigned int component_i = - fe.system_to_component_index(i).first; - local_rhs(i) += (fe_values.shape_value(i, q) - * rhs_values[q](component_i) * r_value - * local_density - - local_chi_ve * phi_grads_u[i] * old_stress - * r_value - - local_chi_ve * phi_u[i][0] - * local_old_phiphi_stress) - * fe_values.JxW(q); - } else { - const unsigned int component_i = - fe.system_to_component_index(i).first; - local_rhs(i) += fe_values.shape_value(i, q) - * rhs_values[q](component_i) * fe_values.JxW(q) - * local_density; - } - } - } - } // end of singular - - for (unsigned int i = 0; i < dofs_per_cell; ++i) - for (unsigned int j = i + 1; j < dofs_per_cell; ++j) - local_matrix(i, j) = local_matrix(j, i); - - cell->get_dof_indices(local_dof_indices); - constraints.distribute_local_to_global(local_matrix, local_rhs, - local_dof_indices, system_matrix, system_rhs); - } - - std::cout << " Computing preconditioner..." << std::endl << std::flush; - - A_preconditioner = std::shared_ptr< - typename InnerPreconditioner::type>( - new typename InnerPreconditioner::type()); - A_preconditioner->initialize(system_matrix.block(0, 0), - typename InnerPreconditioner::type::AdditionalData()); - - delete aGrav; -} + //defines local viscosities + double local_viscosity = 0; + if (plastic_iteration == 0) + { + local_viscosity = local_quadrature_points_history[q].first_eta; + } + else + local_viscosity = local_quadrature_points_history[q].new_eta; + + // Define the local viscoelastic constants + double local_eta_ve = 2 + / ((1 / local_viscosity) + + (1 / local_quadrature_points_history[q].G + / system_parameters::current_time_interval)); + double local_chi_ve = 1 + / (1 + + (local_quadrature_points_history[q].G + * system_parameters::current_time_interval + / local_viscosity)); + + for (unsigned int k = 0; k < dofs_per_cell; ++k) + { + phi_grads_u[k] = fe_values[velocities].symmetric_gradient(k, + q); + div_phi_u[k] = (fe_values[velocities].divergence(k, q)); + phi_u[k] = (fe_values[velocities].value(k, q)); + if (system_parameters::cylindrical == true) + { + div_phi_u[k] *= (r_value); + div_phi_u[k] += (phi_u[k][0]); + } + phi_p[k] = fe_values[pressure].value(k, q); + } + + for (unsigned int i = 0; i < dofs_per_cell; ++i) + { + for (unsigned int j = 0; j <= i; ++j) + { + if (system_parameters::cylindrical == true) + { + local_matrix(i, j) += (phi_grads_u[i] + * phi_grads_u[j] * 2 * local_eta_ve + * r_value + + 2 * phi_u[i][0] * phi_u[j][0] + * local_eta_ve / r_value + - div_phi_u[i] * phi_p[j] + * system_parameters::pressure_scale + - phi_p[i] * div_phi_u[j] + * system_parameters::pressure_scale + + phi_p[i] * phi_p[j] * r_value + * system_parameters::pressure_scale) + * fe_values.JxW(q); + } + else + { + local_matrix(i, j) += (phi_grads_u[i] + * phi_grads_u[j] * 2 * local_eta_ve + - div_phi_u[i] * phi_p[j] + * system_parameters::pressure_scale + - phi_p[i] * div_phi_u[j] + * system_parameters::pressure_scale + + phi_p[i] * phi_p[j]) * fe_values.JxW(q); + } + } + if (system_parameters::cylindrical == true) + { + const unsigned int component_i = + fe.system_to_component_index(i).first; + local_rhs(i) += (fe_values.shape_value(i, q) + * rhs_values[q](component_i) * r_value + * local_density + - local_chi_ve * phi_grads_u[i] * old_stress + * r_value + - local_chi_ve * phi_u[i][0] + * local_old_phiphi_stress) + * fe_values.JxW(q); + } + else + { + const unsigned int component_i = + fe.system_to_component_index(i).first; + local_rhs(i) += fe_values.shape_value(i, q) + * rhs_values[q](component_i) * fe_values.JxW(q) + * local_density; + } + } + } + } // end of singular + + for (unsigned int i = 0; i < dofs_per_cell; ++i) + for (unsigned int j = i + 1; j < dofs_per_cell; ++j) + local_matrix(i, j) = local_matrix(j, i); + + cell->get_dof_indices(local_dof_indices); + constraints.distribute_local_to_global(local_matrix, local_rhs, + local_dof_indices, system_matrix, system_rhs); + } + + std::cout << " Computing preconditioner..." << std::endl << std::flush; + + A_preconditioner = std::shared_ptr< + typename InnerPreconditioner::type>( + new typename InnerPreconditioner::type()); + A_preconditioner->initialize(system_matrix.block(0, 0), + typename InnerPreconditioner::type::AdditionalData()); + + delete aGrav; + } //====================== SOLVER ====================== -template -void StokesProblem::solve() { - const InverseMatrix, - typename InnerPreconditioner::type> A_inverse( - system_matrix.block(0, 0), *A_preconditioner); - Vector tmp(solution.block(0).size()); + template + void StokesProblem::solve() + { + const InverseMatrix, + typename InnerPreconditioner::type> A_inverse( + system_matrix.block(0, 0), *A_preconditioner); + Vector tmp(solution.block(0).size()); - { - Vector schur_rhs(solution.block(1).size()); - A_inverse.vmult(tmp, system_rhs.block(0)); - system_matrix.block(1, 0).vmult(schur_rhs, tmp); - schur_rhs -= system_rhs.block(1); + { + Vector schur_rhs(solution.block(1).size()); + A_inverse.vmult(tmp, system_rhs.block(0)); + system_matrix.block(1, 0).vmult(schur_rhs, tmp); + schur_rhs -= system_rhs.block(1); - SchurComplement::type> schur_complement( - system_matrix, A_inverse); + SchurComplement::type> schur_complement( + system_matrix, A_inverse); - int n_iterations = system_parameters::iteration_coefficient - * solution.block(1).size(); - double tolerance_goal = system_parameters::tolerance_coefficient - * schur_rhs.l2_norm(); + int n_iterations = system_parameters::iteration_coefficient + * solution.block(1).size(); + double tolerance_goal = system_parameters::tolerance_coefficient + * schur_rhs.l2_norm(); - SolverControl solver_control(n_iterations, tolerance_goal); - SolverCG<> cg(solver_control); + SolverControl solver_control(n_iterations, tolerance_goal); + SolverCG<> cg(solver_control); - std::cout << "\nMax iterations and tolerance are: " << n_iterations - << " and " << tolerance_goal << std::endl; + std::cout << "\nMax iterations and tolerance are: " << n_iterations + << " and " << tolerance_goal << std::endl; - SparseILU preconditioner; - preconditioner.initialize(system_matrix.block(1, 1), - SparseILU::AdditionalData()); + SparseILU preconditioner; + preconditioner.initialize(system_matrix.block(1, 1), + SparseILU::AdditionalData()); - InverseMatrix, SparseILU > m_inverse( - system_matrix.block(1, 1), preconditioner); + InverseMatrix, SparseILU > m_inverse( + system_matrix.block(1, 1), preconditioner); - cg.solve(schur_complement, solution.block(1), schur_rhs, m_inverse); + cg.solve(schur_complement, solution.block(1), schur_rhs, m_inverse); - constraints.distribute(solution); + constraints.distribute(solution); - std::cout << " " << solver_control.last_step() - << " outer CG Schur complement iterations for pressure" - << std::endl; - } + std::cout << " " << solver_control.last_step() + << " outer CG Schur complement iterations for pressure" + << std::endl; + } - { - system_matrix.block(0, 1).vmult(tmp, solution.block(1)); - tmp *= -1; - tmp += system_rhs.block(0); + { + system_matrix.block(0, 1).vmult(tmp, solution.block(1)); + tmp *= -1; + tmp += system_rhs.block(0); - A_inverse.vmult(solution.block(0), tmp); - constraints.distribute(solution); - solution.block(1) *= (system_parameters::pressure_scale); - } -} + A_inverse.vmult(solution.block(0), tmp); + constraints.distribute(solution); + solution.block(1) *= (system_parameters::pressure_scale); + } + } //====================== OUTPUT RESULTS ====================== -template -void StokesProblem::output_results() const { - std::vector < std::string > solution_names(dim, "velocity"); - solution_names.push_back("pressure"); - - std::vector data_component_interpretation( - dim, DataComponentInterpretation::component_is_part_of_vector); - data_component_interpretation.push_back( - DataComponentInterpretation::component_is_scalar); - - DataOut data_out; - data_out.attach_dof_handler(dof_handler); - data_out.add_data_vector(solution, solution_names, - DataOut::type_dof_data, data_component_interpretation); - data_out.build_patches(); - - std::ostringstream filename; - if (system_parameters::present_timestep < system_parameters::initial_elastic_iterations) - { - filename << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_elastic_displacements" << ".txt"; - } - else - { - filename << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_flow" << Utilities::int_to_string(plastic_iteration, 2) << ".txt"; - } - - std::ofstream output(filename.str().c_str()); - data_out.write_gnuplot(output); -} + template + void StokesProblem::output_results() const + { + std::vector < std::string > solution_names(dim, "velocity"); + solution_names.push_back("pressure"); + + std::vector data_component_interpretation( + dim, DataComponentInterpretation::component_is_part_of_vector); + data_component_interpretation.push_back( + DataComponentInterpretation::component_is_scalar); + + DataOut data_out; + data_out.attach_dof_handler(dof_handler); + data_out.add_data_vector(solution, solution_names, + DataOut::type_dof_data, data_component_interpretation); + data_out.build_patches(); + + std::ostringstream filename; + if (system_parameters::present_timestep < system_parameters::initial_elastic_iterations) + { + filename << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_elastic_displacements" << ".txt"; + } + else + { + filename << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_flow" << Utilities::int_to_string(plastic_iteration, 2) << ".txt"; + } + + std::ofstream output(filename.str().c_str()); + data_out.write_gnuplot(output); + } //====================== FIND AND WRITE TO FILE THE STRESS TENSOR; IMPLEMENT PLASTICITY ====================== -template -void StokesProblem::solution_stesses() { - //note most of this section only works with dim=2 - - //name the output text files - std::ostringstream stress_output; - stress_output << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_principalstresses" << Utilities::int_to_string(plastic_iteration, 2) - << ".txt"; - std::ofstream fout_snew(stress_output.str().c_str()); - fout_snew.close(); - - std::ostringstream stresstensor_output; - stresstensor_output << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_stresstensor" << Utilities::int_to_string(plastic_iteration, 2) - << ".txt"; - std::ofstream fout_sfull(stresstensor_output.str().c_str()); - fout_sfull.close(); - - std::ostringstream failed_cells_output; - failed_cells_output << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_failurelocations" << Utilities::int_to_string(plastic_iteration, 2) - << ".txt"; - std::ofstream fout_failed_cells(failed_cells_output.str().c_str()); - fout_failed_cells.close(); - - std::ostringstream plastic_eta_output; - plastic_eta_output << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_viscositiesreg" << Utilities::int_to_string(plastic_iteration, 2) - << ".txt"; - std::ofstream fout_vrnew(plastic_eta_output.str().c_str()); - fout_vrnew.close(); - - std::ostringstream initial_eta_output; - if (plastic_iteration == 0) - { - initial_eta_output << system_parameters::output_folder << "/time" - << Utilities::int_to_string(system_parameters::present_timestep, 2) - << "_baseviscosities.txt"; - std::ofstream fout_baseeta(initial_eta_output.str().c_str()); - fout_baseeta.close(); - } - - std::cout << "Running stress calculations for plasticity iteration " - << plastic_iteration << "...\n"; - - //This makes the set of points at which the stress tensor is calculated - std::vector > points_list(0); - std::vector material_list(0); - typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(), endc = dof_handler.end(); - //This loop gets the gradients of the velocity field and saves it in the tensor_gradient_? objects DIM - for (; cell != endc; ++cell) { - points_list.push_back(cell->center()); - material_list.push_back(cell->material_id()); - } - // Make the FEValues object to evaluate values and derivatives at quadrature points - FEValues fe_values(fe, quadrature_formula, - update_values | update_gradients | update_quadrature_points | update_JxW_values); - - // Make the object that will hold the velocities and velocity gradients at the quadrature points - std::vector < std::vector >> velocity_grads(quadrature_formula.size(), - std::vector < Tensor<1, dim> > (dim + 1)); - std::vector > velocities(quadrature_formula.size(), - Vector(dim + 1)); - // Make the object to find rheology - Rheology rheology; - - // Write the solution flow velocity and derivative for each cell - std::vector > vector_values(0); - std::vector < std::vector > > gradient_values(0); - std::vector failing_cells; - // Write the stresses from the previous step into vectors - std::vector> old_stress; - std::vector old_phiphi_stress; - std::vector cell_Gs; - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) - { - // Makes pointer to data in quadrature_point_history - PointHistory *local_quadrature_points_history = - reinterpret_cast *>(cell->user_pointer()); - - fe_values.reinit(cell); - fe_values.get_function_gradients(solution, velocity_grads); - fe_values.get_function_values(solution, velocities); - Vector current_cell_velocity(dim+1); - std::vector> current_cell_grads(dim+1); - SymmetricTensor<2, dim> current_cell_old_stress; - current_cell_old_stress = 0; - double current_cell_old_phiphi_stress = 0; - double cell_area = 0; - - // Averages across each cell to find mean velocities, gradients, and old stresses - for (unsigned int q = 0; q < quadrature_formula.size(); ++q) - { - cell_area += fe_values.JxW(q); - velocities[q] *= fe_values.JxW(q); - current_cell_velocity += velocities[q]; - for (unsigned int i = 0; i < (dim+1); i++) - { - velocity_grads[q][i] *= fe_values.JxW(q); - current_cell_grads[i] += velocity_grads[q][i]; - } - current_cell_old_stress += local_quadrature_points_history[q].old_stress * fe_values.JxW(q); - current_cell_old_phiphi_stress += local_quadrature_points_history[q].old_phiphi_stress * fe_values.JxW(q); - } - current_cell_velocity /= cell_area; - for (unsigned int i = 0; i < (dim+1); i++) - current_cell_grads[i] /= cell_area; - current_cell_old_stress /= cell_area; - current_cell_old_phiphi_stress /= cell_area; - - vector_values.push_back(current_cell_velocity); - gradient_values.push_back(current_cell_grads); - old_stress.push_back(current_cell_old_stress); - old_phiphi_stress.push_back(current_cell_old_phiphi_stress); - - // Get cell shear modulus: assumes it's constant for the cell - unsigned int mat_id = cell->material_id(); - double local_G = rheology.get_G(mat_id); - cell_Gs.push_back(local_G); - } - - //tracks where failure occurred - std::vector reduction_factor; - unsigned int total_fails = 0; - if (plastic_iteration == 0) - cell_viscosities.resize(0); - //loop across all the cells to find and adjust eta of failing cells - for (unsigned int i = 0; i < triangulation.n_active_cells(); i++) - { - double current_cell_viscosity = 0; - - // Fill viscosities vector, analytically if plastic_iteration == 0 and from previous viscosities for later iteration - if (plastic_iteration == 0) - { - double local_viscosity; - local_viscosity = rheology.get_eta(points_list[i][0], points_list[i][1]); - current_cell_viscosity = local_viscosity; - cell_viscosities.push_back(current_cell_viscosity); - } - else - { - current_cell_viscosity = cell_viscosities[i]; - } - - - double cell_eta_ve = 2 - / ((1 / current_cell_viscosity) - + (1 / cell_Gs[i] - / system_parameters::current_time_interval)); - double cell_chi_ve = 1 - / (1 - + (cell_Gs[i] - * system_parameters::current_time_interval - / current_cell_viscosity)); - - //find local pressure - double cell_p = vector_values[i].operator()(2); - //find stresses tensor - //makes non-diagonalized local matrix A - double sigma13 = 0.5 - * (gradient_values[i][0][1] + gradient_values[i][1][0]); - mat A; - A << gradient_values[i][0][0] << 0 << sigma13 << endr - << 0 << vector_values[i].operator()(0) / points_list[i].operator()(0)<< 0 << endr - << sigma13 << 0 << gradient_values[i][1][1] << endr; - mat olddevstress; - olddevstress << old_stress[i][0][0] << 0 << old_stress[i][0][1] << endr - << 0 << old_phiphi_stress[i] << 0 << endr - << old_stress[i][0][1] << 0 << old_stress[i][1][1] << endr; - vec P; - P << cell_p << cell_p << cell_p; - mat Pmat = diagmat(P); - mat B; - B = (cell_eta_ve * A + cell_chi_ve * olddevstress) - Pmat; - - //finds principal stresses - vec eigval; - mat eigvec; - eig_sym(eigval, eigvec, B); - double sigma1 = -min(eigval); - double sigma3 = -max(eigval); - - // Writes text files for principal stresses, full stress tensor, base viscosities - std::ofstream fout_snew(stress_output.str().c_str(), std::ios::app); - fout_snew << " " << sigma1 << " " << sigma3 << "\n"; - fout_snew.close(); - - std::ofstream fout_sfull(stresstensor_output.str().c_str(), std::ios::app); - fout_sfull << A(0,0) << " " << A(1,1) << " " << A(2,2) << " " << A(0,2) << "\n"; - fout_sfull.close(); - - if (plastic_iteration == 0) - { - std::ofstream fout_baseeta(initial_eta_output.str().c_str(), std::ios::app); - fout_baseeta << points_list[i]<< " " << current_cell_viscosity << "\n"; - fout_baseeta.close(); - } - - // Finds adjusted effective viscosity - if (system_parameters::plasticity_on) - { - if(system_parameters::failure_criterion == 0) //Apply Byerlee's rule - { - if (sigma1 >= 5 * sigma3) // this guarantees that viscosities only go down, never up - { - failing_cells.push_back(true); - double temp_reductionfactor = 1; - if (sigma3 < 0) - temp_reductionfactor = 100; - else - temp_reductionfactor = 1.9 * sigma1 / 5 / sigma3; - - reduction_factor.push_back(temp_reductionfactor); - total_fails++; - - // Text file of all failure locations - std::ofstream fout_failed_cells(failed_cells_output.str().c_str(), std::ios::app); - fout_failed_cells << points_list[i] << "\n"; - fout_failed_cells.close(); - } - else - { - reduction_factor.push_back(1); - failing_cells.push_back(false); - } - } - else - { - if(system_parameters::failure_criterion == 1) //Apply Schultz criterion for frozen sand, RMR=45 - { - double temp_reductionfactor = 1; - if(sigma3 < -114037) - { - //std::cout << " ext "; - failing_cells.push_back(true); - temp_reductionfactor = 10; - reduction_factor.push_back(temp_reductionfactor); - total_fails++; - - // Text file of all failure locations - std::ofstream fout_failed_cells(failed_cells_output.str().c_str(), std::ios::app); - fout_failed_cells << points_list[i] << "\n"; - fout_failed_cells.close(); - } - else - { - double sigma_c = 160e6; //Unconfined compressive strength - double yield_sigma1 = sigma3 + std::sqrt( (3.086 * sigma_c * sigma3) + (0.002 * sigma3 * sigma3) ); - if (sigma1 >= yield_sigma1) - { - //std::cout << " comp "; - failing_cells.push_back(true); - temp_reductionfactor = 1.0 * sigma1 / 5 / sigma3; - - reduction_factor.push_back(temp_reductionfactor); - total_fails++; - - // Text file of all failure locations - std::ofstream fout_failed_cells(failed_cells_output.str().c_str(), std::ios::app); - fout_failed_cells << points_list[i] << "\n"; - fout_failed_cells.close(); - } - else - { - reduction_factor.push_back(1); - failing_cells.push_back(false); - } - } - } - else - { - std::cout << "Specified failure criterion not found\n"; - } - } - } - else - reduction_factor.push_back(1); - } - - // If there are enough failed cells, update eta at all quadrature points and perform smoothing - std::cout << " Number of failing cells: " << total_fails << "\n"; - double last_max_plasticity_double = last_max_plasticity; - double total_fails_double = total_fails; - double decrease_in_plasticity = ((last_max_plasticity_double - total_fails_double) / last_max_plasticity_double); - if(plastic_iteration == 0) - decrease_in_plasticity = 1; - last_max_plasticity = total_fails; - if (total_fails <= 100 || decrease_in_plasticity <= 0.2) - { - system_parameters::continue_plastic_iterations = false; - for(unsigned int j=0; j < triangulation.n_active_cells(); j++) - { - // Writes to file the undisturbed cell viscosities - std::ofstream fout_vrnew(plastic_eta_output.str().c_str(), std::ios::app); - fout_vrnew << " " << cell_viscosities[j] << "\n"; - fout_vrnew.close(); - } - } - else{ - quad_viscosities.resize(triangulation.n_active_cells()); - // Decrease the eta at quadrature points in failing cells - unsigned int cell_no = 0; - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) - { - fe_values.reinit(cell); - // Make local_quadrature_points_history pointer to the cell data - PointHistory *local_quadrature_points_history = - reinterpret_cast *>(cell->user_pointer()); - Assert( - local_quadrature_points_history >= &quadrature_point_history.front(), - ExcInternalError()); - Assert( - local_quadrature_points_history < &quadrature_point_history.back(), - ExcInternalError()); - - quad_viscosities[cell_no].resize(quadrature_formula.size()); - - for (unsigned int q = 0; q < quadrature_formula.size(); ++q) - { - if (plastic_iteration == 0) - local_quadrature_points_history[q].new_eta = local_quadrature_points_history[q].first_eta; - local_quadrature_points_history[q].new_eta /= reduction_factor[cell_no]; - // Prevents viscosities from dropping below the floor necessary for numerical stability - if (local_quadrature_points_history[q].new_eta < system_parameters::eta_floor) - local_quadrature_points_history[q].new_eta = system_parameters::eta_floor; - - quad_viscosities[cell_no][q].reinit(dim+1); - for(unsigned int ii=0; ii::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) - { - if(failing_cells[cell_no]) - { - fe_values.reinit(cell); - // Averages across each cell to find mean eta - double cell_area = 0; - for (unsigned int q = 0; q < quadrature_formula.size(); ++q) - { - cell_area += fe_values.JxW(q); - cell_viscosities[cell_no] += quad_viscosities[cell_no][q][dim] * fe_values.JxW(q); - } - cell_viscosities[cell_no] /= cell_area; - - // Writes to file - std::ofstream fout_vrnew(plastic_eta_output.str().c_str(), std::ios::app); - fout_vrnew << " " << cell_viscosities[cell_no] << "\n"; - fout_vrnew.close(); - } - else - { - std::ofstream fout_vrnew(plastic_eta_output.str().c_str(), std::ios::app); - fout_vrnew << " " << cell_viscosities[cell_no] << "\n"; - fout_vrnew.close(); - } - cell_no++; - } - } -} + template + void StokesProblem::solution_stesses() + { + //note most of this section only works with dim=2 + + //name the output text files + std::ostringstream stress_output; + stress_output << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_principalstresses" << Utilities::int_to_string(plastic_iteration, 2) + << ".txt"; + std::ofstream fout_snew(stress_output.str().c_str()); + fout_snew.close(); + + std::ostringstream stresstensor_output; + stresstensor_output << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_stresstensor" << Utilities::int_to_string(plastic_iteration, 2) + << ".txt"; + std::ofstream fout_sfull(stresstensor_output.str().c_str()); + fout_sfull.close(); + + std::ostringstream failed_cells_output; + failed_cells_output << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_failurelocations" << Utilities::int_to_string(plastic_iteration, 2) + << ".txt"; + std::ofstream fout_failed_cells(failed_cells_output.str().c_str()); + fout_failed_cells.close(); + + std::ostringstream plastic_eta_output; + plastic_eta_output << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_viscositiesreg" << Utilities::int_to_string(plastic_iteration, 2) + << ".txt"; + std::ofstream fout_vrnew(plastic_eta_output.str().c_str()); + fout_vrnew.close(); + + std::ostringstream initial_eta_output; + if (plastic_iteration == 0) + { + initial_eta_output << system_parameters::output_folder << "/time" + << Utilities::int_to_string(system_parameters::present_timestep, 2) + << "_baseviscosities.txt"; + std::ofstream fout_baseeta(initial_eta_output.str().c_str()); + fout_baseeta.close(); + } + + std::cout << "Running stress calculations for plasticity iteration " + << plastic_iteration << "...\n"; + + //This makes the set of points at which the stress tensor is calculated + std::vector > points_list(0); + std::vector material_list(0); + typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(), endc = dof_handler.end(); + //This loop gets the gradients of the velocity field and saves it in the tensor_gradient_? objects DIM + for (; cell != endc; ++cell) + { + points_list.push_back(cell->center()); + material_list.push_back(cell->material_id()); + } + // Make the FEValues object to evaluate values and derivatives at quadrature points + FEValues fe_values(fe, quadrature_formula, + update_values | update_gradients | update_quadrature_points | update_JxW_values); + + // Make the object that will hold the velocities and velocity gradients at the quadrature points + std::vector < std::vector >> velocity_grads(quadrature_formula.size(), + std::vector < Tensor<1, dim> > (dim + 1)); + std::vector > velocities(quadrature_formula.size(), + Vector(dim + 1)); + // Make the object to find rheology + Rheology rheology; + + // Write the solution flow velocity and derivative for each cell + std::vector > vector_values(0); + std::vector < std::vector > > gradient_values(0); + std::vector failing_cells; + // Write the stresses from the previous step into vectors + std::vector> old_stress; + std::vector old_phiphi_stress; + std::vector cell_Gs; + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + { + // Makes pointer to data in quadrature_point_history + PointHistory *local_quadrature_points_history = + reinterpret_cast *>(cell->user_pointer()); + + fe_values.reinit(cell); + fe_values.get_function_gradients(solution, velocity_grads); + fe_values.get_function_values(solution, velocities); + Vector current_cell_velocity(dim+1); + std::vector> current_cell_grads(dim+1); + SymmetricTensor<2, dim> current_cell_old_stress; + current_cell_old_stress = 0; + double current_cell_old_phiphi_stress = 0; + double cell_area = 0; + + // Averages across each cell to find mean velocities, gradients, and old stresses + for (unsigned int q = 0; q < quadrature_formula.size(); ++q) + { + cell_area += fe_values.JxW(q); + velocities[q] *= fe_values.JxW(q); + current_cell_velocity += velocities[q]; + for (unsigned int i = 0; i < (dim+1); i++) + { + velocity_grads[q][i] *= fe_values.JxW(q); + current_cell_grads[i] += velocity_grads[q][i]; + } + current_cell_old_stress += local_quadrature_points_history[q].old_stress * fe_values.JxW(q); + current_cell_old_phiphi_stress += local_quadrature_points_history[q].old_phiphi_stress * fe_values.JxW(q); + } + current_cell_velocity /= cell_area; + for (unsigned int i = 0; i < (dim+1); i++) + current_cell_grads[i] /= cell_area; + current_cell_old_stress /= cell_area; + current_cell_old_phiphi_stress /= cell_area; + + vector_values.push_back(current_cell_velocity); + gradient_values.push_back(current_cell_grads); + old_stress.push_back(current_cell_old_stress); + old_phiphi_stress.push_back(current_cell_old_phiphi_stress); + + // Get cell shear modulus: assumes it's constant for the cell + unsigned int mat_id = cell->material_id(); + double local_G = rheology.get_G(mat_id); + cell_Gs.push_back(local_G); + } + + //tracks where failure occurred + std::vector reduction_factor; + unsigned int total_fails = 0; + if (plastic_iteration == 0) + cell_viscosities.resize(0); + //loop across all the cells to find and adjust eta of failing cells + for (unsigned int i = 0; i < triangulation.n_active_cells(); i++) + { + double current_cell_viscosity = 0; + + // Fill viscosities vector, analytically if plastic_iteration == 0 and from previous viscosities for later iteration + if (plastic_iteration == 0) + { + double local_viscosity; + local_viscosity = rheology.get_eta(points_list[i][0], points_list[i][1]); + current_cell_viscosity = local_viscosity; + cell_viscosities.push_back(current_cell_viscosity); + } + else + { + current_cell_viscosity = cell_viscosities[i]; + } + + + double cell_eta_ve = 2 + / ((1 / current_cell_viscosity) + + (1 / cell_Gs[i] + / system_parameters::current_time_interval)); + double cell_chi_ve = 1 + / (1 + + (cell_Gs[i] + * system_parameters::current_time_interval + / current_cell_viscosity)); + + //find local pressure + double cell_p = vector_values[i].operator()(2); + //find stresses tensor + //makes non-diagonalized local matrix A + double sigma13 = 0.5 + * (gradient_values[i][0][1] + gradient_values[i][1][0]); + mat A; + A << gradient_values[i][0][0] << 0 << sigma13 << endr + << 0 << vector_values[i].operator()(0) / points_list[i].operator()(0)<< 0 << endr + << sigma13 << 0 << gradient_values[i][1][1] << endr; + mat olddevstress; + olddevstress << old_stress[i][0][0] << 0 << old_stress[i][0][1] << endr + << 0 << old_phiphi_stress[i] << 0 << endr + << old_stress[i][0][1] << 0 << old_stress[i][1][1] << endr; + vec P; + P << cell_p << cell_p << cell_p; + mat Pmat = diagmat(P); + mat B; + B = (cell_eta_ve * A + cell_chi_ve * olddevstress) - Pmat; + + //finds principal stresses + vec eigval; + mat eigvec; + eig_sym(eigval, eigvec, B); + double sigma1 = -min(eigval); + double sigma3 = -max(eigval); + + // Writes text files for principal stresses, full stress tensor, base viscosities + std::ofstream fout_snew(stress_output.str().c_str(), std::ios::app); + fout_snew << " " << sigma1 << " " << sigma3 << "\n"; + fout_snew.close(); + + std::ofstream fout_sfull(stresstensor_output.str().c_str(), std::ios::app); + fout_sfull << A(0,0) << " " << A(1,1) << " " << A(2,2) << " " << A(0,2) << "\n"; + fout_sfull.close(); + + if (plastic_iteration == 0) + { + std::ofstream fout_baseeta(initial_eta_output.str().c_str(), std::ios::app); + fout_baseeta << points_list[i]<< " " << current_cell_viscosity << "\n"; + fout_baseeta.close(); + } + + // Finds adjusted effective viscosity + if (system_parameters::plasticity_on) + { + if (system_parameters::failure_criterion == 0) //Apply Byerlee's rule + { + if (sigma1 >= 5 * sigma3) // this guarantees that viscosities only go down, never up + { + failing_cells.push_back(true); + double temp_reductionfactor = 1; + if (sigma3 < 0) + temp_reductionfactor = 100; + else + temp_reductionfactor = 1.9 * sigma1 / 5 / sigma3; + + reduction_factor.push_back(temp_reductionfactor); + total_fails++; + + // Text file of all failure locations + std::ofstream fout_failed_cells(failed_cells_output.str().c_str(), std::ios::app); + fout_failed_cells << points_list[i] << "\n"; + fout_failed_cells.close(); + } + else + { + reduction_factor.push_back(1); + failing_cells.push_back(false); + } + } + else + { + if (system_parameters::failure_criterion == 1) //Apply Schultz criterion for frozen sand, RMR=45 + { + double temp_reductionfactor = 1; + if (sigma3 < -114037) + { + //std::cout << " ext "; + failing_cells.push_back(true); + temp_reductionfactor = 10; + reduction_factor.push_back(temp_reductionfactor); + total_fails++; + + // Text file of all failure locations + std::ofstream fout_failed_cells(failed_cells_output.str().c_str(), std::ios::app); + fout_failed_cells << points_list[i] << "\n"; + fout_failed_cells.close(); + } + else + { + double sigma_c = 160e6; //Unconfined compressive strength + double yield_sigma1 = sigma3 + std::sqrt( (3.086 * sigma_c * sigma3) + (0.002 * sigma3 * sigma3) ); + if (sigma1 >= yield_sigma1) + { + //std::cout << " comp "; + failing_cells.push_back(true); + temp_reductionfactor = 1.0 * sigma1 / 5 / sigma3; + + reduction_factor.push_back(temp_reductionfactor); + total_fails++; + + // Text file of all failure locations + std::ofstream fout_failed_cells(failed_cells_output.str().c_str(), std::ios::app); + fout_failed_cells << points_list[i] << "\n"; + fout_failed_cells.close(); + } + else + { + reduction_factor.push_back(1); + failing_cells.push_back(false); + } + } + } + else + { + std::cout << "Specified failure criterion not found\n"; + } + } + } + else + reduction_factor.push_back(1); + } + + // If there are enough failed cells, update eta at all quadrature points and perform smoothing + std::cout << " Number of failing cells: " << total_fails << "\n"; + double last_max_plasticity_double = last_max_plasticity; + double total_fails_double = total_fails; + double decrease_in_plasticity = ((last_max_plasticity_double - total_fails_double) / last_max_plasticity_double); + if (plastic_iteration == 0) + decrease_in_plasticity = 1; + last_max_plasticity = total_fails; + if (total_fails <= 100 || decrease_in_plasticity <= 0.2) + { + system_parameters::continue_plastic_iterations = false; + for (unsigned int j=0; j < triangulation.n_active_cells(); j++) + { + // Writes to file the undisturbed cell viscosities + std::ofstream fout_vrnew(plastic_eta_output.str().c_str(), std::ios::app); + fout_vrnew << " " << cell_viscosities[j] << "\n"; + fout_vrnew.close(); + } + } + else + { + quad_viscosities.resize(triangulation.n_active_cells()); + // Decrease the eta at quadrature points in failing cells + unsigned int cell_no = 0; + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + { + fe_values.reinit(cell); + // Make local_quadrature_points_history pointer to the cell data + PointHistory *local_quadrature_points_history = + reinterpret_cast *>(cell->user_pointer()); + Assert( + local_quadrature_points_history >= &quadrature_point_history.front(), + ExcInternalError()); + Assert( + local_quadrature_points_history < &quadrature_point_history.back(), + ExcInternalError()); + + quad_viscosities[cell_no].resize(quadrature_formula.size()); + + for (unsigned int q = 0; q < quadrature_formula.size(); ++q) + { + if (plastic_iteration == 0) + local_quadrature_points_history[q].new_eta = local_quadrature_points_history[q].first_eta; + local_quadrature_points_history[q].new_eta /= reduction_factor[cell_no]; + // Prevents viscosities from dropping below the floor necessary for numerical stability + if (local_quadrature_points_history[q].new_eta < system_parameters::eta_floor) + local_quadrature_points_history[q].new_eta = system_parameters::eta_floor; + + quad_viscosities[cell_no][q].reinit(dim+1); + for (unsigned int ii=0; ii::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + { + if (failing_cells[cell_no]) + { + fe_values.reinit(cell); + // Averages across each cell to find mean eta + double cell_area = 0; + for (unsigned int q = 0; q < quadrature_formula.size(); ++q) + { + cell_area += fe_values.JxW(q); + cell_viscosities[cell_no] += quad_viscosities[cell_no][q][dim] * fe_values.JxW(q); + } + cell_viscosities[cell_no] /= cell_area; + + // Writes to file + std::ofstream fout_vrnew(plastic_eta_output.str().c_str(), std::ios::app); + fout_vrnew << " " << cell_viscosities[cell_no] << "\n"; + fout_vrnew.close(); + } + else + { + std::ofstream fout_vrnew(plastic_eta_output.str().c_str(), std::ios::app); + fout_vrnew << " " << cell_viscosities[cell_no] << "\n"; + fout_vrnew.close(); + } + cell_no++; + } + } + } //====================== SMOOTHES THE VISCOSITY FIELD AT ALL QUADRATURE POINTS ====================== -template -void StokesProblem::smooth_eta_field(std::vector failing_cells) -{ - std::cout << " Smoothing viscosity field...\n"; - unsigned int cell_no = 0; - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) - { - if(failing_cells[cell_no]) - { - FEValues fe_values(fe, quadrature_formula, update_quadrature_points); - PointHistory *local_quadrature_points_history = - reinterpret_cast *>(cell->user_pointer()); - - // Currently this algorithm does not permit refinement. To permit refinement, daughter cells of neighbors must be identified - // Find pointers and indices of all cells within certain radius - bool find_more_cells = true; - std::vector cell_touched(triangulation.n_active_cells(), false); - std::vector< TriaIterator< CellAccessor > > neighbor_cells; - std::vector neighbor_indices; - unsigned int start_cell = 0; // Which cell in the neighbor_cells vector to start from - int new_cells_found = 0; - neighbor_cells.push_back(cell); - neighbor_indices.push_back(cell_no); - cell_touched[cell_no] = true; - while(find_more_cells) - { - new_cells_found = 0; - for(unsigned int i = start_cell; i::faces_per_cell; ++f) - { - if (!neighbor_cells[i]->face(f)->at_boundary()) - { - int test_cell_no = neighbor_cells[i]->neighbor_index(f); - if(!cell_touched[test_cell_no]) - if(cell->center().distance(neighbor_cells[i]->neighbor(f)->center()) < 2 * system_parameters::smoothing_radius) - { - // What to do if another nearby cell is found that hasn't been found before - neighbor_cells.push_back(neighbor_cells[i]->neighbor(f)); - neighbor_indices.push_back(test_cell_no); - cell_touched[test_cell_no] = true; - start_cell++; - new_cells_found++; - } - } - } - } - if (new_cells_found == 0){ - find_more_cells = false; - } - else - start_cell = neighbor_cells.size() - new_cells_found; - } - - fe_values.reinit(cell); - // Collect the viscosities at nearby quadrature points - for (unsigned int q = 0; q < quadrature_formula.size(); ++q) - { - std::vector nearby_etas_q; - for (unsigned int i = 0; i test_q; - for(unsigned int d=0; d + void StokesProblem::smooth_eta_field(std::vector failing_cells) + { + std::cout << " Smoothing viscosity field...\n"; + unsigned int cell_no = 0; + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + { + if (failing_cells[cell_no]) + { + FEValues fe_values(fe, quadrature_formula, update_quadrature_points); + PointHistory *local_quadrature_points_history = + reinterpret_cast *>(cell->user_pointer()); + + // Currently this algorithm does not permit refinement. To permit refinement, daughter cells of neighbors must be identified + // Find pointers and indices of all cells within certain radius + bool find_more_cells = true; + std::vector cell_touched(triangulation.n_active_cells(), false); + std::vector< TriaIterator< CellAccessor > > neighbor_cells; + std::vector neighbor_indices; + unsigned int start_cell = 0; // Which cell in the neighbor_cells vector to start from + int new_cells_found = 0; + neighbor_cells.push_back(cell); + neighbor_indices.push_back(cell_no); + cell_touched[cell_no] = true; + while (find_more_cells) + { + new_cells_found = 0; + for (unsigned int i = start_cell; i::faces_per_cell; ++f) + { + if (!neighbor_cells[i]->face(f)->at_boundary()) + { + int test_cell_no = neighbor_cells[i]->neighbor_index(f); + if (!cell_touched[test_cell_no]) + if (cell->center().distance(neighbor_cells[i]->neighbor(f)->center()) < 2 * system_parameters::smoothing_radius) + { + // What to do if another nearby cell is found that hasn't been found before + neighbor_cells.push_back(neighbor_cells[i]->neighbor(f)); + neighbor_indices.push_back(test_cell_no); + cell_touched[test_cell_no] = true; + start_cell++; + new_cells_found++; + } + } + } + } + if (new_cells_found == 0) + { + find_more_cells = false; + } + else + start_cell = neighbor_cells.size() - new_cells_found; + } + + fe_values.reinit(cell); + // Collect the viscosities at nearby quadrature points + for (unsigned int q = 0; q < quadrature_formula.size(); ++q) + { + std::vector nearby_etas_q; + for (unsigned int i = 0; i test_q; + for (unsigned int d=0; d -void StokesProblem::update_quadrature_point_history() { - std::cout << " Updating stress field..."; - - FEValues fe_values(fe, quadrature_formula, - update_values | update_gradients | update_quadrature_points); - - // Make the object that will hold the velocity gradients - std::vector < std::vector >> velocity_grads(quadrature_formula.size(), - std::vector < Tensor<1, dim> > (dim + 1)); - std::vector > velocities(quadrature_formula.size(), - Vector(dim + 1)); - - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) { - PointHistory *local_quadrature_points_history = - reinterpret_cast *>(cell->user_pointer()); - Assert( - local_quadrature_points_history >= &quadrature_point_history.front(), - ExcInternalError()); - Assert( - local_quadrature_points_history < &quadrature_point_history.back(), - ExcInternalError()); - - fe_values.reinit(cell); - fe_values.get_function_gradients(solution, velocity_grads); - fe_values.get_function_values(solution, velocities); - - for (unsigned int q = 0; q < quadrature_formula.size(); ++q) { - // Define the local viscoelastic constants - double local_eta_ve = 2 - / ((1 / local_quadrature_points_history[q].new_eta) - + (1 / local_quadrature_points_history[q].G - / system_parameters::current_time_interval)); - double local_chi_ve = - 1 - / (1 - + (local_quadrature_points_history[q].G - * system_parameters::current_time_interval - / local_quadrature_points_history[q].new_eta)); - - // Compute new stress at each quadrature point - SymmetricTensor<2, dim> new_stress; - for (unsigned int i = 0; i < dim; ++i) - new_stress[i][i] = - local_eta_ve * velocity_grads[q][i][i] - + local_chi_ve - * local_quadrature_points_history[q].old_stress[i][i]; - - for (unsigned int i = 0; i < dim; ++i) - for (unsigned int j = i + 1; j < dim; ++j) - new_stress[i][j] = - local_eta_ve - * (velocity_grads[q][i][j] - + velocity_grads[q][j][i]) / 2 - + local_chi_ve - * local_quadrature_points_history[q].old_stress[i][j]; - - // Rotate new stress - AuxFunctions rotation_object; - const Tensor<2, dim> rotation = rotation_object.get_rotation_matrix( - velocity_grads[q]); - const SymmetricTensor<2, dim> rotated_new_stress = symmetrize( - transpose(rotation) - * static_cast >(new_stress) - * rotation); - local_quadrature_points_history[q].old_stress = rotated_new_stress; - - // For axisymmetric case, make the phi-phi element of stress tensor - local_quadrature_points_history[q].old_phiphi_stress = - (2 * local_eta_ve * velocities[q](0) - / fe_values.quadrature_point(q)[0] - + local_chi_ve - * local_quadrature_points_history[q].old_phiphi_stress); - } - } -} + template + void StokesProblem::update_quadrature_point_history() + { + std::cout << " Updating stress field..."; + + FEValues fe_values(fe, quadrature_formula, + update_values | update_gradients | update_quadrature_points); + + // Make the object that will hold the velocity gradients + std::vector < std::vector >> velocity_grads(quadrature_formula.size(), + std::vector < Tensor<1, dim> > (dim + 1)); + std::vector > velocities(quadrature_formula.size(), + Vector(dim + 1)); + + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + { + PointHistory *local_quadrature_points_history = + reinterpret_cast *>(cell->user_pointer()); + Assert( + local_quadrature_points_history >= &quadrature_point_history.front(), + ExcInternalError()); + Assert( + local_quadrature_points_history < &quadrature_point_history.back(), + ExcInternalError()); + + fe_values.reinit(cell); + fe_values.get_function_gradients(solution, velocity_grads); + fe_values.get_function_values(solution, velocities); + + for (unsigned int q = 0; q < quadrature_formula.size(); ++q) + { + // Define the local viscoelastic constants + double local_eta_ve = 2 + / ((1 / local_quadrature_points_history[q].new_eta) + + (1 / local_quadrature_points_history[q].G + / system_parameters::current_time_interval)); + double local_chi_ve = + 1 + / (1 + + (local_quadrature_points_history[q].G + * system_parameters::current_time_interval + / local_quadrature_points_history[q].new_eta)); + + // Compute new stress at each quadrature point + SymmetricTensor<2, dim> new_stress; + for (unsigned int i = 0; i < dim; ++i) + new_stress[i][i] = + local_eta_ve * velocity_grads[q][i][i] + + local_chi_ve + * local_quadrature_points_history[q].old_stress[i][i]; + + for (unsigned int i = 0; i < dim; ++i) + for (unsigned int j = i + 1; j < dim; ++j) + new_stress[i][j] = + local_eta_ve + * (velocity_grads[q][i][j] + + velocity_grads[q][j][i]) / 2 + + local_chi_ve + * local_quadrature_points_history[q].old_stress[i][j]; + + // Rotate new stress + AuxFunctions rotation_object; + const Tensor<2, dim> rotation = rotation_object.get_rotation_matrix( + velocity_grads[q]); + const SymmetricTensor<2, dim> rotated_new_stress = symmetrize( + transpose(rotation) + * static_cast >(new_stress) + * rotation); + local_quadrature_points_history[q].old_stress = rotated_new_stress; + + // For axisymmetric case, make the phi-phi element of stress tensor + local_quadrature_points_history[q].old_phiphi_stress = + (2 * local_eta_ve * velocities[q](0) + / fe_values.quadrature_point(q)[0] + + local_chi_ve + * local_quadrature_points_history[q].old_phiphi_stress); + } + } + } //====================== REDEFINE THE TIME INTERVAL FOR THE VISCOUS STEPS ====================== -template -void StokesProblem::update_time_interval() -{ - double move_goal_per_step = system_parameters::initial_disp_target; - if(system_parameters::present_timestep > system_parameters::initial_elastic_iterations) - { - move_goal_per_step = system_parameters::initial_disp_target - - ((system_parameters::initial_disp_target - system_parameters::final_disp_target) / - system_parameters::total_viscous_steps * - (system_parameters::present_timestep - system_parameters::initial_elastic_iterations)); - } - - double zero_tolerance = 1e-3; - double max_velocity = 0; - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell)// loop over all cells - { - if(cell->at_boundary()) - { - int zero_faces = 0; - for(unsigned int f=0; f::faces_per_cell; f++) - for(unsigned int i=0; iface(f)->center()[i]) < zero_tolerance) - zero_faces++; - if (zero_faces==0) - { - for (unsigned int v = 0; v < GeometryInfo::vertices_per_cell; ++v) - { - Point vertex_velocity; - Point vertex_position; - for (unsigned int d = 0; d < dim; ++d) - { - vertex_velocity[d] = solution(cell->vertex_dof_index(v, d)); - vertex_position[d] = cell->vertex(v)[d]; - } - //velocity to be evaluated is the radial component of a surface vertex - double local_velocity = 0; - for (unsigned int d = 0; d < dim; ++d) - { - local_velocity += vertex_velocity[d] * vertex_position [d]; - } - local_velocity /= std::sqrt( vertex_position.square() ); - if(local_velocity < 0) - local_velocity *= -1; - if(local_velocity > max_velocity) - { - max_velocity = local_velocity; - } - } - } - } - } - // NOTE: It is possible for this time interval to be very different from that used in the viscoelasticity calculation. - system_parameters::current_time_interval = move_goal_per_step / max_velocity; - double step_time_yr = system_parameters::current_time_interval / SECSINYEAR; - std::cout << "Timestep interval changed to: " - << step_time_yr - << " years\n"; -} + template + void StokesProblem::update_time_interval() + { + double move_goal_per_step = system_parameters::initial_disp_target; + if (system_parameters::present_timestep > system_parameters::initial_elastic_iterations) + { + move_goal_per_step = system_parameters::initial_disp_target - + ((system_parameters::initial_disp_target - system_parameters::final_disp_target) / + system_parameters::total_viscous_steps * + (system_parameters::present_timestep - system_parameters::initial_elastic_iterations)); + } + + double zero_tolerance = 1e-3; + double max_velocity = 0; + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell)// loop over all cells + { + if (cell->at_boundary()) + { + int zero_faces = 0; + for (unsigned int f=0; f::faces_per_cell; f++) + for (unsigned int i=0; iface(f)->center()[i]) < zero_tolerance) + zero_faces++; + if (zero_faces==0) + { + for (unsigned int v = 0; v < GeometryInfo::vertices_per_cell; ++v) + { + Point vertex_velocity; + Point vertex_position; + for (unsigned int d = 0; d < dim; ++d) + { + vertex_velocity[d] = solution(cell->vertex_dof_index(v, d)); + vertex_position[d] = cell->vertex(v)[d]; + } + //velocity to be evaluated is the radial component of a surface vertex + double local_velocity = 0; + for (unsigned int d = 0; d < dim; ++d) + { + local_velocity += vertex_velocity[d] * vertex_position [d]; + } + local_velocity /= std::sqrt( vertex_position.square() ); + if (local_velocity < 0) + local_velocity *= -1; + if (local_velocity > max_velocity) + { + max_velocity = local_velocity; + } + } + } + } + } + // NOTE: It is possible for this time interval to be very different from that used in the viscoelasticity calculation. + system_parameters::current_time_interval = move_goal_per_step / max_velocity; + double step_time_yr = system_parameters::current_time_interval / SECSINYEAR; + std::cout << "Timestep interval changed to: " + << step_time_yr + << " years\n"; + } //====================== MOVE MESH ====================== -template -void StokesProblem::move_mesh() { - - std::cout << "\n" << " Moving mesh...\n"; - std::vector vertex_touched(triangulation.n_vertices(), false); - for (typename DoFHandler::active_cell_iterator cell = - dof_handler.begin_active(); cell != dof_handler.end(); ++cell) - for (unsigned int v = 0; v < GeometryInfo::vertices_per_cell; ++v) - if (vertex_touched[cell->vertex_index(v)] == false) { - vertex_touched[cell->vertex_index(v)] = true; - - Point vertex_displacement; - for (unsigned int d = 0; d < dim; ++d) - vertex_displacement[d] = solution( - cell->vertex_dof_index(v, d)); - cell->vertex(v) += vertex_displacement - * system_parameters::current_time_interval; - } -} + template + void StokesProblem::move_mesh() + { + + std::cout << "\n" << " Moving mesh...\n"; + std::vector vertex_touched(triangulation.n_vertices(), false); + for (typename DoFHandler::active_cell_iterator cell = + dof_handler.begin_active(); cell != dof_handler.end(); ++cell) + for (unsigned int v = 0; v < GeometryInfo::vertices_per_cell; ++v) + if (vertex_touched[cell->vertex_index(v)] == false) + { + vertex_touched[cell->vertex_index(v)] = true; + + Point vertex_displacement; + for (unsigned int d = 0; d < dim; ++d) + vertex_displacement[d] = solution( + cell->vertex_dof_index(v, d)); + cell->vertex(v) += vertex_displacement + * system_parameters::current_time_interval; + } + } //====================== WRITE MESH TO FILE ====================== -template -void StokesProblem::write_mesh() -{ - // output mesh in ucd - std::ostringstream initial_mesh_file; - initial_mesh_file << system_parameters::output_folder << "/time" << - Utilities::int_to_string(system_parameters::present_timestep, 2) << - "_mesh.inp"; - std::ofstream out_ucd (initial_mesh_file.str().c_str()); - GridOut grid_out; - grid_out.write_ucd (triangulation, out_ucd); -} + template + void StokesProblem::write_mesh() + { + // output mesh in ucd + std::ostringstream initial_mesh_file; + initial_mesh_file << system_parameters::output_folder << "/time" << + Utilities::int_to_string(system_parameters::present_timestep, 2) << + "_mesh.inp"; + std::ofstream out_ucd (initial_mesh_file.str().c_str()); + GridOut grid_out; + grid_out.write_ucd (triangulation, out_ucd); + } //====================== FIT ELLIPSE TO SURFACE AND WRITE RADII TO FILE ====================== -template -void StokesProblem::do_ellipse_fits() -{ - std::ostringstream ellipses_filename; - ellipses_filename << system_parameters::output_folder << "/ellipse_fits.txt"; - // Find ellipsoidal axes for all layers - std::vector ellipse_axes(0); - // compute fit to boundary 0, 1, 2 ... - std::cout << endl; - for(unsigned int i = 0; i ellipse_axes(0); + // compute fit to boundary 0, 1, 2 ... + std::cout << endl; + for (unsigned int i = 0; i + void StokesProblem::append_physical_times(int max_plastic) + { + std::ostringstream times_filename; + times_filename << system_parameters::output_folder << "/physical_times.txt"; + std::ofstream fout_times(times_filename.str().c_str(), std::ios::app); + fout_times << system_parameters::present_timestep << " " + << system_parameters::present_time/SECSINYEAR << " " + << max_plastic << "\n"; + // << system_parameters::q_axes[0] << " " << system_parameters::p_axes[0] << " " + // << system_parameters::q_axes[1] << " " << system_parameters::p_axes[1] << "\n"; + fout_times.close(); + } //====================== WRITE VERTICES TO FILE ====================== -template -void StokesProblem::write_vertices(unsigned char boundary_that_we_need) { - std::ostringstream vertices_output; - vertices_output << system_parameters::output_folder << "/time" << - Utilities::int_to_string(system_parameters::present_timestep, 2) << "_" << - Utilities::int_to_string(boundary_that_we_need, 2) << - "_surface.txt"; - std::ofstream fout_final_vertices(vertices_output.str().c_str()); - fout_final_vertices.close(); - - std::vector vertex_touched(triangulation.n_vertices(), false); - - if (boundary_that_we_need == 0) - { - // Figure out if the vertex is on the boundary of the domain - for (typename Triangulation::active_cell_iterator cell = - triangulation.begin_active(); cell != triangulation.end(); ++cell) - for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) - { - unsigned char boundary_ids = cell->face(f)->boundary_id(); - if(boundary_ids == boundary_that_we_need) - { - for (unsigned int v=0; v::vertices_per_face; ++v) - if (vertex_touched[cell->face(f)->vertex_index(v)] == false) - { - vertex_touched[cell->face(f)->vertex_index(v)] = true; - std::ofstream fout_final_vertices(vertices_output.str().c_str(), std::ios::app); - fout_final_vertices << cell->face(f)->vertex(v) << "\n"; - fout_final_vertices.close(); - } - } - } - } - else - { - // Figure out if the vertex is on an internal boundary - for (typename Triangulation::active_cell_iterator cell = - triangulation.begin_active(); cell != triangulation.end(); ++cell) - for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) - { - if (cell->neighbor(f) != triangulation.end()) { - if (cell->material_id() != cell->neighbor(f)->material_id()) //finds face is at internal boundary - { - int high_mat_id = std::max(cell->material_id(), - cell->neighbor(f)->material_id()); - if (high_mat_id == boundary_that_we_need) //finds faces at the correct internal boundary - { - for (unsigned int v = 0; - v < GeometryInfo::vertices_per_face; - ++v) - if (vertex_touched[cell->face(f)->vertex_index( - v)] == false) { - vertex_touched[cell->face(f)->vertex_index( - v)] = true; - std::ofstream fout_final_vertices(vertices_output.str().c_str(), std::ios::app); - fout_final_vertices << cell->face(f)->vertex(v) << "\n"; - fout_final_vertices.close(); - } - } - } - } - } - } -} + template + void StokesProblem::write_vertices(unsigned char boundary_that_we_need) + { + std::ostringstream vertices_output; + vertices_output << system_parameters::output_folder << "/time" << + Utilities::int_to_string(system_parameters::present_timestep, 2) << "_" << + Utilities::int_to_string(boundary_that_we_need, 2) << + "_surface.txt"; + std::ofstream fout_final_vertices(vertices_output.str().c_str()); + fout_final_vertices.close(); + + std::vector vertex_touched(triangulation.n_vertices(), false); + + if (boundary_that_we_need == 0) + { + // Figure out if the vertex is on the boundary of the domain + for (typename Triangulation::active_cell_iterator cell = + triangulation.begin_active(); cell != triangulation.end(); ++cell) + for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) + { + unsigned char boundary_ids = cell->face(f)->boundary_id(); + if (boundary_ids == boundary_that_we_need) + { + for (unsigned int v=0; v::vertices_per_face; ++v) + if (vertex_touched[cell->face(f)->vertex_index(v)] == false) + { + vertex_touched[cell->face(f)->vertex_index(v)] = true; + std::ofstream fout_final_vertices(vertices_output.str().c_str(), std::ios::app); + fout_final_vertices << cell->face(f)->vertex(v) << "\n"; + fout_final_vertices.close(); + } + } + } + } + else + { + // Figure out if the vertex is on an internal boundary + for (typename Triangulation::active_cell_iterator cell = + triangulation.begin_active(); cell != triangulation.end(); ++cell) + for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) + { + if (cell->neighbor(f) != triangulation.end()) + { + if (cell->material_id() != cell->neighbor(f)->material_id()) //finds face is at internal boundary + { + int high_mat_id = std::max(cell->material_id(), + cell->neighbor(f)->material_id()); + if (high_mat_id == boundary_that_we_need) //finds faces at the correct internal boundary + { + for (unsigned int v = 0; + v < GeometryInfo::vertices_per_face; + ++v) + if (vertex_touched[cell->face(f)->vertex_index( + v)] == false) + { + vertex_touched[cell->face(f)->vertex_index( + v)] = true; + std::ofstream fout_final_vertices(vertices_output.str().c_str(), std::ios::app); + fout_final_vertices << cell->face(f)->vertex(v) << "\n"; + fout_final_vertices.close(); + } + } + } + } + } + } + } //====================== SETUP INITIAL MESH ====================== -template -void StokesProblem::setup_initial_mesh() { - GridIn grid_in; - grid_in.attach_triangulation(triangulation); - std::ifstream mesh_stream(system_parameters::mesh_filename, - std::ifstream::in); - grid_in.read_ucd(mesh_stream); - - // output initial mesh in eps - std::ostringstream initial_mesh_file; - initial_mesh_file << system_parameters::output_folder << "/initial_mesh.eps"; - std::ofstream out_eps (initial_mesh_file.str().c_str()); - GridOut grid_out; - grid_out.write_eps (triangulation, out_eps); - out_eps.close(); + template + void StokesProblem::setup_initial_mesh() + { + GridIn grid_in; + grid_in.attach_triangulation(triangulation); + std::ifstream mesh_stream(system_parameters::mesh_filename, + std::ifstream::in); + grid_in.read_ucd(mesh_stream); + + // output initial mesh in eps + std::ostringstream initial_mesh_file; + initial_mesh_file << system_parameters::output_folder << "/initial_mesh.eps"; + std::ofstream out_eps (initial_mesh_file.str().c_str()); + GridOut grid_out; + grid_out.write_eps (triangulation, out_eps); + out_eps.close(); // set boundary ids // boundary indicator 0 is outer free surface; 1, 2, 3 ... is boundary between layers, 99 is flat boundaries typename Triangulation::active_cell_iterator - cell=triangulation.begin_active(), endc=triangulation.end(); + cell=triangulation.begin_active(), endc=triangulation.end(); unsigned int how_many; // how many components away from cardinal planes - std::ostringstream boundaries_file; - boundaries_file << system_parameters::output_folder << "/boundaries.txt"; - std::ofstream fout_boundaries(boundaries_file.str().c_str()); - fout_boundaries.close(); - - double zero_tolerance = 1e-3; - for (; cell != endc; ++cell) // loop over all cells - { - for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) // loop over all vertices - { - if (cell->face(f)->at_boundary()) - { - // print boundary - std::ofstream fout_boundaries(boundaries_file.str().c_str(), std::ios::app); - fout_boundaries << cell->face(f)->center()[0] << " " << cell->face(f)->center()[1]<< "\n"; - fout_boundaries.close(); - - how_many = 0; - for(unsigned int i=0; iface(f)->center()[i]) > zero_tolerance) - how_many++; - if (how_many==dim) - cell->face(f)->set_all_boundary_ids(0); // if face center coordinates > zero_tol, set bnry indicators to 0 - else - cell->face(f)->set_all_boundary_ids(99); - } - } - } - - std::ostringstream ellipses_filename; - ellipses_filename << system_parameters::output_folder << "/ellipse_fits.txt"; - std::ofstream fout_ellipses(ellipses_filename.str().c_str()); - fout_ellipses.close(); - - // Find ellipsoidal axes for all layers - std::vector ellipse_axes(0); - // compute fit to boundary 0, 1, 2 ... - std::cout << endl; - for(unsigned int i = 0; i::faces_per_cell; ++f) // loop over all vertices + { + if (cell->face(f)->at_boundary()) + { + // print boundary + std::ofstream fout_boundaries(boundaries_file.str().c_str(), std::ios::app); + fout_boundaries << cell->face(f)->center()[0] << " " << cell->face(f)->center()[1]<< "\n"; + fout_boundaries.close(); + + how_many = 0; + for (unsigned int i=0; iface(f)->center()[i]) > zero_tolerance) + how_many++; + if (how_many==dim) + cell->face(f)->set_all_boundary_ids(0); // if face center coordinates > zero_tol, set bnry indicators to 0 + else + cell->face(f)->set_all_boundary_ids(99); + } + } + } + + std::ostringstream ellipses_filename; + ellipses_filename << system_parameters::output_folder << "/ellipse_fits.txt"; + std::ofstream fout_ellipses(ellipses_filename.str().c_str()); + fout_ellipses.close(); + + // Find ellipsoidal axes for all layers + std::vector ellipse_axes(0); + // compute fit to boundary 0, 1, 2 ... + std::cout << endl; + for (unsigned int i = 0; i::active_cell_iterator cell = + triangulation.begin_active(), endc = triangulation.end(); + for (; cell != endc; ++cell) + for (unsigned int v = 0; + v < GeometryInfo::vertices_per_cell; ++v) + { + Point current_vertex = cell->vertex(v); + + const double x_coord = current_vertex.operator()(0); + const double y_coord = current_vertex.operator()(1); + double expected_z = -1; + + if ((x_coord - a) < -1e-10) + expected_z = b + * std::sqrt(1 - (x_coord * x_coord / a / a)); + + if (y_coord >= expected_z) + { + cell->set_refine_flag(); + break; + } + } + triangulation.execute_coarsening_and_refinement(); + } + } + + + // output initial mesh in eps + std::ostringstream refined_mesh_file; + refined_mesh_file << system_parameters::output_folder << "/refined_mesh.eps"; + std::ofstream out_eps_refined (refined_mesh_file.str().c_str()); + GridOut grid_out_refined; + grid_out_refined.write_eps (triangulation, out_eps_refined); + out_eps_refined.close(); + write_vertices(0); + write_vertices(1); + write_mesh(); + } //====================== REFINE MESH ====================== -template -void StokesProblem::refine_mesh() { - Vector estimated_error_per_cell(triangulation.n_active_cells()); + template + void StokesProblem::refine_mesh() + { + Vector estimated_error_per_cell(triangulation.n_active_cells()); - std::vector component_mask(dim + 1, false); - component_mask[dim] = true; - KellyErrorEstimator::estimate(dof_handler, QGauss(degree + 1), - typename FunctionMap::type(), solution, - estimated_error_per_cell, component_mask); + std::vector component_mask(dim + 1, false); + component_mask[dim] = true; + KellyErrorEstimator::estimate(dof_handler, QGauss(degree + 1), + typename FunctionMap::type(), solution, + estimated_error_per_cell, component_mask); - GridRefinement::refine_and_coarsen_fixed_number(triangulation, - estimated_error_per_cell, 0.3, 0.0); - triangulation.execute_coarsening_and_refinement(); -} + GridRefinement::refine_and_coarsen_fixed_number(triangulation, + estimated_error_per_cell, 0.3, 0.0); + triangulation.execute_coarsening_and_refinement(); + } //====================== SET UP THE DATA STRUCTURES TO REMEMBER STRESS FIELD ====================== -template -void StokesProblem::setup_quadrature_point_history() { - unsigned int our_cells = 0; - for (typename Triangulation::active_cell_iterator cell = - triangulation.begin_active(); cell != triangulation.end(); ++cell) - ++our_cells; + template + void StokesProblem::setup_quadrature_point_history() + { + unsigned int our_cells = 0; + for (typename Triangulation::active_cell_iterator cell = + triangulation.begin_active(); cell != triangulation.end(); ++cell) + ++our_cells; - triangulation.clear_user_data(); + triangulation.clear_user_data(); - quadrature_point_history.resize(our_cells * quadrature_formula.size()); + quadrature_point_history.resize(our_cells * quadrature_formula.size()); - unsigned int history_index = 0; - for (typename Triangulation::active_cell_iterator cell = - triangulation.begin_active(); cell != triangulation.end(); ++cell) { - cell->set_user_pointer(&quadrature_point_history[history_index]); - history_index += quadrature_formula.size(); - } + unsigned int history_index = 0; + for (typename Triangulation::active_cell_iterator cell = + triangulation.begin_active(); cell != triangulation.end(); ++cell) + { + cell->set_user_pointer(&quadrature_point_history[history_index]); + history_index += quadrature_formula.size(); + } - Assert(history_index == quadrature_point_history.size(), ExcInternalError()); -} + Assert(history_index == quadrature_point_history.size(), ExcInternalError()); + } //====================== DOES ELASTIC STEPS ====================== -template -void StokesProblem::do_elastic_steps() -{ - unsigned int elastic_iteration = 0; - - while (elastic_iteration < system_parameters::initial_elastic_iterations) - { - - std::cout << "\n\nElastic iteration " << elastic_iteration - << "\n"; - setup_dofs(); - - if (system_parameters::present_timestep == 0) - initialize_eta_and_G(); - - if(elastic_iteration == 0) - system_parameters::current_time_interval = - system_parameters::viscous_time; //This is the time interval needed in assembling the problem - - std::cout << " Assembling..." << std::endl << std::flush; - assemble_system(); - - std::cout << " Solving..." << std::flush; - solve(); - - output_results(); - update_quadrature_point_history(); - - append_physical_times(0); - elastic_iteration++; - system_parameters::present_timestep++; - do_ellipse_fits(); - write_vertices(0); - write_vertices(1); - write_mesh(); - update_time_interval(); - } -} + template + void StokesProblem::do_elastic_steps() + { + unsigned int elastic_iteration = 0; + + while (elastic_iteration < system_parameters::initial_elastic_iterations) + { + + std::cout << "\n\nElastic iteration " << elastic_iteration + << "\n"; + setup_dofs(); + + if (system_parameters::present_timestep == 0) + initialize_eta_and_G(); + + if (elastic_iteration == 0) + system_parameters::current_time_interval = + system_parameters::viscous_time; //This is the time interval needed in assembling the problem + + std::cout << " Assembling..." << std::endl << std::flush; + assemble_system(); + + std::cout << " Solving..." << std::flush; + solve(); + + output_results(); + update_quadrature_point_history(); + + append_physical_times(0); + elastic_iteration++; + system_parameters::present_timestep++; + do_ellipse_fits(); + write_vertices(0); + write_vertices(1); + write_mesh(); + update_time_interval(); + } + } //====================== DO A SINGLE VISCOELASTOPLASTIC TIMESTEP ====================== -template -void StokesProblem::do_flow_step() { - plastic_iteration = 0; - while (plastic_iteration < system_parameters::max_plastic_iterations) { - if (system_parameters::continue_plastic_iterations == true) { - std::cout << "Plasticity iteration " << plastic_iteration << "\n"; - setup_dofs(); - - std::cout << " Assembling..." << std::endl << std::flush; - assemble_system(); - - std::cout << " Solving..." << std::flush; - solve(); - - output_results(); - solution_stesses(); - - if (system_parameters::continue_plastic_iterations == false) - break; - - plastic_iteration++; - } - } -} + template + void StokesProblem::do_flow_step() + { + plastic_iteration = 0; + while (plastic_iteration < system_parameters::max_plastic_iterations) + { + if (system_parameters::continue_plastic_iterations == true) + { + std::cout << "Plasticity iteration " << plastic_iteration << "\n"; + setup_dofs(); + + std::cout << " Assembling..." << std::endl << std::flush; + assemble_system(); + + std::cout << " Solving..." << std::flush; + solve(); + + output_results(); + solution_stesses(); + + if (system_parameters::continue_plastic_iterations == false) + break; + + plastic_iteration++; + } + } + } //====================== RUN ====================== -template -void StokesProblem::run() -{ - // Sets up mesh and data structure for viscosity and stress at quadrature points - setup_initial_mesh(); - setup_quadrature_point_history(); - - // Makes the physical_times.txt file - std::ostringstream times_filename; - times_filename << system_parameters::output_folder << "/physical_times.txt"; - std::ofstream fout_times(times_filename.str().c_str()); - fout_times.close(); - - // Computes elastic timesteps - do_elastic_steps(); - // Computes viscous timesteps - unsigned int VEPstep = 0; - while (system_parameters::present_timestep - < (system_parameters::initial_elastic_iterations - + system_parameters::total_viscous_steps)) { - - if (system_parameters::continue_plastic_iterations == false) - system_parameters::continue_plastic_iterations = true; - std::cout << "\n\nViscoelastoplastic iteration " << VEPstep << "\n\n"; - // Computes plasticity - do_flow_step(); - update_quadrature_point_history(); - move_mesh(); - append_physical_times(plastic_iteration); - system_parameters::present_timestep++; - system_parameters::present_time = system_parameters::present_time + system_parameters::current_time_interval; - do_ellipse_fits(); - write_vertices(0); - write_vertices(1); - write_mesh(); - VEPstep++; - } - append_physical_times(-1); - } + template + void StokesProblem::run() + { + // Sets up mesh and data structure for viscosity and stress at quadrature points + setup_initial_mesh(); + setup_quadrature_point_history(); + + // Makes the physical_times.txt file + std::ostringstream times_filename; + times_filename << system_parameters::output_folder << "/physical_times.txt"; + std::ofstream fout_times(times_filename.str().c_str()); + fout_times.close(); + + // Computes elastic timesteps + do_elastic_steps(); + // Computes viscous timesteps + unsigned int VEPstep = 0; + while (system_parameters::present_timestep + < (system_parameters::initial_elastic_iterations + + system_parameters::total_viscous_steps)) + { + + if (system_parameters::continue_plastic_iterations == false) + system_parameters::continue_plastic_iterations = true; + std::cout << "\n\nViscoelastoplastic iteration " << VEPstep << "\n\n"; + // Computes plasticity + do_flow_step(); + update_quadrature_point_history(); + move_mesh(); + append_physical_times(plastic_iteration); + system_parameters::present_timestep++; + system_parameters::present_time = system_parameters::present_time + system_parameters::current_time_interval; + do_ellipse_fits(); + write_vertices(0); + write_vertices(1); + write_mesh(); + VEPstep++; + } + append_physical_times(-1); + } } //====================== MAIN ====================== -int main(int argc, char* argv[]) { - - // output program name - std::cout << "Running: " << argv[0] << std::endl; - - char* cfg_filename = new char[120]; - - if (argc == 1) // if no input parameters (as if launched from eclipse) - { - std::strcpy(cfg_filename,"config/ConfigurationV2.cfg"); - } - else - std::strcpy(cfg_filename,argv[1]); - - try { - using namespace dealii; - using namespace Step22; - config_in cfg(cfg_filename); - - std::clock_t t1; - std::clock_t t2; - t1 = std::clock(); - - deallog.depth_console(0); - - StokesProblem<2> flow_problem(1); - flow_problem.run(); - - std::cout << std::endl << "\a"; - - t2 = std::clock(); - float diff (((float)t2 - (float)t1) / (float)CLOCKS_PER_SEC); - std::cout << "\n Program run in: " << diff << " seconds" << endl; - } catch (std::exception &exc) { - std::cerr << std::endl << std::endl - << "----------------------------------------------------" - << std::endl; - std::cerr << "Exception on processing: " << std::endl << exc.what() - << std::endl << "Aborting!" << std::endl - << "----------------------------------------------------" - << std::endl; - - return 1; - } catch (...) { - std::cerr << std::endl << std::endl - << "----------------------------------------------------" - << std::endl; - std::cerr << "Unknown exception!" << std::endl << "Aborting!" - << std::endl - << "----------------------------------------------------" - << std::endl; - return 1; - } - - return 0; +int main(int argc, char *argv[]) +{ + + // output program name + std::cout << "Running: " << argv[0] << std::endl; + + char *cfg_filename = new char[120]; + + if (argc == 1) // if no input parameters (as if launched from eclipse) + { + std::strcpy(cfg_filename,"config/ConfigurationV2.cfg"); + } + else + std::strcpy(cfg_filename,argv[1]); + + try + { + using namespace dealii; + using namespace Step22; + config_in cfg(cfg_filename); + + std::clock_t t1; + std::clock_t t2; + t1 = std::clock(); + + deallog.depth_console(0); + + StokesProblem<2> flow_problem(1); + flow_problem.run(); + + std::cout << std::endl << "\a"; + + t2 = std::clock(); + float diff (((float)t2 - (float)t1) / (float)CLOCKS_PER_SEC); + std::cout << "\n Program run in: " << diff << " seconds" << endl; + } + catch (std::exception &exc) + { + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Exception on processing: " << std::endl << exc.what() + << std::endl << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + + return 1; + } + catch (...) + { + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Unknown exception!" << std::endl << "Aborting!" + << std::endl + << "----------------------------------------------------" + << std::endl; + return 1; + } + + return 0; } diff --git a/CeresFE/support_code/config_in.h b/CeresFE/support_code/config_in.h index 57283e8..0ee79b9 100644 --- a/CeresFE/support_code/config_in.h +++ b/CeresFE/support_code/config_in.h @@ -17,101 +17,103 @@ using namespace std; using namespace libconfig; -namespace Step22 { -namespace system_parameters { +namespace Step22 +{ + namespace system_parameters + { // Mesh file name -string mesh_filename; -string output_folder; + string mesh_filename; + string output_folder; // Body parameters -double r_mean; -double period; -double omegasquared; -double beta; -double intercept; + double r_mean; + double period; + double omegasquared; + double beta; + double intercept; // Rheology parameters -vector depths_eta; -vector eta_kinks; -vector depths_rho; -vector rho; -vector material_id; -vector G; - -double eta_ceiling; -double eta_floor; -double eta_Ea; -bool lat_dependence; - -unsigned int sizeof_depths_eta; -unsigned int sizeof_depths_rho; -unsigned int sizeof_rho; -unsigned int sizeof_eta_kinks; -unsigned int sizeof_material_id; -unsigned int sizeof_G; - -double pressure_scale; -double q; -bool cylindrical; -bool continue_plastic_iterations; + vector depths_eta; + vector eta_kinks; + vector depths_rho; + vector rho; + vector material_id; + vector G; + + double eta_ceiling; + double eta_floor; + double eta_Ea; + bool lat_dependence; + + unsigned int sizeof_depths_eta; + unsigned int sizeof_depths_rho; + unsigned int sizeof_rho; + unsigned int sizeof_eta_kinks; + unsigned int sizeof_material_id; + unsigned int sizeof_G; + + double pressure_scale; + double q; + bool cylindrical; + bool continue_plastic_iterations; // plasticity variables -bool plasticity_on; -unsigned int failure_criterion; -unsigned int max_plastic_iterations; -double smoothing_radius; + bool plasticity_on; + unsigned int failure_criterion; + unsigned int max_plastic_iterations; + double smoothing_radius; // viscoelasticity variables -unsigned int initial_elastic_iterations; -double elastic_time; -double viscous_time; -double initial_disp_target; -double final_disp_target; -double current_time_interval; + unsigned int initial_elastic_iterations; + double elastic_time; + double viscous_time; + double initial_disp_target; + double final_disp_target; + double current_time_interval; //mesh refinement variables -unsigned int global_refinement; -unsigned int small_r_refinement; -unsigned int crustal_refinement; -double crust_refine_region; -unsigned int surface_refinement; + unsigned int global_refinement; + unsigned int small_r_refinement; + unsigned int crustal_refinement; + double crust_refine_region; + unsigned int surface_refinement; //solver variables -int iteration_coefficient; -double tolerance_coefficient; + int iteration_coefficient; + double tolerance_coefficient; //time step variables -double present_time; -unsigned int present_timestep; -unsigned int total_viscous_steps; + double present_time; + unsigned int present_timestep; + unsigned int total_viscous_steps; // ellipse axes -vector q_axes; -vector p_axes; + vector q_axes; + vector p_axes; -} + } -class config_in -{ -public: - config_in(char*); - -private: - void write_config(); -}; - -void config_in::write_config() -{ - std::ostringstream config_parameters; - config_parameters << system_parameters::output_folder << "/run_parameters.txt"; - std::ofstream fout_config(config_parameters.str().c_str()); + class config_in + { + public: + config_in(char *); + + private: + void write_config(); + }; + + void config_in::write_config() + { + std::ostringstream config_parameters; + config_parameters << system_parameters::output_folder << "/run_parameters.txt"; + std::ofstream fout_config(config_parameters.str().c_str()); - // mesh filename - fout_config << "mesh filename: " << system_parameters::mesh_filename << endl << endl; + // mesh filename + fout_config << "mesh filename: " << system_parameters::mesh_filename << endl << endl; - // body parameters + // body parameters fout_config << "r_mean = " << system_parameters::r_mean << endl; fout_config << "period = " << system_parameters::period << endl; fout_config << "omegasquared = " << system_parameters::omegasquared << endl; @@ -120,23 +122,23 @@ void config_in::write_config() // rheology parameters - for(unsigned int i=0; i class ellipsoid_fit { public: - inline ellipsoid_fit (Triangulation* pi) - { - p_triangulation = pi; - }; - void compute_fit(std::vector &ell, unsigned char bndry); + inline ellipsoid_fit (Triangulation *pi) + { + p_triangulation = pi; + }; + void compute_fit(std::vector &ell, unsigned char bndry); private: - Triangulation* p_triangulation; + Triangulation *p_triangulation; }; @@ -63,110 +63,120 @@ private: template void ellipsoid_fit::compute_fit(std::vector &ell, unsigned char boundary_that_we_need) { - typename Triangulation::active_cell_iterator cell = p_triangulation->begin_active(); - typename Triangulation::active_cell_iterator endc = p_triangulation->end(); - - FullMatrix A(p_triangulation->n_vertices(),dim); - Vector x(dim); - Vector b(p_triangulation->n_vertices()); - - std::vector vertex_touched (p_triangulation->n_vertices(), - false); - - unsigned int j = 0; - unsigned char boundary_ids; - std::vector ind_bnry_row; - std::vector ind_bnry_col; - - // assemble the sensitivity matrix and r.h.s. - for (; cell != endc; ++cell) { - if (boundary_that_we_need != 0) - cell->set_manifold_id(cell->material_id()); - for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) { - if (boundary_that_we_need == 0) //if this is the outer surface, then look for boundary ID 0; otherwise look for material ID change. - { - boundary_ids = cell->face(f)->boundary_id(); - if (boundary_ids == boundary_that_we_need) { - for (unsigned int v = 0; - v < GeometryInfo::vertices_per_face; ++v) - if (vertex_touched[cell->face(f)->vertex_index(v)] - == false) { - vertex_touched[cell->face(f)->vertex_index(v)] = - true; - for (unsigned int i = 0; i < dim; ++i) { - // stiffness matrix entry - A(j, i) = pow(cell->face(f)->vertex(v)[i], 2); - // r.h.s. entry - b[j] = 1.0; - // if mesh if not full: set the indicator - } - ind_bnry_row.push_back(j); - j++; - } - } - } else { //find the faces that are at the boundary between materials, get the vertices, and write them into the stiffness matrix - if (cell->neighbor(f) != endc) { - if (cell->material_id() != cell->neighbor(f)->material_id()) //finds face is at internal boundary - { - int high_mat_id = std::max(cell->material_id(), - cell->neighbor(f)->material_id()); - if (high_mat_id == boundary_that_we_need) //finds faces at the correct internal boundary - { - for (unsigned int v = 0; - v < GeometryInfo::vertices_per_face; - ++v) - if (vertex_touched[cell->face(f)->vertex_index( - v)] == false) { - vertex_touched[cell->face(f)->vertex_index( - v)] = true; - for (unsigned int i = 0; i < dim; ++i) { - // stiffness matrix entry - A(j, i) = pow( - cell->face(f)->vertex(v)[i], 2); - // r.h.s. entry - b[j] = 1.0; - // if mesh if not full: set the indicator - } - ind_bnry_row.push_back(j); - j++; - } - } - } - } - } - } - } - if (ind_bnry_row.size()>0) - { - - // maxtrix A'*A and vector A'*b; A'*A*x = A'*b -- normal system of equations - FullMatrix AtA(dim,dim); - Vector Atb(dim); - - FullMatrix A_out(ind_bnry_row.size(),dim); - Vector b_out(ind_bnry_row.size()); - - for(unsigned int i=0;i solver (solver_control); - solver.solve (AtA, x, Atb, PreconditionIdentity()); - - // find ellipsoidal axes - for(unsigned int i=0; i::active_cell_iterator cell = p_triangulation->begin_active(); + typename Triangulation::active_cell_iterator endc = p_triangulation->end(); + + FullMatrix A(p_triangulation->n_vertices(),dim); + Vector x(dim); + Vector b(p_triangulation->n_vertices()); + + std::vector vertex_touched (p_triangulation->n_vertices(), + false); + + unsigned int j = 0; + unsigned char boundary_ids; + std::vector ind_bnry_row; + std::vector ind_bnry_col; + + // assemble the sensitivity matrix and r.h.s. + for (; cell != endc; ++cell) + { + if (boundary_that_we_need != 0) + cell->set_manifold_id(cell->material_id()); + for (unsigned int f = 0; f < GeometryInfo::faces_per_cell; ++f) + { + if (boundary_that_we_need == 0) //if this is the outer surface, then look for boundary ID 0; otherwise look for material ID change. + { + boundary_ids = cell->face(f)->boundary_id(); + if (boundary_ids == boundary_that_we_need) + { + for (unsigned int v = 0; + v < GeometryInfo::vertices_per_face; ++v) + if (vertex_touched[cell->face(f)->vertex_index(v)] + == false) + { + vertex_touched[cell->face(f)->vertex_index(v)] = + true; + for (unsigned int i = 0; i < dim; ++i) + { + // stiffness matrix entry + A(j, i) = pow(cell->face(f)->vertex(v)[i], 2); + // r.h.s. entry + b[j] = 1.0; + // if mesh if not full: set the indicator + } + ind_bnry_row.push_back(j); + j++; + } + } + } + else //find the faces that are at the boundary between materials, get the vertices, and write them into the stiffness matrix + { + if (cell->neighbor(f) != endc) + { + if (cell->material_id() != cell->neighbor(f)->material_id()) //finds face is at internal boundary + { + int high_mat_id = std::max(cell->material_id(), + cell->neighbor(f)->material_id()); + if (high_mat_id == boundary_that_we_need) //finds faces at the correct internal boundary + { + for (unsigned int v = 0; + v < GeometryInfo::vertices_per_face; + ++v) + if (vertex_touched[cell->face(f)->vertex_index( + v)] == false) + { + vertex_touched[cell->face(f)->vertex_index( + v)] = true; + for (unsigned int i = 0; i < dim; ++i) + { + // stiffness matrix entry + A(j, i) = pow( + cell->face(f)->vertex(v)[i], 2); + // r.h.s. entry + b[j] = 1.0; + // if mesh if not full: set the indicator + } + ind_bnry_row.push_back(j); + j++; + } + } + } + } + } + } + } + if (ind_bnry_row.size()>0) + { + + // maxtrix A'*A and vector A'*b; A'*A*x = A'*b -- normal system of equations + FullMatrix AtA(dim,dim); + Vector Atb(dim); + + FullMatrix A_out(ind_bnry_row.size(),dim); + Vector b_out(ind_bnry_row.size()); + + for (unsigned int i=0; i solver (solver_control); + solver.solve (AtA, x, Atb, PreconditionIdentity()); + + // find ellipsoidal axes + for (unsigned int i=0; i #include @@ -12,160 +12,161 @@ namespace A_Grav_namespace { - namespace system_parameters { - double mantle_rho; - double core_rho; - double excess_rho; - double r_eq; - double r_polar; - - double r_core_eq; - double r_core_polar; - } - -template -class AnalyticGravity -{ + namespace system_parameters + { + double mantle_rho; + double core_rho; + double excess_rho; + double r_eq; + double r_polar; + + double r_core_eq; + double r_core_polar; + } + + template + class AnalyticGravity + { public: void setup_vars (std::vector v); - void get_gravity (const dealii::Point &p, std::vector &g); - - private: - double ecc; - double eV; - double ke; - double r00; - double r01; - double r11; - double ecc_c; - double eV_c; - double ke_c; - double r00_c; - double r01_c; - double r11_c; - double g_coeff; - double g_coeff_c; -}; - -template -void AnalyticGravity::get_gravity (const dealii::Point &p, std::vector &g) - { - double rsph = std::sqrt(p[0] * p[0] + p[1] * p[1]); - double thetasph = std::atan2(p[0], p[1]); - double costhetasph = std::cos(thetasph); - - //convert to elliptical coordinates for silicates - double stemp = std::sqrt((rsph * rsph - eV * eV + std::sqrt((rsph * rsph - eV * eV) * (rsph * rsph - eV * eV) - + 4 * eV * eV * rsph * rsph * costhetasph *costhetasph)) / 2); - double vout = stemp / system_parameters::r_eq / std::sqrt(1 - ecc * ecc); - double eout = std::acos(rsph * costhetasph / stemp); - - //convert to elliptical coordinates for core correction - double stemp_c = std::sqrt((rsph * rsph - eV_c * eV_c + std::sqrt((rsph * rsph - eV_c * eV_c) * (rsph * rsph - eV_c * eV_c) - + 4 * eV_c * eV_c * rsph * rsph * costhetasph *costhetasph)) / 2); - double vout_c = stemp_c / system_parameters::r_core_eq / std::sqrt(1 - ecc_c * ecc_c); - double eout_c = std::acos(rsph * costhetasph / stemp_c); - - //shell contribution - g[0] = g_coeff * r11 * std::sqrt((1 - ecc * ecc) * vout * vout + ecc * ecc) * std::sin(eout); - g[1] = g_coeff * r01 * vout * std::cos(eout) / std::sqrt(1 - ecc * ecc); - - //core contribution - double expected_y = system_parameters::r_core_polar * std::sqrt(1 - - (p[0] * p[0] / system_parameters::r_core_eq / system_parameters::r_core_eq)); - - - if(p[1] <= expected_y) - { - g[0] += g_coeff_c * r11_c * std::sqrt((1 - ecc_c * ecc_c) * vout_c * vout_c + ecc_c * ecc_c) * std::sin(eout_c); - g[1] += g_coeff_c * r01_c * vout_c * std::cos(eout_c) / std::sqrt(1 - ecc_c * ecc_c); - } - else - { - double g_coeff_co = - 2.795007963255562e-10 * system_parameters::excess_rho * system_parameters::r_core_eq - / vout_c / vout_c; - double r00_co = 0; - double r01_co = 0; - double r11_co = 0; - - if(system_parameters::r_core_polar == system_parameters::r_core_eq) - { - r00_co = 1; - r01_co = 1; - r11_co = 1; - } - else - { - r00_co = ke_c * vout_c * std::atan2(1, ke_c * vout_c); - double ke_co2 = ke_c * ke_c * vout_c * vout_c; - r01_co = 3 * ke_co2 * (1 - r00_co); - r11_co = 3 * ((ke_co2 + 1) * r00_co - ke_co2) / 2; - } - g[0] += g_coeff_co * vout_c * r11_co / std::sqrt((1 - ecc_c* ecc_c) * vout_c * vout_c + ecc_c * ecc_c) * std::sin(eout_c); - g[1] += g_coeff_co * r01_co * std::cos(eout_c) / std::sqrt(1 - ecc_c * ecc_c); - } - } - -template -void AnalyticGravity::setup_vars (std::vector v) -{ - system_parameters::r_eq = v[0]; - system_parameters::r_polar = v[1]; - system_parameters::r_core_eq = v[2]; - system_parameters::r_core_polar = v[3]; - system_parameters::mantle_rho = v[4]; - system_parameters::core_rho = v[5]; - system_parameters::excess_rho = system_parameters::core_rho - system_parameters::mantle_rho; - - - // Shell - if (system_parameters::r_polar > system_parameters::r_eq) - { - //This makes the gravity field nearly that of a sphere in case the body becomes prolate - std::cout << "\nWarning: The model body has become prolate. \n"; - ecc = 0.001; - } - else - { - ecc = std::sqrt(1 - (system_parameters::r_polar * system_parameters::r_polar / system_parameters::r_eq / system_parameters::r_eq)); - } - - eV = ecc * system_parameters::r_eq; - ke = std::sqrt(1 - (ecc * ecc)) / ecc; - r00 = ke * std::atan2(1, ke); - double ke2 = ke * ke; - r01 = 3 * ke2 * (1 - r00); - r11 = 3 * ((ke2 + 1) * r00 - ke2) / 2; - g_coeff = - 2.795007963255562e-10 * system_parameters::mantle_rho * system_parameters::r_eq; - - // Core - if (system_parameters::r_core_polar > system_parameters::r_core_eq) - { - std::cout << "\nWarning: The model core has become prolate. \n"; - ecc_c = 0.001; - } - else - { - ecc_c = std::sqrt(1 - (system_parameters::r_core_polar * system_parameters::r_core_polar / system_parameters::r_core_eq / system_parameters::r_core_eq)); - } - eV_c = ecc_c * system_parameters::r_core_eq; - if(system_parameters::r_core_polar == system_parameters::r_core_eq) - { - ke_c = 1; - r00_c = 1; - r01_c = 1; - r11_c = 1; - g_coeff_c = - 2.795007963255562e-10 * system_parameters::excess_rho * system_parameters::r_core_eq; - } - else - { - ke_c = std::sqrt(1 - (ecc_c * ecc_c)) / ecc_c; - r00_c = ke_c * std::atan2(1, ke_c); - double ke2_c = ke_c * ke_c; - r01_c = 3 * ke2_c * (1 - r00_c); - r11_c = 3 * ((ke2_c + 1) * r00_c - ke2_c) / 2; - g_coeff_c = - 2.795007963255562e-10 * system_parameters::excess_rho * system_parameters::r_core_eq; - } -// std::cout << "Loaded variables: ecc = " << ecc_c << " ke = " << ke_c << " r00 = " << r00_c << " r01 = " << r01_c << " r11 = " << r11_c << "\n"; -} + void get_gravity (const dealii::Point &p, std::vector &g); + + private: + double ecc; + double eV; + double ke; + double r00; + double r01; + double r11; + double ecc_c; + double eV_c; + double ke_c; + double r00_c; + double r01_c; + double r11_c; + double g_coeff; + double g_coeff_c; + }; + + template + void AnalyticGravity::get_gravity (const dealii::Point &p, std::vector &g) + { + double rsph = std::sqrt(p[0] * p[0] + p[1] * p[1]); + double thetasph = std::atan2(p[0], p[1]); + double costhetasph = std::cos(thetasph); + + //convert to elliptical coordinates for silicates + double stemp = std::sqrt((rsph * rsph - eV * eV + std::sqrt((rsph * rsph - eV * eV) * (rsph * rsph - eV * eV) + + 4 * eV * eV * rsph * rsph * costhetasph *costhetasph)) / 2); + double vout = stemp / system_parameters::r_eq / std::sqrt(1 - ecc * ecc); + double eout = std::acos(rsph * costhetasph / stemp); + + //convert to elliptical coordinates for core correction + double stemp_c = std::sqrt((rsph * rsph - eV_c * eV_c + std::sqrt((rsph * rsph - eV_c * eV_c) * (rsph * rsph - eV_c * eV_c) + + 4 * eV_c * eV_c * rsph * rsph * costhetasph *costhetasph)) / 2); + double vout_c = stemp_c / system_parameters::r_core_eq / std::sqrt(1 - ecc_c * ecc_c); + double eout_c = std::acos(rsph * costhetasph / stemp_c); + + //shell contribution + g[0] = g_coeff * r11 * std::sqrt((1 - ecc * ecc) * vout * vout + ecc * ecc) * std::sin(eout); + g[1] = g_coeff * r01 * vout * std::cos(eout) / std::sqrt(1 - ecc * ecc); + + //core contribution + double expected_y = system_parameters::r_core_polar * std::sqrt(1 - + (p[0] * p[0] / system_parameters::r_core_eq / system_parameters::r_core_eq)); + + + if (p[1] <= expected_y) + { + g[0] += g_coeff_c * r11_c * std::sqrt((1 - ecc_c * ecc_c) * vout_c * vout_c + ecc_c * ecc_c) * std::sin(eout_c); + g[1] += g_coeff_c * r01_c * vout_c * std::cos(eout_c) / std::sqrt(1 - ecc_c * ecc_c); + } + else + { + double g_coeff_co = - 2.795007963255562e-10 * system_parameters::excess_rho * system_parameters::r_core_eq + / vout_c / vout_c; + double r00_co = 0; + double r01_co = 0; + double r11_co = 0; + + if (system_parameters::r_core_polar == system_parameters::r_core_eq) + { + r00_co = 1; + r01_co = 1; + r11_co = 1; + } + else + { + r00_co = ke_c * vout_c * std::atan2(1, ke_c * vout_c); + double ke_co2 = ke_c * ke_c * vout_c * vout_c; + r01_co = 3 * ke_co2 * (1 - r00_co); + r11_co = 3 * ((ke_co2 + 1) * r00_co - ke_co2) / 2; + } + g[0] += g_coeff_co * vout_c * r11_co / std::sqrt((1 - ecc_c* ecc_c) * vout_c * vout_c + ecc_c * ecc_c) * std::sin(eout_c); + g[1] += g_coeff_co * r01_co * std::cos(eout_c) / std::sqrt(1 - ecc_c * ecc_c); + } + } + + template + void AnalyticGravity::setup_vars (std::vector v) + { + system_parameters::r_eq = v[0]; + system_parameters::r_polar = v[1]; + system_parameters::r_core_eq = v[2]; + system_parameters::r_core_polar = v[3]; + system_parameters::mantle_rho = v[4]; + system_parameters::core_rho = v[5]; + system_parameters::excess_rho = system_parameters::core_rho - system_parameters::mantle_rho; + + + // Shell + if (system_parameters::r_polar > system_parameters::r_eq) + { + //This makes the gravity field nearly that of a sphere in case the body becomes prolate + std::cout << "\nWarning: The model body has become prolate. \n"; + ecc = 0.001; + } + else + { + ecc = std::sqrt(1 - (system_parameters::r_polar * system_parameters::r_polar / system_parameters::r_eq / system_parameters::r_eq)); + } + + eV = ecc * system_parameters::r_eq; + ke = std::sqrt(1 - (ecc * ecc)) / ecc; + r00 = ke * std::atan2(1, ke); + double ke2 = ke * ke; + r01 = 3 * ke2 * (1 - r00); + r11 = 3 * ((ke2 + 1) * r00 - ke2) / 2; + g_coeff = - 2.795007963255562e-10 * system_parameters::mantle_rho * system_parameters::r_eq; + + // Core + if (system_parameters::r_core_polar > system_parameters::r_core_eq) + { + std::cout << "\nWarning: The model core has become prolate. \n"; + ecc_c = 0.001; + } + else + { + ecc_c = std::sqrt(1 - (system_parameters::r_core_polar * system_parameters::r_core_polar / system_parameters::r_core_eq / system_parameters::r_core_eq)); + } + eV_c = ecc_c * system_parameters::r_core_eq; + if (system_parameters::r_core_polar == system_parameters::r_core_eq) + { + ke_c = 1; + r00_c = 1; + r01_c = 1; + r11_c = 1; + g_coeff_c = - 2.795007963255562e-10 * system_parameters::excess_rho * system_parameters::r_core_eq; + } + else + { + ke_c = std::sqrt(1 - (ecc_c * ecc_c)) / ecc_c; + r00_c = ke_c * std::atan2(1, ke_c); + double ke2_c = ke_c * ke_c; + r01_c = 3 * ke2_c * (1 - r00_c); + r11_c = 3 * ((ke2_c + 1) * r00_c - ke2_c) / 2; + g_coeff_c = - 2.795007963255562e-10 * system_parameters::excess_rho * system_parameters::r_core_eq; + } +// std::cout << "Loaded variables: ecc = " << ecc_c << " ke = " << ke_c << " r00 = " << r00_c << " r01 = " << r01_c << " r11 = " << r11_c << "\n"; + } } diff --git a/CeresFE/support_code/local_math.h b/CeresFE/support_code/local_math.h index cbece34..8817258 100644 --- a/CeresFE/support_code/local_math.h +++ b/CeresFE/support_code/local_math.h @@ -91,5 +91,5 @@ //} -#endif /* LOCALMATH_H */ +#endif /* LOCALMATH_H */ diff --git a/Distributed_LDG_Method/Functions.cc b/Distributed_LDG_Method/Functions.cc index 9963daf..7850be9 100644 --- a/Distributed_LDG_Method/Functions.cc +++ b/Distributed_LDG_Method/Functions.cc @@ -14,33 +14,33 @@ template class RightHandSide : public Function { public: - RightHandSide() : Function(1) - {} + RightHandSide() : Function(1) + {} - virtual double value(const Point &p, - const unsigned int component = 0 ) const; + virtual double value(const Point &p, + const unsigned int component = 0 ) const; }; template class DirichletBoundaryValues : public Function { public: - DirichletBoundaryValues() : Function(1) - {} + DirichletBoundaryValues() : Function(1) + {} - virtual double value(const Point &p, - const unsigned int component = 0 ) const; + virtual double value(const Point &p, + const unsigned int component = 0 ) const; }; template class TrueSolution : public Function { public: - TrueSolution() : Function(dim+1) - {} + TrueSolution() : Function(dim+1) + {} - virtual void vector_value(const Point & p, - Vector &valuess) const; + virtual void vector_value(const Point &p, + Vector &valuess) const; }; template @@ -49,9 +49,9 @@ RightHandSide:: value(const Point &p, const unsigned int ) const { - const double x = p[0]; - const double y = p[1]; - return 4*M_PI*M_PI*(cos(2*M_PI*y) - sin(2*M_PI*x)); + const double x = p[0]; + const double y = p[1]; + return 4*M_PI*M_PI*(cos(2*M_PI*y) - sin(2*M_PI*x)); } @@ -61,9 +61,9 @@ DirichletBoundaryValues:: value(const Point &p, const unsigned int ) const { - const double x = p[0]; - const double y = p[1]; - return cos(2*M_PI*y) -sin(2*M_PI*x) - x; + const double x = p[0]; + const double y = p[1]; + return cos(2*M_PI*y) -sin(2*M_PI*x) - x; } @@ -73,14 +73,14 @@ TrueSolution:: vector_value(const Point &p, Vector &values) const { - Assert(values.size() == dim+1, - ExcDimensionMismatch(values.size(), dim+1) ); + Assert(values.size() == dim+1, + ExcDimensionMismatch(values.size(), dim+1) ); - double x = p[0]; - double y = p[1]; + double x = p[0]; + double y = p[1]; - values(0) = 1 + 2*M_PI*cos(2*M_PI*x); - values(1) = 2*M_PI*sin(2*M_PI*y); + values(0) = 1 + 2*M_PI*cos(2*M_PI*x); + values(1) = 2*M_PI*sin(2*M_PI*y); - values(2) = cos(2*M_PI*y) - sin(2*M_PI*x) - x; + values(2) = cos(2*M_PI*y) - sin(2*M_PI*x) - x; } diff --git a/Distributed_LDG_Method/LDGPoisson.cc b/Distributed_LDG_Method/LDGPoisson.cc index 6f7ee56..2a922e2 100644 --- a/Distributed_LDG_Method/LDGPoisson.cc +++ b/Distributed_LDG_Method/LDGPoisson.cc @@ -24,9 +24,9 @@ #include #include -// Here's where the classes for the DG methods begin. +// Here's where the classes for the DG methods begin. // We can use either the Lagrange polynomials, -#include +#include // or the Legendre polynomials #include // as basis functions. I'll be using the Lagrange polynomials. @@ -54,132 +54,132 @@ #include -// The functions class contains all the defintions of the functions we -// will use, i.e. the right hand side function, the boundary conditions -// and the test functions. +// The functions class contains all the defintions of the functions we +// will use, i.e. the right hand side function, the boundary conditions +// and the test functions. #include "Functions.cc" using namespace dealii; -// Here is the main class for the Local Discontinuous Galerkin method -// applied to Poisson's equation, we won't explain much of the -// the class and method declarations, but dive deeper into describing the -// functions when they are defined. The only thing I will menion -// about the class declaration is that this is where I labeled +// Here is the main class for the Local Discontinuous Galerkin method +// applied to Poisson's equation, we won't explain much of the +// the class and method declarations, but dive deeper into describing the +// functions when they are defined. The only thing I will menion +// about the class declaration is that this is where I labeled // the different types of boundaries using enums. template class LDGPoissonProblem { - + public: - LDGPoissonProblem(const unsigned int degree, - const unsigned int n_refine); + LDGPoissonProblem(const unsigned int degree, + const unsigned int n_refine); - ~LDGPoissonProblem(); + ~LDGPoissonProblem(); - void run(); + void run(); private: - void make_grid(); + void make_grid(); - void make_dofs(); + void make_dofs(); - void assemble_system(); + void assemble_system(); - void assemble_cell_terms(const FEValues &cell_fe, - FullMatrix &cell_matrix, - Vector &cell_vector); + void assemble_cell_terms(const FEValues &cell_fe, + FullMatrix &cell_matrix, + Vector &cell_vector); - void assemble_Neumann_boundary_terms(const FEFaceValues &face_fe, - FullMatrix &local_matrix, - Vector &local_vector); + void assemble_Neumann_boundary_terms(const FEFaceValues &face_fe, + FullMatrix &local_matrix, + Vector &local_vector); - void assemble_Dirichlet_boundary_terms(const FEFaceValues &face_fe, - FullMatrix &local_matrix, - Vector &local_vector, - const double & h); + void assemble_Dirichlet_boundary_terms(const FEFaceValues &face_fe, + FullMatrix &local_matrix, + Vector &local_vector, + const double &h); - void assemble_flux_terms(const FEFaceValuesBase &fe_face_values, - const FEFaceValuesBase &fe_neighbor_face_values, - FullMatrix &vi_ui_matrix, - FullMatrix &vi_ue_matrix, - FullMatrix &ve_ui_matrix, - FullMatrix &ve_ue_matrix, - const double & h); + void assemble_flux_terms(const FEFaceValuesBase &fe_face_values, + const FEFaceValuesBase &fe_neighbor_face_values, + FullMatrix &vi_ui_matrix, + FullMatrix &vi_ue_matrix, + FullMatrix &ve_ui_matrix, + FullMatrix &ve_ue_matrix, + const double &h); - void distribute_local_flux_to_global( - const FullMatrix & vi_ui_matrix, - const FullMatrix & vi_ue_matrix, - const FullMatrix & ve_ui_matrix, - const FullMatrix & ve_ue_matrix, - const std::vector & local_dof_indices, - const std::vector & local_neighbor_dof_indices); + void distribute_local_flux_to_global( + const FullMatrix &vi_ui_matrix, + const FullMatrix &vi_ue_matrix, + const FullMatrix &ve_ui_matrix, + const FullMatrix &ve_ue_matrix, + const std::vector &local_dof_indices, + const std::vector &local_neighbor_dof_indices); - void solve(); + void solve(); - void output_results() const; + void output_results() const; - const unsigned int degree; - const unsigned int n_refine; - double penalty; - double h_max; - double h_min; + const unsigned int degree; + const unsigned int n_refine; + double penalty; + double h_max; + double h_min; - enum - { - Dirichlet, - Neumann - }; + enum + { + Dirichlet, + Neumann + }; - parallel::distributed::Triangulation triangulation; - FESystem fe; - DoFHandler dof_handler; + parallel::distributed::Triangulation triangulation; + FESystem fe; + DoFHandler dof_handler; - ConstraintMatrix constraints; + ConstraintMatrix constraints; - SparsityPattern sparsity_pattern; + SparsityPattern sparsity_pattern; - TrilinosWrappers::SparseMatrix system_matrix; - TrilinosWrappers::MPI::Vector locally_relevant_solution; - TrilinosWrappers::MPI::Vector system_rhs; + TrilinosWrappers::SparseMatrix system_matrix; + TrilinosWrappers::MPI::Vector locally_relevant_solution; + TrilinosWrappers::MPI::Vector system_rhs; - ConditionalOStream pcout; - TimerOutput computing_timer; + ConditionalOStream pcout; + TimerOutput computing_timer; - SolverControl solver_control; - TrilinosWrappers::SolverDirect solver; + SolverControl solver_control; + TrilinosWrappers::SolverDirect solver; - const RightHandSide rhs_function; - const DirichletBoundaryValues Dirichlet_bc_function; - const TrueSolution true_solution; + const RightHandSide rhs_function; + const DirichletBoundaryValues Dirichlet_bc_function; + const TrueSolution true_solution; }; // @sect4{Class constructor and destructor} -// The constructor and destructor for this class is very much like the -// like those for step-40. The difference being that we'll be passing -// in an integer, degree, which tells us the maxiumum order -// of the polynomial to use as well as n_refine which is the -// global number of times we refine our mesh. The other main differences -// are that we use a FESystem object for our choice of basis +// The constructor and destructor for this class is very much like the +// like those for step-40. The difference being that we'll be passing +// in an integer, degree, which tells us the maxiumum order +// of the polynomial to use as well as n_refine which is the +// global number of times we refine our mesh. The other main differences +// are that we use a FESystem object for our choice of basis // functions. This is reminiscent of the mixed finite element method in // step-20, however, in our case we use a FESystem // of the form, // -// +// // fe( FESystem(FE_DGQ(degree), dim), 1, -// FE_DGQ(degree), 1) +// FE_DGQ(degree), 1) // -// +// // which tells us that the basis functions contain discontinous polynomials // of order degree in each of the dim dimensions // for the vector field. For the scalar unknown we -// use a discontinuous polynomial of the order degree. -// The LDG method for Poisson equations solves for both the primary variable -// as well as its gradient, just like the mixed finite element method. -// However, unlike the mixed method, the LDG method uses discontinuous +// use a discontinuous polynomial of the order degree. +// The LDG method for Poisson equations solves for both the primary variable +// as well as its gradient, just like the mixed finite element method. +// However, unlike the mixed method, the LDG method uses discontinuous // polynomials to approximate both variables. // The other difference bewteen our constructor and that of step-40 is that // we all instantiate our linear solver in the constructor definition. @@ -187,26 +187,26 @@ template LDGPoissonProblem:: LDGPoissonProblem(const unsigned int degree, const unsigned int n_refine) - : - degree(degree), - n_refine(n_refine), - triangulation(MPI_COMM_WORLD, - typename Triangulation::MeshSmoothing - (Triangulation::smoothing_on_refinement | - Triangulation::smoothing_on_coarsening)), - fe( FESystem(FE_DGQ(degree), dim), 1, - FE_DGQ(degree), 1), - dof_handler(triangulation), - pcout(std::cout, - Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0), - computing_timer(MPI_COMM_WORLD, - pcout, - TimerOutput::summary, - TimerOutput::wall_times), - solver_control(1), - solver(solver_control), - rhs_function(), - Dirichlet_bc_function() + : + degree(degree), + n_refine(n_refine), + triangulation(MPI_COMM_WORLD, + typename Triangulation::MeshSmoothing + (Triangulation::smoothing_on_refinement | + Triangulation::smoothing_on_coarsening)), + fe( FESystem(FE_DGQ(degree), dim), 1, + FE_DGQ(degree), 1), + dof_handler(triangulation), + pcout(std::cout, + Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0), + computing_timer(MPI_COMM_WORLD, + pcout, + TimerOutput::summary, + TimerOutput::wall_times), + solver_control(1), + solver(solver_control), + rhs_function(), + Dirichlet_bc_function() { } @@ -214,7 +214,7 @@ template LDGPoissonProblem:: ~LDGPoissonProblem() { - dof_handler.clear(); + dof_handler.clear(); } // @sect4{Make_grid} @@ -230,42 +230,42 @@ make_grid() triangulation.refine_global(n_refine); unsigned int local_refine = 2; - for(unsigned int i =0; i ::active_cell_iterator - cell = triangulation.begin_active(), - endc = triangulation.end(); - - // We loop over all the cells in the mesh - // and mark the appropriate cells for refinement. - // In this example we only choose cells which are - // near $x=0$ and $x=1$ in the - // the domain. This was just to show that - // the LDG method is working with local - // refinement and discussions on building - // more realistic refinement stategies are - // discussed elsewhere in the deal.ii - // documentation. - for(; cell != endc; cell++) + for (unsigned int i =0; i ::active_cell_iterator + cell = triangulation.begin_active(), + endc = triangulation.end(); + + // We loop over all the cells in the mesh + // and mark the appropriate cells for refinement. + // In this example we only choose cells which are + // near $x=0$ and $x=1$ in the + // the domain. This was just to show that + // the LDG method is working with local + // refinement and discussions on building + // more realistic refinement stategies are + // discussed elsewhere in the deal.ii + // documentation. + for (; cell != endc; cell++) { - if((cell->center()[1]) > 0.9 ) + if ((cell->center()[1]) > 0.9 ) { - if((cell->center()[0] > 0.9) || (cell->center()[0] < 0.1)) - cell->set_refine_flag(); + if ((cell->center()[0] > 0.9) || (cell->center()[0] < 0.1)) + cell->set_refine_flag(); } } - // Now that we have marked all the cells - // that we want to refine locally we can go ahead and - // refine them. - triangulation.execute_coarsening_and_refinement(); - } + // Now that we have marked all the cells + // that we want to refine locally we can go ahead and + // refine them. + triangulation.execute_coarsening_and_refinement(); + } // To label the boundary faces of the mesh with their // type, i.e. Dirichlet or Neumann, // we loop over all the cells in the mesh and then over // all the faces of each cell. We then have to figure out - // which faces are on the bounadry and set all faces - // on the boundary to have + // which faces are on the bounadry and set all faces + // on the boundary to have // boundary_id to be Dirichlet. // We remark that one could easily set more complicated // conditions where there are both Dirichlet or @@ -273,147 +273,147 @@ make_grid() typename Triangulation::cell_iterator cell = triangulation.begin(), endc = triangulation.end(); - for(; cell != endc; cell++) - { - for(unsigned int face_no=0; - face_no < GeometryInfo::faces_per_cell; - face_no++) + for (; cell != endc; cell++) { - if(cell->face(face_no)->at_boundary() ) - cell->face(face_no)->set_boundary_id(Dirichlet); - } - } + for (unsigned int face_no=0; + face_no < GeometryInfo::faces_per_cell; + face_no++) + { + if (cell->face(face_no)->at_boundary() ) + cell->face(face_no)->set_boundary_id(Dirichlet); + } + } } // @sect3{make_dofs} -// This function is responsible for distributing the degrees of -// freedom (dofs) to the processors and allocating memory for +// This function is responsible for distributing the degrees of +// freedom (dofs) to the processors and allocating memory for // the global system matrix, system_matrix, -// and global right hand side vector, system_rhs . -// The dofs are the unknown coefficients for the polynomial -// approximation of our solution to Poisson's equation in the scalar +// and global right hand side vector, system_rhs . +// The dofs are the unknown coefficients for the polynomial +// approximation of our solution to Poisson's equation in the scalar // variable and its gradient. template void LDGPoissonProblem:: make_dofs() { - TimerOutput::Scope t(computing_timer, "setup"); - - // The first step to setting up our linear system is to - // distribute the degrees of freedom (dofs) across the processors, - // this is done with the distribute_dofs() - // method of the DoFHandler. We remark - // the same exact function call that occurs when using deal.ii - // on a single machine, the DoFHandler automatically knows - // that we are distributed setting because it was instantiated - // with a distributed triangulation! - dof_handler.distribute_dofs(fe); - - // We now renumber the dofs so that the vector of unkonwn dofs - // that we are solving for, locally_relevant_solution, - // corresponds to a vector of the form, - // - // $ \left[\begin{matrix} \textbf{Q} \\ \textbf{U} \end{matrix}\right] $ - DoFRenumbering::component_wise(dof_handler); - - // Now we get the locally owned dofs, that is the dofs that our local - // to this processor. These dofs corresponding entries in the - // matrix and vectors that we will write to. - IndexSet locally_owned_dofs = dof_handler.locally_owned_dofs(); - - // In additon to the locally owned dofs, we also need the the locally - // relevant dofs. These are the dofs that have read access to and we - // need in order to do computations on our processor, but, that - // we do not have the ability to write to. - IndexSet locally_relevant_dofs; - DoFTools::extract_locally_relevant_dofs(dof_handler, - locally_relevant_dofs); - - std::vector dofs_per_component(dim+1); - DoFTools::count_dofs_per_component(dof_handler, dofs_per_component); - - // Discontinuous Galerkin methods are fantanistic methods in part because - // many of the limitations of traditional finite element methods no longer - // exist. Specifically, the need to use constraint matrices - // in order handle hanging nodes is no longer necessary. However, - // we will continue to use the constraint matrices inorder to efficiently - // distribute local computations to the global system, i.e. to the - // system_matrix and system_rhs. Therefore, we - // just instantiate the constraints matrix object, clear and close it. - constraints.clear(); - constraints.close(); - - - // Just like step-40 we create a dynamic sparsity pattern - // and distribute it to the processors. Notice how we do not have to - // explictly mention that we are using a FESystem for system of - // variables instead of a FE_DGQ for a scalar variable - // or that we are using a discributed DoFHandler. All these specifics - // are taken care of under the hood by the deal.ii library. - // In order to build the sparsity - // pattern we use the DoFTools::make_flux_sparsity_pattern function - // since we using a DG method and need to take into account the DG - // fluxes in the sparsity pattern. - DynamicSparsityPattern dsp(dof_handler.n_dofs()); - DoFTools::make_flux_sparsity_pattern(dof_handler, - dsp); - - SparsityTools::distribute_sparsity_pattern(dsp, - dof_handler.n_locally_owned_dofs_per_processor(), - MPI_COMM_WORLD, - locally_relevant_dofs); - - // Here is one area that I had to learn the hard way. The local - // discontinuous Galerkin method like the mixed method with the - // Raviart-Thomas element is written - // in mixed form and will lead to a block-structured matrix. - // In step-20 we see that we that we initialize the - // system_martrix - // such that we explicitly declare it to be block-structured. - // It turns out there are reasons to do this when you are going to be - // using a Schur complement method to solve the system of equations. - // While the LDG method will lead to a block-structured matrix, - // we do not have to explicitly declare our matrix to be one. - // I found that most of the distributed linear solvers did not - // accept block structured matrices and since I was using a - // distributed direct solver it was unnecessary to explicitly use a - // block structured matrix. - system_matrix.reinit(locally_owned_dofs, - locally_owned_dofs, - dsp, - MPI_COMM_WORLD); - - // The final note that I will make in that this subroutine is that - // we initialize this processors solution and the - // right hand side vector the exact same was as we did in step-40. - // We should note that the locally_relevant_solution solution - // vector includes dofs that are locally relevant to our computations - // while the system_rhs right hand side vector will only - // include dofs that are locally owned by this processor. - locally_relevant_solution.reinit(locally_relevant_dofs, - MPI_COMM_WORLD); - - system_rhs.reinit(locally_owned_dofs, - locally_relevant_dofs, - MPI_COMM_WORLD, - true); - - const unsigned int n_vector_field = dim * dofs_per_component[0]; - const unsigned int n_potential = dofs_per_component[dim]; - - pcout << "Number of active cells : " - << triangulation.n_global_active_cells() - << std::endl - << "Number of degrees of freedom: " - << dof_handler.n_dofs() - << " (" << n_vector_field << " + " << n_potential << ")" - << std::endl; + TimerOutput::Scope t(computing_timer, "setup"); + + // The first step to setting up our linear system is to + // distribute the degrees of freedom (dofs) across the processors, + // this is done with the distribute_dofs() + // method of the DoFHandler. We remark + // the same exact function call that occurs when using deal.ii + // on a single machine, the DoFHandler automatically knows + // that we are distributed setting because it was instantiated + // with a distributed triangulation! + dof_handler.distribute_dofs(fe); + + // We now renumber the dofs so that the vector of unkonwn dofs + // that we are solving for, locally_relevant_solution, + // corresponds to a vector of the form, + // + // $ \left[\begin{matrix} \textbf{Q} \\ \textbf{U} \end{matrix}\right] $ + DoFRenumbering::component_wise(dof_handler); + + // Now we get the locally owned dofs, that is the dofs that our local + // to this processor. These dofs corresponding entries in the + // matrix and vectors that we will write to. + IndexSet locally_owned_dofs = dof_handler.locally_owned_dofs(); + + // In additon to the locally owned dofs, we also need the the locally + // relevant dofs. These are the dofs that have read access to and we + // need in order to do computations on our processor, but, that + // we do not have the ability to write to. + IndexSet locally_relevant_dofs; + DoFTools::extract_locally_relevant_dofs(dof_handler, + locally_relevant_dofs); + + std::vector dofs_per_component(dim+1); + DoFTools::count_dofs_per_component(dof_handler, dofs_per_component); + + // Discontinuous Galerkin methods are fantanistic methods in part because + // many of the limitations of traditional finite element methods no longer + // exist. Specifically, the need to use constraint matrices + // in order handle hanging nodes is no longer necessary. However, + // we will continue to use the constraint matrices inorder to efficiently + // distribute local computations to the global system, i.e. to the + // system_matrix and system_rhs. Therefore, we + // just instantiate the constraints matrix object, clear and close it. + constraints.clear(); + constraints.close(); + + + // Just like step-40 we create a dynamic sparsity pattern + // and distribute it to the processors. Notice how we do not have to + // explictly mention that we are using a FESystem for system of + // variables instead of a FE_DGQ for a scalar variable + // or that we are using a discributed DoFHandler. All these specifics + // are taken care of under the hood by the deal.ii library. + // In order to build the sparsity + // pattern we use the DoFTools::make_flux_sparsity_pattern function + // since we using a DG method and need to take into account the DG + // fluxes in the sparsity pattern. + DynamicSparsityPattern dsp(dof_handler.n_dofs()); + DoFTools::make_flux_sparsity_pattern(dof_handler, + dsp); + + SparsityTools::distribute_sparsity_pattern(dsp, + dof_handler.n_locally_owned_dofs_per_processor(), + MPI_COMM_WORLD, + locally_relevant_dofs); + + // Here is one area that I had to learn the hard way. The local + // discontinuous Galerkin method like the mixed method with the + // Raviart-Thomas element is written + // in mixed form and will lead to a block-structured matrix. + // In step-20 we see that we that we initialize the + // system_martrix + // such that we explicitly declare it to be block-structured. + // It turns out there are reasons to do this when you are going to be + // using a Schur complement method to solve the system of equations. + // While the LDG method will lead to a block-structured matrix, + // we do not have to explicitly declare our matrix to be one. + // I found that most of the distributed linear solvers did not + // accept block structured matrices and since I was using a + // distributed direct solver it was unnecessary to explicitly use a + // block structured matrix. + system_matrix.reinit(locally_owned_dofs, + locally_owned_dofs, + dsp, + MPI_COMM_WORLD); + + // The final note that I will make in that this subroutine is that + // we initialize this processors solution and the + // right hand side vector the exact same was as we did in step-40. + // We should note that the locally_relevant_solution solution + // vector includes dofs that are locally relevant to our computations + // while the system_rhs right hand side vector will only + // include dofs that are locally owned by this processor. + locally_relevant_solution.reinit(locally_relevant_dofs, + MPI_COMM_WORLD); + + system_rhs.reinit(locally_owned_dofs, + locally_relevant_dofs, + MPI_COMM_WORLD, + true); + + const unsigned int n_vector_field = dim * dofs_per_component[0]; + const unsigned int n_potential = dofs_per_component[dim]; + + pcout << "Number of active cells : " + << triangulation.n_global_active_cells() + << std::endl + << "Number of degrees of freedom: " + << dof_handler.n_dofs() + << " (" << n_vector_field << " + " << n_potential << ")" + << std::endl; } //@sect4{assemble_system} -// This is the function that will assemble the global system matrix and -// global right hand side vector for the LDG method. It starts out +// This is the function that will assemble the global system matrix and +// global right hand side vector for the LDG method. It starts out // like many of the deal.ii tutorial codes: declaring quadrature formulas // and UpdateFlags objects, as well as vectors that will hold the // dof indices for the cells we are working on in the global system. @@ -422,479 +422,479 @@ void LDGPoissonProblem:: assemble_system() { - TimerOutput::Scope t(computing_timer, "assembly"); - - QGauss quadrature_formula(fe.degree+1); - QGauss face_quadrature_formula(fe.degree+1); - - const UpdateFlags update_flags = update_values - | update_gradients - | update_quadrature_points - | update_JxW_values; - - const UpdateFlags face_update_flags = update_values - | update_normal_vectors - | update_quadrature_points - | update_JxW_values; - - const unsigned int dofs_per_cell = fe.dofs_per_cell; - std::vector local_dof_indices(dofs_per_cell); - std::vector - local_neighbor_dof_indices(dofs_per_cell); - - // We first remark that we have the FEValues objects for - // the values of our cell basis functions as was done in most - // other examples. Now because we - // are using discontinuous Galerkin methods we also introduce a - // FEFaceValues object, fe_face_values, - // for evaluating the basis functions - // on one side of an element face as well as another FEFaceValues object, - // fe_neighbor_face_values, for evaluating the basis functions - // on the opposite side of the face, i.e. on the neighoring element's face. - // In addition, we also introduce a FESubfaceValues object, - // fe_subface_values, that - // will be used for dealing with faces that have multiple refinement - // levels, i.e. hanging nodes. When we have to evaluate the fluxes across - // a face that multiple refinement levels, we need to evaluate the - // fluxes across all its childrens' faces; we'll explain this more when - // the time comes. - FEValues fe_values(fe, quadrature_formula, update_flags); - - FEFaceValues fe_face_values(fe,face_quadrature_formula, - face_update_flags); - - FEFaceValues fe_neighbor_face_values(fe, - face_quadrature_formula, - face_update_flags); - - FESubfaceValues fe_subface_values(fe, face_quadrature_formula, - face_update_flags); - - // Here are the local (dense) matrix and right hand side vector for - // the solid integrals as well as the integrals on the boundaries in the - // local discontinuous Galerkin method. These terms will be built for - // each local element in the mesh and then distributed to the global - // system matrix and right hand side vector. - FullMatrix local_matrix(dofs_per_cell,dofs_per_cell); - Vector local_vector(dofs_per_cell); - - // The next four matrices are used to incorporate the flux integrals across - // interior faces of the mesh: - FullMatrix vi_ui_matrix(dofs_per_cell, dofs_per_cell); - FullMatrix vi_ue_matrix(dofs_per_cell, dofs_per_cell); - FullMatrix ve_ui_matrix(dofs_per_cell, dofs_per_cell); - FullMatrix ve_ue_matrix(dofs_per_cell, dofs_per_cell); - // As explained in the section on the LDG method we take our test - // function to be v and multiply it on the left side of our differential - // equation that is on u and peform integration by parts as explained in the - // introduction. Using this notation for test and solution function, - // the matrices below will then stand for: - // - // vi_ui - Taking the value of the test function from - // interior of this cell's face and the solution function - // from the interior of this cell. - // - // vi_ue - Taking the value of the test function from - // interior of this cell's face and the solution function - // from the exterior of this cell. - // - // ve_ui - Taking the value of the test function from - // exterior of this cell's face and the solution function - // from the interior of this cell. - // - // ve_ue - Taking the value of the test function from - // exterior of this cell's face and the solution function - // from the exterior of this cell. - - // Now that we have gotten preliminary orders out of the way, - // we loop over all the cells - // and assemble the local system matrix and local right hand side vector - // using the DoFHandler::active_cell_iterator, - typename DoFHandler::active_cell_iterator - cell = dof_handler.begin_active(), - endc = dof_handler.end(); - - for(; cell!=endc; cell++) + TimerOutput::Scope t(computing_timer, "assembly"); + + QGauss quadrature_formula(fe.degree+1); + QGauss face_quadrature_formula(fe.degree+1); + + const UpdateFlags update_flags = update_values + | update_gradients + | update_quadrature_points + | update_JxW_values; + + const UpdateFlags face_update_flags = update_values + | update_normal_vectors + | update_quadrature_points + | update_JxW_values; + + const unsigned int dofs_per_cell = fe.dofs_per_cell; + std::vector local_dof_indices(dofs_per_cell); + std::vector + local_neighbor_dof_indices(dofs_per_cell); + + // We first remark that we have the FEValues objects for + // the values of our cell basis functions as was done in most + // other examples. Now because we + // are using discontinuous Galerkin methods we also introduce a + // FEFaceValues object, fe_face_values, + // for evaluating the basis functions + // on one side of an element face as well as another FEFaceValues object, + // fe_neighbor_face_values, for evaluating the basis functions + // on the opposite side of the face, i.e. on the neighoring element's face. + // In addition, we also introduce a FESubfaceValues object, + // fe_subface_values, that + // will be used for dealing with faces that have multiple refinement + // levels, i.e. hanging nodes. When we have to evaluate the fluxes across + // a face that multiple refinement levels, we need to evaluate the + // fluxes across all its childrens' faces; we'll explain this more when + // the time comes. + FEValues fe_values(fe, quadrature_formula, update_flags); + + FEFaceValues fe_face_values(fe,face_quadrature_formula, + face_update_flags); + + FEFaceValues fe_neighbor_face_values(fe, + face_quadrature_formula, + face_update_flags); + + FESubfaceValues fe_subface_values(fe, face_quadrature_formula, + face_update_flags); + + // Here are the local (dense) matrix and right hand side vector for + // the solid integrals as well as the integrals on the boundaries in the + // local discontinuous Galerkin method. These terms will be built for + // each local element in the mesh and then distributed to the global + // system matrix and right hand side vector. + FullMatrix local_matrix(dofs_per_cell,dofs_per_cell); + Vector local_vector(dofs_per_cell); + + // The next four matrices are used to incorporate the flux integrals across + // interior faces of the mesh: + FullMatrix vi_ui_matrix(dofs_per_cell, dofs_per_cell); + FullMatrix vi_ue_matrix(dofs_per_cell, dofs_per_cell); + FullMatrix ve_ui_matrix(dofs_per_cell, dofs_per_cell); + FullMatrix ve_ue_matrix(dofs_per_cell, dofs_per_cell); + // As explained in the section on the LDG method we take our test + // function to be v and multiply it on the left side of our differential + // equation that is on u and peform integration by parts as explained in the + // introduction. Using this notation for test and solution function, + // the matrices below will then stand for: + // + // vi_ui - Taking the value of the test function from + // interior of this cell's face and the solution function + // from the interior of this cell. + // + // vi_ue - Taking the value of the test function from + // interior of this cell's face and the solution function + // from the exterior of this cell. + // + // ve_ui - Taking the value of the test function from + // exterior of this cell's face and the solution function + // from the interior of this cell. + // + // ve_ue - Taking the value of the test function from + // exterior of this cell's face and the solution function + // from the exterior of this cell. + + // Now that we have gotten preliminary orders out of the way, + // we loop over all the cells + // and assemble the local system matrix and local right hand side vector + // using the DoFHandler::active_cell_iterator, + typename DoFHandler::active_cell_iterator + cell = dof_handler.begin_active(), + endc = dof_handler.end(); + + for (; cell!=endc; cell++) { - // Now, since we are working in a distributed setting, - // we can only work on cells and write to dofs in the - // system_matrix - // and rhs_vector - // that corresponds to cells that are locally owned - // by this processor. We note that while we can only write to locally - // owned dofs, we will still use information from cells that are - // locally relevant. This is very much the same as in step-40. - if(cell->is_locally_owned()) + // Now, since we are working in a distributed setting, + // we can only work on cells and write to dofs in the + // system_matrix + // and rhs_vector + // that corresponds to cells that are locally owned + // by this processor. We note that while we can only write to locally + // owned dofs, we will still use information from cells that are + // locally relevant. This is very much the same as in step-40. + if (cell->is_locally_owned()) { - // We now assemble the local contributions to the system matrix - // that includes the solid integrals in the LDG method as well as - // the right hand side vector. This involves resetting the local - // matrix and vector to contain all zeros, reinitializing the - // FEValues object for this cell and then building the - // local_matrix and local_rhs vector. - local_matrix = 0; - local_vector = 0; - - fe_values.reinit(cell); - assemble_cell_terms(fe_values, - local_matrix, - local_vector); - - // We remark that we need to get the local indices for the dofs to - // to this cell before we begin to compute the contributions - // from the numerical fluxes, i.e. the boundary conditions and - // interior fluxes. - cell->get_dof_indices(local_dof_indices); - - // Now is where we start to loop over all the faces of the cell - // and construct the local contribtuions from the numerical fluxes. - // The numerical fluxes will be due to 3 contributions: the - // interior faces, the faces on the Neumann boundary and the faces - // on the Dirichlet boundary. We instantiate a - // face_iterator to loop - // over all the faces of this cell and first see if the face is on - // the boundary. Notice how we do not reinitiaize the - // fe_face_values - // object for the face until we know that we are actually on face - // that lies on the boundary of the domain. The reason for doing this - // is for computational efficiency; reinitializing the FEFaceValues - // for each face is expensive and we do not want to do it unless we - // are actually going use it to do computations. After this, we test - // if the face - // is on the a Dirichlet or a Neumann segment of the boundary and - // call the appropriate subroutine to assemble the contributions for - // that boundary. Note that this assembles the flux contribution - // in the local_matrix as well as the boundary - // condition that ends up - // in the local_vector. - for(unsigned int face_no=0; - face_no< GeometryInfo::faces_per_cell; - face_no++) + // We now assemble the local contributions to the system matrix + // that includes the solid integrals in the LDG method as well as + // the right hand side vector. This involves resetting the local + // matrix and vector to contain all zeros, reinitializing the + // FEValues object for this cell and then building the + // local_matrix and local_rhs vector. + local_matrix = 0; + local_vector = 0; + + fe_values.reinit(cell); + assemble_cell_terms(fe_values, + local_matrix, + local_vector); + + // We remark that we need to get the local indices for the dofs to + // to this cell before we begin to compute the contributions + // from the numerical fluxes, i.e. the boundary conditions and + // interior fluxes. + cell->get_dof_indices(local_dof_indices); + + // Now is where we start to loop over all the faces of the cell + // and construct the local contribtuions from the numerical fluxes. + // The numerical fluxes will be due to 3 contributions: the + // interior faces, the faces on the Neumann boundary and the faces + // on the Dirichlet boundary. We instantiate a + // face_iterator to loop + // over all the faces of this cell and first see if the face is on + // the boundary. Notice how we do not reinitiaize the + // fe_face_values + // object for the face until we know that we are actually on face + // that lies on the boundary of the domain. The reason for doing this + // is for computational efficiency; reinitializing the FEFaceValues + // for each face is expensive and we do not want to do it unless we + // are actually going use it to do computations. After this, we test + // if the face + // is on the a Dirichlet or a Neumann segment of the boundary and + // call the appropriate subroutine to assemble the contributions for + // that boundary. Note that this assembles the flux contribution + // in the local_matrix as well as the boundary + // condition that ends up + // in the local_vector. + for (unsigned int face_no=0; + face_no< GeometryInfo::faces_per_cell; + face_no++) { - typename DoFHandler::face_iterator face = - cell->face(face_no); + typename DoFHandler::face_iterator face = + cell->face(face_no); - if(face->at_boundary() ) + if (face->at_boundary() ) { - fe_face_values.reinit(cell, face_no); + fe_face_values.reinit(cell, face_no); - if(face->boundary_id() == Dirichlet) + if (face->boundary_id() == Dirichlet) { - // Here notice that in order to assemble the - // flux due to the penalty term for the the - // Dirichlet boundary condition we need the - // local cell diameter size and we can get - // that value for this specific cell with - // the following, - double h = cell->diameter(); - assemble_Dirichlet_boundary_terms(fe_face_values, - local_matrix, - local_vector, - h); + // Here notice that in order to assemble the + // flux due to the penalty term for the the + // Dirichlet boundary condition we need the + // local cell diameter size and we can get + // that value for this specific cell with + // the following, + double h = cell->diameter(); + assemble_Dirichlet_boundary_terms(fe_face_values, + local_matrix, + local_vector, + h); } - else if(face->boundary_id() == Neumann) + else if (face->boundary_id() == Neumann) { - assemble_Neumann_boundary_terms(fe_face_values, - local_matrix, - local_vector); + assemble_Neumann_boundary_terms(fe_face_values, + local_matrix, + local_vector); } - else - Assert(false, ExcNotImplemented() ); + else + Assert(false, ExcNotImplemented() ); } - else + else { - // At this point we know that the face we are on is an - // interior face. We can begin to assemble the interior - // flux matrices, but first we want to make sure that the - // neighbor cell to this face is a valid cell. Once we know - // that the neighbor is a valid cell then we also want to get - // the meighbor cell that shares this cell's face. - // - Assert(cell->neighbor(face_no).state() == - IteratorState::valid, - ExcInternalError()); - - typename DoFHandler::cell_iterator neighbor = - cell->neighbor(face_no); - - // Now that we have the two cells whose face we want to - // compute the numerical flux across, we need to know - // if the face has been refined, i.e. if it has children - // faces. This occurs when one of the cells has a - // different level of refinement than - // the other cell. If this is the case, then this face - // has a different level of refinement than the other faces - // of the cell, i.e. on this face there is a hanging node. - // Hanging nodes are not a problem in DG methods, the only - // time we have to watch out for them is at this step - // and as you will see the changes we have to our make - // are minor. - if(face->has_children()) + // At this point we know that the face we are on is an + // interior face. We can begin to assemble the interior + // flux matrices, but first we want to make sure that the + // neighbor cell to this face is a valid cell. Once we know + // that the neighbor is a valid cell then we also want to get + // the meighbor cell that shares this cell's face. + // + Assert(cell->neighbor(face_no).state() == + IteratorState::valid, + ExcInternalError()); + + typename DoFHandler::cell_iterator neighbor = + cell->neighbor(face_no); + + // Now that we have the two cells whose face we want to + // compute the numerical flux across, we need to know + // if the face has been refined, i.e. if it has children + // faces. This occurs when one of the cells has a + // different level of refinement than + // the other cell. If this is the case, then this face + // has a different level of refinement than the other faces + // of the cell, i.e. on this face there is a hanging node. + // Hanging nodes are not a problem in DG methods, the only + // time we have to watch out for them is at this step + // and as you will see the changes we have to our make + // are minor. + if (face->has_children()) { - // We now need to find the face of our neighbor cell - // such that neighbor(neigh_face_no) = cell(face_no). - const unsigned int neighbor_face_no = - cell->neighbor_of_neighbor(face_no); - - // Once we do this we then have to loop over all the - // subfaces (children faces) of our cell's face and - // compute the interior fluxes across the children faces - // and the neighbor's face. - for(unsigned int subface_no=0; - subface_no < face->number_of_children(); - ++subface_no) + // We now need to find the face of our neighbor cell + // such that neighbor(neigh_face_no) = cell(face_no). + const unsigned int neighbor_face_no = + cell->neighbor_of_neighbor(face_no); + + // Once we do this we then have to loop over all the + // subfaces (children faces) of our cell's face and + // compute the interior fluxes across the children faces + // and the neighbor's face. + for (unsigned int subface_no=0; + subface_no < face->number_of_children(); + ++subface_no) { - // We then get the neighbor cell's subface that - // matches our cell face's subface and the - // specific subface number. We assert that the parent - // face cannot be more than one level of - // refinement above the child's face. This is - // because the deal.ii library does not allow - // neighboring cells to have refinement levels - // that are more than one level in difference. - typename DoFHandler::cell_iterator neighbor_child = - cell->neighbor_child_on_subface(face_no, - subface_no); - - Assert(!neighbor_child->has_children(), - ExcInternalError()); - - // Now that we are ready to build the local flux - // matrices for - // this face we reset them e zero and - // reinitialize this fe_values - // to this cell's subface and - // neighbor_child's - // FEFaceValues and the FESubfaceValues - // objects on the appropriate faces. - vi_ui_matrix = 0; - vi_ue_matrix = 0; - ve_ui_matrix = 0; - ve_ue_matrix = 0; - - fe_subface_values.reinit(cell, face_no, subface_no); - fe_neighbor_face_values.reinit(neighbor_child, - neighbor_face_no); - - // In addition, we get the minimum of diameters of - // the two cells to include in the penalty term - double h = std::min(cell->diameter(), - neighbor_child->diameter()); - - // We now finally assemble the interior fluxes for - // the case of a face which has been refined using - // exactly the same subroutine as we do when both - // cells have the same refinement level. - assemble_flux_terms(fe_subface_values, - fe_neighbor_face_values, - vi_ui_matrix, - vi_ue_matrix, - ve_ui_matrix, - ve_ue_matrix, - h); - - // Now all that is left to be done before distribuing - // the local flux matrices to the global system - // is get the neighbor child faces dof indices. - neighbor_child->get_dof_indices(local_neighbor_dof_indices); - - // Once we have this cells dof indices and the - // neighboring cell's dof indices we can use the - // ConstraintMatrix to distribute the local flux - // matrices to the global system matrix. - // This is done through the class function - // distribute_local_flux_to_global(). - distribute_local_flux_to_global( - vi_ui_matrix, - vi_ue_matrix, - ve_ui_matrix, - ve_ue_matrix, - local_dof_indices, - local_neighbor_dof_indices); - } - } - else + // We then get the neighbor cell's subface that + // matches our cell face's subface and the + // specific subface number. We assert that the parent + // face cannot be more than one level of + // refinement above the child's face. This is + // because the deal.ii library does not allow + // neighboring cells to have refinement levels + // that are more than one level in difference. + typename DoFHandler::cell_iterator neighbor_child = + cell->neighbor_child_on_subface(face_no, + subface_no); + + Assert(!neighbor_child->has_children(), + ExcInternalError()); + + // Now that we are ready to build the local flux + // matrices for + // this face we reset them e zero and + // reinitialize this fe_values + // to this cell's subface and + // neighbor_child's + // FEFaceValues and the FESubfaceValues + // objects on the appropriate faces. + vi_ui_matrix = 0; + vi_ue_matrix = 0; + ve_ui_matrix = 0; + ve_ue_matrix = 0; + + fe_subface_values.reinit(cell, face_no, subface_no); + fe_neighbor_face_values.reinit(neighbor_child, + neighbor_face_no); + + // In addition, we get the minimum of diameters of + // the two cells to include in the penalty term + double h = std::min(cell->diameter(), + neighbor_child->diameter()); + + // We now finally assemble the interior fluxes for + // the case of a face which has been refined using + // exactly the same subroutine as we do when both + // cells have the same refinement level. + assemble_flux_terms(fe_subface_values, + fe_neighbor_face_values, + vi_ui_matrix, + vi_ue_matrix, + ve_ui_matrix, + ve_ue_matrix, + h); + + // Now all that is left to be done before distribuing + // the local flux matrices to the global system + // is get the neighbor child faces dof indices. + neighbor_child->get_dof_indices(local_neighbor_dof_indices); + + // Once we have this cells dof indices and the + // neighboring cell's dof indices we can use the + // ConstraintMatrix to distribute the local flux + // matrices to the global system matrix. + // This is done through the class function + // distribute_local_flux_to_global(). + distribute_local_flux_to_global( + vi_ui_matrix, + vi_ue_matrix, + ve_ui_matrix, + ve_ue_matrix, + local_dof_indices, + local_neighbor_dof_indices); + } + } + else { - // At this point we know that this cell and the neighbor - // of this cell are on the same refinement level and - // the work to assemble the interior flux matrices - // is very much the same as before. Infact it is - // much simpler since we do not have to loop through the - // subfaces. However, we have to check that we do - // not compute the same contribution twice. This would - // happen because we are looping over all the faces of - // all the cells in the mesh - // and assembling the interior flux matrices for each face. - // To avoid doing assembling the interior flux matrices - // twice we only compute the - // interior fluxes once for each face by restricting that - // the following computation only occur on the on - // the cell face with the lower CellId. - if(neighbor->level() == cell->level() && - cell->id() < neighbor->id()) + // At this point we know that this cell and the neighbor + // of this cell are on the same refinement level and + // the work to assemble the interior flux matrices + // is very much the same as before. Infact it is + // much simpler since we do not have to loop through the + // subfaces. However, we have to check that we do + // not compute the same contribution twice. This would + // happen because we are looping over all the faces of + // all the cells in the mesh + // and assembling the interior flux matrices for each face. + // To avoid doing assembling the interior flux matrices + // twice we only compute the + // interior fluxes once for each face by restricting that + // the following computation only occur on the on + // the cell face with the lower CellId. + if (neighbor->level() == cell->level() && + cell->id() < neighbor->id()) { - // Here we find the neighbor face such that - // neighbor(neigh_face_no) = cell(face_no). - // In addition we, reinitialize the FEFaceValues - // and neighbor cell's FEFaceValues on their - // respective cells' faces, as well as get the - // minimum diameter of this cell - // and the neighbor cell and assign - // it to h. - const unsigned int neighbor_face_no = - cell->neighbor_of_neighbor(face_no); - - vi_ui_matrix = 0; - vi_ue_matrix = 0; - ve_ui_matrix = 0; - ve_ue_matrix = 0; - - fe_face_values.reinit(cell, face_no); - fe_neighbor_face_values.reinit(neighbor, - neighbor_face_no); - - double h = std::min(cell->diameter(), - neighbor->diameter()); - - // Just as before we assemble the interior fluxes - // using the - // assemble_flux_terms subroutine, - // get the neighbor cell's - // face dof indices and use the constraint matrix to - // distribute the local flux matrices to the global - // system_matrix using the class - // function - // distribute_local_flux_to_global() - assemble_flux_terms(fe_face_values, - fe_neighbor_face_values, - vi_ui_matrix, - vi_ue_matrix, - ve_ui_matrix, - ve_ue_matrix, - h); - - neighbor->get_dof_indices(local_neighbor_dof_indices); - - distribute_local_flux_to_global( - vi_ui_matrix, - vi_ue_matrix, - ve_ui_matrix, - ve_ue_matrix, - local_dof_indices, - local_neighbor_dof_indices); - - - } - } - } - } - - - // Now that have looped over all the faces for this - // cell and computed as well as disributed the local - // flux matrices to the system_matrix, we - // can finally distribute the cell's local_matrix - // and local_vector contribution to the - // global system matrix and global right hand side vector. - // We remark that we have to wait until this point - // to distribute the local_matrix - // and system_rhs to the global system. - // The reason being that in looping over the faces - // the faces on the boundary of the domain contribute - // to the local_matrix - // and system_rhs. We could distribute - // the local contributions for each component seperately, - // but writing to the distributed sparse matrix and vector - // is expensive and want to to minimize the number of times - // we do so. - constraints.distribute_local_to_global(local_matrix, - local_dof_indices, - system_matrix); - - constraints.distribute_local_to_global(local_vector, - local_dof_indices, - system_rhs); - - } + // Here we find the neighbor face such that + // neighbor(neigh_face_no) = cell(face_no). + // In addition we, reinitialize the FEFaceValues + // and neighbor cell's FEFaceValues on their + // respective cells' faces, as well as get the + // minimum diameter of this cell + // and the neighbor cell and assign + // it to h. + const unsigned int neighbor_face_no = + cell->neighbor_of_neighbor(face_no); + + vi_ui_matrix = 0; + vi_ue_matrix = 0; + ve_ui_matrix = 0; + ve_ue_matrix = 0; + + fe_face_values.reinit(cell, face_no); + fe_neighbor_face_values.reinit(neighbor, + neighbor_face_no); + + double h = std::min(cell->diameter(), + neighbor->diameter()); + + // Just as before we assemble the interior fluxes + // using the + // assemble_flux_terms subroutine, + // get the neighbor cell's + // face dof indices and use the constraint matrix to + // distribute the local flux matrices to the global + // system_matrix using the class + // function + // distribute_local_flux_to_global() + assemble_flux_terms(fe_face_values, + fe_neighbor_face_values, + vi_ui_matrix, + vi_ue_matrix, + ve_ui_matrix, + ve_ue_matrix, + h); + + neighbor->get_dof_indices(local_neighbor_dof_indices); + + distribute_local_flux_to_global( + vi_ui_matrix, + vi_ue_matrix, + ve_ui_matrix, + ve_ue_matrix, + local_dof_indices, + local_neighbor_dof_indices); + + + } + } + } + } + + + // Now that have looped over all the faces for this + // cell and computed as well as disributed the local + // flux matrices to the system_matrix, we + // can finally distribute the cell's local_matrix + // and local_vector contribution to the + // global system matrix and global right hand side vector. + // We remark that we have to wait until this point + // to distribute the local_matrix + // and system_rhs to the global system. + // The reason being that in looping over the faces + // the faces on the boundary of the domain contribute + // to the local_matrix + // and system_rhs. We could distribute + // the local contributions for each component seperately, + // but writing to the distributed sparse matrix and vector + // is expensive and want to to minimize the number of times + // we do so. + constraints.distribute_local_to_global(local_matrix, + local_dof_indices, + system_matrix); + + constraints.distribute_local_to_global(local_vector, + local_dof_indices, + system_rhs); + + } } - // We need to synchronize assembly of our global system - // matrix and global right hand side vector with all the other - // processors and - // use the compress() function to do this. - // This was discussed in detail in step-40. - system_matrix.compress(VectorOperation::add); - system_rhs.compress(VectorOperation::add); + // We need to synchronize assembly of our global system + // matrix and global right hand side vector with all the other + // processors and + // use the compress() function to do this. + // This was discussed in detail in step-40. + system_matrix.compress(VectorOperation::add); + system_rhs.compress(VectorOperation::add); } // @sect4{assemble_cell_terms} // This function deals with constructing the local matrix due to -// the solid integrals over each element and is very similar to the +// the solid integrals over each element and is very similar to the // the other examples in the deal.ii tutorials. template void LDGPoissonProblem:: assemble_cell_terms( - const FEValues &cell_fe, - FullMatrix &cell_matrix, - Vector &cell_vector) + const FEValues &cell_fe, + FullMatrix &cell_matrix, + Vector &cell_vector) { - const unsigned int dofs_per_cell = cell_fe.dofs_per_cell; - const unsigned int n_q_points = cell_fe.n_quadrature_points; + const unsigned int dofs_per_cell = cell_fe.dofs_per_cell; + const unsigned int n_q_points = cell_fe.n_quadrature_points; - const FEValuesExtractors::Vector VectorField(0); - const FEValuesExtractors::Scalar Potential(dim); + const FEValuesExtractors::Vector VectorField(0); + const FEValuesExtractors::Scalar Potential(dim); - std::vector rhs_values(n_q_points); + std::vector rhs_values(n_q_points); - // We first get the value of the right hand side function - // evaluated at the quadrature points in the cell. - rhs_function.value_list(cell_fe.get_quadrature_points(), - rhs_values); + // We first get the value of the right hand side function + // evaluated at the quadrature points in the cell. + rhs_function.value_list(cell_fe.get_quadrature_points(), + rhs_values); - // Now, we loop over the quadrature points in the - // cell and then loop over the degrees of freedom and perform - // quadrature to approximate the integrals. - for(unsigned int q=0; q psi_i_field = cell_fe[VectorField].value(i,q); - const double div_psi_i_field = cell_fe[VectorField].divergence(i,q); - const double psi_i_potential = cell_fe[Potential].value(i,q); - const Tensor<1, dim> grad_psi_i_potential = cell_fe[Potential].gradient(i,q); + const Tensor<1, dim> psi_i_field = cell_fe[VectorField].value(i,q); + const double div_psi_i_field = cell_fe[VectorField].divergence(i,q); + const double psi_i_potential = cell_fe[Potential].value(i,q); + const Tensor<1, dim> grad_psi_i_potential = cell_fe[Potential].gradient(i,q); - for(unsigned int j=0; j psi_j_field = cell_fe[VectorField].value(j,q); - const double psi_j_potential = cell_fe[Potential].value(j,q); - - // This computation corresponds to assembling the local system - // matrix for the integral over an element, - // - // $\int_{\Omega_{e}} \left(\textbf{w} \cdot \textbf{q} - // - \nabla \cdot \textbf{w} u - // - \nabla w \cdot \textbf{q} - // \right) dx $ - cell_matrix(i,j) += ( (psi_i_field * psi_j_field) - - - (div_psi_i_field * psi_j_potential) - - - (grad_psi_i_potential * psi_j_field) - ) * cell_fe.JxW(q); - } - - // And this local right hand vector corresponds to the integral - // over the element cell, - // - // $ \int_{\Omega_{e}} w \, f(\textbf{x}) \, dx $ - cell_vector(i) += psi_i_potential * - rhs_values[q] * - cell_fe.JxW(q); - } - } -} + const Tensor<1, dim> psi_j_field = cell_fe[VectorField].value(j,q); + const double psi_j_potential = cell_fe[Potential].value(j,q); + + // This computation corresponds to assembling the local system + // matrix for the integral over an element, + // + // $\int_{\Omega_{e}} \left(\textbf{w} \cdot \textbf{q} + // - \nabla \cdot \textbf{w} u + // - \nabla w \cdot \textbf{q} + // \right) dx $ + cell_matrix(i,j) += ( (psi_i_field * psi_j_field) + - + (div_psi_i_field * psi_j_potential) + - + (grad_psi_i_potential * psi_j_field) + ) * cell_fe.JxW(q); + } + + // And this local right hand vector corresponds to the integral + // over the element cell, + // + // $ \int_{\Omega_{e}} w \, f(\textbf{x}) \, dx $ + cell_vector(i) += psi_i_potential * + rhs_values[q] * + cell_fe.JxW(q); + } + } +} // @sect4{assemble_Dirichlet_boundary_terms} // Here we have the function that builds the local_matrix @@ -905,70 +905,70 @@ template void LDGPoissonProblem:: assemble_Dirichlet_boundary_terms( - const FEFaceValues &face_fe, - FullMatrix &local_matrix, - Vector &local_vector, - const double & h) + const FEFaceValues &face_fe, + FullMatrix &local_matrix, + Vector &local_vector, + const double &h) { - const unsigned int dofs_per_cell = face_fe.dofs_per_cell; - const unsigned int n_q_points = face_fe.n_quadrature_points; + const unsigned int dofs_per_cell = face_fe.dofs_per_cell; + const unsigned int n_q_points = face_fe.n_quadrature_points; - const FEValuesExtractors::Vector VectorField(0); - const FEValuesExtractors::Scalar Potential(dim); + const FEValuesExtractors::Vector VectorField(0); + const FEValuesExtractors::Scalar Potential(dim); - std::vector Dirichlet_bc_values(n_q_points); + std::vector Dirichlet_bc_values(n_q_points); - // In order to evaluate the flux on the Dirichlet boundary face we - // first get the value of the Dirichlet boundary function on the quadrature - // points of the face. Then we loop over all the quadrature points and - // degrees of freedom and approximate the integrals on the Dirichlet boundary - // element faces. - Dirichlet_bc_function.value_list(face_fe.get_quadrature_points(), - Dirichlet_bc_values); + // In order to evaluate the flux on the Dirichlet boundary face we + // first get the value of the Dirichlet boundary function on the quadrature + // points of the face. Then we loop over all the quadrature points and + // degrees of freedom and approximate the integrals on the Dirichlet boundary + // element faces. + Dirichlet_bc_function.value_list(face_fe.get_quadrature_points(), + Dirichlet_bc_values); - for(unsigned int q=0; q psi_i_field = face_fe[VectorField].value(i,q); - const double psi_i_potential = face_fe[Potential].value(i,q); + const Tensor<1, dim> psi_i_field = face_fe[VectorField].value(i,q); + const double psi_i_potential = face_fe[Potential].value(i,q); - for(unsigned int j=0; j psi_j_field = face_fe[VectorField].value(j,q); - const double psi_j_potential = face_fe[Potential].value(j,q); - - // We compute contribution for the flux $\widehat{q}$ on - // the Dirichlet boundary which enters our system matrix as, - // - // $ \int_{\text{face}} w \, ( \textbf{n} \cdot \textbf{q} - // + \sigma u) ds $ - local_matrix(i,j) += psi_i_potential * ( - face_fe.normal_vector(q) * - psi_j_field - + - (penalty/h) * - psi_j_potential) * - face_fe.JxW(q); - - } - - // We also compute the contribution for the flux for $\widehat{u}$ - // on the Dirichlet boundary which is the Dirichlet boundary - // condition function and enters the right hand side vector as - // - // $\int_{\text{face}} (-\textbf{w} \cdot \textbf{n} - // + \sigma w) \, u_{D} ds $ - local_vector(i) += (-1.0 * psi_i_field * - face_fe.normal_vector(q) - + - (penalty/h) * - psi_i_potential) * - Dirichlet_bc_values[q] * - face_fe.JxW(q); - } - } -} + const Tensor<1, dim> psi_j_field = face_fe[VectorField].value(j,q); + const double psi_j_potential = face_fe[Potential].value(j,q); + + // We compute contribution for the flux $\widehat{q}$ on + // the Dirichlet boundary which enters our system matrix as, + // + // $ \int_{\text{face}} w \, ( \textbf{n} \cdot \textbf{q} + // + \sigma u) ds $ + local_matrix(i,j) += psi_i_potential * ( + face_fe.normal_vector(q) * + psi_j_field + + + (penalty/h) * + psi_j_potential) * + face_fe.JxW(q); + + } + + // We also compute the contribution for the flux for $\widehat{u}$ + // on the Dirichlet boundary which is the Dirichlet boundary + // condition function and enters the right hand side vector as + // + // $\int_{\text{face}} (-\textbf{w} \cdot \textbf{n} + // + \sigma w) \, u_{D} ds $ + local_vector(i) += (-1.0 * psi_i_field * + face_fe.normal_vector(q) + + + (penalty/h) * + psi_i_potential) * + Dirichlet_bc_values[q] * + face_fe.JxW(q); + } + } +} // @sect4{assemble_Neumann_boundary_terms} // Here we have the function that builds the local_matrix @@ -977,121 +977,121 @@ template void LDGPoissonProblem:: assemble_Neumann_boundary_terms( - const FEFaceValues &face_fe, - FullMatrix &local_matrix, - Vector &local_vector) + const FEFaceValues &face_fe, + FullMatrix &local_matrix, + Vector &local_vector) { - const unsigned int dofs_per_cell = face_fe.dofs_per_cell; - const unsigned int n_q_points = face_fe.n_quadrature_points; + const unsigned int dofs_per_cell = face_fe.dofs_per_cell; + const unsigned int n_q_points = face_fe.n_quadrature_points; - const FEValuesExtractors::Vector VectorField(0); - const FEValuesExtractors::Scalar Potential(dim); + const FEValuesExtractors::Vector VectorField(0); + const FEValuesExtractors::Scalar Potential(dim); - // In order to get evaluate the flux on the Neumann boundary face we - // first get the value of the Neumann boundary function on the quadrature - // points of the face. Then we loop over all the quadrature points and - // degrees of freedom and approximate the integrals on the Neumann boundary - // element faces. - std::vector Neumann_bc_values(n_q_points); + // In order to get evaluate the flux on the Neumann boundary face we + // first get the value of the Neumann boundary function on the quadrature + // points of the face. Then we loop over all the quadrature points and + // degrees of freedom and approximate the integrals on the Neumann boundary + // element faces. + std::vector Neumann_bc_values(n_q_points); - for(unsigned int q=0; q psi_i_field = face_fe[VectorField].value(i,q); - const double psi_i_potential = face_fe[Potential].value(i,q); + const Tensor<1, dim> psi_i_field = face_fe[VectorField].value(i,q); + const double psi_i_potential = face_fe[Potential].value(i,q); - for(unsigned int j=0; j void LDGPoissonProblem:: assemble_flux_terms( - const FEFaceValuesBase &fe_face_values, - const FEFaceValuesBase &fe_neighbor_face_values, - FullMatrix &vi_ui_matrix, - FullMatrix &vi_ue_matrix, - FullMatrix &ve_ui_matrix, - FullMatrix &ve_ue_matrix, - const double & h) + const FEFaceValuesBase &fe_face_values, + const FEFaceValuesBase &fe_neighbor_face_values, + FullMatrix &vi_ui_matrix, + FullMatrix &vi_ue_matrix, + FullMatrix &ve_ui_matrix, + FullMatrix &ve_ue_matrix, + const double &h) { - const unsigned int n_face_points = fe_face_values.n_quadrature_points; - const unsigned int dofs_this_cell = fe_face_values.dofs_per_cell; - const unsigned int dofs_neighbor_cell = fe_neighbor_face_values.dofs_per_cell; - - const FEValuesExtractors::Vector VectorField(0); - const FEValuesExtractors::Scalar Potential(dim); - - // The first thing we do is after the boilerplate is define - // the unit vector $\boldsymbol \beta$ that is used in defining - // the LDG/ALternating fluxes. - Point beta; - for(int i=0; i beta; + for (int i=0; i psi_i_field_minus = - fe_face_values[VectorField].value(i,q); - const double psi_i_potential_minus = - fe_face_values[Potential].value(i,q); + const Tensor<1,dim> psi_i_field_minus = + fe_face_values[VectorField].value(i,q); + const double psi_i_potential_minus = + fe_face_values[Potential].value(i,q); - for(unsigned int j=0; j psi_j_field_minus = - fe_face_values[VectorField].value(j,q); - const double psi_j_potential_minus = - fe_face_values[Potential].value(j,q); - - // We compute the flux matrix where the test function's - // as well as the solution function's values are taken from - // the interior as, - // - // $\int_{\text{face}} - // \left( \frac{1}{2} \, \textbf{n}^{-} - // \cdot ( \textbf{w}^{-} u^{-} - // + w^{-} \textbf{q}^{-}) - // + \boldsymbol \beta \cdot \textbf{w}^{-} u^{-} - // - w^{-} \boldsymbol \beta \cdot \textbf{q}^{-} - // + \sigma w^{-} \, u^{-} \right) ds$ - vi_ui_matrix(i,j) += (0.5 * ( + const Tensor<1,dim> psi_j_field_minus = + fe_face_values[VectorField].value(j,q); + const double psi_j_potential_minus = + fe_face_values[Potential].value(j,q); + + // We compute the flux matrix where the test function's + // as well as the solution function's values are taken from + // the interior as, + // + // $\int_{\text{face}} + // \left( \frac{1}{2} \, \textbf{n}^{-} + // \cdot ( \textbf{w}^{-} u^{-} + // + w^{-} \textbf{q}^{-}) + // + \boldsymbol \beta \cdot \textbf{w}^{-} u^{-} + // - w^{-} \boldsymbol \beta \cdot \textbf{q}^{-} + // + \sigma w^{-} \, u^{-} \right) ds$ + vi_ui_matrix(i,j) += (0.5 * ( psi_i_field_minus * fe_face_values.normal_vector(q) * psi_j_potential_minus @@ -1099,200 +1099,200 @@ assemble_flux_terms( psi_i_potential_minus * fe_face_values.normal_vector(q) * psi_j_field_minus ) - + - beta * - psi_i_field_minus * - psi_j_potential_minus - - - beta * - psi_i_potential_minus * - psi_j_field_minus - + - (penalty/h) * - psi_i_potential_minus * - psi_j_potential_minus - ) * - fe_face_values.JxW(q); - } + + + beta * + psi_i_field_minus * + psi_j_potential_minus + - + beta * + psi_i_potential_minus * + psi_j_field_minus + + + (penalty/h) * + psi_i_potential_minus * + psi_j_potential_minus + ) * + fe_face_values.JxW(q); + } - for(unsigned int j=0; j psi_j_field_plus = - fe_neighbor_face_values[VectorField].value(j,q); - const double psi_j_potential_plus = - fe_neighbor_face_values[Potential].value(j,q); - - // We compute the flux matrix where the test function is - // from the interior of this elements face and solution - // function is taken from the exterior. This corresponds - // to the computation, - // - // $\int_{\text{face}} - // \left( \frac{1}{2} \, \textbf{n}^{-} \cdot - // ( \textbf{w}^{-} u^{+} - // + w^{-} \textbf{q}^{+}) - // - \boldsymbol \beta \cdot \textbf{w}^{-} u^{+} - // + w^{-} \boldsymbol \beta \cdot \textbf{q}^{+} - // - \sigma w^{-} \, u^{+} \right) ds $ - vi_ue_matrix(i,j) += ( 0.5 * ( - psi_i_field_minus * - fe_face_values.normal_vector(q) * - psi_j_potential_plus - + - psi_i_potential_minus * - fe_face_values.normal_vector(q) * - psi_j_field_plus ) - - - beta * - psi_i_field_minus * - psi_j_potential_plus - + - beta * - psi_i_potential_minus * - psi_j_field_plus - - - (penalty/h) * - psi_i_potential_minus * - psi_j_potential_plus - ) * - fe_face_values.JxW(q); - } - } + const Tensor<1,dim> psi_j_field_plus = + fe_neighbor_face_values[VectorField].value(j,q); + const double psi_j_potential_plus = + fe_neighbor_face_values[Potential].value(j,q); + + // We compute the flux matrix where the test function is + // from the interior of this elements face and solution + // function is taken from the exterior. This corresponds + // to the computation, + // + // $\int_{\text{face}} + // \left( \frac{1}{2} \, \textbf{n}^{-} \cdot + // ( \textbf{w}^{-} u^{+} + // + w^{-} \textbf{q}^{+}) + // - \boldsymbol \beta \cdot \textbf{w}^{-} u^{+} + // + w^{-} \boldsymbol \beta \cdot \textbf{q}^{+} + // - \sigma w^{-} \, u^{+} \right) ds $ + vi_ue_matrix(i,j) += ( 0.5 * ( + psi_i_field_minus * + fe_face_values.normal_vector(q) * + psi_j_potential_plus + + + psi_i_potential_minus * + fe_face_values.normal_vector(q) * + psi_j_field_plus ) + - + beta * + psi_i_field_minus * + psi_j_potential_plus + + + beta * + psi_i_potential_minus * + psi_j_field_plus + - + (penalty/h) * + psi_i_potential_minus * + psi_j_potential_plus + ) * + fe_face_values.JxW(q); + } + } - for(unsigned int i=0; i psi_i_field_plus = - fe_neighbor_face_values[VectorField].value(i,q); - const double psi_i_potential_plus = - fe_neighbor_face_values[Potential].value(i,q); + const Tensor<1,dim> psi_i_field_plus = + fe_neighbor_face_values[VectorField].value(i,q); + const double psi_i_potential_plus = + fe_neighbor_face_values[Potential].value(i,q); - for(unsigned int j=0; j psi_j_field_minus = - fe_face_values[VectorField].value(j,q); - const double psi_j_potential_minus = - fe_face_values[Potential].value(j,q); - - - // We compute the flux matrix where the test function is - // from the exterior of this elements face and solution - // function is taken from the interior. This corresponds - // to the computation, - // - // $ \int_{\text{face}} - // \left( -\frac{1}{2}\, \textbf{n}^{-} \cdot - // (\textbf{w}^{+} u^{-} - // + w^{+} \textbf{q}^{-} ) - // - \boldsymbol \beta \cdot \textbf{w}^{+} u^{-} - // + w^{+} \boldsymbol \beta \cdot \textbf{q}^{-} - // - \sigma w^{+} u^{-} \right) ds $ - ve_ui_matrix(i,j) += (-0.5 * ( - psi_i_field_plus * - fe_face_values.normal_vector(q) * - psi_j_potential_minus - + - psi_i_potential_plus * - fe_face_values.normal_vector(q) * - psi_j_field_minus) - - - beta * - psi_i_field_plus * - psi_j_potential_minus - + - beta * - psi_i_potential_plus * - psi_j_field_minus - - - (penalty/h) * - psi_i_potential_plus * - psi_j_potential_minus - ) * - fe_face_values.JxW(q); - } + const Tensor<1,dim> psi_j_field_minus = + fe_face_values[VectorField].value(j,q); + const double psi_j_potential_minus = + fe_face_values[Potential].value(j,q); + + + // We compute the flux matrix where the test function is + // from the exterior of this elements face and solution + // function is taken from the interior. This corresponds + // to the computation, + // + // $ \int_{\text{face}} + // \left( -\frac{1}{2}\, \textbf{n}^{-} \cdot + // (\textbf{w}^{+} u^{-} + // + w^{+} \textbf{q}^{-} ) + // - \boldsymbol \beta \cdot \textbf{w}^{+} u^{-} + // + w^{+} \boldsymbol \beta \cdot \textbf{q}^{-} + // - \sigma w^{+} u^{-} \right) ds $ + ve_ui_matrix(i,j) += (-0.5 * ( + psi_i_field_plus * + fe_face_values.normal_vector(q) * + psi_j_potential_minus + + + psi_i_potential_plus * + fe_face_values.normal_vector(q) * + psi_j_field_minus) + - + beta * + psi_i_field_plus * + psi_j_potential_minus + + + beta * + psi_i_potential_plus * + psi_j_field_minus + - + (penalty/h) * + psi_i_potential_plus * + psi_j_potential_minus + ) * + fe_face_values.JxW(q); + } - for(unsigned int j=0; j psi_j_field_plus = - fe_neighbor_face_values[VectorField].value(j,q); - const double psi_j_potential_plus = - fe_neighbor_face_values[Potential].value(j,q); - - // And lastly we compute the flux matrix where the test - // function and solution function are taken from the exterior - // cell to this face. This corresponds to the computation, - // - // $\int_{\text{face}} - // \left( -\frac{1}{2}\, \textbf{n}^{-} \cdot - // ( \textbf{w}^{+} u^{+} - // + w^{+} \textbf{q}^{+} ) - // + \boldsymbol \beta \cdot \textbf{w}^{+} u^{+} - // - w^{+} \boldsymbol \beta \cdot \textbf{q}^{+} - // + \sigma w^{+} u^{+} \right) ds $ - ve_ue_matrix(i,j) += (-0.5 * ( - psi_i_field_plus * - fe_face_values.normal_vector(q) * - psi_j_potential_plus - + - psi_i_potential_plus * - fe_face_values.normal_vector(q) * - psi_j_field_plus ) - + - beta * - psi_i_field_plus * - psi_j_potential_plus - - - beta * - psi_i_potential_plus * - psi_j_field_plus - + - (penalty/h) * - psi_i_potential_plus * - psi_j_potential_plus - ) * - fe_face_values.JxW(q); - } + const Tensor<1,dim> psi_j_field_plus = + fe_neighbor_face_values[VectorField].value(j,q); + const double psi_j_potential_plus = + fe_neighbor_face_values[Potential].value(j,q); + + // And lastly we compute the flux matrix where the test + // function and solution function are taken from the exterior + // cell to this face. This corresponds to the computation, + // + // $\int_{\text{face}} + // \left( -\frac{1}{2}\, \textbf{n}^{-} \cdot + // ( \textbf{w}^{+} u^{+} + // + w^{+} \textbf{q}^{+} ) + // + \boldsymbol \beta \cdot \textbf{w}^{+} u^{+} + // - w^{+} \boldsymbol \beta \cdot \textbf{q}^{+} + // + \sigma w^{+} u^{+} \right) ds $ + ve_ue_matrix(i,j) += (-0.5 * ( + psi_i_field_plus * + fe_face_values.normal_vector(q) * + psi_j_potential_plus + + + psi_i_potential_plus * + fe_face_values.normal_vector(q) * + psi_j_field_plus ) + + + beta * + psi_i_field_plus * + psi_j_potential_plus + - + beta * + psi_i_potential_plus * + psi_j_field_plus + + + (penalty/h) * + psi_i_potential_plus * + psi_j_potential_plus + ) * + fe_face_values.JxW(q); + } - } - } -} + } + } +} // @sect4{distribute_local_flux_to_global} // In this function we use the ConstraintMatrix to distribute -// the local flux matrices to the global system matrix. -// Since I have to do this twice in assembling the +// the local flux matrices to the global system matrix. +// Since I have to do this twice in assembling the // system matrix, I made function to do it rather than have // repeated code. // We remark that the reader take special note of -// the which matrices we are distributing and the order -// in which we pass the dof indices vectors. In distributing -// the first matrix, i.e. vi_ui_matrix, we are -// taking the test function and solution function values from -// the interior of this cell and therefore only need the +// the which matrices we are distributing and the order +// in which we pass the dof indices vectors. In distributing +// the first matrix, i.e. vi_ui_matrix, we are +// taking the test function and solution function values from +// the interior of this cell and therefore only need the // local_dof_indices since it contains the dof // indices to this cell. When we distribute the second matrix, -// vi_ue_matrix, the test function is taken +// vi_ue_matrix, the test function is taken // form the inteior of -// this cell while the solution function is taken from the -// exterior, i.e. the neighbor cell. Notice that the order +// this cell while the solution function is taken from the +// exterior, i.e. the neighbor cell. Notice that the order // degrees of freedom index vectors matrch this pattern: first -// the local_dof_indices which is local to +// the local_dof_indices which is local to // this cell and then // the local_neighbor_dof_indices which is // local to the neighbor's // cell. The order in which we pass the dof indices for the -// matrices is paramount to constructing our global system -// matrix properly. The ordering of the last two matrices +// matrices is paramount to constructing our global system +// matrix properly. The ordering of the last two matrices // follow the same logic as the first two we discussed. template -void +void LDGPoissonProblem:: distribute_local_flux_to_global( - const FullMatrix & vi_ui_matrix, - const FullMatrix & vi_ue_matrix, - const FullMatrix & ve_ui_matrix, - const FullMatrix & ve_ue_matrix, - const std::vector & local_dof_indices, - const std::vector & local_neighbor_dof_indices) + const FullMatrix &vi_ui_matrix, + const FullMatrix &vi_ue_matrix, + const FullMatrix &ve_ui_matrix, + const FullMatrix &ve_ue_matrix, + const std::vector &local_dof_indices, + const std::vector &local_neighbor_dof_indices) { constraints.distribute_local_to_global(vi_ui_matrix, local_dof_indices, @@ -1304,9 +1304,9 @@ distribute_local_flux_to_global( system_matrix); constraints.distribute_local_to_global(ve_ui_matrix, - local_neighbor_dof_indices, - local_dof_indices, - system_matrix); + local_neighbor_dof_indices, + local_dof_indices, + system_matrix); constraints.distribute_local_to_global(ve_ue_matrix, local_neighbor_dof_indices, @@ -1319,135 +1319,135 @@ distribute_local_flux_to_global( // As mentioned earlier I used a direct solver to solve // the linear system of equations resulting from the LDG // method applied to the Poisson equation. One could also -// use a iterative sovler, however, we then need to use +// use a iterative sovler, however, we then need to use // a preconditoner and that was something I did not wanted // to get into. For information on preconditioners -// for the LDG Method see this +// for the LDG Method see this // // paper. The uses of a direct sovler here is -// somewhat of a limitation. The built-in distributed -// direct solver in Trilinos reduces everything to one -// processor, solves the system and then distributes -// everything back out to the other processors. However, -// by linking to more advanced direct sovlers through +// somewhat of a limitation. The built-in distributed +// direct solver in Trilinos reduces everything to one +// processor, solves the system and then distributes +// everything back out to the other processors. However, +// by linking to more advanced direct sovlers through // Trilinos one can accomplish fully distributed computations // and not much about the following function calls will -// change. +// change. template void LDGPoissonProblem:: solve() { - TimerOutput::Scope t(computing_timer, "solve"); - - // As in step-40 in order to perform a linear solve - // we need solution vector where there is no overlap across - // the processors and we create this by instantiating - // completely_distributed_solution solution - // vector using - // the copy constructor on the global system right hand - // side vector which itself is completely distributed vector. - TrilinosWrappers::MPI::Vector - completely_distributed_solution(system_rhs); - - // Now we can preform the solve on the completeley distributed - // right hand side vector, system matrix and the completely - // distributed solution. - solver.solve(system_matrix, - completely_distributed_solution, - system_rhs); - - // We now distribute the constraints of our system onto the - // completely solution vector, but in our case with the LDG - // method there are none. - constraints.distribute(completely_distributed_solution); - - // Lastly we copy the completely distributed solution vector, - // completely_distributed_solution, - // to solution vector which has some overlap between - // processors, locally_relevant_solution. - // We need the overlapped portions of our solution - // in order to be able to do computations using the solution - // later in the code or in post processing. - locally_relevant_solution = completely_distributed_solution; + TimerOutput::Scope t(computing_timer, "solve"); + + // As in step-40 in order to perform a linear solve + // we need solution vector where there is no overlap across + // the processors and we create this by instantiating + // completely_distributed_solution solution + // vector using + // the copy constructor on the global system right hand + // side vector which itself is completely distributed vector. + TrilinosWrappers::MPI::Vector + completely_distributed_solution(system_rhs); + + // Now we can preform the solve on the completeley distributed + // right hand side vector, system matrix and the completely + // distributed solution. + solver.solve(system_matrix, + completely_distributed_solution, + system_rhs); + + // We now distribute the constraints of our system onto the + // completely solution vector, but in our case with the LDG + // method there are none. + constraints.distribute(completely_distributed_solution); + + // Lastly we copy the completely distributed solution vector, + // completely_distributed_solution, + // to solution vector which has some overlap between + // processors, locally_relevant_solution. + // We need the overlapped portions of our solution + // in order to be able to do computations using the solution + // later in the code or in post processing. + locally_relevant_solution = completely_distributed_solution; } // @sect4{output_results} // This function deals with the writing of the reuslts in parallel -// to disk. It is almost exactly the same as -// in step-40 and we wont go into it. It is noteworthy +// to disk. It is almost exactly the same as +// in step-40 and we wont go into it. It is noteworthy // that in step-40 the output is only the scalar solution, -// while in our situation, we are outputing both the scalar +// while in our situation, we are outputing both the scalar // solution as well as the vector field solution. The only -// difference between this function and the one in step-40 +// difference between this function and the one in step-40 // is in the solution_names vector where we have to add -// the gradient dimensions. Everything else is taken care +// the gradient dimensions. Everything else is taken care // of by the deal.ii library! template void LDGPoissonProblem:: output_results() const { - std::vector solution_names; - switch(dim) + std::vector solution_names; + switch (dim) { case 1: - solution_names.push_back("u"); - solution_names.push_back("du/dx"); - break; + solution_names.push_back("u"); + solution_names.push_back("du/dx"); + break; case 2: - solution_names.push_back("grad(u)_x"); - solution_names.push_back("grad(u)_y"); - solution_names.push_back("u"); - break; + solution_names.push_back("grad(u)_x"); + solution_names.push_back("grad(u)_y"); + solution_names.push_back("u"); + break; case 3: - solution_names.push_back("grad(u)_x"); - solution_names.push_back("grad(u)_y"); - solution_names.push_back("grad(u)_z"); - solution_names.push_back("u"); - break; + solution_names.push_back("grad(u)_x"); + solution_names.push_back("grad(u)_y"); + solution_names.push_back("grad(u)_z"); + solution_names.push_back("u"); + break; default: - Assert(false, ExcNotImplemented() ); + Assert(false, ExcNotImplemented() ); } - DataOut data_out; - data_out.attach_dof_handler(dof_handler); - data_out.add_data_vector(locally_relevant_solution, - solution_names); + DataOut data_out; + data_out.attach_dof_handler(dof_handler); + data_out.add_data_vector(locally_relevant_solution, + solution_names); - Vector subdomain(triangulation.n_active_cells()); + Vector subdomain(triangulation.n_active_cells()); - for(unsigned int i=0; i filenames; - for(unsigned int i=0; - i < Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); - i++) + std::vector filenames; + for (unsigned int i=0; + i < Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); + i++) { - filenames.push_back("solution." + - Utilities::int_to_string(i,4) + - ".vtu"); + filenames.push_back("solution." + + Utilities::int_to_string(i,4) + + ".vtu"); } - std::ofstream master_output("solution.pvtu"); - data_out.write_pvtu_record(master_output, filenames); - } + std::ofstream master_output("solution.pvtu"); + data_out.write_pvtu_record(master_output, filenames); + } } @@ -1460,59 +1460,60 @@ void LDGPoissonProblem:: run() { - penalty = 1.0; - make_grid(); - make_dofs(); - assemble_system(); - solve(); - output_results(); + penalty = 1.0; + make_grid(); + make_dofs(); + assemble_system(); + solve(); + output_results(); } // @sect3{main} // Here it the main class of our program, since it is nearly exactly // the same as step-40 and many of the other examples I won't -// elaborate on it. +// elaborate on it. int main(int argc, char *argv[]) { - try { - using namespace dealii; + try + { + using namespace dealii; + + deallog.depth_console(0); - deallog.depth_console(0); + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, + numbers::invalid_unsigned_int); - Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, - numbers::invalid_unsigned_int); + unsigned int degree = 1; + unsigned int n_refine = 6; + LDGPoissonProblem<2> Poisson(degree, n_refine); + Poisson.run(); - unsigned int degree = 1; - unsigned int n_refine = 6; - LDGPoissonProblem<2> Poisson(degree, n_refine); - Poisson.run(); - } - catch (std::exception &exc) + catch (std::exception &exc) { - std::cerr << std::endl << std::endl - << "----------------------------------------------------" - << std::endl; - std::cerr << "Exception on processing: " << std::endl - << exc.what() << std::endl - << "Aborting!" << std::endl - << "----------------------------------------------------" - << std::endl; - - return 1; + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Exception on processing: " << std::endl + << exc.what() << std::endl + << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + + return 1; } - catch (...) + catch (...) { - std::cerr << std::endl << std::endl - << "----------------------------------------------------" - << std::endl; - std::cerr << "Unknown exception!" << std::endl - << "Aborting!" << std::endl - << "----------------------------------------------------" - << std::endl; - return 1; + std::cerr << std::endl << std::endl + << "----------------------------------------------------" + << std::endl; + std::cerr << "Unknown exception!" << std::endl + << "Aborting!" << std::endl + << "----------------------------------------------------" + << std::endl; + return 1; } - return 0; + return 0; } diff --git a/ElastoplasticTorsion/ElastoplasticTorsion.cc b/ElastoplasticTorsion/ElastoplasticTorsion.cc index 3792099..4c4640a 100644 --- a/ElastoplasticTorsion/ElastoplasticTorsion.cc +++ b/ElastoplasticTorsion/ElastoplasticTorsion.cc @@ -38,10 +38,10 @@ step-15 step-29. - For further details see the technical report + For further details see the technical report "Solving variational problems with uniform gradient bounds by p-Laplacian - approximation: Elastoplastic torsion implementation using the deal.II - library" + approximation: Elastoplastic torsion implementation using the deal.II + library" available at the documentation and at http://www.dim.uchile.cl/~sflores. */ diff --git a/MultipointFluxMixedFiniteElementMethods/data.h b/MultipointFluxMixedFiniteElementMethods/data.h index fc2ab1a..38d519c 100644 --- a/MultipointFluxMixedFiniteElementMethods/data.h +++ b/MultipointFluxMixedFiniteElementMethods/data.h @@ -42,15 +42,15 @@ namespace MFMFE const double y = p[1]; switch (dim) - { + { case 2: return -(x*(y*y*y*y)*6.0-(y*y)*sin(x*y*2.0)*2.0+2.0)*(x*2.0+x*x+y*y+1.0)-sin(x*y)*(cos(x*y*2.0)+(x*x)*(y*y*y)*1.2E1 - -x*y*sin(x*y*2.0)*2.0)*2.0-(x*2.0+2.0)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*cos(x*y*2.0))+(x*x)*(sin(x*y*2.0) - -x*(y*y)*6.0)*pow(x+1.0,2.0)*2.0-x*cos(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*(pow(cos(x*y),2.0)*2.0-1.0)) - -x*y*cos(x*y)*((x*x)*(y*y*y)*4.0+pow(cos(x*y),2.0)*2.0-1.0); + -x*y*sin(x*y*2.0)*2.0)*2.0-(x*2.0+2.0)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*cos(x*y*2.0))+(x*x)*(sin(x*y*2.0) + -x*(y*y)*6.0)*pow(x+1.0,2.0)*2.0-x*cos(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*(pow(cos(x*y),2.0)*2.0-1.0)) + -x*y*cos(x*y)*((x*x)*(y*y*y)*4.0+pow(cos(x*y),2.0)*2.0-1.0); default: Assert(false, ExcMessage("The RHS data for dim != 2 is not provided")); - } + } } @@ -73,12 +73,12 @@ namespace MFMFE const double y = p[1]; switch (dim) - { + { case 2: return (x*x*x)*(y*y*y*y)+cos(x*y)*sin(x*y)+x*x; default: Assert(false, ExcMessage("The BC data for dim != 2 is not provided")); - } + } } @@ -108,7 +108,7 @@ namespace MFMFE const double y = p[1]; switch (dim) - { + { case 2: values(0) = -(x*2.0+(x*x)*(y*y*y*y)*3.0+y*cos(x*y*2.0))*(x*2.0+x*x+y*y+1.0)-x*sin(x*y)*(cos(x*y*2.0)+(x*x)*(y*y*y)*4.0); values(1) = -sin(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*cos(x*y*2.0))-x*(cos(x*y*2.0)+(x*x)*(y*y*y)*4.0)*pow(x+1.0,2.0); @@ -116,7 +116,7 @@ namespace MFMFE break; default: Assert(false, ExcMessage("The exact solution for dim != 2 is not provided")); - } + } } template @@ -128,25 +128,25 @@ namespace MFMFE const double y = p[1]; switch (dim) - { + { case 2: grads[0][0] = -(x*(y*y*y*y)*6.0-(y*y)*sin(x*y*2.0)*2.0+2.0)*(x*2.0+x*x+y*y+1.0)-sin(x*y)*(cos(x*y*2.0) - +(x*x)*(y*y*y)*1.2E1-x*y*sin(x*y*2.0)*2.0)-(x*2.0+2.0)*(x*2.0+(x*x)*(y*y*y*y)*3.0 - +y*cos(x*y*2.0))-x*y*cos(x*y)*((x*x)*(y*y*y)*4.0+pow(cos(x*y),2.0)*2.0-1.0); + +(x*x)*(y*y*y)*1.2E1-x*y*sin(x*y*2.0)*2.0)-(x*2.0+2.0)*(x*2.0+(x*x)*(y*y*y*y)*3.0 + +y*cos(x*y*2.0))-x*y*cos(x*y)*((x*x)*(y*y*y)*4.0+pow(cos(x*y),2.0)*2.0-1.0); grads[0][1] = -(cos(x*y*2.0)+(x*x)*(y*y*y)*1.2E1-x*y*sin(x*y*2.0)*2.0)*(x*2.0+x*x+y*y+1.0) - -y*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*cos(x*y*2.0))*2.0-(x*x)*cos(x*y)*((x*x)*(y*y*y)*4.0 - +pow(cos(x*y),2.0)*2.0-1.0)+(x*x)*sin(x*y)*(sin(x*y*2.0)-x*(y*y)*6.0)*2.0; + -y*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*cos(x*y*2.0))*2.0-(x*x)*cos(x*y)*((x*x)*(y*y*y)*4.0 + +pow(cos(x*y),2.0)*2.0-1.0)+(x*x)*sin(x*y)*(sin(x*y*2.0)-x*(y*y)*6.0)*2.0; grads[1][0] = -sin(x*y)*(x*(y*y*y*y)*6.0-(y*y)*sin(x*y*2.0)*2.0+2.0)-pow(x+1.0,2.0)*(cos(x*y*2.0) - +(x*x)*(y*y*y)*1.2E1-x*y*sin(x*y*2.0)*2.0)-x*(cos(x*y*2.0)+(x*x)*(y*y*y)*4.0)*(x*2.0+2.0) - -y*cos(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*(pow(cos(x*y),2.0)*2.0-1.0)); + +(x*x)*(y*y*y)*1.2E1-x*y*sin(x*y*2.0)*2.0)-x*(cos(x*y*2.0)+(x*x)*(y*y*y)*4.0)*(x*2.0+2.0) + -y*cos(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0+y*(pow(cos(x*y),2.0)*2.0-1.0)); grads[1][1] = -sin(x*y)*(cos(x*y*2.0)+(x*x)*(y*y*y)*1.2E1-x*y*sin(x*y*2.0)*2.0)+(x*x)*(sin(x*y*2.0) - -x*(y*y)*6.0)*pow(x+1.0,2.0)*2.0-x*cos(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0 - +y*(pow(cos(x*y),2.0)*2.0-1.0)); + -x*(y*y)*6.0)*pow(x+1.0,2.0)*2.0-x*cos(x*y)*(x*2.0+(x*x)*(y*y*y*y)*3.0 + +y*(pow(cos(x*y),2.0)*2.0-1.0)); grads[2] = 0; break; default: Assert(false, ExcMessage("The exact solution's gradient for dim != 2 is not provided")); - } + } } @@ -170,24 +170,24 @@ namespace MFMFE ExcDimensionMismatch (points.size(), values.size())); for (unsigned int p=0; p #if DEAL_II_VERSION_MAJOR >= 9 && defined(DEAL_II_WITH_TRILINOS) - #include - #define ENABLE_SACADO_FORMULATION +#include +#define ENABLE_SACADO_FORMULATION #endif // These must be included below the AD headers so that @@ -134,7 +134,7 @@ namespace Cook_Membrane // @sect4{Finite Element system} -// Here we specify the polynomial order used to approximate the solution. +// Here we specify the polynomial order used to approximate the solution. // The quadrature order should be adjusted accordingly. struct FESystem { @@ -407,7 +407,7 @@ namespace Cook_Membrane // Finally we consolidate all of the above structures into a single container // that holds all of our run-time selections. - struct AllParameters : + struct AllParameters : public AssemblyMethod, public FESystem, public Geometry, @@ -509,7 +509,7 @@ namespace Cook_Membrane // @sect3{Compressible neo-Hookean material within a one-field formulation} -// As discussed in the literature and step-44, Neo-Hookean materials are a type +// As discussed in the literature and step-44, Neo-Hookean materials are a type // of hyperelastic materials. The entire domain is assumed to be composed of a // compressible neo-Hookean material. This class defines the behaviour of // this material within a one-field formulation. Compressible neo-Hookean @@ -534,8 +534,8 @@ namespace Cook_Membrane // and provides a central point that one would need to modify if one were to // implement a different material model. For it to work, we will store one // object of this type per quadrature point, and in each of these objects -// store the current state (characterized by the values or measures of the -// displacement field) so that we can compute the elastic coefficients +// store the current state (characterized by the values or measures of the +// displacement field) so that we can compute the elastic coefficients // linearized around the current state. template class Material_Compressible_Neo_Hook_One_Field @@ -610,7 +610,7 @@ namespace Cook_Membrane NumberType get_dPsi_vol_dJ(const NumberType &det_F) const { - return (kappa / 2.0) * (det_F - 1.0 / det_F); + return (kappa / 2.0) * (det_F - 1.0 / det_F); } // The following functions are used internally in determining the result @@ -620,7 +620,7 @@ namespace Cook_Membrane SymmetricTensor<2,dim,NumberType> get_tau_vol(const NumberType &det_F) const { - return NumberType(get_dPsi_vol_dJ(det_F) * det_F) * Physics::Elasticity::StandardTensors::I; + return NumberType(get_dPsi_vol_dJ(det_F) * det_F) * Physics::Elasticity::StandardTensors::I; } // Next, determine the isochoric Kirchhoff stress @@ -648,21 +648,21 @@ namespace Cook_Membrane NumberType get_d2Psi_vol_dJ2(const NumberType &det_F) const { - return ( (kappa / 2.0) * (1.0 + 1.0 / (det_F * det_F))); + return ( (kappa / 2.0) * (1.0 + 1.0 / (det_F * det_F))); } // Calculate the volumetric part of the tangent $J - // \mathfrak{c}_\textrm{vol}$. Again, note the difference in its - // definition when compared to step-44. The extra terms result from two - // quantities in $\boldsymbol{\tau}_{\textrm{vol}}$ being dependent on + // \mathfrak{c}_\textrm{vol}$. Again, note the difference in its + // definition when compared to step-44. The extra terms result from two + // quantities in $\boldsymbol{\tau}_{\textrm{vol}}$ being dependent on // $\boldsymbol{F}$. SymmetricTensor<4,dim,NumberType> get_Jc_vol(const NumberType &det_F) const { - // See Holzapfel p265 - return det_F - * ( (get_dPsi_vol_dJ(det_F) + det_F * get_d2Psi_vol_dJ2(det_F))*Physics::Elasticity::StandardTensors::IxI - - (2.0 * get_dPsi_vol_dJ(det_F))*Physics::Elasticity::StandardTensors::S ); + // See Holzapfel p265 + return det_F + * ( (get_dPsi_vol_dJ(det_F) + det_F * get_d2Psi_vol_dJ2(det_F))*Physics::Elasticity::StandardTensors::IxI + - (2.0 * get_dPsi_vol_dJ(det_F))*Physics::Elasticity::StandardTensors::S ); } // Calculate the isochoric part of the tangent $J @@ -721,7 +721,7 @@ namespace Cook_Membrane void setup_lqp (const Parameters::AllParameters ¶meters) { material.reset(new Material_Compressible_Neo_Hook_One_Field(parameters.mu, - parameters.nu)); + parameters.nu)); } // We offer an interface to retrieve certain data. @@ -872,7 +872,7 @@ namespace Cook_Membrane // There are two reasons that we retain the block system in this problem. // The first is pure laziness to perform further modifications to the // code from which this work originated. The second is that a block system - // would typically necessary when extending this code to multiphysics + // would typically necessary when extending this code to multiphysics // problems. static const unsigned int n_blocks = 1; static const unsigned int n_components = dim; @@ -945,7 +945,7 @@ namespace Cook_Membrane void print_conv_footer(); - + void print_vertical_tip_displacement(); }; @@ -979,7 +979,7 @@ namespace Cook_Membrane n_q_points (qf_cell.size()), n_q_points_f (qf_face.size()) { - + } // The class destructor simply clears the data held by the DOFHandler @@ -995,7 +995,7 @@ namespace Cook_Membrane // interchangeable. We choose to increment time linearly using a constant time // step size. // -// We start the function with preprocessing, and then output the initial grid +// We start the function with preprocessing, and then output the initial grid // before starting the simulation proper with the first time (and loading) // increment. // @@ -1008,7 +1008,7 @@ namespace Cook_Membrane time.increment(); // We then declare the incremental solution update $\varDelta - // \mathbf{\Xi}:= \{\varDelta \mathbf{u}\}$ and start the loop over the + // \mathbf{\Xi}:= \{\varDelta \mathbf{u}\}$ and start the loop over the // time domain. // // At the beginning, we reset the solution update for this time step... @@ -1028,9 +1028,9 @@ namespace Cook_Membrane output_results(); time.increment(); } - - // Lastly, we print the vertical tip displacement of the Cook cantilever - // after the full load is applied + + // Lastly, we print the vertical tip displacement of the Cook cantilever + // after the full load is applied print_vertical_tip_displacement(); } @@ -1042,28 +1042,28 @@ namespace Cook_Membrane // On to the first of the private member functions. Here we create the // triangulation of the domain, for which we choose a scaled an anisotripically // discretised rectangle which is subsequently transformed into the correct -// of the Cook cantilever. Each relevant boundary face is then given a boundary +// of the Cook cantilever. Each relevant boundary face is then given a boundary // ID number. // // We then determine the volume of the reference configuration and print it // for comparison. -template -Point grid_y_transform (const Point &pt_in) -{ - const double &x = pt_in[0]; - const double &y = pt_in[1]; - - const double y_upper = 44.0 + (16.0/48.0)*x; // Line defining upper edge of beam - const double y_lower = 0.0 + (44.0/48.0)*x; // Line defining lower edge of beam - const double theta = y/44.0; // Fraction of height along left side of beam - const double y_transform = (1-theta)*y_lower + theta*y_upper; // Final transformation - - Point pt_out = pt_in; - pt_out[1] = y_transform; - - return pt_out; -} + template + Point grid_y_transform (const Point &pt_in) + { + const double &x = pt_in[0]; + const double &y = pt_in[1]; + + const double y_upper = 44.0 + (16.0/48.0)*x; // Line defining upper edge of beam + const double y_lower = 0.0 + (44.0/48.0)*x; // Line defining lower edge of beam + const double theta = y/44.0; // Fraction of height along left side of beam + const double y_transform = (1-theta)*y_lower + theta*y_upper; // Final transformation + + Point pt_out = pt_in; + pt_out[1] = y_transform; + + return pt_out; + } template void Solid::make_grid() @@ -1074,43 +1074,43 @@ Point grid_y_transform (const Point &pt_in) // (modelling a plane strain condition) if (dim == 3) repetitions[dim-1] = 1; - + const Point bottom_left = (dim == 3 ? Point(0.0, 0.0, -0.5) : Point(0.0, 0.0)); const Point top_right = (dim == 3 ? Point(48.0, 44.0, 0.5) : Point(48.0, 44.0)); - GridGenerator::subdivided_hyper_rectangle(triangulation, + GridGenerator::subdivided_hyper_rectangle(triangulation, repetitions, bottom_left, top_right); - // Since we wish to apply a Neumann BC to the right-hand surface, we - // must find the cell faces in this part of the domain and mark them with - // a distinct boundary ID number. The faces we are looking for are on the - // +x surface and will get boundary ID 11. - // Dirichlet boundaries exist on the left-hand face of the beam (this fixed - // boundary will get ID 1) and on the +Z and -Z faces (which correspond to - // ID 2 and we will use to impose the plane strain condition) - const double tol_boundary = 1e-6; - typename Triangulation::active_cell_iterator cell = - triangulation.begin_active(), endc = triangulation.end(); - for (; cell != endc; ++cell) - for (unsigned int face = 0; - face < GeometryInfo::faces_per_cell; ++face) - if (cell->face(face)->at_boundary() == true) - { - if (std::abs(cell->face(face)->center()[0] - 0.0) < tol_boundary) - cell->face(face)->set_boundary_id(1); // -X faces - else if (std::abs(cell->face(face)->center()[0] - 48.0) < tol_boundary) - cell->face(face)->set_boundary_id(11); // +X faces - else if (std::abs(std::abs(cell->face(face)->center()[0]) - 0.5) < tol_boundary) - cell->face(face)->set_boundary_id(2); // +Z and -Z faces - } - + // Since we wish to apply a Neumann BC to the right-hand surface, we + // must find the cell faces in this part of the domain and mark them with + // a distinct boundary ID number. The faces we are looking for are on the + // +x surface and will get boundary ID 11. + // Dirichlet boundaries exist on the left-hand face of the beam (this fixed + // boundary will get ID 1) and on the +Z and -Z faces (which correspond to + // ID 2 and we will use to impose the plane strain condition) + const double tol_boundary = 1e-6; + typename Triangulation::active_cell_iterator cell = + triangulation.begin_active(), endc = triangulation.end(); + for (; cell != endc; ++cell) + for (unsigned int face = 0; + face < GeometryInfo::faces_per_cell; ++face) + if (cell->face(face)->at_boundary() == true) + { + if (std::abs(cell->face(face)->center()[0] - 0.0) < tol_boundary) + cell->face(face)->set_boundary_id(1); // -X faces + else if (std::abs(cell->face(face)->center()[0] - 48.0) < tol_boundary) + cell->face(face)->set_boundary_id(11); // +X faces + else if (std::abs(std::abs(cell->face(face)->center()[0]) - 0.5) < tol_boundary) + cell->face(face)->set_boundary_id(2); // +Z and -Z faces + } + // Transform the hyper-rectangle into the beam shape GridTools::transform(&grid_y_transform, triangulation); GridTools::scale(parameters.scale, triangulation); - + vol_reference = GridTools::volume(triangulation); vol_current = vol_reference; std::cout << "Grid:\n\t Reference volume: " << vol_reference << std::endl; @@ -1152,12 +1152,12 @@ Point grid_y_transform (const Point &pt_in) csp.block(u_dof, u_dof).reinit(n_dofs_u, n_dofs_u); csp.collect_sizes(); - // Naturally, for a one-field vector-valued problem, all of the + // Naturally, for a one-field vector-valued problem, all of the // components of the system are coupled. Table<2, DoFTools::Coupling> coupling(n_components, n_components); for (unsigned int ii = 0; ii < n_components; ++ii) for (unsigned int jj = 0; jj < n_components; ++jj) - coupling[ii][jj] = DoFTools::always; + coupling[ii][jj] = DoFTools::always; DoFTools::make_sparsity_pattern(dof_handler_ref, coupling, csp, @@ -1204,12 +1204,12 @@ Point grid_y_transform (const Point &pt_in) for (typename Triangulation::active_cell_iterator cell = triangulation.begin_active(); cell != triangulation.end(); ++cell) { - const std::vector > > lqph = - quadrature_point_history.get_data(cell); - Assert(lqph.size() == n_q_points, ExcInternalError()); + const std::vector > > lqph = + quadrature_point_history.get_data(cell); + Assert(lqph.size() == n_q_points, ExcInternalError()); - for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) - lqph[q_point]->setup_lqp(parameters); + for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) + lqph[q_point]->setup_lqp(parameters); } } @@ -1359,7 +1359,7 @@ Point grid_y_transform (const Point &pt_in) } // At the end we also output the result that can be compared to that found in -// the literature, namely the displacement at the upper right corner of the +// the literature, namely the displacement at the upper right corner of the // beam. template void Solid::print_vertical_tip_displacement() @@ -1369,46 +1369,46 @@ Point grid_y_transform (const Point &pt_in) for (unsigned int i = 0; i < l_width; ++i) std::cout << "_"; std::cout << std::endl; - + Point soln_pt (48.0*parameters.scale,60.0*parameters.scale); if (dim == 3) soln_pt[2] = 0.5*parameters.scale; double vertical_tip_displacement = 0.0; double vertical_tip_displacement_check = 0.0; - + typename DoFHandler::active_cell_iterator cell = dof_handler_ref.begin_active(), endc = dof_handler_ref.end(); for (; cell != endc; ++cell) - { - // if (cell->point_inside(soln_pt) == true) - for (unsigned int v=0; v::vertices_per_cell; ++v) - if (cell->vertex(v).distance(soln_pt) < 1e-6) { - // Extract y-component of solution at the given point - // This point is coindicent with a vertex, so we can - // extract it directly as we're using FE_Q finite elements - // that have support at the vertices - vertical_tip_displacement = solution_n(cell->vertex_dof_index(v,u_dof+1)); - - // Sanity check using alternate method to extract the solution - // at the given point. To do this, we must create an FEValues instance - // to help us extract the solution value at the desired point - const MappingQ mapping (parameters.poly_degree); - const Point qp_unit = mapping.transform_real_to_unit_cell(cell,soln_pt); - const Quadrature soln_qrule (qp_unit); - AssertThrow(soln_qrule.size() == 1, ExcInternalError()); - FEValues fe_values_soln (fe, soln_qrule, update_values); - fe_values_soln.reinit(cell); - - // Extract y-component of solution at given point - std::vector< Tensor<1,dim> > soln_values (soln_qrule.size()); - fe_values_soln[u_fe].get_function_values(solution_n, - soln_values); - vertical_tip_displacement_check = soln_values[0][u_dof+1]; - - break; + // if (cell->point_inside(soln_pt) == true) + for (unsigned int v=0; v::vertices_per_cell; ++v) + if (cell->vertex(v).distance(soln_pt) < 1e-6) + { + // Extract y-component of solution at the given point + // This point is coindicent with a vertex, so we can + // extract it directly as we're using FE_Q finite elements + // that have support at the vertices + vertical_tip_displacement = solution_n(cell->vertex_dof_index(v,u_dof+1)); + + // Sanity check using alternate method to extract the solution + // at the given point. To do this, we must create an FEValues instance + // to help us extract the solution value at the desired point + const MappingQ mapping (parameters.poly_degree); + const Point qp_unit = mapping.transform_real_to_unit_cell(cell,soln_pt); + const Quadrature soln_qrule (qp_unit); + AssertThrow(soln_qrule.size() == 1, ExcInternalError()); + FEValues fe_values_soln (fe, soln_qrule, update_values); + fe_values_soln.reinit(cell); + + // Extract y-component of solution at given point + std::vector< Tensor<1,dim> > soln_values (soln_qrule.size()); + fe_values_soln[u_fe].get_function_values(solution_n, + soln_values); + vertical_tip_displacement_check = soln_values[0][u_dof+1]; + + break; + } } - } AssertThrow(vertical_tip_displacement > 0.0, ExcMessage("Found no cell with point inside!")) std::cout << "Vertical tip displacement: " << vertical_tip_displacement @@ -1442,7 +1442,7 @@ Point grid_y_transform (const Point &pt_in) // Determine the true Newton update error for the problem template void Solid::get_error_update(const BlockVector &newton_update, - Errors &error_update) + Errors &error_update) { BlockVector error_ud(dofs_per_block); for (unsigned int i = 0; i < dof_handler_ref.n_dofs(); ++i) @@ -1519,7 +1519,7 @@ Point grid_y_transform (const Point &pt_in) ScratchData_ASM(const FiniteElement &fe_cell, const QGauss &qf_cell, const UpdateFlags uf_cell, - const QGauss & qf_face, + const QGauss & qf_face, const UpdateFlags uf_face, const BlockVector &solution_total) : @@ -1571,7 +1571,7 @@ Point grid_y_transform (const Point &pt_in) }; // Of course, we still have to define how we assemble the tangent matrix - // contribution for a single cell. + // contribution for a single cell. void assemble_system_one_cell(const typename DoFHandler::active_cell_iterator &cell, ScratchData_ASM &scratch, @@ -1597,9 +1597,9 @@ Point grid_y_transform (const Point &pt_in) BlockVector &system_rhs = const_cast *>(data.solid)->system_rhs; constraints.distribute_local_to_global( - data.cell_matrix, data.cell_rhs, - data.local_dof_indices, - tangent_matrix, system_rhs); + data.cell_matrix, data.cell_rhs, + data.local_dof_indices, + tangent_matrix, system_rhs); } protected: @@ -1640,12 +1640,12 @@ Point grid_y_transform (const Point &pt_in) for (unsigned int f_q_point = 0; f_q_point < n_q_points_f; ++f_q_point) { - // We specify the traction in reference configuration. - // For this problem, a defined total vertical force is applied + // We specify the traction in reference configuration. + // For this problem, a defined total vertical force is applied // in the reference configuration. // The direction of the applied traction is assumed not to - // evolve with the deformation of the domain. - + // evolve with the deformation of the domain. + // Note that the contributions to the right hand side vector we // compute here only exist in the displacement components of the // vector. @@ -1707,7 +1707,7 @@ Point grid_y_transform (const Point &pt_in) cell->get_dof_indices(data.local_dof_indices); const std::vector > > lqph = - const_cast *>(data.solid)->quadrature_point_history.get_data(cell); + const_cast *>(data.solid)->quadrature_point_history.get_data(cell); Assert(lqph.size() == n_q_points, ExcInternalError()); // We first need to find the solution gradients at quadrature points @@ -1830,14 +1830,14 @@ Point grid_y_transform (const Point &pt_in) cell->get_dof_indices(data.local_dof_indices); const std::vector > > lqph = - const_cast *>(data.solid)->quadrature_point_history.get_data(cell); + const_cast *>(data.solid)->quadrature_point_history.get_data(cell); Assert(lqph.size() == n_q_points, ExcInternalError()); const unsigned int n_independent_variables = data.local_dof_indices.size(); std::vector local_dof_values(n_independent_variables); cell->get_dof_values(scratch.solution_total, - local_dof_values.begin(), - local_dof_values.end()); + local_dof_values.begin(), + local_dof_values.end()); // We now retrieve a set of degree-of-freedom values that // have the operations that are performed with them tracked. @@ -1848,68 +1848,68 @@ Point grid_y_transform (const Point &pt_in) // Compute all values, gradients etc. based on sensitive // AD degree-of-freedom values. scratch.fe_values_ref[u_fe].get_function_gradients_from_local_dof_values( - local_dof_values_ad, - scratch.solution_grads_u_total); + local_dof_values_ad, + scratch.solution_grads_u_total); // Accumulate the residual value for each degree of freedom. // Note: Its important that the vectors is initialised (zero'd) correctly. std::vector residual_ad (dofs_per_cell, ADNumberType(0.0)); for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) - { - const Tensor<2,dim,ADNumberType> &grad_u = scratch.solution_grads_u_total[q_point]; - const Tensor<2,dim,ADNumberType> F = Physics::Elasticity::Kinematics::F(grad_u); - const ADNumberType det_F = determinant(F); - const Tensor<2,dim,ADNumberType> F_bar = Physics::Elasticity::Kinematics::F_iso(F); - const SymmetricTensor<2,dim,ADNumberType> b_bar = Physics::Elasticity::Kinematics::b(F_bar); - const Tensor<2,dim,ADNumberType> F_inv = invert(F); - Assert(det_F > ADNumberType(0.0), ExcInternalError()); - - for (unsigned int k = 0; k < dofs_per_cell; ++k) - { - const unsigned int k_group = fe.system_to_base_index(k).first.first; + { + const Tensor<2,dim,ADNumberType> &grad_u = scratch.solution_grads_u_total[q_point]; + const Tensor<2,dim,ADNumberType> F = Physics::Elasticity::Kinematics::F(grad_u); + const ADNumberType det_F = determinant(F); + const Tensor<2,dim,ADNumberType> F_bar = Physics::Elasticity::Kinematics::F_iso(F); + const SymmetricTensor<2,dim,ADNumberType> b_bar = Physics::Elasticity::Kinematics::b(F_bar); + const Tensor<2,dim,ADNumberType> F_inv = invert(F); + Assert(det_F > ADNumberType(0.0), ExcInternalError()); - if (k_group == u_dof) - { - scratch.grad_Nx[q_point][k] = scratch.fe_values_ref[u_fe].gradient(k, q_point) * F_inv; - scratch.symm_grad_Nx[q_point][k] = symmetrize(scratch.grad_Nx[q_point][k]); - } - else - Assert(k_group <= u_dof, ExcInternalError()); - } + for (unsigned int k = 0; k < dofs_per_cell; ++k) + { + const unsigned int k_group = fe.system_to_base_index(k).first.first; - const SymmetricTensor<2,dim,ADNumberType> tau = lqph[q_point]->get_tau(det_F,b_bar); + if (k_group == u_dof) + { + scratch.grad_Nx[q_point][k] = scratch.fe_values_ref[u_fe].gradient(k, q_point) * F_inv; + scratch.symm_grad_Nx[q_point][k] = symmetrize(scratch.grad_Nx[q_point][k]); + } + else + Assert(k_group <= u_dof, ExcInternalError()); + } - // Next we define some position-dependent aliases, again to - // make the assembly process easier to follow. - const std::vector > &symm_grad_Nx = scratch.symm_grad_Nx[q_point]; - const double JxW = scratch.fe_values_ref.JxW(q_point); + const SymmetricTensor<2,dim,ADNumberType> tau = lqph[q_point]->get_tau(det_F,b_bar); - for (unsigned int i = 0; i < dofs_per_cell; ++i) - { - const unsigned int i_group = fe.system_to_base_index(i).first.first; + // Next we define some position-dependent aliases, again to + // make the assembly process easier to follow. + const std::vector > &symm_grad_Nx = scratch.symm_grad_Nx[q_point]; + const double JxW = scratch.fe_values_ref.JxW(q_point); - if (i_group == u_dof) - residual_ad[i] += (symm_grad_Nx[i] * tau) * JxW; - else - Assert(i_group <= u_dof, ExcInternalError()); - } - } + for (unsigned int i = 0; i < dofs_per_cell; ++i) + { + const unsigned int i_group = fe.system_to_base_index(i).first.first; + + if (i_group == u_dof) + residual_ad[i] += (symm_grad_Nx[i] * tau) * JxW; + else + Assert(i_group <= u_dof, ExcInternalError()); + } + } for (unsigned int I=0; I struct Assembler > > : Assembler_Base > > { @@ -1935,14 +1935,14 @@ Point grid_y_transform (const Point &pt_in) cell->get_dof_indices(data.local_dof_indices); const std::vector > > lqph = - data.solid->quadrature_point_history.get_data(cell); + data.solid->quadrature_point_history.get_data(cell); Assert(lqph.size() == n_q_points, ExcInternalError()); const unsigned int n_independent_variables = data.local_dof_indices.size(); std::vector local_dof_values(n_independent_variables); cell->get_dof_values(scratch.solution_total, - local_dof_values.begin(), - local_dof_values.end()); + local_dof_values.begin(), + local_dof_values.end()); // We now retrieve a set of degree-of-freedom values that // have the operations that are performed with them tracked. @@ -1953,8 +1953,8 @@ Point grid_y_transform (const Point &pt_in) // Compute all values, gradients etc. based on sensitive // AD degree-of-freedom values. scratch.fe_values_ref[u_fe].get_function_gradients_from_local_dof_values( - local_dof_values_ad, - scratch.solution_grads_u_total); + local_dof_values_ad, + scratch.solution_grads_u_total); // Next we compute the total potential energy of the element. // This is defined as follows: @@ -1962,41 +1962,41 @@ Point grid_y_transform (const Point &pt_in) // Note: Its important that this value is initialised (zero'd) correctly. ADNumberType cell_energy_ad = ADNumberType(0.0); for (unsigned int q_point = 0; q_point < n_q_points; ++q_point) - { - const Tensor<2,dim,ADNumberType> &grad_u = scratch.solution_grads_u_total[q_point]; - const Tensor<2,dim,ADNumberType> F = Physics::Elasticity::Kinematics::F(grad_u); - const ADNumberType det_F = determinant(F); - const Tensor<2,dim,ADNumberType> F_bar = Physics::Elasticity::Kinematics::F_iso(F); - const SymmetricTensor<2,dim,ADNumberType> b_bar = Physics::Elasticity::Kinematics::b(F_bar); - Assert(det_F > ADNumberType(0.0), ExcInternalError()); - - // Next we define some position-dependent aliases, again to - // make the assembly process easier to follow. - const double JxW = scratch.fe_values_ref.JxW(q_point); - - const ADNumberType Psi = lqph[q_point]->get_Psi(det_F,b_bar); - - // We extract the configuration-dependent material energy - // from our QPH history objects for the current quadrature point - // and integrate its contribution to increment the total - // cell energy. - cell_energy_ad += Psi * JxW; - } + { + const Tensor<2,dim,ADNumberType> &grad_u = scratch.solution_grads_u_total[q_point]; + const Tensor<2,dim,ADNumberType> F = Physics::Elasticity::Kinematics::F(grad_u); + const ADNumberType det_F = determinant(F); + const Tensor<2,dim,ADNumberType> F_bar = Physics::Elasticity::Kinematics::F_iso(F); + const SymmetricTensor<2,dim,ADNumberType> b_bar = Physics::Elasticity::Kinematics::b(F_bar); + Assert(det_F > ADNumberType(0.0), ExcInternalError()); + + // Next we define some position-dependent aliases, again to + // make the assembly process easier to follow. + const double JxW = scratch.fe_values_ref.JxW(q_point); + + const ADNumberType Psi = lqph[q_point]->get_Psi(det_F,b_bar); + + // We extract the configuration-dependent material energy + // from our QPH history objects for the current quadrature point + // and integrate its contribution to increment the total + // cell energy. + cell_energy_ad += Psi * JxW; + } // Compute derivatives of reverse-mode AD variables ADNumberType::Gradcomp(); for (unsigned int I=0; I grid_y_transform (const Point &pt_in) constraints, fe.component_mask(u_fe)); } - + // Zero Z-displacement through thickness direction // This corresponds to a plane strain condition being imposed on the beam if (dim == 3) - { - const int boundary_id = 2; - const FEValuesExtractors::Scalar z_displacement(2); - - if (apply_dirichlet_bc == true) - VectorTools::interpolate_boundary_values(dof_handler_ref, - boundary_id, - ZeroFunction(n_components), - constraints, - fe.component_mask(z_displacement)); - else - VectorTools::interpolate_boundary_values(dof_handler_ref, - boundary_id, - ZeroFunction(n_components), - constraints, - fe.component_mask(z_displacement)); - } + { + const int boundary_id = 2; + const FEValuesExtractors::Scalar z_displacement(2); + + if (apply_dirichlet_bc == true) + VectorTools::interpolate_boundary_values(dof_handler_ref, + boundary_id, + ZeroFunction(n_components), + constraints, + fe.component_mask(z_displacement)); + else + VectorTools::interpolate_boundary_values(dof_handler_ref, + boundary_id, + ZeroFunction(n_components), + constraints, + fe.component_mask(z_displacement)); + } constraints.close(); } @@ -2251,51 +2251,51 @@ int main (int argc, char *argv[]) deallog.depth_console(0); Parameters::AllParameters parameters("parameters.prm"); if (parameters.automatic_differentiation_order == 0) - { - std::cout << "Assembly method: Residual and linearisation are computed manually." << std::endl; + { + std::cout << "Assembly method: Residual and linearisation are computed manually." << std::endl; - // Allow multi-threading - Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, - dealii::numbers::invalid_unsigned_int); + // Allow multi-threading + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, + dealii::numbers::invalid_unsigned_int); - typedef double NumberType; - Solid solid_3d(parameters); - solid_3d.run(); - } - #ifdef ENABLE_SACADO_FORMULATION - else if (parameters.automatic_differentiation_order == 1) - { - std::cout << "Assembly method: Residual computed manually; linearisation performed using AD." << std::endl; - - // Allow multi-threading - Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, - dealii::numbers::invalid_unsigned_int); - - typedef Sacado::Fad::DFad NumberType; - Solid solid_3d(parameters); - solid_3d.run(); - } - else if (parameters.automatic_differentiation_order == 2) - { - std::cout << "Assembly method: Residual and linearisation computed using AD." << std::endl; - - // Sacado Rad-Fad is not thread-safe, so disable threading. - // Parallisation using MPI would be possible though. - Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, - 1); - - typedef Sacado::Rad::ADvar< Sacado::Fad::DFad > NumberType; - Solid solid_3d(parameters); - solid_3d.run(); - } - #endif + typedef double NumberType; + Solid solid_3d(parameters); + solid_3d.run(); + } +#ifdef ENABLE_SACADO_FORMULATION + else if (parameters.automatic_differentiation_order == 1) + { + std::cout << "Assembly method: Residual computed manually; linearisation performed using AD." << std::endl; + + // Allow multi-threading + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, + dealii::numbers::invalid_unsigned_int); + + typedef Sacado::Fad::DFad NumberType; + Solid solid_3d(parameters); + solid_3d.run(); + } + else if (parameters.automatic_differentiation_order == 2) + { + std::cout << "Assembly method: Residual and linearisation computed using AD." << std::endl; + + // Sacado Rad-Fad is not thread-safe, so disable threading. + // Parallisation using MPI would be possible though. + Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, + 1); + + typedef Sacado::Rad::ADvar< Sacado::Fad::DFad > NumberType; + Solid solid_3d(parameters); + solid_3d.run(); + } +#endif else - { - AssertThrow(false, - ExcMessage("The selected assembly method is not supported. " - "You need deal.II 9.0 and Trilinos with the Sacado package " - "to enable assembly using automatic differentiation.")); - } + { + AssertThrow(false, + ExcMessage("The selected assembly method is not supported. " + "You need deal.II 9.0 and Trilinos with the Sacado package " + "to enable assembly using automatic differentiation.")); + } } catch (std::exception &exc) { diff --git a/cdr/common/include/deal.II-cdr/system_matrix.templates.h b/cdr/common/include/deal.II-cdr/system_matrix.templates.h index 4d8ceb8..accb442 100644 --- a/cdr/common/include/deal.II-cdr/system_matrix.templates.h +++ b/cdr/common/include/deal.II-cdr/system_matrix.templates.h @@ -56,18 +56,18 @@ namespace CDR for (unsigned int j = 0; j < dofs_per_cell; ++j) { const auto convection_contribution = current_convection - *fe_values.shape_grad(j, q); + *fe_values.shape_grad(j, q); cell_matrix(i, j) += fe_values.JxW(q)* - // Here are the time step, mass, and reaction parts: - ((1.0 + time_step/2.0*parameters.reaction_coefficient) - *fe_values.shape_value(i, q)*fe_values.shape_value(j, q) - + time_step/2.0* - // and the convection part: - (fe_values.shape_value(i, q)*convection_contribution - // and, finally, the diffusion part: - + parameters.diffusion_coefficient - *(fe_values.shape_grad(i, q)*fe_values.shape_grad(j, q))) - ); + // Here are the time step, mass, and reaction parts: + ((1.0 + time_step/2.0*parameters.reaction_coefficient) + *fe_values.shape_value(i, q)*fe_values.shape_value(j, q) + + time_step/2.0* + // and the convection part: + (fe_values.shape_value(i, q)*convection_contribution + // and, finally, the diffusion part: + + parameters.diffusion_coefficient + *(fe_values.shape_grad(i, q)*fe_values.shape_grad(j, q))) + ); } } } @@ -87,13 +87,13 @@ namespace CDR MatrixType &system_matrix) { internal_create_system_matrix - (dof_handler, quad, convection_function, parameters, time_step, - [&constraints, &system_matrix](const std::vector &local_indices, - const FullMatrix &cell_matrix) - { - constraints.distribute_local_to_global - (cell_matrix, local_indices, system_matrix); - }); + (dof_handler, quad, convection_function, parameters, time_step, + [&constraints, &system_matrix](const std::vector &local_indices, + const FullMatrix &cell_matrix) + { + constraints.distribute_local_to_global + (cell_matrix, local_indices, system_matrix); + }); } template @@ -106,12 +106,12 @@ namespace CDR MatrixType &system_matrix) { internal_create_system_matrix - (dof_handler, quad, convection_function, parameters, time_step, - [&system_matrix](const std::vector &local_indices, - const FullMatrix &cell_matrix) - { - system_matrix.add(local_indices, cell_matrix); - }); + (dof_handler, quad, convection_function, parameters, time_step, + [&system_matrix](const std::vector &local_indices, + const FullMatrix &cell_matrix) + { + system_matrix.add(local_indices, cell_matrix); + }); } } #endif diff --git a/cdr/common/include/deal.II-cdr/system_rhs.templates.h b/cdr/common/include/deal.II-cdr/system_rhs.templates.h index ae75602..44c768c 100644 --- a/cdr/common/include/deal.II-cdr/system_rhs.templates.h +++ b/cdr/common/include/deal.II-cdr/system_rhs.templates.h @@ -37,7 +37,7 @@ namespace CDR auto &fe = dof_handler.get_fe(); const auto dofs_per_cell = fe.dofs_per_cell; const double time_step = (parameters.stop_time - parameters.start_time) - /parameters.n_time_steps; + /parameters.n_time_steps; FEValues fe_values(fe, quad, update_values | update_gradients | update_quadrature_points | update_JxW_values); @@ -67,31 +67,31 @@ namespace CDR convection_function(fe_values.quadrature_point(q)); const double current_forcing = forcing_function - (current_time, fe_values.quadrature_point(q)); + (current_time, fe_values.quadrature_point(q)); const double previous_forcing = forcing_function - (previous_time, fe_values.quadrature_point(q)); + (previous_time, fe_values.quadrature_point(q)); for (unsigned int i = 0; i < dofs_per_cell; ++i) { for (unsigned int j = 0; j < dofs_per_cell; ++j) { const auto convection_contribution = current_convection - *fe_values.shape_grad(j, q); + *fe_values.shape_grad(j, q); cell_rhs(i) += fe_values.JxW(q)* - // Here are the mass and reaction part: - (((1.0 - time_step/2.0*parameters.reaction_coefficient) - *fe_values.shape_value(i, q)*fe_values.shape_value(j, q) - - time_step/2.0* - // the convection part: - (fe_values.shape_value(i, q)*convection_contribution - // the diffusion part: - + parameters.diffusion_coefficient - *(fe_values.shape_grad(i, q)*fe_values.shape_grad(j, q)))) - *current_fe_coefficients[j] - // and, finally, the forcing function part: - + time_step/2.0* - (current_forcing + previous_forcing) - *fe_values.shape_value(i, q)); + // Here are the mass and reaction part: + (((1.0 - time_step/2.0*parameters.reaction_coefficient) + *fe_values.shape_value(i, q)*fe_values.shape_value(j, q) + - time_step/2.0* + // the convection part: + (fe_values.shape_value(i, q)*convection_contribution + // the diffusion part: + + parameters.diffusion_coefficient + *(fe_values.shape_grad(i, q)*fe_values.shape_grad(j, q)))) + *current_fe_coefficients[j] + // and, finally, the forcing function part: + + time_step/2.0* + (current_forcing + previous_forcing) + *fe_values.shape_value(i, q)); } } } diff --git a/cdr/common/include/deal.II-cdr/write_pvtu_output.templates.h b/cdr/common/include/deal.II-cdr/write_pvtu_output.templates.h index ee0930d..15e5154 100644 --- a/cdr/common/include/deal.II-cdr/write_pvtu_output.templates.h +++ b/cdr/common/include/deal.II-cdr/write_pvtu_output.templates.h @@ -58,9 +58,9 @@ namespace CDR } std::ofstream output - ("solution-" + Utilities::int_to_string(time_step_n) + "." - + Utilities::int_to_string(subdomain_n, 4) - + ".vtu"); + ("solution-" + Utilities::int_to_string(time_step_n) + "." + + Utilities::int_to_string(subdomain_n, 4) + + ".vtu"); data_out.write_vtu(output); @@ -70,10 +70,10 @@ namespace CDR for (unsigned int i = 0; i < Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD); ++i) filenames.push_back - ("solution-" + Utilities::int_to_string (time_step_n) + "." - + Utilities::int_to_string (i, 4) + ".vtu"); + ("solution-" + Utilities::int_to_string (time_step_n) + "." + + Utilities::int_to_string (i, 4) + ".vtu"); std::ofstream master_output - ("solution-" + Utilities::int_to_string(time_step_n) + ".pvtu"); + ("solution-" + Utilities::int_to_string(time_step_n) + ".pvtu"); data_out.write_pvtu_record(master_output, filenames); } } diff --git a/cdr/common/source/write_pvtu_output.cc b/cdr/common/source/write_pvtu_output.cc index f74f2c2..f0efe08 100644 --- a/cdr/common/source/write_pvtu_output.cc +++ b/cdr/common/source/write_pvtu_output.cc @@ -11,7 +11,7 @@ namespace CDR WritePVTUOutput::WritePVTUOutput(const unsigned int patch_level) : patch_level {patch_level}, - this_mpi_process {Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)} + this_mpi_process {Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)} {} template diff --git a/cdr/solver/cdr.cc b/cdr/solver/cdr.cc index da832e6..b2391fa 100644 --- a/cdr/solver/cdr.cc +++ b/cdr/solver/cdr.cc @@ -98,33 +98,34 @@ template CDRProblem::CDRProblem(const CDR::Parameters ¶meters) : parameters(parameters), time_step {(parameters.stop_time - parameters.start_time) - /parameters.n_time_steps}, - current_time {parameters.start_time}, - mpi_communicator (MPI_COMM_WORLD), - n_mpi_processes {Utilities::MPI::n_mpi_processes(mpi_communicator)}, - this_mpi_process {Utilities::MPI::this_mpi_process(mpi_communicator)}, - fe(parameters.fe_order), - quad(parameters.fe_order + 2), - boundary_description(Point()), - triangulation(mpi_communicator, typename Triangulation::MeshSmoothing - (Triangulation::smoothing_on_refinement | - Triangulation::smoothing_on_coarsening)), - dof_handler(triangulation), - convection_function - { - [](const Point p) -> Tensor<1, dim> - {Tensor<1, dim> v; v[0] = -p[1]; v[1] = p[0]; return v;} - }, - forcing_function + /parameters.n_time_steps +}, +current_time {parameters.start_time}, +mpi_communicator (MPI_COMM_WORLD), +n_mpi_processes {Utilities::MPI::n_mpi_processes(mpi_communicator)}, +this_mpi_process {Utilities::MPI::this_mpi_process(mpi_communicator)}, +fe(parameters.fe_order), +quad(parameters.fe_order + 2), +boundary_description(Point()), +triangulation(mpi_communicator, typename Triangulation::MeshSmoothing + (Triangulation::smoothing_on_refinement | + Triangulation::smoothing_on_coarsening)), +dof_handler(triangulation), +convection_function +{ + [](const Point p) -> Tensor<1, dim> + {Tensor<1, dim> v; v[0] = -p[1]; v[1] = p[0]; return v;} +}, +forcing_function +{ + [](double t, const Point p) -> double { - [](double t, const Point p) -> double - { - return std::exp(-8*t)*std::exp(-40*Utilities::fixed_power<6>(p[0] - 1.5)) - *std::exp(-40*Utilities::fixed_power<6>(p[1])); - } - }, - first_run {true}, - pcout (std::cout, this_mpi_process == 0) + return std::exp(-8*t)*std::exp(-40*Utilities::fixed_power<6>(p[0] - 1.5)) + *std::exp(-40*Utilities::fixed_power<6>(p[1])); + } +}, +first_run {true}, +pcout (std::cout, this_mpi_process == 0) { Assert(dim == 2, ExcNotImplemented()); } @@ -264,11 +265,11 @@ void CDRProblem::refine_mesh() // Transferring the solution between different grids is ultimately just a // few function calls but they must be made in exactly the right order. parallel::distributed::SolutionTransfer - solution_transfer(dof_handler); + solution_transfer(dof_handler); triangulation.prepare_coarsening_and_refinement(); solution_transfer.prepare_for_coarsening_and_refinement - (locally_relevant_solution); + (locally_relevant_solution); triangulation.execute_coarsening_and_refinement(); setup_dofs(); @@ -278,7 +279,7 @@ void CDRProblem::refine_mesh() // parallel::distributed::SolutionTransfer::interpolate is called it uses // those values to populate temporary. TrilinosWrappers::MPI::Vector temporary - (locally_owned_dofs, mpi_communicator); + (locally_owned_dofs, mpi_communicator); solution_transfer.interpolate(temporary); // After temporary has the correct value, this call correctly // populates completely_distributed_solution, which had its diff --git a/goal_oriented_elastoplasticity/elastoplastic.cc b/goal_oriented_elastoplasticity/elastoplastic.cc index ad0c270..6dd79f9 100644 --- a/goal_oriented_elastoplasticity/elastoplastic.cc +++ b/goal_oriented_elastoplasticity/elastoplastic.cc @@ -2294,7 +2294,7 @@ namespace ElastoPlastic primal_fe_face_values.reinit (primal_cell, face); primal_fe_face_values.get_function_gradients (primal_solution, - primal_solution_gradients); + primal_solution_gradients); primal_fe_face_values.get_function_hessians (primal_solution, primal_solution_hessians); @@ -2930,7 +2930,7 @@ namespace ElastoPlastic // ------------- integrate_over_regular_face ----------- fe_face_values_cell.reinit(cell, face_no); fe_face_values_cell.get_function_gradients (primal_solution, - cell_grads); + cell_grads); Assert (cell->neighbor(face_no).state() == IteratorState::valid, ExcInternalError()); @@ -2941,7 +2941,7 @@ namespace ElastoPlastic fe_face_values_neighbor.reinit(neighbor, neighbor_neighbor); fe_face_values_neighbor.get_function_gradients (primal_solution, - neighbor_grads); + neighbor_grads); for (unsigned int q_point=0; q_pointneighbor(face_no).state() == IteratorState::valid, ExcInternalError()); @@ -5214,7 +5214,7 @@ namespace ElastoPlastic fe_face_values_neighbor.reinit(neighbor, neighbor_neighbor); fe_face_values_neighbor.get_function_gradients (tmp_solution, - neighbor_grads); + neighbor_grads); for (unsigned int q_point=0; q_point #include #include -#include +#include #include #include #include @@ -50,231 +50,231 @@ using namespace dealii; ////////////////////////////////////////////////////////// //////////////////// TRANSPORT SOLVER //////////////////// ////////////////////////////////////////////////////////// -// This is a solver for the transpor solver. -// We assume the velocity is divergence free -// and solve the equation in conservation form. +// This is a solver for the transpor solver. +// We assume the velocity is divergence free +// and solve the equation in conservation form. /////////////////////////////////// //---------- NOTATION ---------- // /////////////////////////////////// // We use notation popular in the literature of conservation laws. -// For this reason the solution is denoted as u, unm1, unp1, etc. -// and the velocity is treated as vx, vy and vz. +// For this reason the solution is denoted as u, unm1, unp1, etc. +// and the velocity is treated as vx, vy and vz. template class LevelSetSolver - { - public: - //////////////////////// - // INITIAL CONDITIONS // - //////////////////////// - void initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy); - void initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy, - PETScWrappers::MPI::Vector locally_relevant_solution_vz); - ///////////////////////// - // BOUNDARY CONDITIONS // - ///////////////////////// - void set_boundary_conditions(std::vector &boundary_values_id_u, - std::vector boundary_values_u); - ////////////////// - // SET VELOCITY // - ////////////////// - void set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy); - void set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy, - PETScWrappers::MPI::Vector locally_relevant_solution_vz); - /////////////////////// - // SET AND GET ALPHA // - /////////////////////// - void get_unp1(PETScWrappers::MPI::Vector &locally_relevant_solution_u); - /////////////////// - // NTH TIME STEP // - /////////////////// - void nth_time_step(); - /////////// - // SETUP // - /////////// - void setup(); - - LevelSetSolver (const unsigned int degree_LS, - const unsigned int degree_U, - const double time_step, - const double cK, - const double cE, - const bool verbose, - std::string ALGORITHM, - const unsigned int TIME_INTEGRATION, - parallel::distributed::Triangulation &triangulation, - MPI_Comm &mpi_communicator); - ~LevelSetSolver(); - - private: - //////////////////////////////////////// - // ASSEMBLE MASS (and other) MATRICES // - //////////////////////////////////////// - void assemble_ML(); - void invert_ML(); - void assemble_MC(); - ////////////////////////////////////// - // LOW ORDER METHOD (DiJ Viscosity) // - ////////////////////////////////////// - void assemble_C_Matrix(); - void assemble_K_times_vector(PETScWrappers::MPI::Vector &solution); - void assemble_K_DL_DH_times_vector(PETScWrappers::MPI::Vector &solution); - /////////////////////// - // ENTROPY VISCOSITY // - /////////////////////// - void assemble_EntRes_Matrix(); - /////////////////////////// - // FOR MAXIMUM PRINCIPLE // - /////////////////////////// - void compute_bounds(PETScWrappers::MPI::Vector &un_solution); - void check_max_principle(PETScWrappers::MPI::Vector &unp1_solution); - /////////////////////// - // COMPUTE SOLUTIONS // - /////////////////////// - void compute_MPP_uL_and_NMPP_uH(PETScWrappers::MPI::Vector &MPP_uL_solution, - PETScWrappers::MPI::Vector &NMPP_uH_solution, - PETScWrappers::MPI::Vector &un_solution); - void compute_MPP_uH(PETScWrappers::MPI::Vector &MPP_uH_solution, - PETScWrappers::MPI::Vector &MPP_uL_solution_ghosted, - PETScWrappers::MPI::Vector &NMPP_uH_solution_ghosted, - PETScWrappers::MPI::Vector &un_solution); - void compute_MPP_uH_with_iterated_FCT(PETScWrappers::MPI::Vector &MPP_uH_solution, - PETScWrappers::MPI::Vector &MPP_uL_solution_ghosted, - PETScWrappers::MPI::Vector &NMPP_uH_solution_ghosted, - PETScWrappers::MPI::Vector &un_solution); - void compute_solution(PETScWrappers::MPI::Vector &unp1, - PETScWrappers::MPI::Vector &un, - std::string algorithm); - void compute_solution_SSP33(PETScWrappers::MPI::Vector &unp1, - PETScWrappers::MPI::Vector &un, - std::string algorithm); - /////////////// - // UTILITIES // - /////////////// - void get_sparsity_pattern(); - void get_map_from_Q1_to_Q2(); - void solve(const ConstraintMatrix &constraints, - PETScWrappers::MPI::SparseMatrix &Matrix, - std_cxx1x::shared_ptr preconditioner, - PETScWrappers::MPI::Vector &completely_distributed_solution, - const PETScWrappers::MPI::Vector &rhs); - void save_old_solution(); - void save_old_vel_solution(); - /////////////////////// - // MY PETSC WRAPPERS // - /////////////////////// - void get_vector_values(PETScWrappers::VectorBase &vector, - const std::vector &indices, - std::vector &values); - void get_vector_values(PETScWrappers::VectorBase &vector, - const std::vector &indices, - std::map &map_from_Q1_to_Q2, - std::vector &values); - - MPI_Comm mpi_communicator; - - //FINITE ELEMENT SPACE - int degree_MAX; - int degree_LS; - DoFHandler dof_handler_LS; - FE_Q fe_LS; - IndexSet locally_owned_dofs_LS; - IndexSet locally_relevant_dofs_LS; - - int degree_U; - DoFHandler dof_handler_U; - FE_Q fe_U; - IndexSet locally_owned_dofs_U; - IndexSet locally_relevant_dofs_U; - - // OPERATORS times SOLUTION VECTOR // - PETScWrappers::MPI::Vector K_times_solution; - PETScWrappers::MPI::Vector DL_times_solution; - PETScWrappers::MPI::Vector DH_times_solution; - - // MASS MATRIX - PETScWrappers::MPI::SparseMatrix MC_matrix; - std_cxx1x::shared_ptr MC_preconditioner; - - // BOUNDARIES - std::vector boundary_values_id_u; - std::vector boundary_values_u; - - ////////////// - // MATRICES // - ////////////// - // FOR FIRST ORDER VISCOSITY - PETScWrappers::MPI::SparseMatrix Cx_matrix, CTx_matrix, Cy_matrix, CTy_matrix, Cz_matrix, CTz_matrix; - PETScWrappers::MPI::SparseMatrix dLij_matrix; - // FOR ENTROPY VISCOSITY - PETScWrappers::MPI::SparseMatrix EntRes_matrix, SuppSize_matrix, dCij_matrix; - // FOR FCT (flux and limited flux) - PETScWrappers::MPI::SparseMatrix A_matrix, LxA_matrix; - // FOR ITERATIVE FCT - PETScWrappers::MPI::SparseMatrix Akp1_matrix, LxAkp1_matrix; - - // GHOSTED VECTORS - PETScWrappers::MPI::Vector uStage1, uStage2; - PETScWrappers::MPI::Vector unm1, un; - PETScWrappers::MPI::Vector R_pos_vector, R_neg_vector; - PETScWrappers::MPI::Vector MPP_uL_solution_ghosted, MPP_uLkp1_solution_ghosted, NMPP_uH_solution_ghosted; - PETScWrappers::MPI::Vector locally_relevant_solution_vx; - PETScWrappers::MPI::Vector locally_relevant_solution_vy; - PETScWrappers::MPI::Vector locally_relevant_solution_vz; - PETScWrappers::MPI::Vector locally_relevant_solution_vx_old; - PETScWrappers::MPI::Vector locally_relevant_solution_vy_old; - PETScWrappers::MPI::Vector locally_relevant_solution_vz_old; - - // NON-GHOSTED VECTORS - PETScWrappers::MPI::Vector uStage1_nonGhosted, uStage2_nonGhosted; - PETScWrappers::MPI::Vector unp1; - PETScWrappers::MPI::Vector R_pos_vector_nonGhosted, R_neg_vector_nonGhosted; - PETScWrappers::MPI::Vector umin_vector, umax_vector; - PETScWrappers::MPI::Vector MPP_uL_solution, NMPP_uH_solution, MPP_uH_solution; - PETScWrappers::MPI::Vector RHS; - - // LUMPED MASS MATRIX - PETScWrappers::MPI::Vector ML_vector, ones_vector; - PETScWrappers::MPI::Vector inverse_ML_vector; - - // CONSTRAINTS - ConstraintMatrix constraints; - - // TIME STEPPING - double time_step; - - // SOME PARAMETERS - double cE, cK; - double solver_tolerance; - double entropy_normalization_factor; - - // UTILITIES - bool verbose; - std::string ALGORITHM; - unsigned int TIME_INTEGRATION; - - ConditionalOStream pcout; - - std::map map_from_Q1_to_Q2; - std::map > sparsity_pattern; - }; +{ +public: + //////////////////////// + // INITIAL CONDITIONS // + //////////////////////// + void initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_u, + PETScWrappers::MPI::Vector locally_relevant_solution_vx, + PETScWrappers::MPI::Vector locally_relevant_solution_vy); + void initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_u, + PETScWrappers::MPI::Vector locally_relevant_solution_vx, + PETScWrappers::MPI::Vector locally_relevant_solution_vy, + PETScWrappers::MPI::Vector locally_relevant_solution_vz); + ///////////////////////// + // BOUNDARY CONDITIONS // + ///////////////////////// + void set_boundary_conditions(std::vector &boundary_values_id_u, + std::vector boundary_values_u); + ////////////////// + // SET VELOCITY // + ////////////////// + void set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_vx, + PETScWrappers::MPI::Vector locally_relevant_solution_vy); + void set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_vx, + PETScWrappers::MPI::Vector locally_relevant_solution_vy, + PETScWrappers::MPI::Vector locally_relevant_solution_vz); + /////////////////////// + // SET AND GET ALPHA // + /////////////////////// + void get_unp1(PETScWrappers::MPI::Vector &locally_relevant_solution_u); + /////////////////// + // NTH TIME STEP // + /////////////////// + void nth_time_step(); + /////////// + // SETUP // + /////////// + void setup(); + + LevelSetSolver (const unsigned int degree_LS, + const unsigned int degree_U, + const double time_step, + const double cK, + const double cE, + const bool verbose, + std::string ALGORITHM, + const unsigned int TIME_INTEGRATION, + parallel::distributed::Triangulation &triangulation, + MPI_Comm &mpi_communicator); + ~LevelSetSolver(); + +private: + //////////////////////////////////////// + // ASSEMBLE MASS (and other) MATRICES // + //////////////////////////////////////// + void assemble_ML(); + void invert_ML(); + void assemble_MC(); + ////////////////////////////////////// + // LOW ORDER METHOD (DiJ Viscosity) // + ////////////////////////////////////// + void assemble_C_Matrix(); + void assemble_K_times_vector(PETScWrappers::MPI::Vector &solution); + void assemble_K_DL_DH_times_vector(PETScWrappers::MPI::Vector &solution); + /////////////////////// + // ENTROPY VISCOSITY // + /////////////////////// + void assemble_EntRes_Matrix(); + /////////////////////////// + // FOR MAXIMUM PRINCIPLE // + /////////////////////////// + void compute_bounds(PETScWrappers::MPI::Vector &un_solution); + void check_max_principle(PETScWrappers::MPI::Vector &unp1_solution); + /////////////////////// + // COMPUTE SOLUTIONS // + /////////////////////// + void compute_MPP_uL_and_NMPP_uH(PETScWrappers::MPI::Vector &MPP_uL_solution, + PETScWrappers::MPI::Vector &NMPP_uH_solution, + PETScWrappers::MPI::Vector &un_solution); + void compute_MPP_uH(PETScWrappers::MPI::Vector &MPP_uH_solution, + PETScWrappers::MPI::Vector &MPP_uL_solution_ghosted, + PETScWrappers::MPI::Vector &NMPP_uH_solution_ghosted, + PETScWrappers::MPI::Vector &un_solution); + void compute_MPP_uH_with_iterated_FCT(PETScWrappers::MPI::Vector &MPP_uH_solution, + PETScWrappers::MPI::Vector &MPP_uL_solution_ghosted, + PETScWrappers::MPI::Vector &NMPP_uH_solution_ghosted, + PETScWrappers::MPI::Vector &un_solution); + void compute_solution(PETScWrappers::MPI::Vector &unp1, + PETScWrappers::MPI::Vector &un, + std::string algorithm); + void compute_solution_SSP33(PETScWrappers::MPI::Vector &unp1, + PETScWrappers::MPI::Vector &un, + std::string algorithm); + /////////////// + // UTILITIES // + /////////////// + void get_sparsity_pattern(); + void get_map_from_Q1_to_Q2(); + void solve(const ConstraintMatrix &constraints, + PETScWrappers::MPI::SparseMatrix &Matrix, + std_cxx1x::shared_ptr preconditioner, + PETScWrappers::MPI::Vector &completely_distributed_solution, + const PETScWrappers::MPI::Vector &rhs); + void save_old_solution(); + void save_old_vel_solution(); + /////////////////////// + // MY PETSC WRAPPERS // + /////////////////////// + void get_vector_values(PETScWrappers::VectorBase &vector, + const std::vector &indices, + std::vector &values); + void get_vector_values(PETScWrappers::VectorBase &vector, + const std::vector &indices, + std::map &map_from_Q1_to_Q2, + std::vector &values); + + MPI_Comm mpi_communicator; + + //FINITE ELEMENT SPACE + int degree_MAX; + int degree_LS; + DoFHandler dof_handler_LS; + FE_Q fe_LS; + IndexSet locally_owned_dofs_LS; + IndexSet locally_relevant_dofs_LS; + + int degree_U; + DoFHandler dof_handler_U; + FE_Q fe_U; + IndexSet locally_owned_dofs_U; + IndexSet locally_relevant_dofs_U; + + // OPERATORS times SOLUTION VECTOR // + PETScWrappers::MPI::Vector K_times_solution; + PETScWrappers::MPI::Vector DL_times_solution; + PETScWrappers::MPI::Vector DH_times_solution; + + // MASS MATRIX + PETScWrappers::MPI::SparseMatrix MC_matrix; + std_cxx1x::shared_ptr MC_preconditioner; + + // BOUNDARIES + std::vector boundary_values_id_u; + std::vector boundary_values_u; + + ////////////// + // MATRICES // + ////////////// + // FOR FIRST ORDER VISCOSITY + PETScWrappers::MPI::SparseMatrix Cx_matrix, CTx_matrix, Cy_matrix, CTy_matrix, Cz_matrix, CTz_matrix; + PETScWrappers::MPI::SparseMatrix dLij_matrix; + // FOR ENTROPY VISCOSITY + PETScWrappers::MPI::SparseMatrix EntRes_matrix, SuppSize_matrix, dCij_matrix; + // FOR FCT (flux and limited flux) + PETScWrappers::MPI::SparseMatrix A_matrix, LxA_matrix; + // FOR ITERATIVE FCT + PETScWrappers::MPI::SparseMatrix Akp1_matrix, LxAkp1_matrix; + + // GHOSTED VECTORS + PETScWrappers::MPI::Vector uStage1, uStage2; + PETScWrappers::MPI::Vector unm1, un; + PETScWrappers::MPI::Vector R_pos_vector, R_neg_vector; + PETScWrappers::MPI::Vector MPP_uL_solution_ghosted, MPP_uLkp1_solution_ghosted, NMPP_uH_solution_ghosted; + PETScWrappers::MPI::Vector locally_relevant_solution_vx; + PETScWrappers::MPI::Vector locally_relevant_solution_vy; + PETScWrappers::MPI::Vector locally_relevant_solution_vz; + PETScWrappers::MPI::Vector locally_relevant_solution_vx_old; + PETScWrappers::MPI::Vector locally_relevant_solution_vy_old; + PETScWrappers::MPI::Vector locally_relevant_solution_vz_old; + + // NON-GHOSTED VECTORS + PETScWrappers::MPI::Vector uStage1_nonGhosted, uStage2_nonGhosted; + PETScWrappers::MPI::Vector unp1; + PETScWrappers::MPI::Vector R_pos_vector_nonGhosted, R_neg_vector_nonGhosted; + PETScWrappers::MPI::Vector umin_vector, umax_vector; + PETScWrappers::MPI::Vector MPP_uL_solution, NMPP_uH_solution, MPP_uH_solution; + PETScWrappers::MPI::Vector RHS; + + // LUMPED MASS MATRIX + PETScWrappers::MPI::Vector ML_vector, ones_vector; + PETScWrappers::MPI::Vector inverse_ML_vector; + + // CONSTRAINTS + ConstraintMatrix constraints; + + // TIME STEPPING + double time_step; + + // SOME PARAMETERS + double cE, cK; + double solver_tolerance; + double entropy_normalization_factor; + + // UTILITIES + bool verbose; + std::string ALGORITHM; + unsigned int TIME_INTEGRATION; + + ConditionalOStream pcout; + + std::map map_from_Q1_to_Q2; + std::map > sparsity_pattern; +}; template LevelSetSolver::LevelSetSolver (const unsigned int degree_LS, - const unsigned int degree_U, - const double time_step, - const double cK, - const double cE, - const bool verbose, - std::string ALGORITHM, - const unsigned int TIME_INTEGRATION, - parallel::distributed::Triangulation &triangulation, - MPI_Comm &mpi_communicator) + const unsigned int degree_U, + const double time_step, + const double cK, + const double cE, + const bool verbose, + std::string ALGORITHM, + const unsigned int TIME_INTEGRATION, + parallel::distributed::Triangulation &triangulation, + MPI_Comm &mpi_communicator) : mpi_communicator (mpi_communicator), degree_LS(degree_LS), @@ -310,8 +310,8 @@ LevelSetSolver::~LevelSetSolver () //////////////////////////////////////// template void LevelSetSolver::initial_condition (PETScWrappers::MPI::Vector un, - PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy) + PETScWrappers::MPI::Vector locally_relevant_solution_vx, + PETScWrappers::MPI::Vector locally_relevant_solution_vy) { this->un = un; this->locally_relevant_solution_vx = locally_relevant_solution_vx; @@ -324,9 +324,9 @@ void LevelSetSolver::initial_condition (PETScWrappers::MPI::Vector un, template void LevelSetSolver::initial_condition (PETScWrappers::MPI::Vector un, - PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy, - PETScWrappers::MPI::Vector locally_relevant_solution_vz) + PETScWrappers::MPI::Vector locally_relevant_solution_vx, + PETScWrappers::MPI::Vector locally_relevant_solution_vy, + PETScWrappers::MPI::Vector locally_relevant_solution_vz) { this->un = un; this->locally_relevant_solution_vx = locally_relevant_solution_vx; @@ -344,7 +344,7 @@ void LevelSetSolver::initial_condition (PETScWrappers::MPI::Vector un, ///////////////////////////////////////// template void LevelSetSolver::set_boundary_conditions(std::vector &boundary_values_id_u, - std::vector boundary_values_u) + std::vector boundary_values_u) { this->boundary_values_id_u = boundary_values_id_u; this->boundary_values_u = boundary_values_u; @@ -355,7 +355,7 @@ void LevelSetSolver::set_boundary_conditions(std::vector void LevelSetSolver::set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy) + PETScWrappers::MPI::Vector locally_relevant_solution_vy) { // SAVE OLD SOLUTION save_old_vel_solution(); @@ -366,8 +366,8 @@ void LevelSetSolver::set_velocity(PETScWrappers::MPI::Vector locally_releva template void LevelSetSolver::set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_vx, - PETScWrappers::MPI::Vector locally_relevant_solution_vy, - PETScWrappers::MPI::Vector locally_relevant_solution_vz) + PETScWrappers::MPI::Vector locally_relevant_solution_vy, + PETScWrappers::MPI::Vector locally_relevant_solution_vz) { // SAVE OLD SOLUTION save_old_vel_solution(); @@ -381,14 +381,14 @@ void LevelSetSolver::set_velocity(PETScWrappers::MPI::Vector locally_releva ////////// SET AND GET U ////////// /////////////////////////////////// template -void LevelSetSolver::get_unp1(PETScWrappers::MPI::Vector &unp1){unp1=this->unp1;} +void LevelSetSolver::get_unp1(PETScWrappers::MPI::Vector &unp1) {unp1=this->unp1;} // ------------------------------------------------------------------------------- // // ------------------------------ COMPUTE SOLUTIONS ------------------------------ // // ------------------------------------------------------------------------------- // template void LevelSetSolver::nth_time_step() -{ +{ assemble_EntRes_Matrix(); // COMPUTE SOLUTION // if (TIME_INTEGRATION==FORWARD_EULER) @@ -397,15 +397,15 @@ void LevelSetSolver::nth_time_step() compute_solution_SSP33(unp1,un,ALGORITHM); // BOUNDARY CONDITIONS unp1.set(boundary_values_id_u,boundary_values_u); - unp1.compress(VectorOperation::insert); - // CHECK MAXIMUM PRINCIPLE + unp1.compress(VectorOperation::insert); + // CHECK MAXIMUM PRINCIPLE if (CHECK_MAX_PRINCIPLE) { compute_bounds(un); check_max_principle(unp1); } - //pcout << "*********************************************************************... " - // << unp1.min() << ", " << unp1.max() << std::endl; + //pcout << "*********************************************************************... " + // << unp1.min() << ", " << unp1.max() << std::endl; save_old_solution(); } @@ -419,12 +419,12 @@ void LevelSetSolver::setup() degree_MAX = std::max(degree_LS,degree_U); //////////////////////////// // SETUP FOR DOF HANDLERS // - //////////////////////////// + //////////////////////////// // setup system LS dof_handler_LS.distribute_dofs (fe_LS); locally_owned_dofs_LS = dof_handler_LS.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_LS,locally_relevant_dofs_LS); - // setup system U + // setup system U dof_handler_U.distribute_dofs (fe_U); locally_owned_dofs_U = dof_handler_U.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_U,locally_relevant_dofs_U); @@ -442,7 +442,7 @@ void LevelSetSolver::setup() NMPP_uH_solution.reinit(locally_owned_dofs_LS,mpi_communicator); RHS.reinit(locally_owned_dofs_LS,mpi_communicator); uStage1_nonGhosted.reinit (locally_owned_dofs_LS,mpi_communicator); - uStage2_nonGhosted.reinit (locally_owned_dofs_LS,mpi_communicator); + uStage2_nonGhosted.reinit (locally_owned_dofs_LS,mpi_communicator); unp1.reinit (locally_owned_dofs_LS,mpi_communicator); MPP_uH_solution.reinit (locally_owned_dofs_LS,mpi_communicator); // vectors for lumped mass matrix @@ -463,7 +463,7 @@ void LevelSetSolver::setup() // GHOSTED VECTORS (used within some assemble process) // ///////////////////////////////////////////////////////// uStage1.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); - uStage2.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); + uStage2.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); unm1.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); un.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); MPP_uL_solution_ghosted.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); @@ -484,95 +484,95 @@ void LevelSetSolver::setup() //////////////////// // SETUP MATRICES // //////////////////// - // MATRICES + // MATRICES DynamicSparsityPattern dsp (locally_relevant_dofs_LS); DoFTools::make_sparsity_pattern (dof_handler_LS,dsp,constraints,false); SparsityTools::distribute_sparsity_pattern (dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - mpi_communicator, - locally_relevant_dofs_LS); + dof_handler_LS.n_locally_owned_dofs_per_processor(), + mpi_communicator, + locally_relevant_dofs_LS); MC_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); Cx_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); CTx_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); Cy_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); CTy_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); if (dim==3) { Cz_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); CTz_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); } dLij_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); EntRes_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); SuppSize_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); dCij_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); A_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); LxA_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); Akp1_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); LxAkp1_matrix.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); //COMPUTE MASS MATRICES (AND OTHERS) FOR FIRST TIME STEP // - assemble_ML(); + assemble_ML(); invert_ML(); - assemble_MC(); + assemble_MC(); assemble_C_Matrix(); // get mat for DOFs between Q1 and Q2 get_map_from_Q1_to_Q2(); @@ -586,37 +586,37 @@ template void LevelSetSolver::assemble_ML() { ML_vector=0; - + const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_LS (fe_LS, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); - + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); + const unsigned int dofs_per_cell = fe_LS.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); - + Vector cell_ML (dofs_per_cell); std::vector local_dof_indices (dofs_per_cell); typename DoFHandler::active_cell_iterator - cell_LS = dof_handler_LS.begin_active(), - endc_LS = dof_handler_LS.end(); - + cell_LS = dof_handler_LS.begin_active(), + endc_LS = dof_handler_LS.end(); + for (; cell_LS!=endc_LS; ++cell_LS) if (cell_LS->is_locally_owned()) { - cell_ML = 0; - fe_values_LS.reinit (cell_LS); - for (unsigned int q_point=0; q_pointget_dof_indices (local_dof_indices); - constraints.distribute_local_to_global (cell_ML,local_dof_indices,ML_vector); + cell_ML = 0; + fe_values_LS.reinit (cell_LS); + for (unsigned int q_point=0; q_pointget_dof_indices (local_dof_indices); + constraints.distribute_local_to_global (cell_ML,local_dof_indices,ML_vector); } // compress ML_vector.compress(VectorOperation::add); @@ -627,7 +627,7 @@ void LevelSetSolver::invert_ML() { // loop on locally owned i-DOFs (rows) IndexSet::ElementIterator idofs_iter = locally_owned_dofs_LS.begin(); - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) { int gi = *idofs_iter; inverse_ML_vector(gi) = 1./ML_vector(gi); @@ -639,42 +639,42 @@ template void LevelSetSolver::assemble_MC() { MC_matrix=0; - + const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_LS (fe_LS, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); - + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); + const unsigned int dofs_per_cell = fe_LS.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); - + FullMatrix cell_MC (dofs_per_cell, dofs_per_cell); std::vector local_dof_indices (dofs_per_cell); std::vector shape_values(dofs_per_cell); typename DoFHandler::active_cell_iterator - cell_LS = dof_handler_LS.begin_active(), - endc_LS = dof_handler_LS.end(); - + cell_LS = dof_handler_LS.begin_active(), + endc_LS = dof_handler_LS.end(); + for (; cell_LS!=endc_LS; ++cell_LS) if (cell_LS->is_locally_owned()) { - cell_MC = 0; - fe_values_LS.reinit (cell_LS); - for (unsigned int q_point=0; q_pointget_dof_indices (local_dof_indices); - constraints.distribute_local_to_global (cell_MC,local_dof_indices,MC_matrix); + cell_MC = 0; + fe_values_LS.reinit (cell_LS); + for (unsigned int q_point=0; q_pointget_dof_indices (local_dof_indices); + constraints.distribute_local_to_global (cell_MC,local_dof_indices,MC_matrix); } // compress MC_matrix.compress(VectorOperation::add); @@ -693,81 +693,81 @@ void LevelSetSolver::assemble_C_Matrix () CTy_matrix=0; Cz_matrix=0; CTz_matrix=0; - + const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_LS (fe_LS, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); - + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); + const unsigned int dofs_per_cell_LS = fe_LS.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); - + FullMatrix cell_Cij_x (dofs_per_cell_LS, dofs_per_cell_LS); FullMatrix cell_Cij_y (dofs_per_cell_LS, dofs_per_cell_LS); FullMatrix cell_Cij_z (dofs_per_cell_LS, dofs_per_cell_LS); FullMatrix cell_Cji_x (dofs_per_cell_LS, dofs_per_cell_LS); FullMatrix cell_Cji_y (dofs_per_cell_LS, dofs_per_cell_LS); FullMatrix cell_Cji_z (dofs_per_cell_LS, dofs_per_cell_LS); - + std::vector > shape_grads_LS(dofs_per_cell_LS); std::vector shape_values_LS(dofs_per_cell_LS); - + std::vector local_dof_indices_LS (dofs_per_cell_LS); - - typename DoFHandler::active_cell_iterator cell_LS, endc_LS; + + typename DoFHandler::active_cell_iterator cell_LS, endc_LS; cell_LS = dof_handler_LS.begin_active(); endc_LS = dof_handler_LS.end(); for (; cell_LS!=endc_LS; ++cell_LS) if (cell_LS->is_locally_owned()) { - cell_Cij_x = 0; - cell_Cij_y = 0; - cell_Cji_x = 0; - cell_Cji_y = 0; - if (dim==3) - { - cell_Cij_z = 0; - cell_Cji_z = 0; - } - - fe_values_LS.reinit (cell_LS); - cell_LS->get_dof_indices (local_dof_indices_LS); - - for (unsigned int q_point=0; q_pointget_dof_indices (local_dof_indices_LS); + + for (unsigned int q_point=0; q_point::assemble_K_times_vector(PETScWrappers::MPI::Vector &so const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_LS (fe_LS, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); FEValues fe_values_U (fe_U, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); const unsigned int dofs_per_cell = fe_LS.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); - + Vector cell_K_times_solution (dofs_per_cell); std::vector > un_grads (n_q_points); std::vector old_vx_values (n_q_points); - std::vector old_vy_values (n_q_points); - std::vector old_vz_values (n_q_points); + std::vector old_vy_values (n_q_points); + std::vector old_vz_values (n_q_points); std::vector shape_values(dofs_per_cell); std::vector > shape_grads(dofs_per_cell); Vector un_dofs(dofs_per_cell); - + std::vector indices_LS (dofs_per_cell); // loop on cells typename DoFHandler::active_cell_iterator - cell_LS = dof_handler_LS.begin_active(), - endc_LS = dof_handler_LS.end(); + cell_LS = dof_handler_LS.begin_active(), + endc_LS = dof_handler_LS.end(); typename DoFHandler::active_cell_iterator - cell_U = dof_handler_U.begin_active(); + cell_U = dof_handler_U.begin_active(); Tensor<1,dim> v; for (; cell_LS!=endc_LS; ++cell_U, ++cell_LS) if (cell_LS->is_locally_owned()) { - cell_K_times_solution=0; - - fe_values_LS.reinit (cell_LS); - cell_LS->get_dof_indices (indices_LS); - fe_values_LS.get_function_gradients(solution,un_grads); - - fe_values_U.reinit (cell_U); - fe_values_U.get_function_values(locally_relevant_solution_vx,old_vx_values); - fe_values_U.get_function_values(locally_relevant_solution_vy,old_vy_values); - if (dim==3) fe_values_U.get_function_values(locally_relevant_solution_vz,old_vz_values); - - // compute cell_K_times_solution - for (unsigned int q_point=0; q_pointget_dof_indices (indices_LS); + fe_values_LS.get_function_gradients(solution,un_grads); + + fe_values_U.reinit (cell_U); + fe_values_U.get_function_values(locally_relevant_solution_vx,old_vx_values); + fe_values_U.get_function_values(locally_relevant_solution_vy,old_vy_values); + if (dim==3) fe_values_U.get_function_values(locally_relevant_solution_vz,old_vz_values); + + // compute cell_K_times_solution + for (unsigned int q_point=0; q_point::assemble_K_DL_DH_times_vector const PetscScalar *Cxi, *Cyi, *Czi, *CTxi, *CTyi, *CTzi; const PetscScalar *EntResi, *SuppSizei, *MCi; double solni; - + Tensor<1,dim> vi,vj; - Tensor<1,dim> C, CT; + Tensor<1,dim> C, CT; // loop on locally owned i-DOFs (rows) IndexSet::ElementIterator idofs_iter = locally_owned_dofs_LS.begin(); - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) { PetscInt gi = *idofs_iter; //double ith_K_times_solution = 0; - + // read velocity of i-th DOF vi[0] = locally_relevant_solution_vx(map_from_Q1_to_Q2[gi]); vi[1] = locally_relevant_solution_vy(map_from_Q1_to_Q2[gi]); - if(dim==3) vi[2] = locally_relevant_solution_vz(map_from_Q1_to_Q2[gi]); + if (dim==3) vi[2] = locally_relevant_solution_vz(map_from_Q1_to_Q2[gi]); solni = solution(gi); // get i-th row of C matrices @@ -888,10 +889,10 @@ void LevelSetSolver::assemble_K_DL_DH_times_vector MatGetRow(CTx_matrix,gi,&ncolumns,&gj,&CTxi); MatGetRow(CTy_matrix,gi,&ncolumns,&gj,&CTyi); if (dim==3) - { - MatGetRow(Cz_matrix,gi,&ncolumns,&gj,&Czi); - MatGetRow(CTz_matrix,gi,&ncolumns,&gj,&CTzi); - } + { + MatGetRow(Cz_matrix,gi,&ncolumns,&gj,&Czi); + MatGetRow(CTz_matrix,gi,&ncolumns,&gj,&CTzi); + } MatGetRow(EntRes_matrix,gi,&ncolumns,&gj,&EntResi); MatGetRow(SuppSize_matrix,gi,&ncolumns,&gj,&SuppSizei); MatGetRow(MC_matrix,gi,&ncolumns,&gj,&MCi); @@ -906,42 +907,42 @@ void LevelSetSolver::assemble_K_DL_DH_times_vector get_vector_values(locally_relevant_solution_vx,gj_indices,map_from_Q1_to_Q2,vx); get_vector_values(locally_relevant_solution_vy,gj_indices,map_from_Q1_to_Q2,vy); if (dim==3) - get_vector_values(locally_relevant_solution_vz,gj_indices,map_from_Q1_to_Q2,vz); + get_vector_values(locally_relevant_solution_vz,gj_indices,map_from_Q1_to_Q2,vz); // Array for i-th row of matrices std::vector dLi(ncolumns), dCi(ncolumns); double dLii = 0, dCii = 0; // loop on sparsity pattern of i-th DOF for (int j =0; j < ncolumns; j++) - { - C[0] = Cxi[j]; - C[1] = Cyi[j]; - CT[0]= CTxi[j]; - CT[1]= CTyi[j]; - vj[0] = vx[j]; - vj[1] = vy[j]; - if (dim==3) - { - C[2] = Czi[j]; - CT[2] = CTzi[j]; - vj[2] = vz[j]; - } - - //ith_K_times_solution += soln[j]*(vj*C); - if (gi!=gj[j]) - { - // low order dissipative matrix - dLi[j] = -std::max(std::abs(vi*C),std::abs(vj*CT)); - dLii -= dLi[j]; - // high order dissipative matrix (entropy viscosity) - double dEij = -std::min(-dLi[j], - cE*std::abs(EntResi[j])/(entropy_normalization_factor*MCi[j]/SuppSizei[j])); - // high order compression matrix - double Compij = cK*std::max(1-std::pow(0.5*(solni+soln[j]),2),0.0)/(std::abs(solni-soln[j])+1E-14); - dCi[j] = dEij*std::max(1-Compij,0.0); - dCii -= dCi[j]; - } - } + { + C[0] = Cxi[j]; + C[1] = Cyi[j]; + CT[0]= CTxi[j]; + CT[1]= CTyi[j]; + vj[0] = vx[j]; + vj[1] = vy[j]; + if (dim==3) + { + C[2] = Czi[j]; + CT[2] = CTzi[j]; + vj[2] = vz[j]; + } + + //ith_K_times_solution += soln[j]*(vj*C); + if (gi!=gj[j]) + { + // low order dissipative matrix + dLi[j] = -std::max(std::abs(vi*C),std::abs(vj*CT)); + dLii -= dLi[j]; + // high order dissipative matrix (entropy viscosity) + double dEij = -std::min(-dLi[j], + cE*std::abs(EntResi[j])/(entropy_normalization_factor*MCi[j]/SuppSizei[j])); + // high order compression matrix + double Compij = cK*std::max(1-std::pow(0.5*(solni+soln[j]),2),0.0)/(std::abs(solni-soln[j])+1E-14); + dCi[j] = dEij*std::max(1-Compij,0.0); + dCii -= dCi[j]; + } + } // save K times solution vector //K_times_solution(gi)=ith_K_times_solution; // save i-th row of matrices on global matrices @@ -956,10 +957,10 @@ void LevelSetSolver::assemble_K_DL_DH_times_vector MatRestoreRow(CTx_matrix,gi,&ncolumns,&gj,&CTxi); MatRestoreRow(CTy_matrix,gi,&ncolumns,&gj,&CTyi); if (dim==3) - { - MatRestoreRow(Cz_matrix,gi,&ncolumns,&gj,&Czi); - MatRestoreRow(CTz_matrix,gi,&ncolumns,&gj,&CTzi); - } + { + MatRestoreRow(Cz_matrix,gi,&ncolumns,&gj,&Czi); + MatRestoreRow(CTz_matrix,gi,&ncolumns,&gj,&CTzi); + } MatRestoreRow(EntRes_matrix,gi,&ncolumns,&gj,&EntResi); MatRestoreRow(SuppSize_matrix,gi,&ncolumns,&gj,&SuppSizei); MatRestoreRow(MC_matrix,gi,&ncolumns,&gj,&MCi); @@ -982,17 +983,17 @@ void LevelSetSolver::assemble_EntRes_Matrix () EntRes_matrix=0; entropy_normalization_factor=0; SuppSize_matrix=0; - + const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_U (fe_U, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); FEValues fe_values_LS (fe_LS, quadrature_formula, - update_values | update_gradients | - update_quadrature_points | - update_JxW_values); - + update_values | update_gradients | + update_quadrature_points | + update_JxW_values); + const unsigned int dofs_per_cell_LS = fe_LS.dofs_per_cell; const unsigned int n_q_points = quadrature_formula.size(); @@ -1005,22 +1006,22 @@ void LevelSetSolver::assemble_EntRes_Matrix () std::vector vyqn (n_q_points); std::vector vzqn (n_q_points); std::vector vxqnm1 (n_q_points); - std::vector vyqnm1 (n_q_points); - std::vector vzqnm1 (n_q_points); - + std::vector vyqnm1 (n_q_points); + std::vector vzqnm1 (n_q_points); + FullMatrix cell_EntRes (dofs_per_cell_LS, dofs_per_cell_LS); FullMatrix cell_volume (dofs_per_cell_LS, dofs_per_cell_LS); - + std::vector > shape_grads_LS(dofs_per_cell_LS); std::vector shape_values_LS(dofs_per_cell_LS); - + std::vector local_dof_indices_LS (dofs_per_cell_LS); - - typename DoFHandler::active_cell_iterator cell_LS, endc_LS; + + typename DoFHandler::active_cell_iterator cell_LS, endc_LS; cell_LS = dof_handler_LS.begin_active(); endc_LS = dof_handler_LS.end(); typename DoFHandler::active_cell_iterator - cell_U = dof_handler_U.begin_active(); + cell_U = dof_handler_U.begin_active(); double Rk; double max_entropy=-1E10, min_entropy=1E10; @@ -1031,68 +1032,68 @@ void LevelSetSolver::assemble_EntRes_Matrix () for (; cell_LS!=endc_LS; ++cell_LS, ++cell_U) if (cell_LS->is_locally_owned()) { - cell_entropy_mass = 0; - cell_volume_double = 0; - cell_max_entropy = -1E10; - cell_min_entropy = 1E10; - cell_EntRes = 0; - cell_volume = 0; - - // get solutions at quadrature points - fe_values_LS.reinit(cell_LS); - cell_LS->get_dof_indices (local_dof_indices_LS); - fe_values_LS.get_function_values(un,uqn); - fe_values_LS.get_function_values(unm1,uqnm1); - fe_values_LS.get_function_gradients(un,guqn); - fe_values_LS.get_function_gradients(unm1,guqnm1); - - fe_values_U.reinit(cell_U); - fe_values_U.get_function_values(locally_relevant_solution_vx,vxqn); - fe_values_U.get_function_values(locally_relevant_solution_vy,vyqn); - if (dim==3) fe_values_U.get_function_values(locally_relevant_solution_vz,vzqn); - fe_values_U.get_function_values(locally_relevant_solution_vx_old,vxqnm1); - fe_values_U.get_function_values(locally_relevant_solution_vy_old,vyqnm1); - if (dim==3) fe_values_U.get_function_values(locally_relevant_solution_vz_old,vzqnm1); - - for (unsigned int q=0; qget_dof_indices (local_dof_indices_LS); + fe_values_LS.get_function_values(un,uqn); + fe_values_LS.get_function_values(unm1,uqnm1); + fe_values_LS.get_function_gradients(un,guqn); + fe_values_LS.get_function_gradients(unm1,guqnm1); + + fe_values_U.reinit(cell_U); + fe_values_U.get_function_values(locally_relevant_solution_vx,vxqn); + fe_values_U.get_function_values(locally_relevant_solution_vy,vyqn); + if (dim==3) fe_values_U.get_function_values(locally_relevant_solution_vz,vzqn); + fe_values_U.get_function_values(locally_relevant_solution_vx_old,vxqnm1); + fe_values_U.get_function_values(locally_relevant_solution_vy_old,vyqnm1); + if (dim==3) fe_values_U.get_function_values(locally_relevant_solution_vz_old,vzqnm1); + + for (unsigned int q=0; q::compute_bounds(PETScWrappers::MPI::Vector &un_solution umax_vector = 0; // loop on locally owned i-DOFs (rows) IndexSet::ElementIterator idofs_iter = locally_owned_dofs_LS.begin(); - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) { int gi = *idofs_iter; @@ -1121,44 +1122,44 @@ void LevelSetSolver::compute_bounds(PETScWrappers::MPI::Vector &un_solution // compute bounds, ith row of flux matrix, P vectors double mini=1E10, maxi=-1E10; for (unsigned int j =0; j < gj_indices.size(); j++) - { - // bounds - mini = std::min(mini,soln[j]); - maxi = std::max(maxi,soln[j]); - } + { + // bounds + mini = std::min(mini,soln[j]); + maxi = std::max(maxi,soln[j]); + } umin_vector(gi) = mini; umax_vector(gi) = maxi; } umin_vector.compress(VectorOperation::insert); - umax_vector.compress(VectorOperation::insert); + umax_vector.compress(VectorOperation::insert); } template -void LevelSetSolver::check_max_principle(PETScWrappers::MPI::Vector &unp1_solution) +void LevelSetSolver::check_max_principle(PETScWrappers::MPI::Vector &unp1_solution) { // compute min and max vectors const unsigned int dofs_per_cell = fe_LS.dofs_per_cell; std::vector local_dof_indices (dofs_per_cell); - + double tol=1e-10; typename DoFHandler::active_cell_iterator - cell_LS = dof_handler_LS.begin_active(), - endc_LS = dof_handler_LS.end(); - + cell_LS = dof_handler_LS.begin_active(), + endc_LS = dof_handler_LS.end(); + for (; cell_LS!=endc_LS; ++cell_LS) if (cell_LS->is_locally_owned() && !cell_LS->at_boundary()) { - cell_LS->get_dof_indices(local_dof_indices); - for (unsigned int i=0; iget_dof_indices(local_dof_indices); + for (unsigned int i=0; i::compute_MPP_uL_and_NMPP_uH NMPP_uH_solution=un_solution; // to start iterative solver at un_solution (instead of zero) // assemble RHS VECTORS assemble_K_times_vector(un_solution); - assemble_K_DL_DH_times_vector(un_solution); + assemble_K_DL_DH_times_vector(un_solution); ///////////////////////////// // COMPUTE MPP u1 solution // ///////////////////////////// @@ -1208,16 +1209,16 @@ void LevelSetSolver::compute_MPP_uH const PetscInt *gj; const PetscScalar *MCi, *dLi, *dCi; double solni, mi, solLi, solHi; - - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) { - int gi = *idofs_iter; + int gi = *idofs_iter; // read vectors at i-th DOF solni=solution(gi); solHi=NMPP_uH_solution_ghosted(gi); solLi=MPP_uL_solution_ghosted(gi); mi=ML_vector(gi); - + // get i-th row of matrices MatGetRow(MC_matrix,gi,&ncolumns,&gj,&MCi); MatGetRow(dLij_matrix,gi,&ncolumns,&gj,&dLi); @@ -1236,19 +1237,19 @@ void LevelSetSolver::compute_MPP_uH double mini=1E10, maxi=-1E10; double Pposi=0 ,Pnegi=0; for (int j =0; j < ncolumns; j++) - { - // bounds - mini = std::min(mini,soln[j]); - maxi = std::max(maxi,soln[j]); - - // i-th row of flux matrix A - Ai[j] = (((gi==gj[j]) ? 1 : 0)*mi - MCi[j])*(solH[j]-soln[j] - (solHi-solni)) - +time_step*(dLi[j]-dCi[j])*(soln[j]-solni); - - // compute P vectors - Pposi += Ai[j]*((Ai[j] > 0) ? 1. : 0.); - Pnegi += Ai[j]*((Ai[j] < 0) ? 1. : 0.); - } + { + // bounds + mini = std::min(mini,soln[j]); + maxi = std::max(maxi,soln[j]); + + // i-th row of flux matrix A + Ai[j] = (((gi==gj[j]) ? 1 : 0)*mi - MCi[j])*(solH[j]-soln[j] - (solHi-solni)) + +time_step*(dLi[j]-dCi[j])*(soln[j]-solni); + + // compute P vectors + Pposi += Ai[j]*((Ai[j] > 0) ? 1. : 0.); + Pnegi += Ai[j]*((Ai[j] < 0) ? 1. : 0.); + } // save i-th row of flux matrix A MatSetValuesRow(A_matrix,gi,&Ai[0]); @@ -1259,7 +1260,7 @@ void LevelSetSolver::compute_MPP_uH // compute R vectors R_pos_vector_nonGhosted(gi) = ((Pposi==0) ? 1. : std::min(1.0,Qposi/Pposi)); R_neg_vector_nonGhosted(gi) = ((Pnegi==0) ? 1. : std::min(1.0,Qnegi/Pnegi)); - + // Restore matrices after reading rows MatRestoreRow(MC_matrix,gi,&ncolumns,&gj,&MCi); MatRestoreRow(dLij_matrix,gi,&ncolumns,&gj,&dLi); @@ -1273,12 +1274,12 @@ void LevelSetSolver::compute_MPP_uH // update ghost values for R vectors R_pos_vector = R_pos_vector_nonGhosted; R_neg_vector = R_neg_vector_nonGhosted; - + // compute limiters. NOTE: this is a different loop due to need of i- and j-th entries of R vectors const double *Ai; - double Rposi, Rnegi; + double Rposi, Rnegi; idofs_iter=locally_owned_dofs_LS.begin(); - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) { int gi = *idofs_iter; Rposi = R_pos_vector(gi); @@ -1298,7 +1299,7 @@ void LevelSetSolver::compute_MPP_uH std::vector LxAi(ncolumns); // loop in sparsity pattern of i-th DOF for (int j =0; j < ncolumns; j++) - LxAi[j] = Ai[j] * ((Ai[j]>0) ? std::min(Rposi,Rneg[j]) : std::min(Rnegi,Rpos[j])); + LxAi[j] = Ai[j] * ((Ai[j]>0) ? std::min(Rposi,Rneg[j]) : std::min(Rnegi,Rpos[j])); // save i-th row of LxA MatSetValuesRow(LxA_matrix,gi,&LxAi[0]); // BTW: there is a dealii wrapper for this @@ -1325,106 +1326,106 @@ void LevelSetSolver::compute_MPP_uH_with_iterated_FCT { Akp1_matrix.copy_from(A_matrix); LxAkp1_matrix.copy_from(LxA_matrix); - + // loop in num of FCT iterations PetscInt ncolumns; const PetscInt *gj; const PetscScalar *Akp1i; double mi; for (int iter=0; iter gj_indices (gj,gj+ncolumns); - std::vector soln(ncolumns); - get_vector_values(un_solution,gj_indices,soln); - - // compute bounds, ith row of flux matrix, P vectors - double mini=1E10, maxi=-1E10; - double Pposi=0 ,Pnegi=0; - for (int j =0; j < ncolumns; j++) - { - // bounds - mini = std::min(mini,soln[j]); - maxi = std::max(maxi,soln[j]); - - // compute P vectors - Pposi += Akp1i[j]*((Akp1i[j] > 0) ? 1. : 0.); - Pnegi += Akp1i[j]*((Akp1i[j] < 0) ? 1. : 0.); - } - // compute Q vectors - double Qposi = mi*(maxi-solLi); - double Qnegi = mi*(mini-solLi); - - // compute R vectors - R_pos_vector_nonGhosted(gi) = ((Pposi==0) ? 1. : std::min(1.0,Qposi/Pposi)); - R_neg_vector_nonGhosted(gi) = ((Pnegi==0) ? 1. : std::min(1.0,Qnegi/Pnegi)); - - // Restore matrices after reading rows - MatRestoreRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); - } - // compress R vectors - R_pos_vector_nonGhosted.compress(VectorOperation::insert); - R_neg_vector_nonGhosted.compress(VectorOperation::insert); - // update ghost values for R vectors - R_pos_vector = R_pos_vector_nonGhosted; - R_neg_vector = R_neg_vector_nonGhosted; - - // compute limiters. NOTE: this is a different loop due to need of i- and j-th entries of R vectors - double Rposi, Rnegi; - idofs_iter=locally_owned_dofs_LS.begin(); - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) - { - int gi = *idofs_iter; - Rposi = R_pos_vector(gi); - Rnegi = R_neg_vector(gi); - - // get i-th row of Akp1 matrix - MatGetRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); - - // get vector values for column indices - const std::vector gj_indices(gj,gj+ncolumns); - std::vector Rpos(ncolumns); - std::vector Rneg(ncolumns); - get_vector_values(R_pos_vector,gj_indices,Rpos); - get_vector_values(R_neg_vector,gj_indices,Rneg); - - // Array for i-th row of LxAkp1 matrix - std::vector LxAkp1i(ncolumns); - for (int j =0; j < ncolumns; j++) - LxAkp1i[j] = Akp1i[j] * ((Akp1i[j]>0) ? std::min(Rposi,Rneg[j]) : std::min(Rnegi,Rpos[j])); - - // save i-th row of LxA - MatSetValuesRow(LxAkp1_matrix,gi,&LxAkp1i[0]); // BTW: there is a dealii wrapper for this - // restore A matrix after reading it - MatRestoreRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); - } - LxAkp1_matrix.compress(VectorOperation::insert); - LxAkp1_matrix.vmult(MPP_uH_solution,ones_vector); - MPP_uH_solution.scale(inverse_ML_vector); - MPP_uH_solution.add(1.0,MPP_uLkp1_solution_ghosted); - } + { + MPP_uLkp1_solution_ghosted = MPP_uH_solution; + Akp1_matrix.add(-1.0, LxAkp1_matrix); //new matrix to limit: A-LxA + + // loop on locally owned i-DOFs (rows) + IndexSet::ElementIterator idofs_iter = locally_owned_dofs_LS.begin(); + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + { + int gi = *idofs_iter; + + // read vectors at i-th DOF + mi=ML_vector(gi); + double solLi = MPP_uLkp1_solution_ghosted(gi); + + // get i-th row of matrices + MatGetRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); + // get vector values for support of i-th DOF + const std::vector gj_indices (gj,gj+ncolumns); + std::vector soln(ncolumns); + get_vector_values(un_solution,gj_indices,soln); + + // compute bounds, ith row of flux matrix, P vectors + double mini=1E10, maxi=-1E10; + double Pposi=0 ,Pnegi=0; + for (int j =0; j < ncolumns; j++) + { + // bounds + mini = std::min(mini,soln[j]); + maxi = std::max(maxi,soln[j]); + + // compute P vectors + Pposi += Akp1i[j]*((Akp1i[j] > 0) ? 1. : 0.); + Pnegi += Akp1i[j]*((Akp1i[j] < 0) ? 1. : 0.); + } + // compute Q vectors + double Qposi = mi*(maxi-solLi); + double Qnegi = mi*(mini-solLi); + + // compute R vectors + R_pos_vector_nonGhosted(gi) = ((Pposi==0) ? 1. : std::min(1.0,Qposi/Pposi)); + R_neg_vector_nonGhosted(gi) = ((Pnegi==0) ? 1. : std::min(1.0,Qnegi/Pnegi)); + + // Restore matrices after reading rows + MatRestoreRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); + } + // compress R vectors + R_pos_vector_nonGhosted.compress(VectorOperation::insert); + R_neg_vector_nonGhosted.compress(VectorOperation::insert); + // update ghost values for R vectors + R_pos_vector = R_pos_vector_nonGhosted; + R_neg_vector = R_neg_vector_nonGhosted; + + // compute limiters. NOTE: this is a different loop due to need of i- and j-th entries of R vectors + double Rposi, Rnegi; + idofs_iter=locally_owned_dofs_LS.begin(); + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + { + int gi = *idofs_iter; + Rposi = R_pos_vector(gi); + Rnegi = R_neg_vector(gi); + + // get i-th row of Akp1 matrix + MatGetRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); + + // get vector values for column indices + const std::vector gj_indices(gj,gj+ncolumns); + std::vector Rpos(ncolumns); + std::vector Rneg(ncolumns); + get_vector_values(R_pos_vector,gj_indices,Rpos); + get_vector_values(R_neg_vector,gj_indices,Rneg); + + // Array for i-th row of LxAkp1 matrix + std::vector LxAkp1i(ncolumns); + for (int j =0; j < ncolumns; j++) + LxAkp1i[j] = Akp1i[j] * ((Akp1i[j]>0) ? std::min(Rposi,Rneg[j]) : std::min(Rnegi,Rpos[j])); + + // save i-th row of LxA + MatSetValuesRow(LxAkp1_matrix,gi,&LxAkp1i[0]); // BTW: there is a dealii wrapper for this + // restore A matrix after reading it + MatRestoreRow(Akp1_matrix,gi,&ncolumns,&gj,&Akp1i); + } + LxAkp1_matrix.compress(VectorOperation::insert); + LxAkp1_matrix.vmult(MPP_uH_solution,ones_vector); + MPP_uH_solution.scale(inverse_ML_vector); + MPP_uH_solution.add(1.0,MPP_uLkp1_solution_ghosted); + } } } template void LevelSetSolver::compute_solution(PETScWrappers::MPI::Vector &unp1, - PETScWrappers::MPI::Vector &un, - std::string algorithm) + PETScWrappers::MPI::Vector &un, + std::string algorithm) { unp1=0; // COMPUTE MPP LOW-ORDER SOLN and NMPP HIGH-ORDER SOLN @@ -1439,9 +1440,9 @@ void LevelSetSolver::compute_solution(PETScWrappers::MPI::Vector &unp1, MPP_uL_solution_ghosted = MPP_uL_solution; NMPP_uH_solution_ghosted=NMPP_uH_solution; compute_MPP_uH_with_iterated_FCT(MPP_uH_solution,MPP_uL_solution_ghosted,NMPP_uH_solution_ghosted,un); - unp1=MPP_uH_solution; + unp1=MPP_uH_solution; } - else + else { pcout << "Error in algorithm" << std::endl; abort(); @@ -1450,8 +1451,8 @@ void LevelSetSolver::compute_solution(PETScWrappers::MPI::Vector &unp1, template void LevelSetSolver::compute_solution_SSP33(PETScWrappers::MPI::Vector &unp1, - PETScWrappers::MPI::Vector &un, - std::string algorithm) + PETScWrappers::MPI::Vector &un, + std::string algorithm) { // GHOSTED VECTORS: un // NON-GHOSTED VECTORS: unp1 @@ -1469,7 +1470,7 @@ void LevelSetSolver::compute_solution_SSP33(PETScWrappers::MPI::Vector &unp ////////////////// // u2=3/4*un+1/4*(u1-dt*RH*u1) compute_solution(uStage2_nonGhosted,uStage1,algorithm); - uStage2_nonGhosted*=1./4; + uStage2_nonGhosted*=1./4; uStage2_nonGhosted.add(3./4,un); uStage2=uStage2_nonGhosted; ///////////////// @@ -1493,7 +1494,7 @@ void LevelSetSolver::get_sparsity_pattern() const PetscInt *gj; const PetscScalar *MCi; - for (;idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) + for (; idofs_iter!=locally_owned_dofs_LS.end(); idofs_iter++) { PetscInt gi = *idofs_iter; // get i-th row of mass matrix (dummy, I just need the indices gj) @@ -1513,27 +1514,27 @@ void LevelSetSolver::get_map_from_Q1_to_Q2() std::vector local_dof_indices_U (dofs_per_cell_U); typename DoFHandler::active_cell_iterator - cell_LS = dof_handler_LS.begin_active(), - endc_LS = dof_handler_LS.end(); + cell_LS = dof_handler_LS.begin_active(), + endc_LS = dof_handler_LS.end(); typename DoFHandler::active_cell_iterator - cell_U = dof_handler_U.begin_active(); + cell_U = dof_handler_U.begin_active(); for (; cell_LS!=endc_LS; ++cell_LS, ++cell_U) if (!cell_LS->is_artificial()) // loop on ghost cells as well { - cell_LS->get_dof_indices(local_dof_indices_LS); - cell_U->get_dof_indices(local_dof_indices_U); - for (unsigned int i=0; iget_dof_indices(local_dof_indices_LS); + cell_U->get_dof_indices(local_dof_indices_U); + for (unsigned int i=0; i -void LevelSetSolver::solve(const ConstraintMatrix &constraints, - PETScWrappers::MPI::SparseMatrix &Matrix, - std_cxx1x::shared_ptr preconditioner, - PETScWrappers::MPI::Vector &completely_distributed_solution, - const PETScWrappers::MPI::Vector &rhs) +void LevelSetSolver::solve(const ConstraintMatrix &constraints, + PETScWrappers::MPI::SparseMatrix &Matrix, + std_cxx1x::shared_ptr preconditioner, + PETScWrappers::MPI::Vector &completely_distributed_solution, + const PETScWrappers::MPI::Vector &rhs) { // all vectors are NON-GHOSTED SolverControl solver_control (dof_handler_LS.n_dofs(), solver_tolerance); @@ -1547,8 +1548,8 @@ void LevelSetSolver::solve(const ConstraintMatrix &constraints, template void LevelSetSolver::save_old_solution() { - unm1 = un; - un = unp1; + unm1 = un; + un = unp1; } template @@ -1556,7 +1557,7 @@ void LevelSetSolver::save_old_vel_solution() { locally_relevant_solution_vx_old = locally_relevant_solution_vx; locally_relevant_solution_vy_old = locally_relevant_solution_vy; - if(dim==3) + if (dim==3) locally_relevant_solution_vz_old = locally_relevant_solution_vz; } @@ -1564,90 +1565,90 @@ void LevelSetSolver::save_old_vel_solution() // ------------------------------ MY PETSC WRAPPERS ------------------------------ // // ------------------------------------------------------------------------------- // template -void LevelSetSolver::get_vector_values (PETScWrappers::VectorBase &vector, - const std::vector &indices, - std::vector &values) +void LevelSetSolver::get_vector_values (PETScWrappers::VectorBase &vector, + const std::vector &indices, + std::vector &values) { - // PETSc wrapper to get sets of values from a petsc vector. + // PETSc wrapper to get sets of values from a petsc vector. // we assume the vector is ghosted - // We need to figure out which elements we - // own locally. Then get a pointer to the + // We need to figure out which elements we + // own locally. Then get a pointer to the // elements that are stored here (both the // ones we own as well as the ghost elements). - // In this array, the locally owned elements - // come first followed by the ghost elements whose - // position we can get from an index set - + // In this array, the locally owned elements + // come first followed by the ghost elements whose + // position we can get from an index set + IndexSet ghost_indices = locally_relevant_dofs_LS; ghost_indices.subtract_set(locally_owned_dofs_LS); PetscInt n_idx, begin, end, i; n_idx = indices.size(); - - VecGetOwnershipRange (vector, &begin, &end); - + + VecGetOwnershipRange (vector, &begin, &end); + Vec solution_in_local_form = PETSC_NULL; VecGhostGetLocalForm(vector, &solution_in_local_form); - + PetscScalar *soln; VecGetArray(solution_in_local_form, &soln); - - for (i = 0; i < n_idx; i++) + + for (i = 0; i < n_idx; i++) { int index = indices[i]; if (index >= begin && index < end) - values[i] = *(soln+index-begin); + values[i] = *(soln+index-begin); else //ghost - { - const unsigned int ghostidx = ghost_indices.index_within_set(index); - values[i] = *(soln+ghostidx+end-begin); - } + { + const unsigned int ghostidx = ghost_indices.index_within_set(index); + values[i] = *(soln+ghostidx+end-begin); + } } VecRestoreArray(solution_in_local_form, &soln); VecGhostRestoreLocalForm(vector, &solution_in_local_form); } template -void LevelSetSolver::get_vector_values (PETScWrappers::VectorBase &vector, - const std::vector &indices, - std::map &map_from_Q1_to_Q2, - std::vector &values) +void LevelSetSolver::get_vector_values (PETScWrappers::VectorBase &vector, + const std::vector &indices, + std::map &map_from_Q1_to_Q2, + std::vector &values) { // THIS IS MEANT TO BE USED WITH VELOCITY VECTORS - // PETSc wrapper to get sets of values from a petsc vector. + // PETSc wrapper to get sets of values from a petsc vector. // we assume the vector is ghosted - // We need to figure out which elements we - // own locally. Then get a pointer to the + // We need to figure out which elements we + // own locally. Then get a pointer to the // elements that are stored here (both the // ones we own as well as the ghost elements). - // In this array, the locally owned elements - // come first followed by the ghost elements whose - // position we can get from an index set - + // In this array, the locally owned elements + // come first followed by the ghost elements whose + // position we can get from an index set + IndexSet ghost_indices = locally_relevant_dofs_U; ghost_indices.subtract_set(locally_owned_dofs_U); PetscInt n_idx, begin, end, i; n_idx = indices.size(); - - VecGetOwnershipRange (vector, &begin, &end); - + + VecGetOwnershipRange (vector, &begin, &end); + Vec solution_in_local_form = PETSC_NULL; VecGhostGetLocalForm(vector, &solution_in_local_form); - + PetscScalar *soln; VecGetArray(solution_in_local_form, &soln); - - for (i = 0; i < n_idx; i++) + + for (i = 0; i < n_idx; i++) { int index = map_from_Q1_to_Q2[indices[i]]; if (index >= begin && index < end) - values[i] = *(soln+index-begin); + values[i] = *(soln+index-begin); else //ghost - { - const unsigned int ghostidx = ghost_indices.index_within_set(index); - values[i] = *(soln+ghostidx+end-begin); - } + { + const unsigned int ghostidx = ghost_indices.index_within_set(index); + values[i] = *(soln+ghostidx+end-begin); + } } VecRestoreArray(solution_in_local_form, &soln); VecGhostRestoreLocalForm(vector, &solution_in_local_form); diff --git a/two_phase_flow/MultiPhase.cc b/two_phase_flow/MultiPhase.cc index dd525c6..3000496 100644 --- a/two_phase_flow/MultiPhase.cc +++ b/two_phase_flow/MultiPhase.cc @@ -42,9 +42,9 @@ using namespace dealii; // TIME_INTEGRATION #define FORWARD_EULER 0 #define SSP33 1 -// PROBLEM +// PROBLEM #define FILLING_TANK 0 -#define BREAKING_DAM 1 +#define BREAKING_DAM 1 #define FALLING_DROP 2 #define SMALL_WAVE_PERTURBATION 3 @@ -60,7 +60,7 @@ class MultiPhase { public: MultiPhase (const unsigned int degree_LS, - const unsigned int degree_U); + const unsigned int degree_U); ~MultiPhase (); void run (); @@ -68,7 +68,7 @@ private: void set_boundary_inlet(); void get_boundary_values_U(); void get_boundary_values_phi(std::vector &boundary_values_id_phi, - std::vector &boundary_values_phi); + std::vector &boundary_values_phi); void output_results(); void output_vectors(); void output_rho(); @@ -78,7 +78,7 @@ private: MPI_Comm mpi_communicator; parallel::distributed::Triangulation triangulation; - + int degree_LS; DoFHandler dof_handler_LS; FE_Q fe_LS; @@ -96,7 +96,7 @@ private: FE_Q fe_P; IndexSet locally_owned_dofs_P; IndexSet locally_relevant_dofs_P; - + ConditionalOStream pcout; // SOLUTION VECTORS @@ -126,7 +126,7 @@ private: double umax; double min_h; - double sharpness; + double sharpness; int sharpness_integer; unsigned int n_refinement; @@ -153,14 +153,14 @@ private: }; template -MultiPhase::MultiPhase (const unsigned int degree_LS, - const unsigned int degree_U) +MultiPhase::MultiPhase (const unsigned int degree_LS, + const unsigned int degree_U) : mpi_communicator (MPI_COMM_WORLD), triangulation (mpi_communicator, - typename Triangulation::MeshSmoothing - (Triangulation::smoothing_on_refinement | - Triangulation::smoothing_on_coarsening)), + typename Triangulation::MeshSmoothing + (Triangulation::smoothing_on_refinement | + Triangulation::smoothing_on_coarsening)), degree_LS(degree_LS), dof_handler_LS (triangulation), fe_LS (degree_LS), @@ -168,7 +168,7 @@ MultiPhase::MultiPhase (const unsigned int degree_LS, dof_handler_U (triangulation), fe_U (degree_U), dof_handler_P (triangulation), - fe_P (degree_U-1), + fe_P (degree_U-1), pcout (std::cout,(Utilities::MPI::this_mpi_process(mpi_communicator)== 0)) {} @@ -185,22 +185,22 @@ MultiPhase::~MultiPhase () ///////////////////////////////////////// template void MultiPhase::setup() -{ +{ // setup system LS dof_handler_LS.distribute_dofs (fe_LS); locally_owned_dofs_LS = dof_handler_LS.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_LS, - locally_relevant_dofs_LS); - // setup system U + locally_relevant_dofs_LS); + // setup system U dof_handler_U.distribute_dofs (fe_U); locally_owned_dofs_U = dof_handler_U.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_U, - locally_relevant_dofs_U); + locally_relevant_dofs_U); // setup system P // dof_handler_P.distribute_dofs (fe_P); locally_owned_dofs_P = dof_handler_P.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_P, - locally_relevant_dofs_P); + locally_relevant_dofs_P); // init vectors for phi locally_relevant_solution_phi.reinit(locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); locally_relevant_solution_phi = 0; @@ -209,7 +209,7 @@ void MultiPhase::setup() locally_relevant_solution_u.reinit (locally_owned_dofs_U,locally_relevant_dofs_U,mpi_communicator); locally_relevant_solution_u = 0; completely_distributed_solution_u.reinit (locally_owned_dofs_U,mpi_communicator); - //init vectors for v + //init vectors for v locally_relevant_solution_v.reinit (locally_owned_dofs_U,locally_relevant_dofs_U,mpi_communicator); locally_relevant_solution_v = 0; completely_distributed_solution_v.reinit (locally_owned_dofs_U,mpi_communicator); @@ -229,33 +229,33 @@ void MultiPhase::initial_condition() // init condition for phi completely_distributed_solution_phi = 0; VectorTools::interpolate(dof_handler_LS, - InitialPhi(PROBLEM, sharpness), - completely_distributed_solution_phi); + InitialPhi(PROBLEM, sharpness), + completely_distributed_solution_phi); constraints.distribute (completely_distributed_solution_phi); locally_relevant_solution_phi = completely_distributed_solution_phi; // init condition for u=0 completely_distributed_solution_u = 0; VectorTools::interpolate(dof_handler_U, - ZeroFunction(), - completely_distributed_solution_u); + ZeroFunction(), + completely_distributed_solution_u); constraints.distribute (completely_distributed_solution_u); locally_relevant_solution_u = completely_distributed_solution_u; // init condition for v completely_distributed_solution_v = 0; VectorTools::interpolate(dof_handler_U, - ZeroFunction(), - completely_distributed_solution_v); + ZeroFunction(), + completely_distributed_solution_v); constraints.distribute (completely_distributed_solution_v); locally_relevant_solution_v = completely_distributed_solution_v; // init condition for p completely_distributed_solution_p = 0; VectorTools::interpolate(dof_handler_P, - ZeroFunction(), - completely_distributed_solution_p); + ZeroFunction(), + completely_distributed_solution_p); constraints.distribute (completely_distributed_solution_p); locally_relevant_solution_p = completely_distributed_solution_p; } - + template void MultiPhase::init_constraints() { @@ -272,36 +272,37 @@ void MultiPhase::get_boundary_values_U() std::map map_boundary_values_v; std::map map_boundary_values_w; - // NO-SLIP CONDITION + // NO-SLIP CONDITION if (PROBLEM==BREAKING_DAM || PROBLEM==FALLING_DROP) { //LEFT - VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction(),map_boundary_values_u); - VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction(),map_boundary_values_v); + VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction(),map_boundary_values_v); // RIGHT - VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction(),map_boundary_values_u); - VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction(),map_boundary_values_v); - // BOTTOM - VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_u); - VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_v); + VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction(),map_boundary_values_v); + // BOTTOM + VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_v); // TOP - VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_u); - VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_v); - } + VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_v); + } else if (PROBLEM==SMALL_WAVE_PERTURBATION) - { // no slip in bottom and top and slip in left and right + { + // no slip in bottom and top and slip in left and right //LEFT - VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction(),map_boundary_values_u); // RIGHT - VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction(),map_boundary_values_u); - // BOTTOM - VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_u); - VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_v); + VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction(),map_boundary_values_u); + // BOTTOM + VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction(),map_boundary_values_v); // TOP - VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_u); - VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_v); + VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_u); + VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_v); } - else if (PROBLEM==FILLING_TANK) + else if (PROBLEM==FILLING_TANK) { //LEFT: entry in x, zero in y VectorTools::interpolate_boundary_values (dof_handler_U,0,BoundaryU(PROBLEM),map_boundary_values_u); @@ -316,7 +317,7 @@ void MultiPhase::get_boundary_values_U() VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction(),map_boundary_values_u); VectorTools::interpolate_boundary_values (dof_handler_U,3,BoundaryV(PROBLEM),map_boundary_values_v); } - else + else { pcout << "Error in type of PROBLEM at Boundary Conditions" << std::endl; abort(); @@ -327,7 +328,7 @@ void MultiPhase::get_boundary_values_U() boundary_values_v.resize(map_boundary_values_v.size()); std::map::const_iterator boundary_value_u =map_boundary_values_u.begin(); std::map::const_iterator boundary_value_v =map_boundary_values_v.begin(); - + for (int i=0; boundary_value_u !=map_boundary_values_u.end(); ++boundary_value_u, ++i) { boundary_values_id_u[i]=boundary_value_u->first; @@ -345,44 +346,44 @@ void MultiPhase::set_boundary_inlet() { const QGauss face_quadrature_formula(1); // center of the face FEFaceValues fe_face_values (fe_U,face_quadrature_formula, - update_values | update_quadrature_points | - update_normal_vectors); + update_values | update_quadrature_points | + update_normal_vectors); const unsigned int n_face_q_points = face_quadrature_formula.size(); std::vector u_value (n_face_q_points); - std::vector v_value (n_face_q_points); - + std::vector v_value (n_face_q_points); + typename DoFHandler::active_cell_iterator - cell_U = dof_handler_U.begin_active(), - endc_U = dof_handler_U.end(); + cell_U = dof_handler_U.begin_active(), + endc_U = dof_handler_U.end(); Tensor<1,dim> u; - + for (; cell_U!=endc_U; ++cell_U) if (cell_U->is_locally_owned()) for (unsigned int face=0; face::faces_per_cell; ++face) - if (cell_U->face(face)->at_boundary()) - { - fe_face_values.reinit(cell_U,face); - fe_face_values.get_function_values(locally_relevant_solution_u,u_value); - fe_face_values.get_function_values(locally_relevant_solution_v,v_value); - u[0]=u_value[0]; - u[1]=v_value[0]; - if (fe_face_values.normal_vector(0)*u < -1e-14) - cell_U->face(face)->set_boundary_id(10); // SET ID 10 to inlet BOUNDARY (10 is an arbitrary number) - } + if (cell_U->face(face)->at_boundary()) + { + fe_face_values.reinit(cell_U,face); + fe_face_values.get_function_values(locally_relevant_solution_u,u_value); + fe_face_values.get_function_values(locally_relevant_solution_v,v_value); + u[0]=u_value[0]; + u[1]=v_value[0]; + if (fe_face_values.normal_vector(0)*u < -1e-14) + cell_U->face(face)->set_boundary_id(10); // SET ID 10 to inlet BOUNDARY (10 is an arbitrary number) + } } template void MultiPhase::get_boundary_values_phi(std::vector &boundary_values_id_phi, - std::vector &boundary_values_phi) + std::vector &boundary_values_phi) { std::map map_boundary_values_phi; unsigned int boundary_id=0; - + set_boundary_inlet(); boundary_id=10; // inlet VectorTools::interpolate_boundary_values (dof_handler_LS,boundary_id,BoundaryPhi(1.0),map_boundary_values_phi); boundary_values_id_phi.resize(map_boundary_values_phi.size()); - boundary_values_phi.resize(map_boundary_values_phi.size()); + boundary_values_phi.resize(map_boundary_values_phi.size()); std::map::const_iterator boundary_value_phi = map_boundary_values_phi.begin(); for (int i=0; boundary_value_phi !=map_boundary_values_phi.end(); ++boundary_value_phi, ++i) { @@ -403,30 +404,30 @@ template void MultiPhase::output_vectors() { DataOut data_out; - data_out.attach_dof_handler (dof_handler_LS); + data_out.attach_dof_handler (dof_handler_LS); data_out.add_data_vector (locally_relevant_solution_phi, "phi"); data_out.build_patches (); - + const std::string filename = ("sol_vectors-" + - Utilities::int_to_string (output_number, 3) + - "." + - Utilities::int_to_string - (triangulation.locally_owned_subdomain(), 4)); + Utilities::int_to_string (output_number, 3) + + "." + + Utilities::int_to_string + (triangulation.locally_owned_subdomain(), 4)); std::ofstream output ((filename + ".vtu").c_str()); data_out.write_vtu (output); - + if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) { std::vector filenames; for (unsigned int i=0; - i::output_vectors() template void MultiPhase::output_rho() { - Postprocessor postprocessor(eps,rho_air,rho_fluid); + Postprocessor postprocessor(eps,rho_air,rho_fluid); DataOut data_out; - data_out.attach_dof_handler (dof_handler_LS); + data_out.attach_dof_handler (dof_handler_LS); data_out.add_data_vector (locally_relevant_solution_phi, postprocessor); - + data_out.build_patches (); - + const std::string filename = ("sol_rho-" + - Utilities::int_to_string (output_number, 3) + - "." + - Utilities::int_to_string - (triangulation.locally_owned_subdomain(), 4)); + Utilities::int_to_string (output_number, 3) + + "." + + Utilities::int_to_string + (triangulation.locally_owned_subdomain(), 4)); std::ofstream output ((filename + ".vtu").c_str()); data_out.write_vtu (output); - + if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) { std::vector filenames; for (unsigned int i=0; - i::run() //PROBLEM=FILLING_TANK; //PROBLEM=SMALL_WAVE_PERTURBATION; //PROBLEM=FALLING_DROP; - - ForceTerms force_function(std::vector{0.0,-1.0}); + + ForceTerms force_function(std::vector {0.0,-1.0}); ////////////////////////////////////// // PARAMETERS FOR TRANSPORT PROBLEM // ////////////////////////////////////// @@ -506,7 +507,7 @@ void MultiPhase::run() //ALGORITHM = "NMPP_uH"; ALGORITHM = "MPP_uH"; - // ADJUST PARAMETERS ACCORDING TO PROBLEM + // ADJUST PARAMETERS ACCORDING TO PROBLEM if (PROBLEM==FALLING_DROP) n_refinement=7; @@ -515,22 +516,22 @@ void MultiPhase::run() ////////////// if (PROBLEM==FILLING_TANK) GridGenerator::hyper_rectangle(triangulation, - Point(0.0,0.0), Point(0.4,0.4), true); + Point(0.0,0.0), Point(0.4,0.4), true); else if (PROBLEM==BREAKING_DAM || PROBLEM==SMALL_WAVE_PERTURBATION) { std::vector< unsigned int > repetitions; repetitions.push_back(2); repetitions.push_back(1); - GridGenerator::subdivided_hyper_rectangle - (triangulation, repetitions, Point(0.0,0.0), Point(1.0,0.5), true); + GridGenerator::subdivided_hyper_rectangle + (triangulation, repetitions, Point(0.0,0.0), Point(1.0,0.5), true); } else if (PROBLEM==FALLING_DROP) { std::vector< unsigned int > repetitions; repetitions.push_back(1); repetitions.push_back(4); - GridGenerator::subdivided_hyper_rectangle - (triangulation, repetitions, Point(0.0,0.0), Point(0.3,0.9), true); + GridGenerator::subdivided_hyper_rectangle + (triangulation, repetitions, Point(0.0,0.0), Point(0.3,0.9), true); } triangulation.refine_global (n_refinement); // SETUP @@ -541,82 +542,82 @@ void MultiPhase::run() time_step = cfl*min_h/umax; eps=1.*min_h; //For reconstruction of density in Navier Stokes sharpness=sharpness_integer*min_h; //adjust value of sharpness (for init cond of phi) - + // INITIAL CONDITIONS initial_condition(); output_results(); - + // NAVIER STOKES SOLVER NavierStokesSolver navier_stokes (degree_LS,degree_U, - time_step,eps, - rho_air,nu_air, - rho_fluid,nu_fluid, - force_function, - verbose, - triangulation,mpi_communicator); + time_step,eps, + rho_air,nu_air, + rho_fluid,nu_fluid, + force_function, + verbose, + triangulation,mpi_communicator); // BOUNDARY CONDITIONS FOR NAVIER STOKES get_boundary_values_U(); navier_stokes.set_boundary_conditions(boundary_values_id_u, boundary_values_id_v, - boundary_values_u, boundary_values_v); + boundary_values_u, boundary_values_v); //set INITIAL CONDITION within NAVIER STOKES navier_stokes.initial_condition(locally_relevant_solution_phi, - locally_relevant_solution_u, - locally_relevant_solution_v, - locally_relevant_solution_p); + locally_relevant_solution_u, + locally_relevant_solution_v, + locally_relevant_solution_p); // TRANSPORT SOLVER LevelSetSolver transport_solver (degree_LS,degree_U, - time_step,cK,cE, - verbose, - ALGORITHM, - TRANSPORT_TIME_INTEGRATION, - triangulation, - mpi_communicator); + time_step,cK,cE, + verbose, + ALGORITHM, + TRANSPORT_TIME_INTEGRATION, + triangulation, + mpi_communicator); // BOUNDARY CONDITIONS FOR PHI get_boundary_values_phi(boundary_values_id_phi,boundary_values_phi); transport_solver.set_boundary_conditions(boundary_values_id_phi,boundary_values_phi); //set INITIAL CONDITION within TRANSPORT PROBLEM transport_solver.initial_condition(locally_relevant_solution_phi, - locally_relevant_solution_u, - locally_relevant_solution_v); + locally_relevant_solution_u, + locally_relevant_solution_v); int dofs_U = 2*dof_handler_U.n_dofs(); int dofs_P = 2*dof_handler_P.n_dofs(); int dofs_LS = dof_handler_LS.n_dofs(); int dofs_TOTAL = dofs_U+dofs_P+dofs_LS; // NO BOUNDARY CONDITIONS for LEVEL SET - pcout << "Cfl: " << cfl << "; umax: " << umax << "; min h: " << min_h - << "; time step: " << time_step << std::endl; - pcout << " Number of active cells: " - << triangulation.n_global_active_cells() << std::endl - << " Number of degrees of freedom: " << std::endl - << " U: " << dofs_U << std::endl - << " P: " << dofs_P << std::endl - << " LS: " << dofs_LS << std::endl - << " TOTAL: " << dofs_TOTAL - << std::endl; + pcout << "Cfl: " << cfl << "; umax: " << umax << "; min h: " << min_h + << "; time step: " << time_step << std::endl; + pcout << " Number of active cells: " + << triangulation.n_global_active_cells() << std::endl + << " Number of degrees of freedom: " << std::endl + << " U: " << dofs_U << std::endl + << " P: " << dofs_P << std::endl + << " LS: " << dofs_LS << std::endl + << " TOTAL: " << dofs_TOTAL + << std::endl; // TIME STEPPING for (timestep_number=1, time=time_step; time<=final_time; time+=time_step,++timestep_number) { - pcout << "Time step " << timestep_number - << " at t=" << time - << std::endl; + pcout << "Time step " << timestep_number + << " at t=" << time + << std::endl; // GET NAVIER STOKES VELOCITY navier_stokes.set_phi(locally_relevant_solution_phi); - navier_stokes.nth_time_step(); + navier_stokes.nth_time_step(); navier_stokes.get_velocity(locally_relevant_solution_u,locally_relevant_solution_v); transport_solver.set_velocity(locally_relevant_solution_u,locally_relevant_solution_v); // GET LEVEL SET SOLUTION transport_solver.nth_time_step(); - transport_solver.get_unp1(locally_relevant_solution_phi); + transport_solver.get_unp1(locally_relevant_solution_phi); if (get_output && time-(output_number)*output_time>0) - output_results(); + output_results(); } navier_stokes.get_velocity(locally_relevant_solution_u, locally_relevant_solution_v); - transport_solver.get_unp1(locally_relevant_solution_phi); + transport_solver.get_unp1(locally_relevant_solution_phi); if (get_output) output_results(); } @@ -630,8 +631,8 @@ int main(int argc, char *argv[]) PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL); deallog.depth_console (0); { - unsigned int degree_LS = 1; - unsigned int degree_U = 2; + unsigned int degree_LS = 1; + unsigned int degree_U = 2; MultiPhase<2> multi_phase(degree_LS, degree_U); multi_phase.run(); } diff --git a/two_phase_flow/NavierStokesSolver.cc b/two_phase_flow/NavierStokesSolver.cc index 761d28e..2df261b 100644 --- a/two_phase_flow/NavierStokesSolver.cc +++ b/two_phase_flow/NavierStokesSolver.cc @@ -44,65 +44,66 @@ using namespace dealii; ///////////////////// NAVIER STOKES SOLVER ////////////////////// ///////////////////////////////////////////////////////////////// template -class NavierStokesSolver { +class NavierStokesSolver +{ public: // constructor for using LEVEL SET - NavierStokesSolver(const unsigned int degree_LS, - const unsigned int degree_U, - const double time_step, - const double eps, - const double rho_air, - const double nu_air, - const double rho_fluid, - const double nu_fluid, - Function &force_function, - const bool verbose, - parallel::distributed::Triangulation &triangulation, - MPI_Comm &mpi_communicator); + NavierStokesSolver(const unsigned int degree_LS, + const unsigned int degree_U, + const double time_step, + const double eps, + const double rho_air, + const double nu_air, + const double rho_fluid, + const double nu_fluid, + Function &force_function, + const bool verbose, + parallel::distributed::Triangulation &triangulation, + MPI_Comm &mpi_communicator); // constructor for NOT LEVEL SET - NavierStokesSolver(const unsigned int degree_LS, - const unsigned int degree_U, - const double time_step, - Function &force_function, - Function &rho_function, - Function &nu_function, - const bool verbose, - parallel::distributed::Triangulation &triangulation, - MPI_Comm &mpi_communicator); + NavierStokesSolver(const unsigned int degree_LS, + const unsigned int degree_U, + const double time_step, + Function &force_function, + Function &rho_function, + Function &nu_function, + const bool verbose, + parallel::distributed::Triangulation &triangulation, + MPI_Comm &mpi_communicator); // rho and nu functions void set_rho_and_nu_functions(const Function &rho_function, - const Function &nu_function); + const Function &nu_function); //initial conditions void initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_rho, - PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v, - PETScWrappers::MPI::Vector locally_relevant_solution_p); + PETScWrappers::MPI::Vector locally_relevant_solution_u, + PETScWrappers::MPI::Vector locally_relevant_solution_v, + PETScWrappers::MPI::Vector locally_relevant_solution_p); void initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_rho, - PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v, - PETScWrappers::MPI::Vector locally_relevant_solution_w, - PETScWrappers::MPI::Vector locally_relevant_solution_p); + PETScWrappers::MPI::Vector locally_relevant_solution_u, + PETScWrappers::MPI::Vector locally_relevant_solution_v, + PETScWrappers::MPI::Vector locally_relevant_solution_w, + PETScWrappers::MPI::Vector locally_relevant_solution_p); //boundary conditions void set_boundary_conditions(std::vector boundary_values_id_u, - std::vector boundary_values_id_v, std::vector boundary_values_u, - std::vector boundary_values_v); + std::vector boundary_values_id_v, std::vector boundary_values_u, + std::vector boundary_values_v); void set_boundary_conditions(std::vector boundary_values_id_u, - std::vector boundary_values_id_v, - std::vector boundary_values_id_w, std::vector boundary_values_u, - std::vector boundary_values_v, std::vector boundary_values_w); + std::vector boundary_values_id_v, + std::vector boundary_values_id_w, std::vector boundary_values_u, + std::vector boundary_values_v, std::vector boundary_values_w); void set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v); + PETScWrappers::MPI::Vector locally_relevant_solution_v); void set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v, - PETScWrappers::MPI::Vector locally_relevant_solution_w); + PETScWrappers::MPI::Vector locally_relevant_solution_v, + PETScWrappers::MPI::Vector locally_relevant_solution_w); void set_phi(PETScWrappers::MPI::Vector locally_relevant_solution_phi); void get_pressure(PETScWrappers::MPI::Vector &locally_relevant_solution_p); void get_velocity(PETScWrappers::MPI::Vector &locally_relevant_solution_u, - PETScWrappers::MPI::Vector &locally_relevant_solution_v); + PETScWrappers::MPI::Vector &locally_relevant_solution_v); void get_velocity(PETScWrappers::MPI::Vector &locally_relevant_solution_u, - PETScWrappers::MPI::Vector &locally_relevant_solution_v, - PETScWrappers::MPI::Vector &locally_relevant_solution_w); + PETScWrappers::MPI::Vector &locally_relevant_solution_v, + PETScWrappers::MPI::Vector &locally_relevant_solution_w); // DO STEPS // void nth_time_step(); // SETUP // @@ -120,13 +121,13 @@ private: void assemble_system_dpsi_q(); // SOLVERS // void solve_U(const ConstraintMatrix &constraints, PETScWrappers::MPI::SparseMatrix &Matrix, - std_cxx1x::shared_ptr preconditioner, - PETScWrappers::MPI::Vector &completely_distributed_solution, - const PETScWrappers::MPI::Vector &rhs); + std_cxx1x::shared_ptr preconditioner, + PETScWrappers::MPI::Vector &completely_distributed_solution, + const PETScWrappers::MPI::Vector &rhs); void solve_P(const ConstraintMatrix &constraints, PETScWrappers::MPI::SparseMatrix &Matrix, - std_cxx1x::shared_ptr preconditioner, - PETScWrappers::MPI::Vector &completely_distributed_solution, - const PETScWrappers::MPI::Vector &rhs); + std_cxx1x::shared_ptr preconditioner, + PETScWrappers::MPI::Vector &completely_distributed_solution, + const PETScWrappers::MPI::Vector &rhs); // GET DIFFERENT FIELDS // void get_rho_and_nu(double phi); void get_velocity(); @@ -233,43 +234,43 @@ private: // CONSTRUCTOR FOR LEVEL SET template NavierStokesSolver::NavierStokesSolver(const unsigned int degree_LS, - const unsigned int degree_U, - const double time_step, - const double eps, - const double rho_air, - const double nu_air, - const double rho_fluid, - const double nu_fluid, - Function &force_function, - const bool verbose, - parallel::distributed::Triangulation &triangulation, - MPI_Comm &mpi_communicator) + const unsigned int degree_U, + const double time_step, + const double eps, + const double rho_air, + const double nu_air, + const double rho_fluid, + const double nu_fluid, + Function &force_function, + const bool verbose, + parallel::distributed::Triangulation &triangulation, + MPI_Comm &mpi_communicator) : - mpi_communicator(mpi_communicator), - triangulation(triangulation), - degree_LS(degree_LS), - dof_handler_LS(triangulation), - fe_LS(degree_LS), - degree_U(degree_U), - dof_handler_U(triangulation), - fe_U(degree_U), - dof_handler_P(triangulation), - fe_P(degree_U-1), + mpi_communicator(mpi_communicator), + triangulation(triangulation), + degree_LS(degree_LS), + dof_handler_LS(triangulation), + fe_LS(degree_LS), + degree_U(degree_U), + dof_handler_U(triangulation), + fe_U(degree_U), + dof_handler_P(triangulation), + fe_P(degree_U-1), force_function(force_function), //This is dummy since rho and nu functions won't be used - rho_function(force_function), - nu_function(force_function), - rho_air(rho_air), - nu_air(nu_air), - rho_fluid(rho_fluid), - nu_fluid(nu_fluid), - time_step(time_step), - eps(eps), - verbose(verbose), - LEVEL_SET(1), + rho_function(force_function), + nu_function(force_function), + rho_air(rho_air), + nu_air(nu_air), + rho_fluid(rho_fluid), + nu_fluid(nu_fluid), + time_step(time_step), + eps(eps), + verbose(verbose), + LEVEL_SET(1), RHO_TIMES_RHS(1), - pcout(std::cout,(Utilities::MPI::this_mpi_process(mpi_communicator)==0)), - rebuild_Matrix_U(true), + pcout(std::cout,(Utilities::MPI::this_mpi_process(mpi_communicator)==0)), + rebuild_Matrix_U(true), rebuild_S_M(true), rebuild_Matrix_U_preconditioners(true), rebuild_S_M_preconditioners(true) @@ -278,40 +279,41 @@ NavierStokesSolver::NavierStokesSolver(const unsigned int degree_LS, // CONSTRUCTOR NOT FOR LEVEL SET template NavierStokesSolver::NavierStokesSolver(const unsigned int degree_LS, - const unsigned int degree_U, - const double time_step, - Function &force_function, - Function &rho_function, - Function &nu_function, - const bool verbose, - parallel::distributed::Triangulation &triangulation, - MPI_Comm &mpi_communicator) : - mpi_communicator(mpi_communicator), - triangulation(triangulation), - degree_LS(degree_LS), - dof_handler_LS(triangulation), - fe_LS(degree_LS), - degree_U(degree_U), - dof_handler_U(triangulation), - fe_U(degree_U), - dof_handler_P(triangulation), - fe_P(degree_U-1), - force_function(force_function), - rho_function(rho_function), - nu_function(nu_function), - time_step(time_step), - verbose(verbose), - LEVEL_SET(0), - RHO_TIMES_RHS(0), - pcout(std::cout,(Utilities::MPI::this_mpi_process(mpi_communicator)==0)), - rebuild_Matrix_U(true), + const unsigned int degree_U, + const double time_step, + Function &force_function, + Function &rho_function, + Function &nu_function, + const bool verbose, + parallel::distributed::Triangulation &triangulation, + MPI_Comm &mpi_communicator) : + mpi_communicator(mpi_communicator), + triangulation(triangulation), + degree_LS(degree_LS), + dof_handler_LS(triangulation), + fe_LS(degree_LS), + degree_U(degree_U), + dof_handler_U(triangulation), + fe_U(degree_U), + dof_handler_P(triangulation), + fe_P(degree_U-1), + force_function(force_function), + rho_function(rho_function), + nu_function(nu_function), + time_step(time_step), + verbose(verbose), + LEVEL_SET(0), + RHO_TIMES_RHS(0), + pcout(std::cout,(Utilities::MPI::this_mpi_process(mpi_communicator)==0)), + rebuild_Matrix_U(true), rebuild_S_M(true), rebuild_Matrix_U_preconditioners(true), rebuild_S_M_preconditioners(true) {setup();} template -NavierStokesSolver::~NavierStokesSolver() { +NavierStokesSolver::~NavierStokesSolver() +{ dof_handler_LS.clear(); dof_handler_U.clear(); dof_handler_P.clear(); @@ -322,19 +324,21 @@ NavierStokesSolver::~NavierStokesSolver() { ///////////////////////////////////////////////////////////// template void NavierStokesSolver::set_rho_and_nu_functions(const Function &rho_function, - const Function &nu_function) { + const Function &nu_function) +{ this->rho_function=rho_function; this->nu_function=nu_function; } template void NavierStokesSolver::initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_phi, - PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v, - PETScWrappers::MPI::Vector locally_relevant_solution_p) { + PETScWrappers::MPI::Vector locally_relevant_solution_u, + PETScWrappers::MPI::Vector locally_relevant_solution_v, + PETScWrappers::MPI::Vector locally_relevant_solution_p) +{ this->locally_relevant_solution_phi=locally_relevant_solution_phi; this->locally_relevant_solution_u=locally_relevant_solution_u; - this->locally_relevant_solution_v=locally_relevant_solution_v; + this->locally_relevant_solution_v=locally_relevant_solution_v; this->locally_relevant_solution_p=locally_relevant_solution_p; // set old vectors to the initial condition (just for first time step) save_old_solution(); @@ -342,10 +346,10 @@ void NavierStokesSolver::initial_condition(PETScWrappers::MPI::Vector local template void NavierStokesSolver::initial_condition(PETScWrappers::MPI::Vector locally_relevant_solution_phi, - PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v, - PETScWrappers::MPI::Vector locally_relevant_solution_w, - PETScWrappers::MPI::Vector locally_relevant_solution_p) + PETScWrappers::MPI::Vector locally_relevant_solution_u, + PETScWrappers::MPI::Vector locally_relevant_solution_v, + PETScWrappers::MPI::Vector locally_relevant_solution_w, + PETScWrappers::MPI::Vector locally_relevant_solution_p) { this->locally_relevant_solution_phi=locally_relevant_solution_phi; this->locally_relevant_solution_u=locally_relevant_solution_u; @@ -358,9 +362,9 @@ void NavierStokesSolver::initial_condition(PETScWrappers::MPI::Vector local template void NavierStokesSolver::set_boundary_conditions(std::vector boundary_values_id_u, - std::vector boundary_values_id_v, - std::vector boundary_values_u, - std::vector boundary_values_v) + std::vector boundary_values_id_v, + std::vector boundary_values_u, + std::vector boundary_values_v) { this->boundary_values_id_u=boundary_values_id_u; this->boundary_values_id_v=boundary_values_id_v; @@ -370,11 +374,11 @@ void NavierStokesSolver::set_boundary_conditions(std::vector void NavierStokesSolver::set_boundary_conditions(std::vector boundary_values_id_u, - std::vector boundary_values_id_v, - std::vector boundary_values_id_w, - std::vector boundary_values_u, - std::vector boundary_values_v, - std::vector boundary_values_w) + std::vector boundary_values_id_v, + std::vector boundary_values_id_w, + std::vector boundary_values_u, + std::vector boundary_values_v, + std::vector boundary_values_w) { this->boundary_values_id_u=boundary_values_id_u; this->boundary_values_id_v=boundary_values_id_v; @@ -386,27 +390,31 @@ void NavierStokesSolver::set_boundary_conditions(std::vector void NavierStokesSolver::set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v) { + PETScWrappers::MPI::Vector locally_relevant_solution_v) +{ this->locally_relevant_solution_u=locally_relevant_solution_u; this->locally_relevant_solution_v=locally_relevant_solution_v; } template void NavierStokesSolver::set_velocity(PETScWrappers::MPI::Vector locally_relevant_solution_u, - PETScWrappers::MPI::Vector locally_relevant_solution_v, - PETScWrappers::MPI::Vector locally_relevant_solution_w) { + PETScWrappers::MPI::Vector locally_relevant_solution_v, + PETScWrappers::MPI::Vector locally_relevant_solution_w) +{ this->locally_relevant_solution_u=locally_relevant_solution_u; this->locally_relevant_solution_v=locally_relevant_solution_v; this->locally_relevant_solution_w=locally_relevant_solution_w; } template -void NavierStokesSolver::set_phi(PETScWrappers::MPI::Vector locally_relevant_solution_phi) { +void NavierStokesSolver::set_phi(PETScWrappers::MPI::Vector locally_relevant_solution_phi) +{ this->locally_relevant_solution_phi=locally_relevant_solution_phi; } template -void NavierStokesSolver::get_rho_and_nu(double phi) { +void NavierStokesSolver::get_rho_and_nu(double phi) +{ double H=0; // get rho, nu if (phi>eps) @@ -422,22 +430,24 @@ void NavierStokesSolver::get_rho_and_nu(double phi) { } template -void NavierStokesSolver::get_pressure(PETScWrappers::MPI::Vector &locally_relevant_solution_p) +void NavierStokesSolver::get_pressure(PETScWrappers::MPI::Vector &locally_relevant_solution_p) { locally_relevant_solution_p=this->locally_relevant_solution_p; } template void NavierStokesSolver::get_velocity(PETScWrappers::MPI::Vector &locally_relevant_solution_u, - PETScWrappers::MPI::Vector &locally_relevant_solution_v) { + PETScWrappers::MPI::Vector &locally_relevant_solution_v) +{ locally_relevant_solution_u=this->locally_relevant_solution_u; locally_relevant_solution_v=this->locally_relevant_solution_v; } template void NavierStokesSolver::get_velocity(PETScWrappers::MPI::Vector &locally_relevant_solution_u, - PETScWrappers::MPI::Vector &locally_relevant_solution_v, - PETScWrappers::MPI::Vector &locally_relevant_solution_w) { + PETScWrappers::MPI::Vector &locally_relevant_solution_v, + PETScWrappers::MPI::Vector &locally_relevant_solution_w) +{ locally_relevant_solution_u=this->locally_relevant_solution_u; locally_relevant_solution_v=this->locally_relevant_solution_v; locally_relevant_solution_w=this->locally_relevant_solution_w; @@ -447,7 +457,8 @@ void NavierStokesSolver::get_velocity(PETScWrappers::MPI::Vector &locally_r ///////////// SETUP AND INITIAL CONDITION ///////////// /////////////////////////////////////////////////////// template -void NavierStokesSolver::setup() { +void NavierStokesSolver::setup() +{ pcout<<"***** SETUP IN NAVIER STOKES SOLVER *****"<::setup() { } template -void NavierStokesSolver::setup_DOF() { +void NavierStokesSolver::setup_DOF() +{ rho_min = 1.; degree_MAX=std::max(degree_LS,degree_U); // setup system LS @@ -473,49 +485,50 @@ void NavierStokesSolver::setup_DOF() { } template -void NavierStokesSolver::setup_VECTORS() { +void NavierStokesSolver::setup_VECTORS() +{ // init vectors for phi locally_relevant_solution_phi.reinit(locally_owned_dofs_LS,locally_relevant_dofs_LS, - mpi_communicator); + mpi_communicator); locally_relevant_solution_phi=0; //init vectors for u locally_relevant_solution_u.reinit(locally_owned_dofs_U,locally_relevant_dofs_U, - mpi_communicator); + mpi_communicator); locally_relevant_solution_u=0; completely_distributed_solution_u.reinit(locally_owned_dofs_U,mpi_communicator); system_rhs_u.reinit(locally_owned_dofs_U,mpi_communicator); //init vectors for u_old locally_relevant_solution_u_old.reinit(locally_owned_dofs_U,locally_relevant_dofs_U, - mpi_communicator); + mpi_communicator); locally_relevant_solution_u_old=0; //init vectors for v locally_relevant_solution_v.reinit(locally_owned_dofs_U,locally_relevant_dofs_U, - mpi_communicator); + mpi_communicator); locally_relevant_solution_v=0; completely_distributed_solution_v.reinit(locally_owned_dofs_U,mpi_communicator); system_rhs_v.reinit(locally_owned_dofs_U,mpi_communicator); //init vectors for v_old locally_relevant_solution_v_old.reinit(locally_owned_dofs_U,locally_relevant_dofs_U, - mpi_communicator); + mpi_communicator); locally_relevant_solution_v_old=0; //init vectors for w locally_relevant_solution_w.reinit(locally_owned_dofs_U,locally_relevant_dofs_U, - mpi_communicator); + mpi_communicator); locally_relevant_solution_w=0; completely_distributed_solution_w.reinit(locally_owned_dofs_U,mpi_communicator); system_rhs_w.reinit(locally_owned_dofs_U,mpi_communicator); //init vectors for w_old locally_relevant_solution_w_old.reinit(locally_owned_dofs_U,locally_relevant_dofs_U, - mpi_communicator); + mpi_communicator); locally_relevant_solution_w_old=0; //init vectors for dpsi locally_relevant_solution_psi.reinit(locally_owned_dofs_P,locally_relevant_dofs_P, - mpi_communicator); + mpi_communicator); locally_relevant_solution_psi=0; system_rhs_psi.reinit(locally_owned_dofs_P,mpi_communicator); //init vectors for dpsi old locally_relevant_solution_psi_old.reinit(locally_owned_dofs_P,locally_relevant_dofs_P, - mpi_communicator); + mpi_communicator); locally_relevant_solution_psi_old=0; //init vectors for q completely_distributed_solution_q.reinit(locally_owned_dofs_P,mpi_communicator); @@ -524,7 +537,7 @@ void NavierStokesSolver::setup_VECTORS() { completely_distributed_solution_psi.reinit(locally_owned_dofs_P,mpi_communicator); //init vectors for p locally_relevant_solution_p.reinit(locally_owned_dofs_P,locally_relevant_dofs_P, - mpi_communicator); + mpi_communicator); locally_relevant_solution_p=0; completely_distributed_solution_p.reinit(locally_owned_dofs_P,mpi_communicator); //////////////////////////// @@ -538,44 +551,45 @@ void NavierStokesSolver::setup_VECTORS() { DynamicSparsityPattern dsp_Matrix(locally_relevant_dofs_U); DoFTools::make_sparsity_pattern(dof_handler_U,dsp_Matrix,constraints,false); SparsityTools::distribute_sparsity_pattern(dsp_Matrix, - dof_handler_U.n_locally_owned_dofs_per_processor(),mpi_communicator, - locally_relevant_dofs_U); + dof_handler_U.n_locally_owned_dofs_per_processor(),mpi_communicator, + locally_relevant_dofs_U); system_Matrix_u.reinit(mpi_communicator,dsp_Matrix, - dof_handler_U.n_locally_owned_dofs_per_processor(), - dof_handler_U.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dof_handler_U.n_locally_owned_dofs_per_processor(), + dof_handler_U.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); system_Matrix_v.reinit(mpi_communicator,dsp_Matrix, - dof_handler_U.n_locally_owned_dofs_per_processor(), - dof_handler_U.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dof_handler_U.n_locally_owned_dofs_per_processor(), + dof_handler_U.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); system_Matrix_w.reinit(mpi_communicator,dsp_Matrix, - dof_handler_U.n_locally_owned_dofs_per_processor(), - dof_handler_U.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dof_handler_U.n_locally_owned_dofs_per_processor(), + dof_handler_U.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); rebuild_Matrix_U=true; // sparsity pattern for S DynamicSparsityPattern dsp_S(locally_relevant_dofs_P); DoFTools::make_sparsity_pattern(dof_handler_P,dsp_S,constraints_psi,false); SparsityTools::distribute_sparsity_pattern(dsp_S, - dof_handler_P.n_locally_owned_dofs_per_processor(),mpi_communicator, - locally_relevant_dofs_P); + dof_handler_P.n_locally_owned_dofs_per_processor(),mpi_communicator, + locally_relevant_dofs_P); system_S.reinit(mpi_communicator,dsp_S,dof_handler_P.n_locally_owned_dofs_per_processor(), - dof_handler_P.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dof_handler_P.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); // sparsity pattern for M DynamicSparsityPattern dsp_M(locally_relevant_dofs_P); DoFTools::make_sparsity_pattern(dof_handler_P,dsp_M,constraints_psi,false); SparsityTools::distribute_sparsity_pattern(dsp_M, - dof_handler_P.n_locally_owned_dofs_per_processor(),mpi_communicator, - locally_relevant_dofs_P); + dof_handler_P.n_locally_owned_dofs_per_processor(),mpi_communicator, + locally_relevant_dofs_P); system_M.reinit(mpi_communicator,dsp_M,dof_handler_P.n_locally_owned_dofs_per_processor(), - dof_handler_P.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dof_handler_P.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); rebuild_S_M=true; } template -void NavierStokesSolver::init_constraints() { +void NavierStokesSolver::init_constraints() +{ //grl constraints constraints.clear(); constraints.reinit(locally_relevant_dofs_U); @@ -594,9 +608,9 @@ void NavierStokesSolver::init_constraints() { ////////////////// ASSEMBLE SYSTEMS /////////////////// /////////////////////////////////////////////////////// template -void NavierStokesSolver::assemble_system_U() +void NavierStokesSolver::assemble_system_U() { - if (rebuild_Matrix_U==true) + if (rebuild_Matrix_U==true) { system_Matrix_u=0; system_Matrix_v=0; @@ -605,25 +619,25 @@ void NavierStokesSolver::assemble_system_U() system_rhs_u=0; system_rhs_v=0; system_rhs_w=0; - + const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_LS(fe_LS,quadrature_formula, - update_values|update_gradients|update_quadrature_points|update_JxW_values); + update_values|update_gradients|update_quadrature_points|update_JxW_values); FEValues fe_values_U(fe_U,quadrature_formula, - update_values|update_gradients|update_quadrature_points|update_JxW_values); + update_values|update_gradients|update_quadrature_points|update_JxW_values); FEValues fe_values_P(fe_P,quadrature_formula, - update_values|update_gradients|update_quadrature_points|update_JxW_values); + update_values|update_gradients|update_quadrature_points|update_JxW_values); const unsigned int dofs_per_cell=fe_U.dofs_per_cell; const unsigned int n_q_points=quadrature_formula.size(); - + FullMatrix cell_A_u(dofs_per_cell,dofs_per_cell); Vector cell_rhs_u(dofs_per_cell); Vector cell_rhs_v(dofs_per_cell); Vector cell_rhs_w(dofs_per_cell); - + std::vector phiqnp1(n_q_points); - + std::vector uqn(n_q_points); std::vector uqnm1(n_q_points); std::vector vqn(n_q_points); @@ -640,11 +654,11 @@ void NavierStokesSolver::assemble_system_U() std::vector > grad_pqn(n_q_points); std::vector > grad_psiqn(n_q_points); std::vector > grad_psiqnm1(n_q_points); - + std::vector local_dof_indices(dofs_per_cell); std::vector > shape_grad(dofs_per_cell); std::vector shape_value(dofs_per_cell); - + double force_u; double force_v; double force_w; @@ -658,159 +672,162 @@ void NavierStokesSolver::assemble_system_U() double rho; Vector force_terms(dim); - typename DoFHandler::active_cell_iterator - cell_U=dof_handler_U.begin_active(), endc_U=dof_handler_U.end(); + typename DoFHandler::active_cell_iterator + cell_U=dof_handler_U.begin_active(), endc_U=dof_handler_U.end(); typename DoFHandler::active_cell_iterator cell_P=dof_handler_P.begin_active(); typename DoFHandler::active_cell_iterator cell_LS=dof_handler_LS.begin_active(); - + for (; cell_U!=endc_U; ++cell_U,++cell_P,++cell_LS) - if (cell_U->is_locally_owned()) { - cell_A_u=0; - cell_rhs_u=0; - cell_rhs_v=0; - cell_rhs_w=0; - - fe_values_LS.reinit(cell_LS); - fe_values_U.reinit(cell_U); - fe_values_P.reinit(cell_P); - - // get function values for LS - fe_values_LS.get_function_values(locally_relevant_solution_phi,phiqnp1); - // get function values for U - fe_values_U.get_function_values(locally_relevant_solution_u,uqn); - fe_values_U.get_function_values(locally_relevant_solution_u_old,uqnm1); - fe_values_U.get_function_values(locally_relevant_solution_v,vqn); - fe_values_U.get_function_values(locally_relevant_solution_v_old,vqnm1); - if (dim==3) - { - fe_values_U.get_function_values(locally_relevant_solution_w,wqn); - fe_values_U.get_function_values(locally_relevant_solution_w_old,wqnm1); - } - // For explicit nonlinearity - // get gradient values for U - //fe_values_U.get_function_gradients(locally_relevant_solution_u,grad_un); - //fe_values_U.get_function_gradients(locally_relevant_solution_v,grad_vn); - //if (dim==3) - //fe_values_U.get_function_gradients(locally_relevant_solution_w,grad_wn); - - // get values and gradients for p and dpsi - fe_values_P.get_function_gradients(locally_relevant_solution_p,grad_pqn); - fe_values_P.get_function_gradients(locally_relevant_solution_psi,grad_psiqn); - fe_values_P.get_function_gradients(locally_relevant_solution_psi_old,grad_psiqnm1); - - for (unsigned int q_point=0; q_pointis_locally_owned()) + { + cell_A_u=0; + cell_rhs_u=0; + cell_rhs_v=0; + cell_rhs_w=0; + + fe_values_LS.reinit(cell_LS); + fe_values_U.reinit(cell_U); + fe_values_P.reinit(cell_P); + + // get function values for LS + fe_values_LS.get_function_values(locally_relevant_solution_phi,phiqnp1); + // get function values for U + fe_values_U.get_function_values(locally_relevant_solution_u,uqn); + fe_values_U.get_function_values(locally_relevant_solution_u_old,uqnm1); + fe_values_U.get_function_values(locally_relevant_solution_v,vqn); + fe_values_U.get_function_values(locally_relevant_solution_v_old,vqnm1); + if (dim==3) + { + fe_values_U.get_function_values(locally_relevant_solution_w,wqn); + fe_values_U.get_function_values(locally_relevant_solution_w_old,wqnm1); + } + // For explicit nonlinearity + // get gradient values for U + //fe_values_U.get_function_gradients(locally_relevant_solution_u,grad_un); + //fe_values_U.get_function_gradients(locally_relevant_solution_v,grad_vn); + //if (dim==3) + //fe_values_U.get_function_gradients(locally_relevant_solution_w,grad_wn); + + // get values and gradients for p and dpsi + fe_values_P.get_function_gradients(locally_relevant_solution_p,grad_pqn); + fe_values_P.get_function_gradients(locally_relevant_solution_psi,grad_psiqn); + fe_values_P.get_function_gradients(locally_relevant_solution_psi_old,grad_psiqnm1); + + for (unsigned int q_point=0; q_pointget_dof_indices(local_dof_indices); + // distribute + if (rebuild_Matrix_U==true) + constraints.distribute_local_to_global(cell_A_u,local_dof_indices,system_Matrix_u); + constraints.distribute_local_to_global(cell_rhs_u,local_dof_indices,system_rhs_u); + constraints.distribute_local_to_global(cell_rhs_v,local_dof_indices,system_rhs_v); + if (dim==3) + constraints.distribute_local_to_global(cell_rhs_w,local_dof_indices,system_rhs_w); } - cell_U->get_dof_indices(local_dof_indices); - // distribute - if (rebuild_Matrix_U==true) - constraints.distribute_local_to_global(cell_A_u,local_dof_indices,system_Matrix_u); - constraints.distribute_local_to_global(cell_rhs_u,local_dof_indices,system_rhs_u); - constraints.distribute_local_to_global(cell_rhs_v,local_dof_indices,system_rhs_v); - if (dim==3) - constraints.distribute_local_to_global(cell_rhs_w,local_dof_indices,system_rhs_w); - } system_rhs_u.compress(VectorOperation::add); system_rhs_v.compress(VectorOperation::add); if (dim==3) system_rhs_w.compress(VectorOperation::add); - if (rebuild_Matrix_U==true) + if (rebuild_Matrix_U==true) { system_Matrix_u.compress(VectorOperation::add); system_Matrix_v.copy_from(system_Matrix_u); - if (dim==3) - system_Matrix_w.copy_from(system_Matrix_u); + if (dim==3) + system_Matrix_w.copy_from(system_Matrix_u); } // BOUNDARY CONDITIONS system_rhs_u.set(boundary_values_id_u,boundary_values_u); system_rhs_u.compress(VectorOperation::insert); system_rhs_v.set(boundary_values_id_v,boundary_values_v); system_rhs_v.compress(VectorOperation::insert); - if (dim==3) + if (dim==3) { system_rhs_w.set(boundary_values_id_w,boundary_values_w); system_rhs_w.compress(VectorOperation::insert); @@ -820,40 +837,42 @@ void NavierStokesSolver::assemble_system_U() system_Matrix_u.clear_rows(boundary_values_id_u,1); system_Matrix_v.clear_rows(boundary_values_id_v,1); if (dim==3) - system_Matrix_w.clear_rows(boundary_values_id_w,1); + system_Matrix_w.clear_rows(boundary_values_id_w,1); if (rebuild_Matrix_U_preconditioners) - { - // PRECONDITIONERS - rebuild_Matrix_U_preconditioners=false; - preconditioner_Matrix_u.reset(new PETScWrappers::PreconditionBoomerAMG - (system_Matrix_u,PETScWrappers::PreconditionBoomerAMG::AdditionalData(false))); - preconditioner_Matrix_v.reset( new PETScWrappers::PreconditionBoomerAMG - (system_Matrix_v,PETScWrappers::PreconditionBoomerAMG::AdditionalData(false))); - if (dim==3) - preconditioner_Matrix_w.reset(new PETScWrappers::PreconditionBoomerAMG - (system_Matrix_w,PETScWrappers::PreconditionBoomerAMG::AdditionalData(false))); - } + { + // PRECONDITIONERS + rebuild_Matrix_U_preconditioners=false; + preconditioner_Matrix_u.reset(new PETScWrappers::PreconditionBoomerAMG + (system_Matrix_u,PETScWrappers::PreconditionBoomerAMG::AdditionalData(false))); + preconditioner_Matrix_v.reset( new PETScWrappers::PreconditionBoomerAMG + (system_Matrix_v,PETScWrappers::PreconditionBoomerAMG::AdditionalData(false))); + if (dim==3) + preconditioner_Matrix_w.reset(new PETScWrappers::PreconditionBoomerAMG + (system_Matrix_w,PETScWrappers::PreconditionBoomerAMG::AdditionalData(false))); + } } rebuild_Matrix_U=true; } template -void NavierStokesSolver::assemble_system_dpsi_q() { - if (rebuild_S_M==true) { - system_S=0; - system_M=0; - } +void NavierStokesSolver::assemble_system_dpsi_q() +{ + if (rebuild_S_M==true) + { + system_S=0; + system_M=0; + } system_rhs_psi=0; system_rhs_q=0; const QGauss quadrature_formula(degree_MAX+1); FEValues fe_values_U(fe_U,quadrature_formula, - update_values|update_gradients|update_quadrature_points|update_JxW_values); + update_values|update_gradients|update_quadrature_points|update_JxW_values); FEValues fe_values_P(fe_P,quadrature_formula, - update_values|update_gradients|update_quadrature_points|update_JxW_values); + update_values|update_gradients|update_quadrature_points|update_JxW_values); FEValues fe_values_LS(fe_LS,quadrature_formula, - update_values|update_gradients|update_quadrature_points|update_JxW_values); + update_values|update_gradients|update_quadrature_points|update_JxW_values); const unsigned int dofs_per_cell=fe_P.dofs_per_cell; const unsigned int n_q_points=quadrature_formula.size(); @@ -872,83 +891,89 @@ void NavierStokesSolver::assemble_system_dpsi_q() { std::vector shape_value(dofs_per_cell); std::vector > shape_grad(dofs_per_cell); - typename DoFHandler::active_cell_iterator - cell_P=dof_handler_P.begin_active(), endc_P=dof_handler_P.end(); + typename DoFHandler::active_cell_iterator + cell_P=dof_handler_P.begin_active(), endc_P=dof_handler_P.end(); typename DoFHandler::active_cell_iterator cell_U=dof_handler_U.begin_active(); typename DoFHandler::active_cell_iterator cell_LS=dof_handler_LS.begin_active(); for (; cell_P!=endc_P; ++cell_P,++cell_U,++cell_LS) - if (cell_P->is_locally_owned()) { - cell_S=0; - cell_M=0; - cell_rhs_psi=0; - cell_rhs_q=0; - - fe_values_P.reinit(cell_P); - fe_values_U.reinit(cell_U); - fe_values_LS.reinit(cell_LS); - - // get function values for LS - fe_values_LS.get_function_values(locally_relevant_solution_phi,phiqnp1); - - // get function grads for u and v - fe_values_U.get_function_gradients(locally_relevant_solution_u,gunp1); - fe_values_U.get_function_gradients(locally_relevant_solution_v,gvnp1); - if (dim==3) - fe_values_U.get_function_gradients(locally_relevant_solution_w,gwnp1); - - for (unsigned int q_point=0; q_pointis_locally_owned()) + { + cell_S=0; + cell_M=0; + cell_rhs_psi=0; + cell_rhs_q=0; + + fe_values_P.reinit(cell_P); + fe_values_U.reinit(cell_U); + fe_values_LS.reinit(cell_LS); + + // get function values for LS + fe_values_LS.get_function_values(locally_relevant_solution_phi,phiqnp1); + + // get function grads for u and v + fe_values_U.get_function_gradients(locally_relevant_solution_u,gunp1); + fe_values_U.get_function_gradients(locally_relevant_solution_v,gvnp1); + if (dim==3) + fe_values_U.get_function_gradients(locally_relevant_solution_w,gwnp1); + + for (unsigned int q_point=0; q_pointget_dof_indices(local_dof_indices); + // Distribute + if (rebuild_S_M==true) + { + constraints_psi.distribute_local_to_global(cell_S,local_dof_indices,system_S); + constraints_psi.distribute_local_to_global(cell_M,local_dof_indices,system_M); + } + constraints_psi.distribute_local_to_global(cell_rhs_q,local_dof_indices,system_rhs_q); + constraints_psi.distribute_local_to_global(cell_rhs_psi,local_dof_indices,system_rhs_psi); } - cell_P->get_dof_indices(local_dof_indices); - // Distribute - if (rebuild_S_M==true) { - constraints_psi.distribute_local_to_global(cell_S,local_dof_indices,system_S); - constraints_psi.distribute_local_to_global(cell_M,local_dof_indices,system_M); - } - constraints_psi.distribute_local_to_global(cell_rhs_q,local_dof_indices,system_rhs_q); - constraints_psi.distribute_local_to_global(cell_rhs_psi,local_dof_indices,system_rhs_psi); - } - if (rebuild_S_M==true) + if (rebuild_S_M==true) { system_M.compress(VectorOperation::add); system_S.compress(VectorOperation::add); if (rebuild_S_M_preconditioners) - { - rebuild_S_M_preconditioners=false; - preconditioner_S.reset(new PETScWrappers::PreconditionBoomerAMG - (system_S,PETScWrappers::PreconditionBoomerAMG::AdditionalData(true))); - preconditioner_M.reset(new PETScWrappers::PreconditionBoomerAMG - (system_M,PETScWrappers::PreconditionBoomerAMG::AdditionalData(true))); - } + { + rebuild_S_M_preconditioners=false; + preconditioner_S.reset(new PETScWrappers::PreconditionBoomerAMG + (system_S,PETScWrappers::PreconditionBoomerAMG::AdditionalData(true))); + preconditioner_M.reset(new PETScWrappers::PreconditionBoomerAMG + (system_M,PETScWrappers::PreconditionBoomerAMG::AdditionalData(true))); + } } system_rhs_psi.compress(VectorOperation::add); system_rhs_q.compress(VectorOperation::add); @@ -960,10 +985,10 @@ void NavierStokesSolver::assemble_system_dpsi_q() { /////////////////////////////////////////////////////// template void NavierStokesSolver::solve_U(const ConstraintMatrix &constraints, - PETScWrappers::MPI::SparseMatrix &Matrix, - std_cxx1x::shared_ptr preconditioner, - PETScWrappers::MPI::Vector &completely_distributed_solution, - const PETScWrappers::MPI::Vector &rhs) + PETScWrappers::MPI::SparseMatrix &Matrix, + std_cxx1x::shared_ptr preconditioner, + PETScWrappers::MPI::Vector &completely_distributed_solution, + const PETScWrappers::MPI::Vector &rhs) { SolverControl solver_control(dof_handler_U.n_dofs(),1e-6); //PETScWrappers::SolverCG solver(solver_control, mpi_communicator); @@ -981,10 +1006,11 @@ void NavierStokesSolver::solve_U(const ConstraintMatrix &constraints, template void NavierStokesSolver::solve_P(const ConstraintMatrix &constraints, - PETScWrappers::MPI::SparseMatrix &Matrix, - std_cxx1x::shared_ptr preconditioner, - PETScWrappers::MPI::Vector &completely_distributed_solution, - const PETScWrappers::MPI::Vector &rhs) { + PETScWrappers::MPI::SparseMatrix &Matrix, + std_cxx1x::shared_ptr preconditioner, + PETScWrappers::MPI::Vector &completely_distributed_solution, + const PETScWrappers::MPI::Vector &rhs) +{ SolverControl solver_control(dof_handler_P.n_dofs(),1e-6); PETScWrappers::SolverCG solver(solver_control,mpi_communicator); //PETScWrappers::SolverGMRES solver(solver_control, mpi_communicator); @@ -1001,14 +1027,15 @@ void NavierStokesSolver::solve_P(const ConstraintMatrix &constraints, //////////////// get different fields ///////////////// /////////////////////////////////////////////////////// template -void NavierStokesSolver::get_velocity() { - assemble_system_U(); +void NavierStokesSolver::get_velocity() +{ + assemble_system_U(); save_old_solution(); solve_U(constraints,system_Matrix_u,preconditioner_Matrix_u,completely_distributed_solution_u,system_rhs_u); locally_relevant_solution_u=completely_distributed_solution_u; solve_U(constraints,system_Matrix_v,preconditioner_Matrix_v,completely_distributed_solution_v,system_rhs_v); - locally_relevant_solution_v=completely_distributed_solution_v; - if (dim==3) + locally_relevant_solution_v=completely_distributed_solution_v; + if (dim==3) { solve_U(constraints,system_Matrix_w,preconditioner_Matrix_w,completely_distributed_solution_w,system_rhs_w); locally_relevant_solution_w=completely_distributed_solution_w; @@ -1016,7 +1043,7 @@ void NavierStokesSolver::get_velocity() { } template -void NavierStokesSolver::get_pressure() +void NavierStokesSolver::get_pressure() { // GET DPSI assemble_system_dpsi_q(); @@ -1034,7 +1061,8 @@ void NavierStokesSolver::get_pressure() /////////////////////// DO STEPS ////////////////////// /////////////////////////////////////////////////////// template -void NavierStokesSolver::nth_time_step() { +void NavierStokesSolver::nth_time_step() +{ get_velocity(); get_pressure(); } @@ -1043,7 +1071,8 @@ void NavierStokesSolver::nth_time_step() { //////////////////////// OTHERS /////////////////////// /////////////////////////////////////////////////////// template -void NavierStokesSolver::save_old_solution() { +void NavierStokesSolver::save_old_solution() +{ locally_relevant_solution_u_old=locally_relevant_solution_u; locally_relevant_solution_v_old=locally_relevant_solution_v; locally_relevant_solution_w_old=locally_relevant_solution_w; diff --git a/two_phase_flow/TestLevelSet.cc b/two_phase_flow/TestLevelSet.cc index af1434f..bee50bb 100644 --- a/two_phase_flow/TestLevelSet.cc +++ b/two_phase_flow/TestLevelSet.cc @@ -45,10 +45,10 @@ using namespace dealii; // TIME_INTEGRATION #define FORWARD_EULER 0 #define SSP33 1 -// PROBLEM +// PROBLEM #define CIRCULAR_ROTATION 0 #define DIAGONAL_ADVECTION 1 -// OTHER FLAGS +// OTHER FLAGS #define VARIABLE_VELOCITY 0 #include "utilities_test_LS.cc" @@ -62,7 +62,7 @@ class TestLevelSet { public: TestLevelSet (const unsigned int degree_LS, - const unsigned int degree_U); + const unsigned int degree_U); ~TestLevelSet (); void run (); @@ -70,7 +70,7 @@ private: // BOUNDARY // void set_boundary_inlet(); void get_boundary_values_phi(std::vector &boundary_values_id_phi, - std::vector &boundary_values_phi); + std::vector &boundary_values_phi); // VELOCITY // void get_interpolated_velocity(); // SETUP AND INIT CONDITIONS // @@ -79,8 +79,8 @@ private: void init_constraints(); // POST PROCESSING // void process_solution(parallel::distributed::Triangulation &triangulation, - DoFHandler &dof_handler_LS, - PETScWrappers::MPI::Vector &solution); + DoFHandler &dof_handler_LS, + PETScWrappers::MPI::Vector &solution); void output_results(); void output_solution(); @@ -97,10 +97,10 @@ private: std::vector boundary_values_id_phi; std::vector boundary_values_phi; - // GENERAL + // GENERAL MPI_Comm mpi_communicator; parallel::distributed::Triangulation triangulation; - + int degree; int degree_LS; DoFHandler dof_handler_LS; @@ -129,7 +129,7 @@ private: double cfl; double min_h; - double sharpness; + double sharpness; int sharpness_integer; unsigned int n_refinement; @@ -153,18 +153,18 @@ private: // MASS MATRIX PETScWrappers::MPI::SparseMatrix matrix_MC, matrix_MC_tnm1; std_cxx1x::shared_ptr preconditioner_MC; - + }; template -TestLevelSet::TestLevelSet (const unsigned int degree_LS, - const unsigned int degree_U) +TestLevelSet::TestLevelSet (const unsigned int degree_LS, + const unsigned int degree_U) : mpi_communicator (MPI_COMM_WORLD), triangulation (mpi_communicator, - typename Triangulation::MeshSmoothing - (Triangulation::smoothing_on_refinement | - Triangulation::smoothing_on_coarsening)), + typename Triangulation::MeshSmoothing + (Triangulation::smoothing_on_refinement | + Triangulation::smoothing_on_coarsening)), degree_LS(degree_LS), dof_handler_LS (triangulation), fe_LS (degree_LS), @@ -192,23 +192,23 @@ void TestLevelSet::get_interpolated_velocity() // velocity in x completely_distributed_solution_u = 0; VectorTools::interpolate(dof_handler_U, - ExactU(PROBLEM,time), - completely_distributed_solution_u); + ExactU(PROBLEM,time), + completely_distributed_solution_u); constraints.distribute (completely_distributed_solution_u); locally_relevant_solution_u = completely_distributed_solution_u; // velocity in y completely_distributed_solution_v = 0; VectorTools::interpolate(dof_handler_U, - ExactV(PROBLEM,time), - completely_distributed_solution_v); + ExactV(PROBLEM,time), + completely_distributed_solution_v); constraints.distribute (completely_distributed_solution_v); locally_relevant_solution_v = completely_distributed_solution_v; if (dim==3) { completely_distributed_solution_w = 0; VectorTools::interpolate(dof_handler_U, - ExactW(PROBLEM,time), - completely_distributed_solution_w); + ExactW(PROBLEM,time), + completely_distributed_solution_w); constraints.distribute (completely_distributed_solution_w); locally_relevant_solution_w = completely_distributed_solution_w; } @@ -222,52 +222,52 @@ void TestLevelSet::set_boundary_inlet() { const QGauss face_quadrature_formula(1); // center of the face FEFaceValues fe_face_values (fe_U,face_quadrature_formula, - update_values | update_quadrature_points | - update_normal_vectors); + update_values | update_quadrature_points | + update_normal_vectors); const unsigned int n_face_q_points = face_quadrature_formula.size(); std::vector u_value (n_face_q_points); - std::vector v_value (n_face_q_points); - std::vector w_value (n_face_q_points); - + std::vector v_value (n_face_q_points); + std::vector w_value (n_face_q_points); + typename DoFHandler::active_cell_iterator - cell_U = dof_handler_U.begin_active(), - endc_U = dof_handler_U.end(); + cell_U = dof_handler_U.begin_active(), + endc_U = dof_handler_U.end(); Tensor<1,dim> u; - + for (; cell_U!=endc_U; ++cell_U) if (cell_U->is_locally_owned()) for (unsigned int face=0; face::faces_per_cell; ++face) - if (cell_U->face(face)->at_boundary()) - { - fe_face_values.reinit(cell_U,face); - fe_face_values.get_function_values(locally_relevant_solution_u,u_value); - fe_face_values.get_function_values(locally_relevant_solution_v,v_value); - if (dim==3) - fe_face_values.get_function_values(locally_relevant_solution_w,w_value); - u[0]=u_value[0]; - u[1]=v_value[0]; - if (dim==3) - u[2]=w_value[0]; - if (fe_face_values.normal_vector(0)*u < -1e-14) - cell_U->face(face)->set_boundary_id(10); - } + if (cell_U->face(face)->at_boundary()) + { + fe_face_values.reinit(cell_U,face); + fe_face_values.get_function_values(locally_relevant_solution_u,u_value); + fe_face_values.get_function_values(locally_relevant_solution_v,v_value); + if (dim==3) + fe_face_values.get_function_values(locally_relevant_solution_w,w_value); + u[0]=u_value[0]; + u[1]=v_value[0]; + if (dim==3) + u[2]=w_value[0]; + if (fe_face_values.normal_vector(0)*u < -1e-14) + cell_U->face(face)->set_boundary_id(10); + } } template void TestLevelSet::get_boundary_values_phi(std::vector &boundary_values_id_phi, - std::vector &boundary_values_phi) + std::vector &boundary_values_phi) { std::map map_boundary_values_phi; unsigned int boundary_id=0; - + set_boundary_inlet(); boundary_id=10; // inlet VectorTools::interpolate_boundary_values (dof_handler_LS, - boundary_id,BoundaryPhi(), - map_boundary_values_phi); + boundary_id,BoundaryPhi(), + map_boundary_values_phi); boundary_values_id_phi.resize(map_boundary_values_phi.size()); - boundary_values_phi.resize(map_boundary_values_phi.size()); + boundary_values_phi.resize(map_boundary_values_phi.size()); std::map::const_iterator boundary_value_phi = map_boundary_values_phi.begin(); for (int i=0; boundary_value_phi !=map_boundary_values_phi.end(); ++boundary_value_phi, ++i) { @@ -281,73 +281,73 @@ void TestLevelSet::get_boundary_values_phi(std::vector &bound ////////////////////////////////// template void TestLevelSet::setup() -{ +{ degree = std::max(degree_LS,degree_U); // setup system LS dof_handler_LS.distribute_dofs (fe_LS); locally_owned_dofs_LS = dof_handler_LS.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_LS, - locally_relevant_dofs_LS); - // setup system U + locally_relevant_dofs_LS); + // setup system U dof_handler_U.distribute_dofs (fe_U); locally_owned_dofs_U = dof_handler_U.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_U, - locally_relevant_dofs_U); + locally_relevant_dofs_U); // setup system U for disp field dof_handler_U_disp_field.distribute_dofs (fe_U_disp_field); locally_owned_dofs_U_disp_field = dof_handler_U_disp_field.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_U_disp_field, - locally_relevant_dofs_U_disp_field); + locally_relevant_dofs_U_disp_field); // init vectors for phi locally_relevant_solution_phi.reinit(locally_owned_dofs_LS, - locally_relevant_dofs_LS, - mpi_communicator); + locally_relevant_dofs_LS, + mpi_communicator); locally_relevant_solution_phi = 0; - completely_distributed_solution_phi.reinit(mpi_communicator, - dof_handler_LS.n_dofs(), - dof_handler_LS.n_locally_owned_dofs()); + completely_distributed_solution_phi.reinit(mpi_communicator, + dof_handler_LS.n_dofs(), + dof_handler_LS.n_locally_owned_dofs()); //init vectors for u locally_relevant_solution_u.reinit(locally_owned_dofs_U, - locally_relevant_dofs_U, - mpi_communicator); + locally_relevant_dofs_U, + mpi_communicator); locally_relevant_solution_u = 0; - completely_distributed_solution_u.reinit(mpi_communicator, - dof_handler_U.n_dofs(), - dof_handler_U.n_locally_owned_dofs()); - //init vectors for v + completely_distributed_solution_u.reinit(mpi_communicator, + dof_handler_U.n_dofs(), + dof_handler_U.n_locally_owned_dofs()); + //init vectors for v locally_relevant_solution_v.reinit(locally_owned_dofs_U, - locally_relevant_dofs_U, - mpi_communicator); + locally_relevant_dofs_U, + mpi_communicator); locally_relevant_solution_v = 0; - completely_distributed_solution_v.reinit(mpi_communicator, - dof_handler_U.n_dofs(), - dof_handler_U.n_locally_owned_dofs()); + completely_distributed_solution_v.reinit(mpi_communicator, + dof_handler_U.n_dofs(), + dof_handler_U.n_locally_owned_dofs()); // init vectors for w locally_relevant_solution_w.reinit(locally_owned_dofs_U, - locally_relevant_dofs_U, - mpi_communicator); + locally_relevant_dofs_U, + mpi_communicator); locally_relevant_solution_w = 0; - completely_distributed_solution_w.reinit(mpi_communicator, - dof_handler_U.n_dofs(), - dof_handler_U.n_locally_owned_dofs()); + completely_distributed_solution_w.reinit(mpi_communicator, + dof_handler_U.n_dofs(), + dof_handler_U.n_locally_owned_dofs()); init_constraints(); // MASS MATRIX DynamicSparsityPattern dsp (locally_relevant_dofs_LS); DoFTools::make_sparsity_pattern (dof_handler_LS,dsp,constraints,false); SparsityTools::distribute_sparsity_pattern (dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - mpi_communicator, - locally_relevant_dofs_LS); + dof_handler_LS.n_locally_owned_dofs_per_processor(), + mpi_communicator, + locally_relevant_dofs_LS); matrix_MC.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); matrix_MC_tnm1.reinit (mpi_communicator, - dsp, - dof_handler_LS.n_locally_owned_dofs_per_processor(), - dof_handler_LS.n_locally_owned_dofs_per_processor(), - Utilities::MPI::this_mpi_process(mpi_communicator)); + dsp, + dof_handler_LS.n_locally_owned_dofs_per_processor(), + dof_handler_LS.n_locally_owned_dofs_per_processor(), + Utilities::MPI::this_mpi_process(mpi_communicator)); } template @@ -358,27 +358,27 @@ void TestLevelSet::initial_condition() // init condition for phi completely_distributed_solution_phi = 0; VectorTools::interpolate(dof_handler_LS, - InitialPhi(PROBLEM, sharpness), - //ZeroFunction(), - completely_distributed_solution_phi); + InitialPhi(PROBLEM, sharpness), + //ZeroFunction(), + completely_distributed_solution_phi); constraints.distribute (completely_distributed_solution_phi); locally_relevant_solution_phi = completely_distributed_solution_phi; // init condition for u=0 completely_distributed_solution_u = 0; VectorTools::interpolate(dof_handler_U, - ExactU(PROBLEM,time), - completely_distributed_solution_u); + ExactU(PROBLEM,time), + completely_distributed_solution_u); constraints.distribute (completely_distributed_solution_u); locally_relevant_solution_u = completely_distributed_solution_u; // init condition for v completely_distributed_solution_v = 0; VectorTools::interpolate(dof_handler_U, - ExactV(PROBLEM,time), - completely_distributed_solution_v); + ExactV(PROBLEM,time), + completely_distributed_solution_v); constraints.distribute (completely_distributed_solution_v); locally_relevant_solution_v = completely_distributed_solution_v; } - + template void TestLevelSet::init_constraints() { @@ -396,31 +396,31 @@ void TestLevelSet::init_constraints() // POST PROCESSING // ///////////////////// template -void TestLevelSet::process_solution(parallel::distributed::Triangulation &triangulation, - DoFHandler &dof_handler_LS, - PETScWrappers::MPI::Vector &solution) +void TestLevelSet::process_solution(parallel::distributed::Triangulation &triangulation, + DoFHandler &dof_handler_LS, + PETScWrappers::MPI::Vector &solution) { Vector difference_per_cell (triangulation.n_active_cells()); // error for phi VectorTools::integrate_difference (dof_handler_LS, - solution, - InitialPhi(PROBLEM,sharpness), - difference_per_cell, - QGauss(degree_LS+3), - VectorTools::L1_norm); - + solution, + InitialPhi(PROBLEM,sharpness), + difference_per_cell, + QGauss(degree_LS+3), + VectorTools::L1_norm); + double u_L1_error = difference_per_cell.l1_norm(); u_L1_error = std::sqrt(Utilities::MPI::sum(u_L1_error * u_L1_error, mpi_communicator)); - + VectorTools::integrate_difference (dof_handler_LS, - solution, - InitialPhi(PROBLEM,sharpness), - difference_per_cell, - QGauss(degree_LS+3), - VectorTools::L2_norm); + solution, + InitialPhi(PROBLEM,sharpness), + difference_per_cell, + QGauss(degree_LS+3), + VectorTools::L2_norm); double u_L2_error = difference_per_cell.l2_norm(); u_L2_error = std::sqrt(Utilities::MPI::sum(u_L2_error * u_L2_error, mpi_communicator)); - + pcout << "L1 error: " << u_L1_error << std::endl; pcout << "L2 error: " << u_L2_error << std::endl; } @@ -436,30 +436,30 @@ template void TestLevelSet::output_solution() { DataOut data_out; - data_out.attach_dof_handler(dof_handler_LS); + data_out.attach_dof_handler(dof_handler_LS); data_out.add_data_vector (locally_relevant_solution_phi, "phi"); data_out.build_patches(); const std::string filename = ("solution-" + - Utilities::int_to_string (output_number, 3) + - "." + - Utilities::int_to_string - (triangulation.locally_owned_subdomain(), 4)); + Utilities::int_to_string (output_number, 3) + + "." + + Utilities::int_to_string + (triangulation.locally_owned_subdomain(), 4)); std::ofstream output ((filename + ".vtu").c_str()); data_out.write_vtu (output); - + if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) { std::vector filenames; for (unsigned int i=0; - i::run() //ALGORITHM = "MPP_u1"; ALGORITHM = "NMPP_uH"; //ALGORITHM = "MPP_uH"; - + ////////////// // GEOMETRY // ////////////// - if (PROBLEM==CIRCULAR_ROTATION || PROBLEM==DIAGONAL_ADVECTION) + if (PROBLEM==CIRCULAR_ROTATION || PROBLEM==DIAGONAL_ADVECTION) GridGenerator::hyper_cube(triangulation); - //GridGenerator::hyper_rectangle(triangulation, Point(0.0,0.0), Point(1.0,1.0), true); + //GridGenerator::hyper_rectangle(triangulation, Point(0.0,0.0), Point(1.0,1.0), true); triangulation.refine_global (n_refinement); - + /////////// // SETUP // /////////// @@ -526,12 +526,12 @@ void TestLevelSet::run() // TRANSPORT SOLVER // ////////////////////// LevelSetSolver level_set (degree_LS,degree_U, - time_step,cK,cE, - verbose, - ALGORITHM, - TRANSPORT_TIME_INTEGRATION, - triangulation, - mpi_communicator); + time_step,cK,cE, + verbose, + ALGORITHM, + TRANSPORT_TIME_INTEGRATION, + triangulation, + mpi_communicator); /////////////////////// // INITIAL CONDITION // @@ -540,54 +540,54 @@ void TestLevelSet::run() output_results(); if (dim==2) level_set.initial_condition(locally_relevant_solution_phi, - locally_relevant_solution_u,locally_relevant_solution_v); + locally_relevant_solution_u,locally_relevant_solution_v); else //dim=3 level_set.initial_condition(locally_relevant_solution_phi, - locally_relevant_solution_u,locally_relevant_solution_v,locally_relevant_solution_w); - + locally_relevant_solution_u,locally_relevant_solution_v,locally_relevant_solution_w); + ///////////////////////////////// - // BOUNDARY CONDITIONS FOR PHI // + // BOUNDARY CONDITIONS FOR PHI // ///////////////////////////////// get_boundary_values_phi(boundary_values_id_phi,boundary_values_phi); level_set.set_boundary_conditions(boundary_values_id_phi,boundary_values_phi); - + // OUTPUT DATA REGARDING TIME STEPPING AND MESH // int dofs_LS = dof_handler_LS.n_dofs(); pcout << "Cfl: " << cfl << std::endl; - pcout << " Number of active cells: " - << triangulation.n_global_active_cells() << std::endl - << " Number of degrees of freedom: " << std::endl - << " LS: " << dofs_LS << std::endl; - - // TIME STEPPING + pcout << " Number of active cells: " + << triangulation.n_global_active_cells() << std::endl + << " Number of degrees of freedom: " << std::endl + << " LS: " << dofs_LS << std::endl; + + // TIME STEPPING timestep_number=0; time=0; - while(time final_time) - { - pcout << "FINAL TIME STEP... " << std::endl; - time_step = final_time-time; - } - pcout << "Time step " << timestep_number - << "\twith dt=" << time_step - << "\tat tn=" << time << std::endl; + { + pcout << "FINAL TIME STEP... " << std::endl; + time_step = final_time-time; + } + pcout << "Time step " << timestep_number + << "\twith dt=" << time_step + << "\tat tn=" << time << std::endl; ////////////////// // GET VELOCITY // (NS or interpolate from a function) at current time tn ////////////////// if (VARIABLE_VELOCITY) - { - get_interpolated_velocity(); - // SET VELOCITY TO LEVEL SET SOLVER - level_set.set_velocity(locally_relevant_solution_u,locally_relevant_solution_v); - } + { + get_interpolated_velocity(); + // SET VELOCITY TO LEVEL SET SOLVER + level_set.set_velocity(locally_relevant_solution_u,locally_relevant_solution_v); + } //////////////////////////// // GET LEVEL SET SOLUTION // (at tnp1) //////////////////////////// level_set.nth_time_step(); - + ///////////////// // UPDATE TIME // ///////////////// @@ -597,10 +597,10 @@ void TestLevelSet::run() // OUTPUT // //////////// if (get_output && time-(output_number)*output_time>=0) - { - level_set.get_unp1(locally_relevant_solution_phi); - output_results(); - } + { + level_set.get_unp1(locally_relevant_solution_phi); + output_results(); + } } pcout << "FINAL TIME T=" << time << std::endl; } @@ -614,7 +614,7 @@ int main(int argc, char *argv[]) PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL); deallog.depth_console (0); { - unsigned int degree = 1; + unsigned int degree = 1; TestLevelSet<2> multiphase(degree, degree); multiphase.run(); } diff --git a/two_phase_flow/TestNavierStokes.cc b/two_phase_flow/TestNavierStokes.cc index 90e0713..7940ea2 100644 --- a/two_phase_flow/TestNavierStokes.cc +++ b/two_phase_flow/TestNavierStokes.cc @@ -50,7 +50,7 @@ class TestNavierStokes { public: TestNavierStokes (const unsigned int degree_LS, - const unsigned int degree_U); + const unsigned int degree_U); ~TestNavierStokes (); void run (); @@ -62,7 +62,7 @@ private: void setup(); void initial_condition(); void init_constraints(); - + PETScWrappers::MPI::Vector locally_relevant_solution_rho; PETScWrappers::MPI::Vector locally_relevant_solution_u; PETScWrappers::MPI::Vector locally_relevant_solution_v; @@ -136,14 +136,14 @@ private: }; template -TestNavierStokes::TestNavierStokes (const unsigned int degree_LS, - const unsigned int degree_U) +TestNavierStokes::TestNavierStokes (const unsigned int degree_LS, + const unsigned int degree_U) : mpi_communicator (MPI_COMM_WORLD), triangulation (mpi_communicator, - typename Triangulation::MeshSmoothing - (Triangulation::smoothing_on_refinement | - Triangulation::smoothing_on_coarsening)), + typename Triangulation::MeshSmoothing + (Triangulation::smoothing_on_refinement | + Triangulation::smoothing_on_coarsening)), degree_LS(degree_LS), dof_handler_LS (triangulation), fe_LS (degree_LS), @@ -169,22 +169,22 @@ TestNavierStokes::~TestNavierStokes () ///////////////////////////////////////// template void TestNavierStokes::setup() -{ +{ // setup system LS dof_handler_LS.distribute_dofs (fe_LS); locally_owned_dofs_LS = dof_handler_LS.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_LS, - locally_relevant_dofs_LS); - // setup system U + locally_relevant_dofs_LS); + // setup system U dof_handler_U.distribute_dofs (fe_U); locally_owned_dofs_U = dof_handler_U.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_U, - locally_relevant_dofs_U); + locally_relevant_dofs_U); // setup system P // dof_handler_P.distribute_dofs (fe_P); locally_owned_dofs_P = dof_handler_P.locally_owned_dofs (); DoFTools::extract_locally_relevant_dofs (dof_handler_P, - locally_relevant_dofs_P); + locally_relevant_dofs_P); init_constraints(); // init vectors for rho locally_relevant_solution_rho.reinit (locally_owned_dofs_LS,locally_relevant_dofs_LS,mpi_communicator); @@ -194,7 +194,7 @@ void TestNavierStokes::setup() locally_relevant_solution_u.reinit (locally_owned_dofs_U,locally_relevant_dofs_U,mpi_communicator); locally_relevant_solution_u = 0; completely_distributed_solution_u.reinit(locally_owned_dofs_U,mpi_communicator); - //init vectors for v + //init vectors for v locally_relevant_solution_v.reinit (locally_owned_dofs_U,locally_relevant_dofs_U,mpi_communicator); locally_relevant_solution_v = 0; completely_distributed_solution_v.reinit(locally_owned_dofs_U,mpi_communicator); @@ -205,7 +205,7 @@ void TestNavierStokes::setup() //init vectors for p locally_relevant_solution_p.reinit(locally_owned_dofs_P,locally_relevant_dofs_P,mpi_communicator); locally_relevant_solution_p = 0; - completely_distributed_solution_p.reinit(locally_owned_dofs_P,mpi_communicator); + completely_distributed_solution_p.reinit(locally_owned_dofs_P,mpi_communicator); } template @@ -216,22 +216,22 @@ void TestNavierStokes::initial_condition() // init condition for rho completely_distributed_solution_rho = 0; VectorTools::interpolate(dof_handler_LS, - RhoFunction(0), - completely_distributed_solution_rho); + RhoFunction(0), + completely_distributed_solution_rho); constraints.distribute (completely_distributed_solution_rho); locally_relevant_solution_rho = completely_distributed_solution_rho; // init condition for u completely_distributed_solution_u = 0; VectorTools::interpolate(dof_handler_U, - ExactSolution_and_BC_U(0,0), - completely_distributed_solution_u); + ExactSolution_and_BC_U(0,0), + completely_distributed_solution_u); constraints.distribute (completely_distributed_solution_u); locally_relevant_solution_u = completely_distributed_solution_u; // init condition for v completely_distributed_solution_v = 0; VectorTools::interpolate(dof_handler_U, - ExactSolution_and_BC_U(0,1), - completely_distributed_solution_v); + ExactSolution_and_BC_U(0,1), + completely_distributed_solution_v); constraints.distribute (completely_distributed_solution_v); locally_relevant_solution_v = completely_distributed_solution_v; // init condition for w @@ -239,20 +239,20 @@ void TestNavierStokes::initial_condition() { completely_distributed_solution_w = 0; VectorTools::interpolate(dof_handler_U, - ExactSolution_and_BC_U(0,2), - completely_distributed_solution_w); + ExactSolution_and_BC_U(0,2), + completely_distributed_solution_w); constraints.distribute (completely_distributed_solution_w); locally_relevant_solution_w = completely_distributed_solution_w; } // init condition for p completely_distributed_solution_p = 0; VectorTools::interpolate(dof_handler_P, - ExactSolution_p(0), - completely_distributed_solution_p); + ExactSolution_p(0), + completely_distributed_solution_p); constraints.distribute (completely_distributed_solution_p); locally_relevant_solution_p = completely_distributed_solution_p; } - + template void TestNavierStokes::init_constraints() { @@ -268,12 +268,12 @@ void TestNavierStokes::fix_pressure() // fix the constant in the pressure completely_distributed_solution_p = locally_relevant_solution_p; double mean_value = VectorTools::compute_mean_value(dof_handler_P, - QGauss(3), - locally_relevant_solution_p, - 0); + QGauss(3), + locally_relevant_solution_p, + 0); if (dim==2) completely_distributed_solution_p.add(-mean_value+std::sin(1)*(std::cos(time)-cos(1+time))); - else + else completely_distributed_solution_p.add(-mean_value+8*std::pow(std::sin(0.5),3)*std::sin(1.5+time)); locally_relevant_solution_p = completely_distributed_solution_p; } @@ -286,7 +286,7 @@ void TestNavierStokes::output_results () data_out.add_data_vector (locally_relevant_solution_u, "u"); data_out.add_data_vector (locally_relevant_solution_v, "v"); if (dim==3) data_out.add_data_vector (locally_relevant_solution_w, "w"); - + Vector subdomain (triangulation.n_active_cells()); for (unsigned int i=0; i::output_results () data_out.build_patches (); const std::string filename = ("solution-" + - Utilities::int_to_string (output_number, 3) + - "." + - Utilities::int_to_string - (triangulation.locally_owned_subdomain(), 4)); + Utilities::int_to_string (output_number, 3) + + "." + + Utilities::int_to_string + (triangulation.locally_owned_subdomain(), 4)); std::ofstream output ((filename + ".vtu").c_str()); data_out.write_vtu (output); @@ -306,13 +306,13 @@ void TestNavierStokes::output_results () { std::vector filenames; for (unsigned int i=0; - i::process_solution(const unsigned int cycle) Vector difference_per_cell (triangulation.n_active_cells()); // error for u VectorTools::integrate_difference (dof_handler_U, - locally_relevant_solution_u, - ExactSolution_and_BC_U(time,0), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::L2_norm); + locally_relevant_solution_u, + ExactSolution_and_BC_U(time,0), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::L2_norm); double u_L2_error = difference_per_cell.l2_norm(); - u_L2_error = + u_L2_error = std::sqrt(Utilities::MPI::sum(u_L2_error * u_L2_error, mpi_communicator)); VectorTools::integrate_difference (dof_handler_U, - locally_relevant_solution_u, - ExactSolution_and_BC_U(time,0), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::H1_norm); + locally_relevant_solution_u, + ExactSolution_and_BC_U(time,0), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::H1_norm); double u_H1_error = difference_per_cell.l2_norm(); - u_H1_error = + u_H1_error = std::sqrt(Utilities::MPI::sum(u_H1_error * u_H1_error, mpi_communicator)); - // error for v + // error for v VectorTools::integrate_difference (dof_handler_U, - locally_relevant_solution_v, - ExactSolution_and_BC_U(time,1), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::L2_norm); + locally_relevant_solution_v, + ExactSolution_and_BC_U(time,1), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::L2_norm); double v_L2_error = difference_per_cell.l2_norm(); - v_L2_error = - std::sqrt(Utilities::MPI::sum(v_L2_error * v_L2_error, - mpi_communicator)); + v_L2_error = + std::sqrt(Utilities::MPI::sum(v_L2_error * v_L2_error, + mpi_communicator)); VectorTools::integrate_difference (dof_handler_U, - locally_relevant_solution_v, - ExactSolution_and_BC_U(time,1), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::H1_norm); + locally_relevant_solution_v, + ExactSolution_and_BC_U(time,1), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::H1_norm); double v_H1_error = difference_per_cell.l2_norm(); - v_H1_error = - std::sqrt(Utilities::MPI::sum(v_H1_error * - v_H1_error, mpi_communicator)); + v_H1_error = + std::sqrt(Utilities::MPI::sum(v_H1_error * + v_H1_error, mpi_communicator)); // error for w double w_L2_error = 0; double w_H1_error = 0; if (dim == 3) { VectorTools::integrate_difference (dof_handler_U, - locally_relevant_solution_w, - ExactSolution_and_BC_U(time,2), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::L2_norm); + locally_relevant_solution_w, + ExactSolution_and_BC_U(time,2), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::L2_norm); w_L2_error = difference_per_cell.l2_norm(); - w_L2_error = - std::sqrt(Utilities::MPI::sum(w_L2_error * w_L2_error, - mpi_communicator)); + w_L2_error = + std::sqrt(Utilities::MPI::sum(w_L2_error * w_L2_error, + mpi_communicator)); VectorTools::integrate_difference (dof_handler_U, - locally_relevant_solution_w, - ExactSolution_and_BC_U(time,2), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::H1_norm); + locally_relevant_solution_w, + ExactSolution_and_BC_U(time,2), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::H1_norm); w_H1_error = difference_per_cell.l2_norm(); - w_H1_error = - std::sqrt(Utilities::MPI::sum(w_H1_error * - w_H1_error, mpi_communicator)); + w_H1_error = + std::sqrt(Utilities::MPI::sum(w_H1_error * + w_H1_error, mpi_communicator)); } // error for p VectorTools::integrate_difference (dof_handler_P, - locally_relevant_solution_p, - ExactSolution_p(time), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::L2_norm); + locally_relevant_solution_p, + ExactSolution_p(time), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::L2_norm); double p_L2_error = difference_per_cell.l2_norm(); - p_L2_error = - std::sqrt(Utilities::MPI::sum(p_L2_error * p_L2_error, - mpi_communicator)); + p_L2_error = + std::sqrt(Utilities::MPI::sum(p_L2_error * p_L2_error, + mpi_communicator)); VectorTools::integrate_difference (dof_handler_P, - locally_relevant_solution_p, - ExactSolution_p(time), - difference_per_cell, - QGauss(degree_U+1), - VectorTools::H1_norm); + locally_relevant_solution_p, + ExactSolution_p(time), + difference_per_cell, + QGauss(degree_U+1), + VectorTools::H1_norm); double p_H1_error = difference_per_cell.l2_norm(); - p_H1_error = - std::sqrt(Utilities::MPI::sum(p_H1_error * p_H1_error, - mpi_communicator)); + p_H1_error = + std::sqrt(Utilities::MPI::sum(p_H1_error * p_H1_error, + mpi_communicator)); - const unsigned int n_active_cells=triangulation.n_active_cells(); + const unsigned int n_active_cells=triangulation.n_active_cells(); const unsigned int n_dofs_U=dof_handler_U.n_dofs(); const unsigned int n_dofs_P=dof_handler_P.n_dofs(); - + convergence_table.add_value("cycle", cycle); convergence_table.add_value("cells", n_active_cells); convergence_table.add_value("dofs_U", n_dofs_U); @@ -457,11 +457,11 @@ void TestNavierStokes::get_boundary_values_U(double t) boundary_values_w.resize(map_boundary_values_w.size()); std::map::const_iterator boundary_value_w =map_boundary_values_w.begin(); for (int i=0; boundary_value_w !=map_boundary_values_w.end(); ++boundary_value_w, ++i) - { - boundary_values_id_w[i]=boundary_value_w->first; - boundary_values_w[i]=boundary_value_w->second; - } - } + { + boundary_values_id_w[i]=boundary_value_w->first; + boundary_values_w[i]=boundary_value_w->second; + } + } for (int i=0; boundary_value_u !=map_boundary_values_u.end(); ++boundary_value_u, ++i) { boundary_values_id_u[i]=boundary_value_u->first; @@ -501,161 +501,161 @@ void TestNavierStokes::run() for (unsigned int cycle=0; cycle navier_stokes (degree_LS, - degree_U, - time_step, - force_function, - rho_function, - nu_function, - verbose, - triangulation, - mpi_communicator); + degree_U, + time_step, + force_function, + rho_function, + nu_function, + verbose, + triangulation, + mpi_communicator); //set INITIAL CONDITION within TRANSPORT PROBLEM if (dim==2) - navier_stokes.initial_condition(locally_relevant_solution_rho, - locally_relevant_solution_u, - locally_relevant_solution_v, - locally_relevant_solution_p); + navier_stokes.initial_condition(locally_relevant_solution_rho, + locally_relevant_solution_u, + locally_relevant_solution_v, + locally_relevant_solution_p); else //dim=3 - navier_stokes.initial_condition(locally_relevant_solution_rho, - locally_relevant_solution_u, - locally_relevant_solution_v, - locally_relevant_solution_w, - locally_relevant_solution_p); + navier_stokes.initial_condition(locally_relevant_solution_rho, + locally_relevant_solution_u, + locally_relevant_solution_v, + locally_relevant_solution_w, + locally_relevant_solution_p); pcout << "Cycle " << cycle << ':' << std::endl; pcout << " Cycle " << cycle - << " Number of active cells: " - << triangulation.n_global_active_cells() << std::endl - << " Number of degrees of freedom (velocity): " - << dof_handler_U.n_dofs() << std::endl - << " min h=" << GridTools::minimal_cell_diameter(triangulation)/std::sqrt(2)/degree_U - << std::endl; - + << " Number of active cells: " + << triangulation.n_global_active_cells() << std::endl + << " Number of degrees of freedom (velocity): " + << dof_handler_U.n_dofs() << std::endl + << " min h=" << GridTools::minimal_cell_diameter(triangulation)/std::sqrt(2)/degree_U + << std::endl; + // TIME STEPPING timestep_number=0; time=0; double time_step_backup=time_step; - while(time final_time-1E-10) - { - pcout << "FINAL TIME STEP..." << std::endl; - time_step_backup=time_step; - time_step=final_time-time; - } - pcout << "Time step " << timestep_number - << "\twith dt=" << time_step - << "\tat tn=" << time - << std::endl; - ///////////////// - // FORCE TERMS // - ///////////////// - force_function.set_time(time+time_step); - ///////////////////////////////// - // DENSITY AND VISCOSITY FIELD // - ///////////////////////////////// - rho_function.set_time(time+time_step); - nu_function.set_time(time+time_step); - ///////////////////////// - // BOUNDARY CONDITIONS // - ///////////////////////// - get_boundary_values_U(time+time_step); - if (dim==2) navier_stokes.set_boundary_conditions(boundary_values_id_u, boundary_values_id_v, - boundary_values_u, boundary_values_v); - else navier_stokes.set_boundary_conditions(boundary_values_id_u, - boundary_values_id_v, - boundary_values_id_w, - boundary_values_u, boundary_values_v, boundary_values_w); - ////////////////// - // GET SOLUTION // - ////////////////// - navier_stokes.nth_time_step(); - if (dim==2) - navier_stokes.get_velocity(locally_relevant_solution_u,locally_relevant_solution_v); - else - navier_stokes.get_velocity(locally_relevant_solution_u, - locally_relevant_solution_v, - locally_relevant_solution_w); - navier_stokes.get_pressure(locally_relevant_solution_p); - - ////////////////// - // FIX PRESSURE // - ////////////////// - fix_pressure(); - - ///////////////// - // UPDATE TIME // - ///////////////// - time+=time_step; - - //////////// - // OUTPUT // - //////////// - if (get_output && time-(output_number)*output_time>=1E-10) - output_results(); - } + while (time final_time-1E-10) + { + pcout << "FINAL TIME STEP..." << std::endl; + time_step_backup=time_step; + time_step=final_time-time; + } + pcout << "Time step " << timestep_number + << "\twith dt=" << time_step + << "\tat tn=" << time + << std::endl; + ///////////////// + // FORCE TERMS // + ///////////////// + force_function.set_time(time+time_step); + ///////////////////////////////// + // DENSITY AND VISCOSITY FIELD // + ///////////////////////////////// + rho_function.set_time(time+time_step); + nu_function.set_time(time+time_step); + ///////////////////////// + // BOUNDARY CONDITIONS // + ///////////////////////// + get_boundary_values_U(time+time_step); + if (dim==2) navier_stokes.set_boundary_conditions(boundary_values_id_u, boundary_values_id_v, + boundary_values_u, boundary_values_v); + else navier_stokes.set_boundary_conditions(boundary_values_id_u, + boundary_values_id_v, + boundary_values_id_w, + boundary_values_u, boundary_values_v, boundary_values_w); + ////////////////// + // GET SOLUTION // + ////////////////// + navier_stokes.nth_time_step(); + if (dim==2) + navier_stokes.get_velocity(locally_relevant_solution_u,locally_relevant_solution_v); + else + navier_stokes.get_velocity(locally_relevant_solution_u, + locally_relevant_solution_v, + locally_relevant_solution_w); + navier_stokes.get_pressure(locally_relevant_solution_p); + + ////////////////// + // FIX PRESSURE // + ////////////////// + fix_pressure(); + + ///////////////// + // UPDATE TIME // + ///////////////// + time+=time_step; + + //////////// + // OUTPUT // + //////////// + if (get_output && time-(output_number)*output_time>=1E-10) + output_results(); + } pcout << "FINAL TIME: " << time << std::endl; time_step=time_step_backup; if (get_error) - process_solution(cycle); - + process_solution(cycle); + if (get_error) - { - convergence_table.set_precision("u L2", 2); - convergence_table.set_precision("u H1", 2); - convergence_table.set_scientific("u L2",true); - convergence_table.set_scientific("u H1",true); - - convergence_table.set_precision("v L2", 2); - convergence_table.set_precision("v H1", 2); - convergence_table.set_scientific("v L2",true); - convergence_table.set_scientific("v H1",true); - - if (dim==3) - { - convergence_table.set_precision("w L2", 2); - convergence_table.set_precision("w H1", 2); - convergence_table.set_scientific("w L2",true); - convergence_table.set_scientific("w H1",true); - } - - convergence_table.set_precision("p L2", 2); - convergence_table.set_precision("p H1", 2); - convergence_table.set_scientific("p L2",true); - convergence_table.set_scientific("p H1",true); - - convergence_table.set_tex_format("cells","r"); - convergence_table.set_tex_format("dofs_U","r"); - convergence_table.set_tex_format("dofs_P","r"); - convergence_table.set_tex_format("dt","r"); - - if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) - { - std::cout << std::endl; - convergence_table.write_text(std::cout); - } - } + { + convergence_table.set_precision("u L2", 2); + convergence_table.set_precision("u H1", 2); + convergence_table.set_scientific("u L2",true); + convergence_table.set_scientific("u H1",true); + + convergence_table.set_precision("v L2", 2); + convergence_table.set_precision("v H1", 2); + convergence_table.set_scientific("v L2",true); + convergence_table.set_scientific("v H1",true); + + if (dim==3) + { + convergence_table.set_precision("w L2", 2); + convergence_table.set_precision("w H1", 2); + convergence_table.set_scientific("w L2",true); + convergence_table.set_scientific("w H1",true); + } + + convergence_table.set_precision("p L2", 2); + convergence_table.set_precision("p H1", 2); + convergence_table.set_scientific("p L2",true); + convergence_table.set_scientific("p H1",true); + + convergence_table.set_tex_format("cells","r"); + convergence_table.set_tex_format("dofs_U","r"); + convergence_table.set_tex_format("dofs_P","r"); + convergence_table.set_tex_format("dt","r"); + + if (Utilities::MPI::this_mpi_process(mpi_communicator) == 0) + { + std::cout << std::endl; + convergence_table.write_text(std::cout); + } + } } } @@ -669,8 +669,8 @@ int main(int argc, char *argv[]) deallog.depth_console (0); { - unsigned int degree_LS = 1; - unsigned int degree_U = 2; + unsigned int degree_LS = 1; + unsigned int degree_U = 2; TestNavierStokes<2> test_navier_stokes(degree_LS, degree_U); test_navier_stokes.run(); } diff --git a/two_phase_flow/utilities.cc b/two_phase_flow/utilities.cc index fc27763..9b56cc6 100644 --- a/two_phase_flow/utilities.cc +++ b/two_phase_flow/utilities.cc @@ -6,28 +6,30 @@ class InitialPhi : public Function { public: InitialPhi (unsigned int PROBLEM, double sharpness=0.005) : Function(), - sharpness(sharpness), - PROBLEM(PROBLEM) {} + sharpness(sharpness), + PROBLEM(PROBLEM) {} virtual double value (const Point &p, const unsigned int component=0) const; double sharpness; unsigned int PROBLEM; }; template double InitialPhi::value (const Point &p, - const unsigned int) const + const unsigned int) const { - double x = p[0]; double y = p[1]; + double x = p[0]; + double y = p[1]; double pi=numbers::PI; if (PROBLEM==FILLING_TANK) return 0.5*(-std::tanh((y-0.3)/sharpness)*std::tanh((y-0.35)/sharpness)+1) - *(-std::tanh((x-0.02)/sharpness)+1)-1; + *(-std::tanh((x-0.02)/sharpness)+1)-1; else if (PROBLEM==BREAKING_DAM) return 0.5*(-std::tanh((x-0.35)/sharpness)*std::tanh((x-0.65)/sharpness)+1) - *(1-std::tanh((y-0.35)/sharpness))-1; + *(1-std::tanh((y-0.35)/sharpness))-1; else if (PROBLEM==FALLING_DROP) { - double x0=0.15; double y0=0.75; + double x0=0.15; + double y0=0.75; double r0=0.1; double r = std::sqrt(std::pow(x-x0,2)+std::pow(y-y0,2)); return 1-(std::tanh((r-r0)/sharpness)+std::tanh((y-0.3)/sharpness)); @@ -37,7 +39,7 @@ double InitialPhi::value (const Point &p, double wave = 0.1*std::sin(pi*x)+0.25; return -std::tanh((y-wave)/sharpness); } - else + else { std::cout << "Error in type of PROBLEM" << std::endl; abort(); @@ -82,16 +84,17 @@ double BoundaryU::value (const Point &p, const unsigned int) const // FILLING THE TANK // ////////////////////// // boundary for filling the tank (inlet) - double x = p[0]; double y = p[1]; + double x = p[0]; + double y = p[1]; if (PROBLEM==FILLING_TANK) { if (x==0 && y>=0.3 && y<=0.35) - return 0.25; - else - return 0.0; + return 0.25; + else + return 0.0; } - else + else { std::cout << "Error in PROBLEM definition" << std::endl; abort(); @@ -110,13 +113,14 @@ template double BoundaryV::value (const Point &p, const unsigned int) const { // boundary for filling the tank (outlet) - double x = p[0]; double y = p[1]; + double x = p[0]; + double y = p[1]; double return_value = 0; if (PROBLEM==FILLING_TANK) { if (y==0.4 && x>=0.3 && x<=0.35) - return_value = 0.25; + return_value = 0.25; } return return_value; } @@ -160,12 +164,12 @@ evaluate_scalar_field (const DataPostprocessorInputs::Scalar &input_data, double H; double rho_value; double phi_value=input_data.solution_values[q]; - if(phi_value > eps) - H=1; - else if (phi_value < -eps) - H=-1; - else - H=phi_value/eps; + if (phi_value > eps) + H=1; + else if (phi_value < -eps) + H=-1; + else + H=phi_value/eps; rho_value = rho_fluid*(1+H)/2. + rho_air*(1-H)/2.; computed_quantities[q] = rho_value; } diff --git a/two_phase_flow/utilities_test_LS.cc b/two_phase_flow/utilities_test_LS.cc index 0c15363..0802bcf 100644 --- a/two_phase_flow/utilities_test_LS.cc +++ b/two_phase_flow/utilities_test_LS.cc @@ -6,39 +6,42 @@ class InitialPhi : public Function { public: InitialPhi (unsigned int PROBLEM, double sharpness=0.005) : Function(), - sharpness(sharpness), - PROBLEM(PROBLEM) {} + sharpness(sharpness), + PROBLEM(PROBLEM) {} virtual double value (const Point &p, const unsigned int component=0) const; double sharpness; unsigned int PROBLEM; }; template double InitialPhi::value (const Point &p, - const unsigned int) const + const unsigned int) const { - double x = p[0]; double y = p[1]; + double x = p[0]; + double y = p[1]; double return_value = -1.; if (PROBLEM==CIRCULAR_ROTATION) { - double x0=0.5; double y0=0.75; + double x0=0.5; + double y0=0.75; double r0=0.15; double r = std::sqrt(std::pow(x-x0,2)+std::pow(y-y0,2)); return_value = -std::tanh((r-r0)/sharpness); } else // (PROBLEM==DIAGONAL_ADVECTION) { - double x0=0.25; double y0=0.25; + double x0=0.25; + double y0=0.25; double r0=0.15; double r=0; if (dim==2) - r = std::sqrt(std::pow(x-x0,2)+std::pow(y-y0,2)); + r = std::sqrt(std::pow(x-x0,2)+std::pow(y-y0,2)); else - { - double z0=0.25; - double z=p[2]; - r = std::sqrt(std::pow(x-x0,2)+std::pow(y-y0,2)+std::pow(z-z0,2)); - } + { + double z0=0.25; + double z=p[2]; + r = std::sqrt(std::pow(x-x0,2)+std::pow(y-y0,2)+std::pow(z-z0,2)); + } return_value = -std::tanh((r-r0)/sharpness); } return return_value; @@ -51,9 +54,9 @@ template class BoundaryPhi : public Function { public: - BoundaryPhi (double t=0) - : - Function() + BoundaryPhi (double t=0) + : + Function() {this->set_time(t);} virtual double value (const Point &p, const unsigned int component=0) const; }; @@ -73,7 +76,7 @@ class ExactU : public Function public: ExactU (unsigned int PROBLEM, double time=0) : Function(), PROBLEM(PROBLEM), time(time) {} virtual double value (const Point &p, const unsigned int component=0) const; - void set_time(double time){this->time=time;}; + void set_time(double time) {this->time=time;}; unsigned PROBLEM; double time; }; @@ -93,7 +96,7 @@ class ExactV : public Function public: ExactV (unsigned int PROBLEM, double time=0) : Function(), PROBLEM(PROBLEM), time(time) {} virtual double value (const Point &p, const unsigned int component=0) const; - void set_time(double time){this->time=time;}; + void set_time(double time) {this->time=time;}; unsigned int PROBLEM; double time; }; @@ -113,7 +116,7 @@ class ExactW : public Function public: ExactW (unsigned int PROBLEM, double time=0) : Function(), PROBLEM(PROBLEM), time(time) {} virtual double value (const Point &p, const unsigned int component=0) const; - void set_time(double time){this->time=time;}; + void set_time(double time) {this->time=time;}; unsigned int PROBLEM; double time; }; diff --git a/two_phase_flow/utilities_test_NS.cc b/two_phase_flow/utilities_test_NS.cc index 9fda324..85302b0 100644 --- a/two_phase_flow/utilities_test_NS.cc +++ b/two_phase_flow/utilities_test_NS.cc @@ -5,12 +5,12 @@ template class RhoFunction : public Function { public: - RhoFunction (double t=0) : Function(){this->set_time(t);} + RhoFunction (double t=0) : Function() {this->set_time(t);} virtual double value (const Point &p, const unsigned int component=0) const; }; template double RhoFunction::value (const Point &p, - const unsigned int) const + const unsigned int) const { double t = this->get_time(); double return_value = 0; @@ -25,7 +25,7 @@ template class NuFunction : public Function { public: - NuFunction (double t=0) : Function(){this->set_time(t);} + NuFunction (double t=0) : Function() {this->set_time(t);} virtual double value (const Point &p, const unsigned int component=0) const; }; template @@ -41,9 +41,9 @@ template class ExactSolution_and_BC_U : public Function { public: - ExactSolution_and_BC_U (double t=0, int field=0) - : - Function(), + ExactSolution_and_BC_U (double t=0, int field=0) + : + Function(), field(field) { this->set_time(t); @@ -56,70 +56,75 @@ public: }; template double ExactSolution_and_BC_U::value (const Point &p, - const unsigned int) const + const unsigned int) const { double t = this->get_time(); double return_value = 0; double Pi = numbers::PI; - double x = p[0]; double y = p[1]; double z = 0; + double x = p[0]; + double y = p[1]; + double z = 0; if (dim == 2) if (field == 0) return_value = std::sin(x)*std::sin(y+t); else - return_value = std::cos(x)*std::cos(y+t); + return_value = std::cos(x)*std::cos(y+t); else //dim=3 { z = p[2]; if (field == 0) - return_value = std::cos(t)*std::cos(Pi*y)*std::cos(Pi*z)*std::sin(Pi*x); + return_value = std::cos(t)*std::cos(Pi*y)*std::cos(Pi*z)*std::sin(Pi*x); else if (field == 1) - return_value = std::cos(t)*std::cos(Pi*x)*std::cos(Pi*z)*std::sin(Pi*y); + return_value = std::cos(t)*std::cos(Pi*x)*std::cos(Pi*z)*std::sin(Pi*y); else - return_value = -2*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::sin(Pi*z); + return_value = -2*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::sin(Pi*z); } - return return_value; + return return_value; } template Tensor<1,dim> ExactSolution_and_BC_U::gradient (const Point &p, - const unsigned int) const -{ // THIS IS USED JUST FOR TESTING NS + const unsigned int) const +{ + // THIS IS USED JUST FOR TESTING NS Tensor<1,dim> return_value; double t = this->get_time(); double Pi = numbers::PI; - double x = p[0]; double y = p[1]; double z = 0; + double x = p[0]; + double y = p[1]; + double z = 0; if (dim == 2) if (field == 0) { - return_value[0] = std::cos(x)*std::sin(y+t); - return_value[1] = std::sin(x)*std::cos(y+t); + return_value[0] = std::cos(x)*std::sin(y+t); + return_value[1] = std::sin(x)*std::cos(y+t); } - else + else { - return_value[0] = -std::sin(x)*std::cos(y+t); - return_value[1] = -std::cos(x)*std::sin(y+t); + return_value[0] = -std::sin(x)*std::cos(y+t); + return_value[1] = -std::cos(x)*std::sin(y+t); } else //dim=3 { z=p[2]; if (field == 0) - { - return_value[0] = Pi*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::cos(Pi*z); - return_value[1] = -(Pi*std::cos(t)*std::cos(Pi*z)*std::sin(Pi*x)*std::sin(Pi*y)); - return_value[2] = -(Pi*std::cos(t)*std::cos(Pi*y)*std::sin(Pi*x)*std::sin(Pi*z)); - } + { + return_value[0] = Pi*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::cos(Pi*z); + return_value[1] = -(Pi*std::cos(t)*std::cos(Pi*z)*std::sin(Pi*x)*std::sin(Pi*y)); + return_value[2] = -(Pi*std::cos(t)*std::cos(Pi*y)*std::sin(Pi*x)*std::sin(Pi*z)); + } else if (field == 1) - { - return_value[0] = -(Pi*std::cos(t)*std::cos(Pi*z)*std::sin(Pi*x)*std::sin(Pi*y)); - return_value[1] = Pi*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::cos(Pi*z); - return_value[2] = -(Pi*std::cos(t)*std::cos(Pi*x)*std::sin(Pi*y)*std::sin(Pi*z)); - } + { + return_value[0] = -(Pi*std::cos(t)*std::cos(Pi*z)*std::sin(Pi*x)*std::sin(Pi*y)); + return_value[1] = Pi*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::cos(Pi*z); + return_value[2] = -(Pi*std::cos(t)*std::cos(Pi*x)*std::sin(Pi*y)*std::sin(Pi*z)); + } else - { - return_value[0] = 2*Pi*std::cos(t)*std::cos(Pi*y)*std::sin(Pi*x)*std::sin(Pi*z); - return_value[1] = 2*Pi*std::cos(t)*std::cos(Pi*x)*std::sin(Pi*y)*std::sin(Pi*z); - return_value[2] = -2*Pi*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::cos(Pi*z); - } + { + return_value[0] = 2*Pi*std::cos(t)*std::cos(Pi*y)*std::sin(Pi*x)*std::sin(Pi*z); + return_value[1] = 2*Pi*std::cos(t)*std::cos(Pi*x)*std::sin(Pi*y)*std::sin(Pi*z); + return_value[2] = -2*Pi*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::cos(Pi*z); + } } return return_value; } @@ -131,7 +136,7 @@ template class ExactSolution_p : public Function { public: - ExactSolution_p (double t=0) : Function(){this->set_time(t);} + ExactSolution_p (double t=0) : Function() {this->set_time(t);} virtual double value (const Point &p, const unsigned int component=0) const; virtual Tensor<1,dim> gradient (const Point &p, const unsigned int component = 0) const; }; @@ -174,9 +179,9 @@ template class ForceTerms : public Function { public: - ForceTerms (double t=0) - : - Function() + ForceTerms (double t=0) + : + Function() { this->set_time(t); nu = 1.; @@ -187,42 +192,44 @@ public: template void ForceTerms::vector_value (const Point &p, Vector &values) const -{ - double x = p[0]; double y = p[1]; double z = 0; +{ + double x = p[0]; + double y = p[1]; + double z = 0; double t = this->get_time(); double Pi = numbers::PI; - + if (dim == 2) { // force in x values[0] = std::cos(t+y)*std::sin(x)*(1+std::pow(std::sin(t+x+y),2)) // time derivative - +2*nu*std::sin(x)*std::sin(t+y) // viscosity - +std::cos(x)*std::sin(x)*(1+std::pow(std::sin(t+x+y),2)) // non-linearity - -std::sin(x)*std::sin(y+t); // pressure - // force in y + +2*nu*std::sin(x)*std::sin(t+y) // viscosity + +std::cos(x)*std::sin(x)*(1+std::pow(std::sin(t+x+y),2)) // non-linearity + -std::sin(x)*std::sin(y+t); // pressure + // force in y values[1] = -(std::cos(x)*std::sin(t+y)*(1+std::pow(std::sin(t+x+y),2))) // time derivative - +2*nu*std::cos(x)*std::cos(t+y) // viscosity - -(std::sin(2*(t+y))*(1+std::pow(std::sin(t+x+y),2)))/2. // non-linearity - +std::cos(x)*std::cos(y+t); // pressure + +2*nu*std::cos(x)*std::cos(t+y) // viscosity + -(std::sin(2*(t+y))*(1+std::pow(std::sin(t+x+y),2)))/2. // non-linearity + +std::cos(x)*std::cos(y+t); // pressure } else //3D { z = p[2]; // force in x values[0]= - -(std::cos(Pi*y)*std::cos(Pi*z)*std::sin(t)*std::sin(Pi*x)*(1+std::pow(std::sin(t+x+y+z),2))) //time der. - +3*std::pow(Pi,2)*std::cos(t)*std::cos(Pi*y)*std::cos(Pi*z)*std::sin(Pi*x) //viscosity - -(Pi*std::pow(std::cos(t),2)*(-3+std::cos(2*(t+x+y+z)))*std::sin(2*Pi*x)*(std::cos(2*Pi*y)+std::pow(std::sin(Pi*z),2)))/4. //NL - +std::cos(t+x+y+z); // pressure + -(std::cos(Pi*y)*std::cos(Pi*z)*std::sin(t)*std::sin(Pi*x)*(1+std::pow(std::sin(t+x+y+z),2))) //time der. + +3*std::pow(Pi,2)*std::cos(t)*std::cos(Pi*y)*std::cos(Pi*z)*std::sin(Pi*x) //viscosity + -(Pi*std::pow(std::cos(t),2)*(-3+std::cos(2*(t+x+y+z)))*std::sin(2*Pi*x)*(std::cos(2*Pi*y)+std::pow(std::sin(Pi*z),2)))/4. //NL + +std::cos(t+x+y+z); // pressure values[1]= - -(std::cos(Pi*x)*std::cos(Pi*z)*std::sin(t)*std::sin(Pi*y)*(1+std::pow(std::sin(t+x+y+z),2))) //time der - +3*std::pow(Pi,2)*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*z)*std::sin(Pi*y) //viscosity - -(Pi*std::pow(std::cos(t),2)*(-3+std::cos(2*(t+x+y+z)))*std::sin(2*Pi*y)*(std::cos(2*Pi*x)+std::pow(std::sin(Pi*z),2)))/4. //NL - +std::cos(t+x+y+z); // pressure + -(std::cos(Pi*x)*std::cos(Pi*z)*std::sin(t)*std::sin(Pi*y)*(1+std::pow(std::sin(t+x+y+z),2))) //time der + +3*std::pow(Pi,2)*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*z)*std::sin(Pi*y) //viscosity + -(Pi*std::pow(std::cos(t),2)*(-3+std::cos(2*(t+x+y+z)))*std::sin(2*Pi*y)*(std::cos(2*Pi*x)+std::pow(std::sin(Pi*z),2)))/4. //NL + +std::cos(t+x+y+z); // pressure values[2]= - 2*std::cos(Pi*x)*std::cos(Pi*y)*std::sin(t)*std::sin(Pi*z)*(1+std::pow(std::sin(t+x+y+z),2)) //time der - -6*std::pow(Pi,2)*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::sin(Pi*z) //viscosity - -(Pi*std::pow(std::cos(t),2)*(2+std::cos(2*Pi*x)+std::cos(2*Pi*y))*(-3+std::cos(2*(t+x+y+z)))*std::sin(2*Pi*z))/4. //NL - +std::cos(t+x+y+z); // pressure + 2*std::cos(Pi*x)*std::cos(Pi*y)*std::sin(t)*std::sin(Pi*z)*(1+std::pow(std::sin(t+x+y+z),2)) //time der + -6*std::pow(Pi,2)*std::cos(t)*std::cos(Pi*x)*std::cos(Pi*y)*std::sin(Pi*z) //viscosity + -(Pi*std::pow(std::cos(t),2)*(2+std::cos(2*Pi*x)+std::cos(2*Pi*y))*(-3+std::cos(2*(t+x+y+z)))*std::sin(2*Pi*z))/4. //NL + +std::cos(t+x+y+z); // pressure } }