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().
*/
// 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<int dim>
-struct InnerPreconditioner;
+ template<int dim>
+ struct InnerPreconditioner;
-template<>
-struct InnerPreconditioner<2> {
- typedef SparseDirectUMFPACK type;
-};
+ template<>
+ struct InnerPreconditioner<2>
+ {
+ typedef SparseDirectUMFPACK type;
+ };
-template<>
-struct InnerPreconditioner<3> {
- typedef SparseILU<double> type;
-};
+ template<>
+ struct InnerPreconditioner<3>
+ {
+ typedef SparseILU<double> type;
+ };
// Auxiliary functions
-template<int dim>
-class AuxFunctions {
-public:
- Tensor<2, 2> get_rotation_matrix(const std::vector<Tensor<1, 2> > &grad_u);
-};
-
-template<int dim>
-Tensor<2, 2> AuxFunctions<dim>::get_rotation_matrix(
- const std::vector<Tensor<1, 2> > &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<int dim>
+ class AuxFunctions
+ {
+ public:
+ Tensor<2, 2> get_rotation_matrix(const std::vector<Tensor<1, 2> > &grad_u);
+ };
+
+ template<int dim>
+ Tensor<2, 2> AuxFunctions<dim>::get_rotation_matrix(
+ const std::vector<Tensor<1, 2> > &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<int dim>
-struct PointHistory {
- SymmetricTensor<2, dim> old_stress;
- double old_phiphi_stress;
- double first_eta;
- double new_eta;
- double G;
-};
+ template<int dim>
+ 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<int dim>
-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<bool> 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<dim> triangulation;
- const MappingQ1<dim> mapping;
- FESystem<dim> fe;
- DoFHandler<dim> dof_handler;
- unsigned int n_u = 0, n_p = 0;
- unsigned int plastic_iteration = 0;
- unsigned int last_max_plasticity = 0;
-
- QGauss<dim> quadrature_formula;
- std::vector< std::vector <Vector<double> > > quad_viscosities; // Indices for this object are [cell][q][q coords, eta]
- std::vector<double> cell_viscosities; // This vector is only used for output, not FE computations
- std::vector<PointHistory<dim> > quadrature_point_history;
-
- ConstraintMatrix constraints;
-
- BlockSparsityPattern sparsity_pattern;
- BlockSparseMatrix<double> system_matrix;
-
- BlockVector<double> solution;
- BlockVector<double> system_rhs;
-
- std::shared_ptr<typename InnerPreconditioner<dim>::type> A_preconditioner;
-
- ellipsoid_fit<dim> ellipsoid;
-};
+ template<int dim>
+ 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<bool> 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<dim> triangulation;
+ const MappingQ1<dim> mapping;
+ FESystem<dim> fe;
+ DoFHandler<dim> dof_handler;
+ unsigned int n_u = 0, n_p = 0;
+ unsigned int plastic_iteration = 0;
+ unsigned int last_max_plasticity = 0;
+
+ QGauss<dim> quadrature_formula;
+ std::vector< std::vector <Vector<double> > > quad_viscosities; // Indices for this object are [cell][q][q coords, eta]
+ std::vector<double> cell_viscosities; // This vector is only used for output, not FE computations
+ std::vector<PointHistory<dim> > quadrature_point_history;
+
+ ConstraintMatrix constraints;
+
+ BlockSparsityPattern sparsity_pattern;
+ BlockSparseMatrix<double> system_matrix;
+
+ BlockVector<double> solution;
+ BlockVector<double> system_rhs;
+
+ std::shared_ptr<typename InnerPreconditioner<dim>::type> A_preconditioner;
+
+ ellipsoid_fit<dim> ellipsoid;
+ };
// Class for boundary conditions and rhs
-template<int dim>
-class BoundaryValuesP: public Function<dim> {
-public:
- BoundaryValuesP() :
- Function<dim>(dim + 1) {
- }
-
- virtual double value(const Point<dim> &p,
- const unsigned int component = 0) const;
-
- virtual void vector_value(const Point<dim> &p, Vector<double> &value) const;
-};
-
-template<int dim>
-double BoundaryValuesP<dim>::value(const Point<dim> &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<int dim>
-void BoundaryValuesP<dim>::vector_value(const Point<dim> &p,
- Vector<double> &values) const {
- for (unsigned int c = 0; c < this->n_components; ++c)
- values(c) = BoundaryValuesP<dim>::value(p, c);
-}
-
-template<int dim>
-class RightHandSide: public Function<dim> {
-public:
- RightHandSide () : Function<dim>(dim+1) {}
+ template<int dim>
+ class BoundaryValuesP: public Function<dim>
+ {
+ public:
+ BoundaryValuesP() :
+ Function<dim>(dim + 1)
+ {
+ }
+
+ virtual double value(const Point<dim> &p,
+ const unsigned int component = 0) const;
+
+ virtual void vector_value(const Point<dim> &p, Vector<double> &value) const;
+ };
+
+ template<int dim>
+ double BoundaryValuesP<dim>::value(const Point<dim> &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<int dim>
+ void BoundaryValuesP<dim>::vector_value(const Point<dim> &p,
+ Vector<double> &values) const
+ {
+ for (unsigned int c = 0; c < this->n_components; ++c)
+ values(c) = BoundaryValuesP<dim>::value(p, c);
+ }
+
+ template<int dim>
+ class RightHandSide: public Function<dim>
+ {
+ public:
+ RightHandSide () : Function<dim>(dim+1) {}
using Function<dim>::value;
using Function<dim>::vector_value;
using Function<dim>::vector_value_list;
- virtual double value(const Point<dim> &p, const unsigned int component,
- A_Grav_namespace::AnalyticGravity<dim> *aGrav) const;
-
- virtual void vector_value(const Point<dim> &p, Vector<double> &value,
- A_Grav_namespace::AnalyticGravity<dim> *aGrav) const;
-
- virtual void vector_value_list(const std::vector<Point<dim> > &points,
- std::vector<Vector<double> > &values,
- A_Grav_namespace::AnalyticGravity<dim> *aGrav) const;
-
-};
-
-template<int dim>
-double RightHandSide<dim>::value(const Point<dim> &p,
- const unsigned int component,
- A_Grav_namespace::AnalyticGravity<dim> *aGrav) const {
-
- std::vector<double> 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<int dim>
-void RightHandSide<dim>::vector_value(const Point<dim> &p,
- Vector<double> &values,
- A_Grav_namespace::AnalyticGravity<dim> *aGrav) const {
- for (unsigned int c = 0; c < this->n_components; ++c)
- values(c) = RightHandSide<dim>::value(p, c, aGrav);
-}
-
-template<int dim>
-void RightHandSide<dim>::vector_value_list(
- const std::vector<Point<dim> > &points,
- std::vector<Vector<double> > &values,
- A_Grav_namespace::AnalyticGravity<dim> *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<dim> &p, const unsigned int component,
+ A_Grav_namespace::AnalyticGravity<dim> *aGrav) const;
+
+ virtual void vector_value(const Point<dim> &p, Vector<double> &value,
+ A_Grav_namespace::AnalyticGravity<dim> *aGrav) const;
+
+ virtual void vector_value_list(const std::vector<Point<dim> > &points,
+ std::vector<Vector<double> > &values,
+ A_Grav_namespace::AnalyticGravity<dim> *aGrav) const;
+
+ };
+
+ template<int dim>
+ double RightHandSide<dim>::value(const Point<dim> &p,
+ const unsigned int component,
+ A_Grav_namespace::AnalyticGravity<dim> *aGrav) const
+ {
+
+ std::vector<double> 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<int dim>
+ void RightHandSide<dim>::vector_value(const Point<dim> &p,
+ Vector<double> &values,
+ A_Grav_namespace::AnalyticGravity<dim> *aGrav) const
+ {
+ for (unsigned int c = 0; c < this->n_components; ++c)
+ values(c) = RightHandSide<dim>::value(p, c, aGrav);
+ }
+
+ template<int dim>
+ void RightHandSide<dim>::vector_value_list(
+ const std::vector<Point<dim> > &points,
+ std::vector<Vector<double> > &values,
+ A_Grav_namespace::AnalyticGravity<dim> *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 Matrix, class Preconditioner>
-class InverseMatrix: public Subscriptor {
-public:
- InverseMatrix(const Matrix &m, const Preconditioner &preconditioner);
+ template<class Matrix, class Preconditioner>
+ class InverseMatrix: public Subscriptor
+ {
+ public:
+ InverseMatrix(const Matrix &m, const Preconditioner &preconditioner);
- void vmult(Vector<double> &dst, const Vector<double> &src) const;
+ void vmult(Vector<double> &dst, const Vector<double> &src) const;
-private:
- const SmartPointer<const Matrix> matrix;
- const SmartPointer<const Preconditioner> preconditioner;
-};
+ private:
+ const SmartPointer<const Matrix> matrix;
+ const SmartPointer<const Preconditioner> preconditioner;
+ };
-template<class Matrix, class Preconditioner>
-InverseMatrix<Matrix, Preconditioner>::InverseMatrix(const Matrix &m,
- const Preconditioner &preconditioner) :
- matrix(&m), preconditioner(&preconditioner) {
-}
+ template<class Matrix, class Preconditioner>
+ InverseMatrix<Matrix, Preconditioner>::InverseMatrix(const Matrix &m,
+ const Preconditioner &preconditioner) :
+ matrix(&m), preconditioner(&preconditioner)
+ {
+ }
-template<class Matrix, class Preconditioner>
-void InverseMatrix<Matrix, Preconditioner>::vmult(Vector<double> &dst,
- const Vector<double> &src) const {
- SolverControl solver_control(1000 * src.size(), 1e-9 * src.l2_norm());
+ template<class Matrix, class Preconditioner>
+ void InverseMatrix<Matrix, Preconditioner>::vmult(Vector<double> &dst,
+ const Vector<double> &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 Preconditioner>
-class SchurComplement: public Subscriptor {
-public:
- SchurComplement(const BlockSparseMatrix<double> &system_matrix,
- const InverseMatrix<SparseMatrix<double>, Preconditioner> &A_inverse);
-
- void vmult(Vector<double> &dst, const Vector<double> &src) const;
-
-private:
- const SmartPointer<const BlockSparseMatrix<double> > system_matrix;
- const SmartPointer<const InverseMatrix<SparseMatrix<double>, Preconditioner> > A_inverse;
-
- mutable Vector<double> tmp1, tmp2;
-};
-
-template<class Preconditioner>
-SchurComplement<Preconditioner>::SchurComplement(
- const BlockSparseMatrix<double> &system_matrix,
- const InverseMatrix<SparseMatrix<double>, 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<class Preconditioner>
-void SchurComplement<Preconditioner>::vmult(Vector<double> &dst,
- const Vector<double> &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 Preconditioner>
+ class SchurComplement: public Subscriptor
+ {
+ public:
+ SchurComplement(const BlockSparseMatrix<double> &system_matrix,
+ const InverseMatrix<SparseMatrix<double>, Preconditioner> &A_inverse);
+
+ void vmult(Vector<double> &dst, const Vector<double> &src) const;
+
+ private:
+ const SmartPointer<const BlockSparseMatrix<double> > system_matrix;
+ const SmartPointer<const InverseMatrix<SparseMatrix<double>, Preconditioner> > A_inverse;
+
+ mutable Vector<double> tmp1, tmp2;
+ };
+
+ template<class Preconditioner>
+ SchurComplement<Preconditioner>::SchurComplement(
+ const BlockSparseMatrix<double> &system_matrix,
+ const InverseMatrix<SparseMatrix<double>, 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<class Preconditioner>
+ void SchurComplement<Preconditioner>::vmult(Vector<double> &dst,
+ const Vector<double> &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<int dim>
-StokesProblem<dim>::StokesProblem(const unsigned int degree) :
- degree(degree),
- triangulation(Triangulation<dim>::maximum_smoothing),
- mapping(),
- fe(FE_Q<dim>(degree + 1), dim, FE_Q<dim>(degree), 1),
- dof_handler(triangulation),
- quadrature_formula(degree + 2),
- ellipsoid(&triangulation)
- {}
+ template<int dim>
+ StokesProblem<dim>::StokesProblem(const unsigned int degree) :
+ degree(degree),
+ triangulation(Triangulation<dim>::maximum_smoothing),
+ mapping(),
+ fe(FE_Q<dim>(degree + 1), dim, FE_Q<dim>(degree), 1),
+ dof_handler(triangulation),
+ quadrature_formula(degree + 2),
+ ellipsoid(&triangulation)
+ {}
// Set up dofs
-template<int dim>
-void StokesProblem<dim>::setup_dofs() {
- A_preconditioner.reset();
- system_matrix.clear();
+ template<int dim>
+ void StokesProblem<dim>::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<unsigned int> block_component(dim + 1, 0);
- block_component[dim] = 1;
- DoFRenumbering::component_wise(dof_handler, block_component);
+ std::vector<unsigned int> block_component(dim + 1, 0);
+ block_component[dim] = 1;
+ DoFRenumbering::component_wise(dof_handler, block_component);
//========================================Apply Boundary Conditions=====================================
- {
- constraints.clear();
- std::vector<bool> 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<dim>(), constraints, component_maskP);
- }
- {
- std::set<types::boundary_id> 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<types::global_dof_index> 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<bool> 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<dim>(), constraints, component_maskP);
+ }
+ {
+ std::set<types::boundary_id> 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<types::global_dof_index> 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<int dim>
-class Rheology {
-public:
- double get_eta(double &r, double &z);
- double get_G(unsigned int mat_id);
-
-private:
- std::vector<double> get_manual_eta_profile();
-
-};
-
-template<int dim>
-std::vector<double> Rheology<dim>::get_manual_eta_profile()
-{
- vector<double> 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<int dim>
-double Rheology<dim>::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<double> 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<int dim>
-double Rheology<dim>::get_G(unsigned int mat_id)
-{
- return system_parameters::G[mat_id];
-}
+ template<int dim>
+ class Rheology
+ {
+ public:
+ double get_eta(double &r, double &z);
+ double get_G(unsigned int mat_id);
+
+ private:
+ std::vector<double> get_manual_eta_profile();
+
+ };
+
+ template<int dim>
+ std::vector<double> Rheology<dim>::get_manual_eta_profile()
+ {
+ vector<double> 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<int dim>
+ double Rheology<dim>::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<double> 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<int dim>
+ double Rheology<dim>::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<int dim>
-void StokesProblem<dim>::initialize_eta_and_G() {
- FEValues<dim> fe_values(fe, quadrature_formula, update_quadrature_points);
+ template<int dim>
+ void StokesProblem<dim>::initialize_eta_and_G()
+ {
+ FEValues<dim> fe_values(fe, quadrature_formula, update_quadrature_points);
- const unsigned int n_q_points = quadrature_formula.size();
- Rheology<dim> rheology;
+ const unsigned int n_q_points = quadrature_formula.size();
+ Rheology<dim> rheology;
- for (typename DoFHandler<dim>::active_cell_iterator cell =
- dof_handler.begin_active(); cell != dof_handler.end(); ++cell) {
- PointHistory<dim> *local_quadrature_points_history =
- reinterpret_cast<PointHistory<dim> *>(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<dim>::active_cell_iterator cell =
+ dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
+ {
+ PointHistory<dim> *local_quadrature_points_history =
+ reinterpret_cast<PointHistory<dim> *>(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<int dim>
-void StokesProblem<dim>::assemble_system() {
- system_matrix = 0;
- system_rhs = 0;
-
- FEValues<dim> 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<double> local_matrix(dofs_per_cell, dofs_per_cell);
- Vector<double> local_rhs(dofs_per_cell);
-
- std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
-
- // runs the gravity script function
- const RightHandSide<dim> right_hand_side;
-
- A_Grav_namespace::AnalyticGravity<dim> * aGrav =
- new A_Grav_namespace::AnalyticGravity<dim>;
- std::vector<double> 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<Vector<double> > rhs_values(n_q_points,
- Vector<double>(dim + 1));
-
- const FEValuesExtractors::Vector velocities(0);
- const FEValuesExtractors::Scalar pressure(dim);
-
- std::vector<SymmetricTensor<2, dim> > phi_grads_u(dofs_per_cell);
- std::vector<double> div_phi_u(dofs_per_cell);
- std::vector<Tensor<1, dim> > phi_u(dofs_per_cell);
- std::vector<double> phi_p(dofs_per_cell);
-
- typename DoFHandler<dim>::active_cell_iterator cell =
- dof_handler.begin_active(), first_cell = dof_handler.begin_active(),
- endc = dof_handler.end();
-
- for (; cell != endc; ++cell) {
- PointHistory<dim> *local_quadrature_points_history =
- reinterpret_cast<PointHistory<dim> *>(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<Vector<double> > new_viscosities(quadrature_formula.size(), Vector<double>(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<dim>::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<Point<dim> > 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<Point<dim> > 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<int dim>
+ void StokesProblem<dim>::assemble_system()
+ {
+ system_matrix = 0;
+ system_rhs = 0;
+
+ FEValues<dim> 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<double> local_matrix(dofs_per_cell, dofs_per_cell);
+ Vector<double> local_rhs(dofs_per_cell);
+
+ std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
+
+ // runs the gravity script function
+ const RightHandSide<dim> right_hand_side;
+
+ A_Grav_namespace::AnalyticGravity<dim> *aGrav =
+ new A_Grav_namespace::AnalyticGravity<dim>;
+ std::vector<double> 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<Vector<double> > rhs_values(n_q_points,
+ Vector<double>(dim + 1));
+
+ const FEValuesExtractors::Vector velocities(0);
+ const FEValuesExtractors::Scalar pressure(dim);
+
+ std::vector<SymmetricTensor<2, dim> > phi_grads_u(dofs_per_cell);
+ std::vector<double> div_phi_u(dofs_per_cell);
+ std::vector<Tensor<1, dim> > phi_u(dofs_per_cell);
+ std::vector<double> phi_p(dofs_per_cell);
+
+ typename DoFHandler<dim>::active_cell_iterator cell =
+ dof_handler.begin_active(), first_cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+
+ for (; cell != endc; ++cell)
+ {
+ PointHistory<dim> *local_quadrature_points_history =
+ reinterpret_cast<PointHistory<dim> *>(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<Vector<double> > new_viscosities(quadrature_formula.size(), Vector<double>(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<dim>::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<Point<dim> > 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<Point<dim> > 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<dim>::type>(
- new typename InnerPreconditioner<dim>::type());
- A_preconditioner->initialize(system_matrix.block(0, 0),
- typename InnerPreconditioner<dim>::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<dim>::type>(
+ new typename InnerPreconditioner<dim>::type());
+ A_preconditioner->initialize(system_matrix.block(0, 0),
+ typename InnerPreconditioner<dim>::type::AdditionalData());
+
+ delete aGrav;
+ }
//====================== SOLVER ======================
-template<int dim>
-void StokesProblem<dim>::solve() {
- const InverseMatrix<SparseMatrix<double>,
- typename InnerPreconditioner<dim>::type> A_inverse(
- system_matrix.block(0, 0), *A_preconditioner);
- Vector<double> tmp(solution.block(0).size());
+ template<int dim>
+ void StokesProblem<dim>::solve()
+ {
+ const InverseMatrix<SparseMatrix<double>,
+ typename InnerPreconditioner<dim>::type> A_inverse(
+ system_matrix.block(0, 0), *A_preconditioner);
+ Vector<double> tmp(solution.block(0).size());
- {
- Vector<double> 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<double> 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<typename InnerPreconditioner<dim>::type> schur_complement(
- system_matrix, A_inverse);
+ SchurComplement<typename InnerPreconditioner<dim>::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<double> preconditioner;
- preconditioner.initialize(system_matrix.block(1, 1),
- SparseILU<double>::AdditionalData());
+ SparseILU<double> preconditioner;
+ preconditioner.initialize(system_matrix.block(1, 1),
+ SparseILU<double>::AdditionalData());
- InverseMatrix<SparseMatrix<double>, SparseILU<double> > m_inverse(
- system_matrix.block(1, 1), preconditioner);
+ InverseMatrix<SparseMatrix<double>, SparseILU<double> > 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<int dim>
-void StokesProblem<dim>::output_results() const {
- std::vector < std::string > solution_names(dim, "velocity");
- solution_names.push_back("pressure");
-
- std::vector<DataComponentInterpretation::DataComponentInterpretation> data_component_interpretation(
- dim, DataComponentInterpretation::component_is_part_of_vector);
- data_component_interpretation.push_back(
- DataComponentInterpretation::component_is_scalar);
-
- DataOut<dim> data_out;
- data_out.attach_dof_handler(dof_handler);
- data_out.add_data_vector(solution, solution_names,
- DataOut<dim>::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<int dim>
+ void StokesProblem<dim>::output_results() const
+ {
+ std::vector < std::string > solution_names(dim, "velocity");
+ solution_names.push_back("pressure");
+
+ std::vector<DataComponentInterpretation::DataComponentInterpretation> data_component_interpretation(
+ dim, DataComponentInterpretation::component_is_part_of_vector);
+ data_component_interpretation.push_back(
+ DataComponentInterpretation::component_is_scalar);
+
+ DataOut<dim> data_out;
+ data_out.attach_dof_handler(dof_handler);
+ data_out.add_data_vector(solution, solution_names,
+ DataOut<dim>::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<int dim>
-void StokesProblem<dim>::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<Point<dim> > points_list(0);
- std::vector<unsigned int> material_list(0);
- typename DoFHandler<dim>::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<dim> 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<Tensor<1, dim> >> velocity_grads(quadrature_formula.size(),
- std::vector < Tensor<1, dim> > (dim + 1));
- std::vector<Vector<double> > velocities(quadrature_formula.size(),
- Vector<double>(dim + 1));
- // Make the object to find rheology
- Rheology<dim> rheology;
-
- // Write the solution flow velocity and derivative for each cell
- std::vector<Vector<double> > vector_values(0);
- std::vector < std::vector<Tensor<1, dim> > > gradient_values(0);
- std::vector<bool> failing_cells;
- // Write the stresses from the previous step into vectors
- std::vector<SymmetricTensor<2, dim>> old_stress;
- std::vector<double> old_phiphi_stress;
- std::vector<double> cell_Gs;
- for (typename DoFHandler<dim>::active_cell_iterator cell =
- dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
- {
- // Makes pointer to data in quadrature_point_history
- PointHistory<dim> *local_quadrature_points_history =
- reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
-
- fe_values.reinit(cell);
- fe_values.get_function_gradients(solution, velocity_grads);
- fe_values.get_function_values(solution, velocities);
- Vector<double> current_cell_velocity(dim+1);
- std::vector<Tensor<1, dim>> 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<double> 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<dim>::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<dim> *local_quadrature_points_history =
- reinterpret_cast<PointHistory<dim> *>(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<dim; ii++)
- quad_viscosities[cell_no][q](ii) = fe_values.quadrature_point(q)[ii];
- quad_viscosities[cell_no][q](dim) = local_quadrature_points_history[q].new_eta;
- }
- cell_no++;
- }
- smooth_eta_field(failing_cells);
-
- // Writes to file the smoothed eta field (which is defined at each quadrature point) for each cell
- cell_no = 0;
-// cell_viscosities.resize(triangulation.n_active_cells(), 0);
- for (typename DoFHandler<dim>::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<int dim>
+ void StokesProblem<dim>::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<Point<dim> > points_list(0);
+ std::vector<unsigned int> material_list(0);
+ typename DoFHandler<dim>::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<dim> 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<Tensor<1, dim> >> velocity_grads(quadrature_formula.size(),
+ std::vector < Tensor<1, dim> > (dim + 1));
+ std::vector<Vector<double> > velocities(quadrature_formula.size(),
+ Vector<double>(dim + 1));
+ // Make the object to find rheology
+ Rheology<dim> rheology;
+
+ // Write the solution flow velocity and derivative for each cell
+ std::vector<Vector<double> > vector_values(0);
+ std::vector < std::vector<Tensor<1, dim> > > gradient_values(0);
+ std::vector<bool> failing_cells;
+ // Write the stresses from the previous step into vectors
+ std::vector<SymmetricTensor<2, dim>> old_stress;
+ std::vector<double> old_phiphi_stress;
+ std::vector<double> cell_Gs;
+ for (typename DoFHandler<dim>::active_cell_iterator cell =
+ dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
+ {
+ // Makes pointer to data in quadrature_point_history
+ PointHistory<dim> *local_quadrature_points_history =
+ reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
+
+ fe_values.reinit(cell);
+ fe_values.get_function_gradients(solution, velocity_grads);
+ fe_values.get_function_values(solution, velocities);
+ Vector<double> current_cell_velocity(dim+1);
+ std::vector<Tensor<1, dim>> 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<double> 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<dim>::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<dim> *local_quadrature_points_history =
+ reinterpret_cast<PointHistory<dim> *>(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<dim; ii++)
+ quad_viscosities[cell_no][q](ii) = fe_values.quadrature_point(q)[ii];
+ quad_viscosities[cell_no][q](dim) = local_quadrature_points_history[q].new_eta;
+ }
+ cell_no++;
+ }
+ smooth_eta_field(failing_cells);
+
+ // Writes to file the smoothed eta field (which is defined at each quadrature point) for each cell
+ cell_no = 0;
+// cell_viscosities.resize(triangulation.n_active_cells(), 0);
+ for (typename DoFHandler<dim>::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<int dim>
-void StokesProblem<dim>::smooth_eta_field(std::vector<bool> failing_cells)
-{
- std::cout << " Smoothing viscosity field...\n";
- unsigned int cell_no = 0;
- for (typename DoFHandler<dim>::active_cell_iterator cell =
- dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
- {
- if(failing_cells[cell_no])
- {
- FEValues<dim> fe_values(fe, quadrature_formula, update_quadrature_points);
- PointHistory<dim> *local_quadrature_points_history =
- reinterpret_cast<PointHistory<dim> *>(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<bool> cell_touched(triangulation.n_active_cells(), false);
- std::vector< TriaIterator< CellAccessor<dim> > > neighbor_cells;
- std::vector<int> 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<neighbor_cells.size(); i++)
- {
- for (unsigned int f = 0; f < GeometryInfo<dim>::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<double> nearby_etas_q;
- for (unsigned int i = 0; i<neighbor_indices.size(); i++)
- for (unsigned int j=0; j<quadrature_formula.size(); j++)
- {
- Point<dim> test_q;
- for(unsigned int d=0; d<dim; d++)
- test_q(d) = quad_viscosities[neighbor_indices[i]][j][d];
- double qq_distance = fe_values.quadrature_point(q).distance(test_q);
- if(qq_distance < system_parameters::smoothing_radius)
- nearby_etas_q.push_back(quad_viscosities[neighbor_indices[i]][j][dim]);
- }
- // Write smoothed viscosities to quadrature_points_history; simple boxcar function is the smoothing kernel
- double mean_eta = 0;
- for(unsigned int l = 0; l<nearby_etas_q.size(); l++)
- {
- mean_eta += nearby_etas_q[l];
- }
- mean_eta /= nearby_etas_q.size();
- local_quadrature_points_history[q].new_eta = mean_eta;
-// std::cout << local_quadrature_points_history[q].new_eta << " ";
- }
- }
- cell_no++;
- }
-}
+ template<int dim>
+ void StokesProblem<dim>::smooth_eta_field(std::vector<bool> failing_cells)
+ {
+ std::cout << " Smoothing viscosity field...\n";
+ unsigned int cell_no = 0;
+ for (typename DoFHandler<dim>::active_cell_iterator cell =
+ dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
+ {
+ if (failing_cells[cell_no])
+ {
+ FEValues<dim> fe_values(fe, quadrature_formula, update_quadrature_points);
+ PointHistory<dim> *local_quadrature_points_history =
+ reinterpret_cast<PointHistory<dim> *>(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<bool> cell_touched(triangulation.n_active_cells(), false);
+ std::vector< TriaIterator< CellAccessor<dim> > > neighbor_cells;
+ std::vector<int> 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<neighbor_cells.size(); i++)
+ {
+ for (unsigned int f = 0; f < GeometryInfo<dim>::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<double> nearby_etas_q;
+ for (unsigned int i = 0; i<neighbor_indices.size(); i++)
+ for (unsigned int j=0; j<quadrature_formula.size(); j++)
+ {
+ Point<dim> test_q;
+ for (unsigned int d=0; d<dim; d++)
+ test_q(d) = quad_viscosities[neighbor_indices[i]][j][d];
+ double qq_distance = fe_values.quadrature_point(q).distance(test_q);
+ if (qq_distance < system_parameters::smoothing_radius)
+ nearby_etas_q.push_back(quad_viscosities[neighbor_indices[i]][j][dim]);
+ }
+ // Write smoothed viscosities to quadrature_points_history; simple boxcar function is the smoothing kernel
+ double mean_eta = 0;
+ for (unsigned int l = 0; l<nearby_etas_q.size(); l++)
+ {
+ mean_eta += nearby_etas_q[l];
+ }
+ mean_eta /= nearby_etas_q.size();
+ local_quadrature_points_history[q].new_eta = mean_eta;
+// std::cout << local_quadrature_points_history[q].new_eta << " ";
+ }
+ }
+ cell_no++;
+ }
+ }
//====================== SAVE STRESS TENSOR AT QUADRATURE POINTS ======================
-template<int dim>
-void StokesProblem<dim>::update_quadrature_point_history() {
- std::cout << " Updating stress field...";
-
- FEValues<dim> 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<Tensor<1, dim> >> velocity_grads(quadrature_formula.size(),
- std::vector < Tensor<1, dim> > (dim + 1));
- std::vector<Vector<double> > velocities(quadrature_formula.size(),
- Vector<double>(dim + 1));
-
- for (typename DoFHandler<dim>::active_cell_iterator cell =
- dof_handler.begin_active(); cell != dof_handler.end(); ++cell) {
- PointHistory<dim> *local_quadrature_points_history =
- reinterpret_cast<PointHistory<dim> *>(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<dim> 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<Tensor<2, dim> >(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<int dim>
+ void StokesProblem<dim>::update_quadrature_point_history()
+ {
+ std::cout << " Updating stress field...";
+
+ FEValues<dim> 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<Tensor<1, dim> >> velocity_grads(quadrature_formula.size(),
+ std::vector < Tensor<1, dim> > (dim + 1));
+ std::vector<Vector<double> > velocities(quadrature_formula.size(),
+ Vector<double>(dim + 1));
+
+ for (typename DoFHandler<dim>::active_cell_iterator cell =
+ dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
+ {
+ PointHistory<dim> *local_quadrature_points_history =
+ reinterpret_cast<PointHistory<dim> *>(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<dim> 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<Tensor<2, dim> >(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<int dim>
-void StokesProblem<dim>::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<dim>::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<GeometryInfo<dim>::faces_per_cell; f++)
- for(unsigned int i=0; i<dim; i++)
- if (fabs(cell->face(f)->center()[i]) < zero_tolerance)
- zero_faces++;
- if (zero_faces==0)
- {
- for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
- {
- Point<dim> vertex_velocity;
- Point<dim> 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<int dim>
+ void StokesProblem<dim>::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<dim>::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<GeometryInfo<dim>::faces_per_cell; f++)
+ for (unsigned int i=0; i<dim; i++)
+ if (fabs(cell->face(f)->center()[i]) < zero_tolerance)
+ zero_faces++;
+ if (zero_faces==0)
+ {
+ for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
+ {
+ Point<dim> vertex_velocity;
+ Point<dim> 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<int dim>
-void StokesProblem<dim>::move_mesh() {
-
- std::cout << "\n" << " Moving mesh...\n";
- std::vector<bool> vertex_touched(triangulation.n_vertices(), false);
- for (typename DoFHandler<dim>::active_cell_iterator cell =
- dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
- for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
- if (vertex_touched[cell->vertex_index(v)] == false) {
- vertex_touched[cell->vertex_index(v)] = true;
-
- Point<dim> 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<int dim>
+ void StokesProblem<dim>::move_mesh()
+ {
+
+ std::cout << "\n" << " Moving mesh...\n";
+ std::vector<bool> vertex_touched(triangulation.n_vertices(), false);
+ for (typename DoFHandler<dim>::active_cell_iterator cell =
+ dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
+ for (unsigned int v = 0; v < GeometryInfo<dim>::vertices_per_cell; ++v)
+ if (vertex_touched[cell->vertex_index(v)] == false)
+ {
+ vertex_touched[cell->vertex_index(v)] = true;
+
+ Point<dim> 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<int dim>
-void StokesProblem<dim>::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<int dim>
+ void StokesProblem<dim>::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<int dim>
-void StokesProblem<dim>::do_ellipse_fits()
-{
- std::ostringstream ellipses_filename;
- ellipses_filename << system_parameters::output_folder << "/ellipse_fits.txt";
- // Find ellipsoidal axes for all layers
- std::vector<double> ellipse_axes(0);
- // compute fit to boundary 0, 1, 2 ...
- std::cout << endl;
- for(unsigned int i = 0; i<system_parameters::sizeof_material_id;i++)
- {
- ellipsoid.compute_fit(ellipse_axes, system_parameters::material_id[i]);
- system_parameters::q_axes.push_back(ellipse_axes[0]);
- system_parameters::p_axes.push_back(ellipse_axes[1]);
-
- std::cout << "a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
- << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << std::endl;
- ellipse_axes.clear();
-
- std::ofstream fout_ellipses(ellipses_filename.str().c_str(), std::ios::app);
- fout_ellipses << system_parameters::present_timestep << " a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
- << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << endl;
- fout_ellipses.close();
- }
-}
+ template<int dim>
+ void StokesProblem<dim>::do_ellipse_fits()
+ {
+ std::ostringstream ellipses_filename;
+ ellipses_filename << system_parameters::output_folder << "/ellipse_fits.txt";
+ // Find ellipsoidal axes for all layers
+ std::vector<double> ellipse_axes(0);
+ // compute fit to boundary 0, 1, 2 ...
+ std::cout << endl;
+ for (unsigned int i = 0; i<system_parameters::sizeof_material_id; i++)
+ {
+ ellipsoid.compute_fit(ellipse_axes, system_parameters::material_id[i]);
+ system_parameters::q_axes.push_back(ellipse_axes[0]);
+ system_parameters::p_axes.push_back(ellipse_axes[1]);
+
+ std::cout << "a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
+ << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << std::endl;
+ ellipse_axes.clear();
+
+ std::ofstream fout_ellipses(ellipses_filename.str().c_str(), std::ios::app);
+ fout_ellipses << system_parameters::present_timestep << " a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
+ << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << endl;
+ fout_ellipses.close();
+ }
+ }
//====================== APPEND LINE TO PHYSICAL_TIMES.TXT FILE WITH STEP NUMBER, PHYSICAL TIME, AND # PLASTIC ITERATIONS ======================
-template<int dim>
-void StokesProblem<dim>::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();
-}
+ template<int dim>
+ void StokesProblem<dim>::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<int dim>
-void StokesProblem<dim>::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<bool> 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<dim>::active_cell_iterator cell =
- triangulation.begin_active(); cell != triangulation.end(); ++cell)
- for (unsigned int f = 0; f < GeometryInfo<dim>::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<GeometryInfo<dim>::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<dim>::active_cell_iterator cell =
- triangulation.begin_active(); cell != triangulation.end(); ++cell)
- for (unsigned int f = 0; f < GeometryInfo<dim>::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<dim>::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<int dim>
+ void StokesProblem<dim>::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<bool> 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<dim>::active_cell_iterator cell =
+ triangulation.begin_active(); cell != triangulation.end(); ++cell)
+ for (unsigned int f = 0; f < GeometryInfo<dim>::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<GeometryInfo<dim>::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<dim>::active_cell_iterator cell =
+ triangulation.begin_active(); cell != triangulation.end(); ++cell)
+ for (unsigned int f = 0; f < GeometryInfo<dim>::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<dim>::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<int dim>
-void StokesProblem<dim>::setup_initial_mesh() {
- GridIn<dim> 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<int dim>
+ void StokesProblem<dim>::setup_initial_mesh()
+ {
+ GridIn<dim> 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<dim>::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<dim>::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; i<dim; i++)
- if (fabs(cell->face(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<double> ellipse_axes(0);
- // compute fit to boundary 0, 1, 2 ...
- std::cout << endl;
- for(unsigned int i = 0; i<system_parameters::sizeof_material_id;i++)
- {
- ellipsoid.compute_fit(ellipse_axes, system_parameters::material_id[i]);
- system_parameters::q_axes.push_back(ellipse_axes[0]);
- system_parameters::p_axes.push_back(ellipse_axes[1]);
-
- std::cout << "a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
- << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << std::endl;
- ellipse_axes.clear();
-
- std::ofstream fout_ellipses(ellipses_filename.str().c_str(), std::ios::app);
- fout_ellipses << system_parameters::present_timestep << " a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
- << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << endl;
- fout_ellipses.close();
- }
-
- triangulation.refine_global(system_parameters::global_refinement);
+ 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<dim>::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; i<dim; i++)
+ if (fabs(cell->face(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<double> ellipse_axes(0);
+ // compute fit to boundary 0, 1, 2 ...
+ std::cout << endl;
+ for (unsigned int i = 0; i<system_parameters::sizeof_material_id; i++)
+ {
+ ellipsoid.compute_fit(ellipse_axes, system_parameters::material_id[i]);
+ system_parameters::q_axes.push_back(ellipse_axes[0]);
+ system_parameters::p_axes.push_back(ellipse_axes[1]);
+
+ std::cout << "a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
+ << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << std::endl;
+ ellipse_axes.clear();
+
+ std::ofstream fout_ellipses(ellipses_filename.str().c_str(), std::ios::app);
+ fout_ellipses << system_parameters::present_timestep << " a_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[0]
+ << " " << " c_"<< system_parameters::material_id[i] <<" = " << ellipse_axes[1] << endl;
+ fout_ellipses.close();
+ }
+
+ triangulation.refine_global(system_parameters::global_refinement);
//refines crustal region
- if (system_parameters::crustal_refinement != 0) {
- double a = system_parameters::q_axes[0] - system_parameters::crust_refine_region;
- double b = system_parameters::p_axes[0] - system_parameters::crust_refine_region;
-
-
- for (unsigned int step = 0;
- step < system_parameters::crustal_refinement; ++step) {
- typename dealii::Triangulation<dim>::active_cell_iterator cell =
- triangulation.begin_active(), endc = triangulation.end();
- for (; cell != endc; ++cell)
- for (unsigned int v = 0;
- v < GeometryInfo<dim>::vertices_per_cell; ++v) {
- Point<dim> 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();
-}
+ if (system_parameters::crustal_refinement != 0)
+ {
+ double a = system_parameters::q_axes[0] - system_parameters::crust_refine_region;
+ double b = system_parameters::p_axes[0] - system_parameters::crust_refine_region;
+
+
+ for (unsigned int step = 0;
+ step < system_parameters::crustal_refinement; ++step)
+ {
+ typename dealii::Triangulation<dim>::active_cell_iterator cell =
+ triangulation.begin_active(), endc = triangulation.end();
+ for (; cell != endc; ++cell)
+ for (unsigned int v = 0;
+ v < GeometryInfo<dim>::vertices_per_cell; ++v)
+ {
+ Point<dim> 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<int dim>
-void StokesProblem<dim>::refine_mesh() {
- Vector<float> estimated_error_per_cell(triangulation.n_active_cells());
+ template<int dim>
+ void StokesProblem<dim>::refine_mesh()
+ {
+ Vector<float> estimated_error_per_cell(triangulation.n_active_cells());
- std::vector<bool> component_mask(dim + 1, false);
- component_mask[dim] = true;
- KellyErrorEstimator<dim>::estimate(dof_handler, QGauss<dim - 1>(degree + 1),
- typename FunctionMap<dim>::type(), solution,
- estimated_error_per_cell, component_mask);
+ std::vector<bool> component_mask(dim + 1, false);
+ component_mask[dim] = true;
+ KellyErrorEstimator<dim>::estimate(dof_handler, QGauss<dim - 1>(degree + 1),
+ typename FunctionMap<dim>::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<int dim>
-void StokesProblem<dim>::setup_quadrature_point_history() {
- unsigned int our_cells = 0;
- for (typename Triangulation<dim>::active_cell_iterator cell =
- triangulation.begin_active(); cell != triangulation.end(); ++cell)
- ++our_cells;
+ template<int dim>
+ void StokesProblem<dim>::setup_quadrature_point_history()
+ {
+ unsigned int our_cells = 0;
+ for (typename Triangulation<dim>::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<dim>::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<dim>::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<int dim>
-void StokesProblem<dim>::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<int dim>
+ void StokesProblem<dim>::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<int dim>
-void StokesProblem<dim>::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<int dim>
+ void StokesProblem<dim>::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<int dim>
-void StokesProblem<dim>::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<int dim>
+ void StokesProblem<dim>::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;
}
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<double> depths_eta;
-vector<double> eta_kinks;
-vector<double> depths_rho;
-vector<double> rho;
-vector<int> material_id;
-vector<double> 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<double> depths_eta;
+ vector<double> eta_kinks;
+ vector<double> depths_rho;
+ vector<double> rho;
+ vector<int> material_id;
+ vector<double> 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<double> q_axes;
-vector<double> p_axes;
+ vector<double> q_axes;
+ vector<double> 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;
// rheology parameters
- for(unsigned int i=0; i<system_parameters::sizeof_depths_eta; i++)
- fout_config << "depths_eta[" << i << "] = " << system_parameters::depths_eta[i] << endl;
+ for (unsigned int i=0; i<system_parameters::sizeof_depths_eta; i++)
+ fout_config << "depths_eta[" << i << "] = " << system_parameters::depths_eta[i] << endl;
- for(unsigned int i=0; i<system_parameters::sizeof_eta_kinks; i++)
- fout_config << "eta_kinks[" << i << "] = " << system_parameters::eta_kinks[i] << endl;
+ for (unsigned int i=0; i<system_parameters::sizeof_eta_kinks; i++)
+ fout_config << "eta_kinks[" << i << "] = " << system_parameters::eta_kinks[i] << endl;
- for(unsigned int i=0; i<system_parameters::sizeof_depths_rho; i++)
- fout_config << "depths_rho[" << i << "] = " << system_parameters::depths_rho[i] << endl;
+ for (unsigned int i=0; i<system_parameters::sizeof_depths_rho; i++)
+ fout_config << "depths_rho[" << i << "] = " << system_parameters::depths_rho[i] << endl;
- for(unsigned int i=0; i<system_parameters::sizeof_rho; i++)
- fout_config << "rho[" << i << "] = " << system_parameters::rho[i] << endl;
+ for (unsigned int i=0; i<system_parameters::sizeof_rho; i++)
+ fout_config << "rho[" << i << "] = " << system_parameters::rho[i] << endl;
- for(unsigned int i=0; i<system_parameters::sizeof_material_id; i++)
- fout_config << "material_id[" << i << "] = " << system_parameters::material_id[i] << endl;
+ for (unsigned int i=0; i<system_parameters::sizeof_material_id; i++)
+ fout_config << "material_id[" << i << "] = " << system_parameters::material_id[i] << endl;
- for(unsigned int i=0; i<system_parameters::sizeof_G; i++)
- fout_config << "G[" << i << "] = " << system_parameters::G[i] << endl;
+ for (unsigned int i=0; i<system_parameters::sizeof_G; i++)
+ fout_config << "G[" << i << "] = " << system_parameters::G[i] << endl;
fout_config << "eta_ceiling = " << system_parameters::eta_ceiling << endl;
fout_config << "eta_floor = " << system_parameters::eta_floor << endl;
// Solver parameters
fout_config << "iteration_coefficient = " << system_parameters::iteration_coefficient << endl;
- fout_config << "tolerance_coefficient = " << system_parameters::tolerance_coefficient << endl;
-
- // Time step parameters
- fout_config << "present_time = " << system_parameters::present_time << endl;
- fout_config << "present_timestep = " << system_parameters::present_timestep << endl;
- fout_config << "total_viscous_steps = " << system_parameters::total_viscous_steps << endl;
-
- fout_config.close();
-}
-
-config_in::config_in(char* filename)
-{
-
- // This example reads the configuration file 'example.cfg' and displays
- // some of its contents.
-
- Config cfg;
-
- // Read the file. If there is an error, report it and exit.
- try
- {
- cfg.readFile(filename);
- }
- catch(const FileIOException &fioex)
- {
- std::cerr << "I/O error while reading file:" << filename << std::endl;
- }
- catch(const ParseException &pex)
- {
- std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
- << " - " << pex.getError() << std::endl;
- }
-
- // Get mesh name.
- try
- {
+ fout_config << "tolerance_coefficient = " << system_parameters::tolerance_coefficient << endl;
+
+ // Time step parameters
+ fout_config << "present_time = " << system_parameters::present_time << endl;
+ fout_config << "present_timestep = " << system_parameters::present_timestep << endl;
+ fout_config << "total_viscous_steps = " << system_parameters::total_viscous_steps << endl;
+
+ fout_config.close();
+ }
+
+ config_in::config_in(char *filename)
+ {
+
+ // This example reads the configuration file 'example.cfg' and displays
+ // some of its contents.
+
+ Config cfg;
+
+ // Read the file. If there is an error, report it and exit.
+ try
+ {
+ cfg.readFile(filename);
+ }
+ catch (const FileIOException &fioex)
+ {
+ std::cerr << "I/O error while reading file:" << filename << std::endl;
+ }
+ catch (const ParseException &pex)
+ {
+ std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
+ << " - " << pex.getError() << std::endl;
+ }
+
+ // Get mesh name.
+ try
+ {
string msh = cfg.lookup("mesh_filename");
- system_parameters::mesh_filename = msh;
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "No 'mesh_filename' setting in configuration file." << endl;
- }
+ system_parameters::mesh_filename = msh;
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "No 'mesh_filename' setting in configuration file." << endl;
+ }
- // get output folder
+ // get output folder
- try
- {
+ try
+ {
string output = cfg.lookup("output_folder");
- system_parameters::output_folder = output;
+ system_parameters::output_folder = output;
- std::cout << "Writing to folder: " << output << endl;
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "No 'output_folder' setting in configuration file." << endl;
- }
+ std::cout << "Writing to folder: " << output << endl;
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "No 'output_folder' setting in configuration file." << endl;
+ }
- // get radii
+ // get radii
- const Setting& root = cfg.getRoot();
+ const Setting &root = cfg.getRoot();
- // get body parameters
- try
- {
- const Setting& body_parameters = root["body_parameters"];
+ // get body parameters
+ try
+ {
+ const Setting &body_parameters = root["body_parameters"];
- body_parameters.lookupValue("period", system_parameters::period);
- system_parameters::omegasquared = pow(TWOPI / 3600.0 / system_parameters::period, 2.0);
- body_parameters.lookupValue("r_mean", system_parameters::r_mean);
- body_parameters.lookupValue("beta", system_parameters::beta);
- body_parameters.lookupValue("intercept", system_parameters::intercept);
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the body parameters block" << endl;
+ body_parameters.lookupValue("period", system_parameters::period);
+ system_parameters::omegasquared = pow(TWOPI / 3600.0 / system_parameters::period, 2.0);
+ body_parameters.lookupValue("r_mean", system_parameters::r_mean);
+ body_parameters.lookupValue("beta", system_parameters::beta);
+ body_parameters.lookupValue("intercept", system_parameters::intercept);
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the body parameters block" << endl;
- }
+ }
- // Rheology parameters
+ // Rheology parameters
- try
- {
- // get depths_eta ---------------------
- const Setting& set_depths_eta = cfg.lookup("rheology_parameters.depths_eta");
+ try
+ {
+ // get depths_eta ---------------------
+ const Setting &set_depths_eta = cfg.lookup("rheology_parameters.depths_eta");
- unsigned int ndepths_eta = set_depths_eta.getLength();
- system_parameters::sizeof_depths_eta = ndepths_eta;
-
- for(unsigned int i=0; i<ndepths_eta; i++)
- {
- system_parameters::depths_eta.push_back(set_depths_eta[i]);
- cout << "depth_eta[" << i << "] = " << system_parameters::depths_eta[i] << endl;
- }
-
-// get eta_kinks -------------------------
- const Setting& set_eta_kinks = cfg.lookup("rheology_parameters.eta_kinks");
-
- unsigned int neta_kinks = set_eta_kinks.getLength();
- system_parameters::sizeof_eta_kinks = neta_kinks;
-
- // cout << "Number of depth = " << ndepths << endl;
-
- for(unsigned int i=0; i<neta_kinks; i++)
- {
- system_parameters::eta_kinks.push_back(set_eta_kinks[i]);
- cout << "eta_kinks[" << i << "] = " << system_parameters::eta_kinks[i] << endl;
- }
-
- // get depths_rho -------------------------
- const Setting& set_depths_rho = cfg.lookup("rheology_parameters.depths_rho");
-
- unsigned int ndepths_rho = set_depths_rho.getLength();
- system_parameters::sizeof_depths_rho = ndepths_rho;
-
- // cout << "Number of depth = " << ndepths << endl;
-
- for(unsigned int i=0; i<ndepths_rho; i++)
- {
- system_parameters::depths_rho.push_back(set_depths_rho[i]);
- cout << "depths_rho[" << i << "] = " << system_parameters::depths_rho[i] << endl;
- }
-
- // get rho -------------------------
- const Setting& set_rho = cfg.lookup("rheology_parameters.rho");
-
- unsigned int nrho = set_rho.getLength();
- system_parameters::sizeof_rho = nrho;
-
- // cout << "Number of depth = " << ndepths << endl;
-
- for(unsigned int i=0; i<nrho; i++)
- {
- system_parameters::rho.push_back(set_rho[i]);
- cout << "rho[" << i << "] = " << system_parameters::rho[i] << endl;
- }
-
- // get material_id -------------------------
- const Setting& set_material_id = cfg.lookup("rheology_parameters.material_id");
-
- unsigned int nmaterial_id = set_material_id.getLength();
- system_parameters::sizeof_material_id = nmaterial_id;
-
- // cout << "Number of depth = " << ndepths << endl;
-
- for(unsigned int i=0; i<nmaterial_id; i++)
- {
- system_parameters::material_id.push_back(set_material_id[i]);
- cout << "material_id[" << i << "] = " << system_parameters::material_id[i] << endl;
- }
-
- // get G -------------------------
- const Setting& set_G = cfg.lookup("rheology_parameters.G");
-
- unsigned int nG = set_G.getLength();
- system_parameters::sizeof_G = nG;
-
- // cout << "Number of depth = " << ndepths << endl;
-
- for(unsigned int i=0; i<nG; i++)
- {
- system_parameters::G.push_back(set_G[i]);
- cout << "G[" << i << "] = " << system_parameters::G[i] << endl;
- }
-
- const Setting& rheology_parameters = root["rheology_parameters"];
- rheology_parameters.lookupValue("eta_ceiling", system_parameters::eta_ceiling);
- rheology_parameters.lookupValue("eta_floor", system_parameters::eta_floor);
- rheology_parameters.lookupValue("eta_Ea", system_parameters::eta_Ea);
- rheology_parameters.lookupValue("lat_dependence", system_parameters::lat_dependence);
- rheology_parameters.lookupValue("pressure_scale", system_parameters::pressure_scale);
- rheology_parameters.lookupValue("q", system_parameters::q);
- rheology_parameters.lookupValue("cylindrical", system_parameters::cylindrical);
- rheology_parameters.lookupValue("continue_plastic_iterations", system_parameters::continue_plastic_iterations);
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the rheology parameters block" << endl;
- }
-
- // Plasticity parameters
- try
- {
-
- const Setting& plasticity_parameters = root["plasticity_parameters"];
- plasticity_parameters.lookupValue("plasticity_on", system_parameters::plasticity_on);
- plasticity_parameters.lookupValue("failure_criterion", system_parameters::failure_criterion);
- plasticity_parameters.lookupValue("max_plastic_iterations", system_parameters::max_plastic_iterations);
- plasticity_parameters.lookupValue("smoothing_radius", system_parameters::smoothing_radius);
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the plasticity parameters block" << endl;
- }
-
- // Viscoelasticity parameters
-
- try
- {
-
- const Setting& viscoelasticity_parameters = root["viscoelasticity_parameters"];
- viscoelasticity_parameters.lookupValue("initial_elastic_iterations", system_parameters::initial_elastic_iterations);
- viscoelasticity_parameters.lookupValue("elastic_time", system_parameters::elastic_time);
- viscoelasticity_parameters.lookupValue("viscous_time", system_parameters::viscous_time);
- viscoelasticity_parameters.lookupValue("initial_disp_target", system_parameters::initial_disp_target);
- viscoelasticity_parameters.lookupValue("final_disp_target", system_parameters::final_disp_target);
- viscoelasticity_parameters.lookupValue("current_time_interval", system_parameters::current_time_interval);
-
- system_parameters::viscous_time *= SECSINYEAR;
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the viscoelasticity parameters block" << endl;
- }
-
- // Mesh refinement parameters
- try
- {
-
- const Setting& mesh_refinement_parameters = root["mesh_refinement_parameters"];
- mesh_refinement_parameters.lookupValue("global_refinement", system_parameters::global_refinement);
- mesh_refinement_parameters.lookupValue("small_r_refinement", system_parameters::small_r_refinement);
- mesh_refinement_parameters.lookupValue("crustal_refinement", system_parameters::crustal_refinement);
- mesh_refinement_parameters.lookupValue("crust_refine_region", system_parameters::crust_refine_region);
- mesh_refinement_parameters.lookupValue("surface_refinement", system_parameters::surface_refinement);
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the mesh refinement parameters block" << endl;
- }
-
- // Solver parameters
- try
- {
- const Setting& solve_parameters = root["solve_parameters"];
- solve_parameters.lookupValue("iteration_coefficient", system_parameters::iteration_coefficient);
- solve_parameters.lookupValue("tolerance_coefficient", system_parameters::tolerance_coefficient);
-
-
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the solver parameters block" << endl;
- }
-
- // Time step parameters
- try
- {
- const Setting& time_step_parameters = root["time_step_parameters"];
- time_step_parameters.lookupValue("present_time", system_parameters::present_time);
- time_step_parameters.lookupValue("present_timestep", system_parameters::present_timestep);
- time_step_parameters.lookupValue("total_viscous_steps", system_parameters::total_viscous_steps);
- }
- catch(const SettingNotFoundException &nfex)
- {
- cerr << "We've got a problem in the time step parameters block" << endl;
- }
-
- write_config();
-}
+ unsigned int ndepths_eta = set_depths_eta.getLength();
+ system_parameters::sizeof_depths_eta = ndepths_eta;
+
+ for (unsigned int i=0; i<ndepths_eta; i++)
+ {
+ system_parameters::depths_eta.push_back(set_depths_eta[i]);
+ cout << "depth_eta[" << i << "] = " << system_parameters::depths_eta[i] << endl;
+ }
+
+// get eta_kinks -------------------------
+ const Setting &set_eta_kinks = cfg.lookup("rheology_parameters.eta_kinks");
+
+ unsigned int neta_kinks = set_eta_kinks.getLength();
+ system_parameters::sizeof_eta_kinks = neta_kinks;
+
+ // cout << "Number of depth = " << ndepths << endl;
+
+ for (unsigned int i=0; i<neta_kinks; i++)
+ {
+ system_parameters::eta_kinks.push_back(set_eta_kinks[i]);
+ cout << "eta_kinks[" << i << "] = " << system_parameters::eta_kinks[i] << endl;
+ }
+
+ // get depths_rho -------------------------
+ const Setting &set_depths_rho = cfg.lookup("rheology_parameters.depths_rho");
+
+ unsigned int ndepths_rho = set_depths_rho.getLength();
+ system_parameters::sizeof_depths_rho = ndepths_rho;
+
+ // cout << "Number of depth = " << ndepths << endl;
+
+ for (unsigned int i=0; i<ndepths_rho; i++)
+ {
+ system_parameters::depths_rho.push_back(set_depths_rho[i]);
+ cout << "depths_rho[" << i << "] = " << system_parameters::depths_rho[i] << endl;
+ }
+
+ // get rho -------------------------
+ const Setting &set_rho = cfg.lookup("rheology_parameters.rho");
+
+ unsigned int nrho = set_rho.getLength();
+ system_parameters::sizeof_rho = nrho;
+
+ // cout << "Number of depth = " << ndepths << endl;
+
+ for (unsigned int i=0; i<nrho; i++)
+ {
+ system_parameters::rho.push_back(set_rho[i]);
+ cout << "rho[" << i << "] = " << system_parameters::rho[i] << endl;
+ }
+
+ // get material_id -------------------------
+ const Setting &set_material_id = cfg.lookup("rheology_parameters.material_id");
+
+ unsigned int nmaterial_id = set_material_id.getLength();
+ system_parameters::sizeof_material_id = nmaterial_id;
+
+ // cout << "Number of depth = " << ndepths << endl;
+
+ for (unsigned int i=0; i<nmaterial_id; i++)
+ {
+ system_parameters::material_id.push_back(set_material_id[i]);
+ cout << "material_id[" << i << "] = " << system_parameters::material_id[i] << endl;
+ }
+
+ // get G -------------------------
+ const Setting &set_G = cfg.lookup("rheology_parameters.G");
+
+ unsigned int nG = set_G.getLength();
+ system_parameters::sizeof_G = nG;
+
+ // cout << "Number of depth = " << ndepths << endl;
+
+ for (unsigned int i=0; i<nG; i++)
+ {
+ system_parameters::G.push_back(set_G[i]);
+ cout << "G[" << i << "] = " << system_parameters::G[i] << endl;
+ }
+
+ const Setting &rheology_parameters = root["rheology_parameters"];
+ rheology_parameters.lookupValue("eta_ceiling", system_parameters::eta_ceiling);
+ rheology_parameters.lookupValue("eta_floor", system_parameters::eta_floor);
+ rheology_parameters.lookupValue("eta_Ea", system_parameters::eta_Ea);
+ rheology_parameters.lookupValue("lat_dependence", system_parameters::lat_dependence);
+ rheology_parameters.lookupValue("pressure_scale", system_parameters::pressure_scale);
+ rheology_parameters.lookupValue("q", system_parameters::q);
+ rheology_parameters.lookupValue("cylindrical", system_parameters::cylindrical);
+ rheology_parameters.lookupValue("continue_plastic_iterations", system_parameters::continue_plastic_iterations);
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the rheology parameters block" << endl;
+ }
+
+ // Plasticity parameters
+ try
+ {
+
+ const Setting &plasticity_parameters = root["plasticity_parameters"];
+ plasticity_parameters.lookupValue("plasticity_on", system_parameters::plasticity_on);
+ plasticity_parameters.lookupValue("failure_criterion", system_parameters::failure_criterion);
+ plasticity_parameters.lookupValue("max_plastic_iterations", system_parameters::max_plastic_iterations);
+ plasticity_parameters.lookupValue("smoothing_radius", system_parameters::smoothing_radius);
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the plasticity parameters block" << endl;
+ }
+
+ // Viscoelasticity parameters
+
+ try
+ {
+
+ const Setting &viscoelasticity_parameters = root["viscoelasticity_parameters"];
+ viscoelasticity_parameters.lookupValue("initial_elastic_iterations", system_parameters::initial_elastic_iterations);
+ viscoelasticity_parameters.lookupValue("elastic_time", system_parameters::elastic_time);
+ viscoelasticity_parameters.lookupValue("viscous_time", system_parameters::viscous_time);
+ viscoelasticity_parameters.lookupValue("initial_disp_target", system_parameters::initial_disp_target);
+ viscoelasticity_parameters.lookupValue("final_disp_target", system_parameters::final_disp_target);
+ viscoelasticity_parameters.lookupValue("current_time_interval", system_parameters::current_time_interval);
+
+ system_parameters::viscous_time *= SECSINYEAR;
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the viscoelasticity parameters block" << endl;
+ }
+
+ // Mesh refinement parameters
+ try
+ {
+
+ const Setting &mesh_refinement_parameters = root["mesh_refinement_parameters"];
+ mesh_refinement_parameters.lookupValue("global_refinement", system_parameters::global_refinement);
+ mesh_refinement_parameters.lookupValue("small_r_refinement", system_parameters::small_r_refinement);
+ mesh_refinement_parameters.lookupValue("crustal_refinement", system_parameters::crustal_refinement);
+ mesh_refinement_parameters.lookupValue("crust_refine_region", system_parameters::crust_refine_region);
+ mesh_refinement_parameters.lookupValue("surface_refinement", system_parameters::surface_refinement);
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the mesh refinement parameters block" << endl;
+ }
+
+ // Solver parameters
+ try
+ {
+ const Setting &solve_parameters = root["solve_parameters"];
+ solve_parameters.lookupValue("iteration_coefficient", system_parameters::iteration_coefficient);
+ solve_parameters.lookupValue("tolerance_coefficient", system_parameters::tolerance_coefficient);
+
+
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the solver parameters block" << endl;
+ }
+
+ // Time step parameters
+ try
+ {
+ const Setting &time_step_parameters = root["time_step_parameters"];
+ time_step_parameters.lookupValue("present_time", system_parameters::present_time);
+ time_step_parameters.lookupValue("present_timestep", system_parameters::present_timestep);
+ time_step_parameters.lookupValue("total_viscous_steps", system_parameters::total_viscous_steps);
+ }
+ catch (const SettingNotFoundException &nfex)
+ {
+ cerr << "We've got a problem in the time step parameters block" << endl;
+ }
+
+ write_config();
+ }
}
class ellipsoid_fit
{
public:
- inline ellipsoid_fit (Triangulation<dim,dim>* pi)
- {
- p_triangulation = pi;
- };
- void compute_fit(std::vector<double> &ell, unsigned char bndry);
+ inline ellipsoid_fit (Triangulation<dim,dim> *pi)
+ {
+ p_triangulation = pi;
+ };
+ void compute_fit(std::vector<double> &ell, unsigned char bndry);
private:
- Triangulation<dim,dim>* p_triangulation;
+ Triangulation<dim,dim> *p_triangulation;
};
template <int dim>
void ellipsoid_fit<dim>::compute_fit(std::vector<double> &ell, unsigned char boundary_that_we_need)
{
- typename Triangulation<dim>::active_cell_iterator cell = p_triangulation->begin_active();
- typename Triangulation<dim>::active_cell_iterator endc = p_triangulation->end();
-
- FullMatrix<double> A(p_triangulation->n_vertices(),dim);
- Vector<double> x(dim);
- Vector<double> b(p_triangulation->n_vertices());
-
- std::vector<bool> vertex_touched (p_triangulation->n_vertices(),
- false);
-
- unsigned int j = 0;
- unsigned char boundary_ids;
- std::vector<unsigned int> ind_bnry_row;
- std::vector<unsigned int> 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<dim>::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<dim>::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<dim>::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<double> AtA(dim,dim);
- Vector<double> Atb(dim);
-
- FullMatrix<double> A_out(ind_bnry_row.size(),dim);
- Vector<double> b_out(ind_bnry_row.size());
-
- for(unsigned int i=0;i<dim;i++)
- ind_bnry_col.push_back(i);
-
- for(unsigned int i=0;i<ind_bnry_row.size();i++)
- b_out(i) = 1;
-
- A_out.extract_submatrix_from(A, ind_bnry_row, ind_bnry_col);
- A_out.Tmmult(AtA,A_out,true);
- A_out.Tvmult(Atb,b_out,true);
-
- // solve normal system of equations
- SolverControl solver_control (1000, 1e-12);
- SolverCG<> solver (solver_control);
- solver.solve (AtA, x, Atb, PreconditionIdentity());
-
- // find ellipsoidal axes
- for(unsigned int i=0; i<dim; i++)
- ell.push_back(sqrt(1.0/x[i]));
- }
- else
- std::cerr << "fit_ellipsoid: no points to fit" << std::endl;
+ typename Triangulation<dim>::active_cell_iterator cell = p_triangulation->begin_active();
+ typename Triangulation<dim>::active_cell_iterator endc = p_triangulation->end();
+
+ FullMatrix<double> A(p_triangulation->n_vertices(),dim);
+ Vector<double> x(dim);
+ Vector<double> b(p_triangulation->n_vertices());
+
+ std::vector<bool> vertex_touched (p_triangulation->n_vertices(),
+ false);
+
+ unsigned int j = 0;
+ unsigned char boundary_ids;
+ std::vector<unsigned int> ind_bnry_row;
+ std::vector<unsigned int> 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<dim>::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<dim>::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<dim>::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<double> AtA(dim,dim);
+ Vector<double> Atb(dim);
+
+ FullMatrix<double> A_out(ind_bnry_row.size(),dim);
+ Vector<double> b_out(ind_bnry_row.size());
+
+ for (unsigned int i=0; i<dim; i++)
+ ind_bnry_col.push_back(i);
+
+ for (unsigned int i=0; i<ind_bnry_row.size(); i++)
+ b_out(i) = 1;
+
+ A_out.extract_submatrix_from(A, ind_bnry_row, ind_bnry_col);
+ A_out.Tmmult(AtA,A_out,true);
+ A_out.Tvmult(Atb,b_out,true);
+
+ // solve normal system of equations
+ SolverControl solver_control (1000, 1e-12);
+ SolverCG<> solver (solver_control);
+ solver.solve (AtA, x, Atb, PreconditionIdentity());
+
+ // find ellipsoidal axes
+ for (unsigned int i=0; i<dim; i++)
+ ell.push_back(sqrt(1.0/x[i]));
+ }
+ else
+ std::cerr << "fit_ellipsoid: no points to fit" << std::endl;
}
/*
Started 10/8/2012, R. R. Fu
-
+
Reference Pohanka 2011, Contrib. Geophys. Geodes.
-
+
*/
#include <math.h>
#include <deal.II/base/point.h>
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 <int dim>
-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 <int dim>
+ class AnalyticGravity
+ {
public:
void setup_vars (std::vector<double> v);
- void get_gravity (const dealii::Point<dim> &p, std::vector<double> &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 <int dim>
-void AnalyticGravity<dim>::get_gravity (const dealii::Point<dim> &p, std::vector<double> &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 <int dim>
-void AnalyticGravity<dim>::setup_vars (std::vector<double> 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<dim> &p, std::vector<double> &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 <int dim>
+ void AnalyticGravity<dim>::get_gravity (const dealii::Point<dim> &p, std::vector<double> &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 <int dim>
+ void AnalyticGravity<dim>::setup_vars (std::vector<double> 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";
+ }
}
//}
-#endif /* LOCALMATH_H */
+#endif /* LOCALMATH_H */
class RightHandSide : public Function<dim>
{
public:
- RightHandSide() : Function<dim>(1)
- {}
+ RightHandSide() : Function<dim>(1)
+ {}
- virtual double value(const Point<dim> &p,
- const unsigned int component = 0 ) const;
+ virtual double value(const Point<dim> &p,
+ const unsigned int component = 0 ) const;
};
template <int dim>
class DirichletBoundaryValues : public Function<dim>
{
public:
- DirichletBoundaryValues() : Function<dim>(1)
- {}
+ DirichletBoundaryValues() : Function<dim>(1)
+ {}
- virtual double value(const Point<dim> &p,
- const unsigned int component = 0 ) const;
+ virtual double value(const Point<dim> &p,
+ const unsigned int component = 0 ) const;
};
template<int dim>
class TrueSolution : public Function<dim>
{
public:
- TrueSolution() : Function<dim>(dim+1)
- {}
+ TrueSolution() : Function<dim>(dim+1)
+ {}
- virtual void vector_value(const Point<dim> & p,
- Vector<double> &valuess) const;
+ virtual void vector_value(const Point<dim> &p,
+ Vector<double> &valuess) const;
};
template <int dim>
value(const Point<dim> &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));
}
value(const Point<dim> &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;
}
vector_value(const Point<dim> &p,
Vector<double> &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;
}
#include <fstream>
#include <iostream>
-// 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 <deal.II/fe/fe_dgq.h>
+#include <deal.II/fe/fe_dgq.h>
// or the Legendre polynomials
#include <deal.II/fe/fe_dgp.h>
// as basis functions. I'll be using the Lagrange polynomials.
#include <deal.II/lac/trilinos_solver.h>
-// 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 <int dim>
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<dim> &cell_fe,
- FullMatrix<double> &cell_matrix,
- Vector<double> &cell_vector);
+ void assemble_cell_terms(const FEValues<dim> &cell_fe,
+ FullMatrix<double> &cell_matrix,
+ Vector<double> &cell_vector);
- void assemble_Neumann_boundary_terms(const FEFaceValues<dim> &face_fe,
- FullMatrix<double> &local_matrix,
- Vector<double> &local_vector);
+ void assemble_Neumann_boundary_terms(const FEFaceValues<dim> &face_fe,
+ FullMatrix<double> &local_matrix,
+ Vector<double> &local_vector);
- void assemble_Dirichlet_boundary_terms(const FEFaceValues<dim> &face_fe,
- FullMatrix<double> &local_matrix,
- Vector<double> &local_vector,
- const double & h);
+ void assemble_Dirichlet_boundary_terms(const FEFaceValues<dim> &face_fe,
+ FullMatrix<double> &local_matrix,
+ Vector<double> &local_vector,
+ const double &h);
- void assemble_flux_terms(const FEFaceValuesBase<dim> &fe_face_values,
- const FEFaceValuesBase<dim> &fe_neighbor_face_values,
- FullMatrix<double> &vi_ui_matrix,
- FullMatrix<double> &vi_ue_matrix,
- FullMatrix<double> &ve_ui_matrix,
- FullMatrix<double> &ve_ue_matrix,
- const double & h);
+ void assemble_flux_terms(const FEFaceValuesBase<dim> &fe_face_values,
+ const FEFaceValuesBase<dim> &fe_neighbor_face_values,
+ FullMatrix<double> &vi_ui_matrix,
+ FullMatrix<double> &vi_ue_matrix,
+ FullMatrix<double> &ve_ui_matrix,
+ FullMatrix<double> &ve_ue_matrix,
+ const double &h);
- void distribute_local_flux_to_global(
- const FullMatrix<double> & vi_ui_matrix,
- const FullMatrix<double> & vi_ue_matrix,
- const FullMatrix<double> & ve_ui_matrix,
- const FullMatrix<double> & ve_ue_matrix,
- const std::vector<types::global_dof_index> & local_dof_indices,
- const std::vector<types::global_dof_index> & local_neighbor_dof_indices);
+ void distribute_local_flux_to_global(
+ const FullMatrix<double> &vi_ui_matrix,
+ const FullMatrix<double> &vi_ue_matrix,
+ const FullMatrix<double> &ve_ui_matrix,
+ const FullMatrix<double> &ve_ue_matrix,
+ const std::vector<types::global_dof_index> &local_dof_indices,
+ const std::vector<types::global_dof_index> &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<dim> triangulation;
- FESystem<dim> fe;
- DoFHandler<dim> dof_handler;
+ parallel::distributed::Triangulation<dim> triangulation;
+ FESystem<dim> fe;
+ DoFHandler<dim> 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<dim> rhs_function;
- const DirichletBoundaryValues<dim> Dirichlet_bc_function;
- const TrueSolution<dim> true_solution;
+ const RightHandSide<dim> rhs_function;
+ const DirichletBoundaryValues<dim> Dirichlet_bc_function;
+ const TrueSolution<dim> 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, <code>degree</code>, which tells us the maxiumum order
-// of the polynomial to use as well as <code>n_refine</code> 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, <code>degree</code>, which tells us the maxiumum order
+// of the polynomial to use as well as <code>n_refine</code> 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,
//
-// <code>
+// <code>
// fe( FESystem<dim>(FE_DGQ<dim>(degree), dim), 1,
-// FE_DGQ<dim>(degree), 1)
+// FE_DGQ<dim>(degree), 1)
// </code>
-//
+//
// which tells us that the basis functions contain discontinous polynomials
// of order <code>degree</code> in each of the <code>dim</code> dimensions
// for the vector field. For the scalar unknown we
-// use a discontinuous polynomial of the order <code>degree</code>.
-// 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 <code>degree</code>.
+// 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.
LDGPoissonProblem<dim>::
LDGPoissonProblem(const unsigned int degree,
const unsigned int n_refine)
- :
- degree(degree),
- n_refine(n_refine),
- triangulation(MPI_COMM_WORLD,
- typename Triangulation<dim>::MeshSmoothing
- (Triangulation<dim>::smoothing_on_refinement |
- Triangulation<dim>::smoothing_on_coarsening)),
- fe( FESystem<dim>(FE_DGQ<dim>(degree), dim), 1,
- FE_DGQ<dim>(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<dim>::MeshSmoothing
+ (Triangulation<dim>::smoothing_on_refinement |
+ Triangulation<dim>::smoothing_on_coarsening)),
+ fe( FESystem<dim>(FE_DGQ<dim>(degree), dim), 1,
+ FE_DGQ<dim>(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()
{
}
LDGPoissonProblem<dim>::
~LDGPoissonProblem()
{
- dof_handler.clear();
+ dof_handler.clear();
}
// @sect4{Make_grid}
triangulation.refine_global(n_refine);
unsigned int local_refine = 2;
- for(unsigned int i =0; i <local_refine; i++)
- {
- typename Triangulation<dim>::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 <local_refine; i++)
+ {
+ typename Triangulation<dim>::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
// <code>boundary_id</code> to be <code>Dirichlet</code>.
// We remark that one could easily set more complicated
// conditions where there are both Dirichlet or
typename Triangulation<dim>::cell_iterator
cell = triangulation.begin(),
endc = triangulation.end();
- for(; cell != endc; cell++)
- {
- for(unsigned int face_no=0;
- face_no < GeometryInfo<dim>::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<dim>::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, <code>system_matrix</code>,
-// and global right hand side vector, <code>system_rhs</code> .
-// 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, <code>system_rhs</code> .
+// 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 <int dim>
void
LDGPoissonProblem<dim>::
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 <code>distribute_dofs()</code>
- // 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, <code>locally_relevant_solution</code>,
- // 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<types::global_dof_index> 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
- // <code>system_matrix</code> and <code>system_rhs</code>. 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
- // <code>system_martrix</code>
- // 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 <code>locally_relevant_solution</code> solution
- // vector includes dofs that are locally relevant to our computations
- // while the <code>system_rhs</code> 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 <code>distribute_dofs()</code>
+ // 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, <code>locally_relevant_solution</code>,
+ // 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<types::global_dof_index> 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
+ // <code>system_matrix</code> and <code>system_rhs</code>. 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
+ // <code>system_martrix</code>
+ // 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 <code>locally_relevant_solution</code> solution
+ // vector includes dofs that are locally relevant to our computations
+ // while the <code>system_rhs</code> 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.
LDGPoissonProblem<dim>::
assemble_system()
{
- TimerOutput::Scope t(computing_timer, "assembly");
-
- QGauss<dim> quadrature_formula(fe.degree+1);
- QGauss<dim-1> 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<types::global_dof_index> local_dof_indices(dofs_per_cell);
- std::vector<types::global_dof_index>
- 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, <code>fe_face_values</code>,
- // for evaluating the basis functions
- // on one side of an element face as well as another FEFaceValues object,
- // <code>fe_neighbor_face_values</code>, 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,
- // <code>fe_subface_values</code>, 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<dim> fe_values(fe, quadrature_formula, update_flags);
-
- FEFaceValues<dim> fe_face_values(fe,face_quadrature_formula,
- face_update_flags);
-
- FEFaceValues<dim> fe_neighbor_face_values(fe,
- face_quadrature_formula,
- face_update_flags);
-
- FESubfaceValues<dim> 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<double> local_matrix(dofs_per_cell,dofs_per_cell);
- Vector<double> local_vector(dofs_per_cell);
-
- // The next four matrices are used to incorporate the flux integrals across
- // interior faces of the mesh:
- FullMatrix<double> vi_ui_matrix(dofs_per_cell, dofs_per_cell);
- FullMatrix<double> vi_ue_matrix(dofs_per_cell, dofs_per_cell);
- FullMatrix<double> ve_ui_matrix(dofs_per_cell, dofs_per_cell);
- FullMatrix<double> 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:
- //
- // <code>vi_ui</code> - Taking the value of the test function from
- // interior of this cell's face and the solution function
- // from the interior of this cell.
- //
- // <code>vi_ue</code> - Taking the value of the test function from
- // interior of this cell's face and the solution function
- // from the exterior of this cell.
- //
- // <code>ve_ui</code> - Taking the value of the test function from
- // exterior of this cell's face and the solution function
- // from the interior of this cell.
- //
- // <code>ve_ue</code> - 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<dim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
-
- for(; cell!=endc; cell++)
+ TimerOutput::Scope t(computing_timer, "assembly");
+
+ QGauss<dim> quadrature_formula(fe.degree+1);
+ QGauss<dim-1> 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<types::global_dof_index> local_dof_indices(dofs_per_cell);
+ std::vector<types::global_dof_index>
+ 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, <code>fe_face_values</code>,
+ // for evaluating the basis functions
+ // on one side of an element face as well as another FEFaceValues object,
+ // <code>fe_neighbor_face_values</code>, 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,
+ // <code>fe_subface_values</code>, 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<dim> fe_values(fe, quadrature_formula, update_flags);
+
+ FEFaceValues<dim> fe_face_values(fe,face_quadrature_formula,
+ face_update_flags);
+
+ FEFaceValues<dim> fe_neighbor_face_values(fe,
+ face_quadrature_formula,
+ face_update_flags);
+
+ FESubfaceValues<dim> 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<double> local_matrix(dofs_per_cell,dofs_per_cell);
+ Vector<double> local_vector(dofs_per_cell);
+
+ // The next four matrices are used to incorporate the flux integrals across
+ // interior faces of the mesh:
+ FullMatrix<double> vi_ui_matrix(dofs_per_cell, dofs_per_cell);
+ FullMatrix<double> vi_ue_matrix(dofs_per_cell, dofs_per_cell);
+ FullMatrix<double> ve_ui_matrix(dofs_per_cell, dofs_per_cell);
+ FullMatrix<double> 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:
+ //
+ // <code>vi_ui</code> - Taking the value of the test function from
+ // interior of this cell's face and the solution function
+ // from the interior of this cell.
+ //
+ // <code>vi_ue</code> - Taking the value of the test function from
+ // interior of this cell's face and the solution function
+ // from the exterior of this cell.
+ //
+ // <code>ve_ui</code> - Taking the value of the test function from
+ // exterior of this cell's face and the solution function
+ // from the interior of this cell.
+ //
+ // <code>ve_ue</code> - 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<dim>::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
- // <code>system_matrix</code>
- // and <code>rhs_vector</code>
- // 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
+ // <code>system_matrix</code>
+ // and <code>rhs_vector</code>
+ // 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
- // <code>local_matrix</code> and <code>local_rhs</code> 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
- // <code>face_iterator</code> 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
- // <code>fe_face_values</code>
- // 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 <code>local_matrix</code> as well as the boundary
- // condition that ends up
- // in the <code>local_vector</code>.
- for(unsigned int face_no=0;
- face_no< GeometryInfo<dim>::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
+ // <code>local_matrix</code> and <code>local_rhs</code> 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
+ // <code>face_iterator</code> 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
+ // <code>fe_face_values</code>
+ // 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 <code>local_matrix</code> as well as the boundary
+ // condition that ends up
+ // in the <code>local_vector</code>.
+ for (unsigned int face_no=0;
+ face_no< GeometryInfo<dim>::faces_per_cell;
+ face_no++)
{
- typename DoFHandler<dim>::face_iterator face =
- cell->face(face_no);
+ typename DoFHandler<dim>::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<dim>::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<dim>::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<dim>::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 <code>fe_values</code>
- // to this cell's subface and
- // <code>neighbor_child</code>'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
- // <code>distribute_local_flux_to_global()</code>.
- 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<dim>::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 <code>fe_values</code>
+ // to this cell's subface and
+ // <code>neighbor_child</code>'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
+ // <code>distribute_local_flux_to_global()</code>.
+ 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 <code>h</code>.
- 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
- // <code>assemble_flux_terms</code> subroutine,
- // get the neighbor cell's
- // face dof indices and use the constraint matrix to
- // distribute the local flux matrices to the global
- // <code>system_matrix</code> using the class
- // function
- // <code>distribute_local_flux_to_global()</code>
- 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 <code>system_matrix</code>, we
- // can finally distribute the cell's <code>local_matrix</code>
- // and <code>local_vector</code> 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 <code>local_matrix</code>
- // and <code>system_rhs</code> to the global system.
- // The reason being that in looping over the faces
- // the faces on the boundary of the domain contribute
- // to the <code>local_matrix</code>
- // and <code>system_rhs</code>. 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 <code>h</code>.
+ 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
+ // <code>assemble_flux_terms</code> subroutine,
+ // get the neighbor cell's
+ // face dof indices and use the constraint matrix to
+ // distribute the local flux matrices to the global
+ // <code>system_matrix</code> using the class
+ // function
+ // <code>distribute_local_flux_to_global()</code>
+ 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 <code>system_matrix</code>, we
+ // can finally distribute the cell's <code>local_matrix</code>
+ // and <code>local_vector</code> 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 <code>local_matrix</code>
+ // and <code>system_rhs</code> to the global system.
+ // The reason being that in looping over the faces
+ // the faces on the boundary of the domain contribute
+ // to the <code>local_matrix</code>
+ // and <code>system_rhs</code>. 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<int dim>
void
LDGPoissonProblem<dim>::
assemble_cell_terms(
- const FEValues<dim> &cell_fe,
- FullMatrix<double> &cell_matrix,
- Vector<double> &cell_vector)
+ const FEValues<dim> &cell_fe,
+ FullMatrix<double> &cell_matrix,
+ Vector<double> &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<double> rhs_values(n_q_points);
+ std::vector<double> 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<n_q_points; q++)
+ // 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<n_q_points; q++)
{
- for(unsigned int i=0; i<dofs_per_cell; i++)
+ for (unsigned int i=0; i<dofs_per_cell; i++)
{
- 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);
+ 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<dofs_per_cell; j++)
+ for (unsigned int j=0; j<dofs_per_cell; j++)
{
- 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);
- }
- }
-}
+ 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 <code>local_matrix</code>
void
LDGPoissonProblem<dim>::
assemble_Dirichlet_boundary_terms(
- const FEFaceValues<dim> &face_fe,
- FullMatrix<double> &local_matrix,
- Vector<double> &local_vector,
- const double & h)
+ const FEFaceValues<dim> &face_fe,
+ FullMatrix<double> &local_matrix,
+ Vector<double> &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<double> Dirichlet_bc_values(n_q_points);
+ std::vector<double> 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<n_q_points; q++)
+ for (unsigned int q=0; q<n_q_points; q++)
{
- for(unsigned int i=0; i<dofs_per_cell; i++)
+ for (unsigned int i=0; i<dofs_per_cell; i++)
{
- const Tensor<1, dim> 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<dofs_per_cell; j++)
+ for (unsigned int j=0; j<dofs_per_cell; j++)
{
- 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);
- }
- }
-}
+ 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 <code>local_matrix</code>
void
LDGPoissonProblem<dim>::
assemble_Neumann_boundary_terms(
- const FEFaceValues<dim> &face_fe,
- FullMatrix<double> &local_matrix,
- Vector<double> &local_vector)
+ const FEFaceValues<dim> &face_fe,
+ FullMatrix<double> &local_matrix,
+ Vector<double> &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<double > 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<double > Neumann_bc_values(n_q_points);
- for(unsigned int q=0; q<n_q_points; q++)
+ for (unsigned int q=0; q<n_q_points; q++)
{
- for(unsigned int i=0; i<dofs_per_cell; i++)
+ for (unsigned int i=0; i<dofs_per_cell; i++)
{
- const Tensor<1, dim> 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<dofs_per_cell; j++)
+ for (unsigned int j=0; j<dofs_per_cell; j++)
{
- const double psi_j_potential = face_fe[Potential].value(j,q);
+ const double psi_j_potential = face_fe[Potential].value(j,q);
- // We compute contribution for the flux $\widehat{u}$ on the
- // Neumann boundary which enters our system matrix as,
- //
- // $\int_{\text{face}} \textbf{w} \cdot \textbf{n} \, u \, ds $
- local_matrix(i,j) += psi_i_field *
- face_fe.normal_vector(q) *
- psi_j_potential *
- face_fe.JxW(q);
-
- }
-
- // We also compute the contribution for the flux for
- // $\widehat{q}$ on the Neumann bounary which is the
- // Neumann boundary condition and enters the right
- // hand side vector as
- //
- // $\int_{\text{face}} -w \, g_{N} \, ds$
- local_vector(i) += -psi_i_potential *
- Neumann_bc_values[q] *
- face_fe.JxW(q);
- }
- }
+ // We compute contribution for the flux $\widehat{u}$ on the
+ // Neumann boundary which enters our system matrix as,
+ //
+ // $\int_{\text{face}} \textbf{w} \cdot \textbf{n} \, u \, ds $
+ local_matrix(i,j) += psi_i_field *
+ face_fe.normal_vector(q) *
+ psi_j_potential *
+ face_fe.JxW(q);
+
+ }
+
+ // We also compute the contribution for the flux for
+ // $\widehat{q}$ on the Neumann bounary which is the
+ // Neumann boundary condition and enters the right
+ // hand side vector as
+ //
+ // $\int_{\text{face}} -w \, g_{N} \, ds$
+ local_vector(i) += -psi_i_potential *
+ Neumann_bc_values[q] *
+ face_fe.JxW(q);
+ }
+ }
}
// @sect4{assemble_flux_terms}
-// Now we finally get to the function which builds the interior fluxes.
+// Now we finally get to the function which builds the interior fluxes.
// This is a rather long function
-// and we will describe what is going on in detail.
+// and we will describe what is going on in detail.
template<int dim>
void
LDGPoissonProblem<dim>::
assemble_flux_terms(
- const FEFaceValuesBase<dim> &fe_face_values,
- const FEFaceValuesBase<dim> &fe_neighbor_face_values,
- FullMatrix<double> &vi_ui_matrix,
- FullMatrix<double> &vi_ue_matrix,
- FullMatrix<double> &ve_ui_matrix,
- FullMatrix<double> &ve_ue_matrix,
- const double & h)
+ const FEFaceValuesBase<dim> &fe_face_values,
+ const FEFaceValuesBase<dim> &fe_neighbor_face_values,
+ FullMatrix<double> &vi_ui_matrix,
+ FullMatrix<double> &vi_ue_matrix,
+ FullMatrix<double> &ve_ui_matrix,
+ FullMatrix<double> &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<dim> beta;
- for(int i=0; i<dim; i++)
- beta(i) = 1.0;
- beta /= sqrt(beta.square() );
-
- // Now we loop over all the quadrature points on the element face
- // and loop over all the degrees of freedom and approximate
- // the following flux integrals.
- for(unsigned int q=0; q<n_face_points; q++)
+ 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<dim> beta;
+ for (int i=0; i<dim; i++)
+ beta(i) = 1.0;
+ beta /= sqrt(beta.square() );
+
+ // Now we loop over all the quadrature points on the element face
+ // and loop over all the degrees of freedom and approximate
+ // the following flux integrals.
+ for (unsigned int q=0; q<n_face_points; q++)
{
- for(unsigned int i=0; i<dofs_this_cell; i++)
+ for (unsigned int i=0; i<dofs_this_cell; i++)
{
- 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);
+ 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<dofs_this_cell; j++)
+ for (unsigned int j=0; j<dofs_this_cell; j++)
{
- 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 * (
+ 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
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<dofs_neighbor_cell; j++)
+ for (unsigned int j=0; j<dofs_neighbor_cell; j++)
{
- 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);
- }
- }
+ 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<dofs_neighbor_cell; i++)
+ for (unsigned int i=0; i<dofs_neighbor_cell; i++)
{
- 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);
+ 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<dofs_this_cell; j++)
+ for (unsigned int j=0; j<dofs_this_cell; j++)
{
- 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);
- }
+ 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<dofs_neighbor_cell; j++)
+ for (unsigned int j=0; j<dofs_neighbor_cell; j++)
{
- 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);
- }
+ 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. <code>vi_ui_matrix</code>, 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. <code>vi_ui_matrix</code>, we are
+// taking the test function and solution function values from
+// the interior of this cell and therefore only need the
// <code>local_dof_indices</code> since it contains the dof
// indices to this cell. When we distribute the second matrix,
-// <code>vi_ue_matrix</code>, the test function is taken
+// <code>vi_ue_matrix</code>, 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 <code>local_dof_indices</code> which is local to
+// the <code>local_dof_indices</code> which is local to
// this cell and then
// the <code>local_neighbor_dof_indices</code> 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<int dim>
-void
+void
LDGPoissonProblem<dim>::
distribute_local_flux_to_global(
- const FullMatrix<double> & vi_ui_matrix,
- const FullMatrix<double> & vi_ue_matrix,
- const FullMatrix<double> & ve_ui_matrix,
- const FullMatrix<double> & ve_ue_matrix,
- const std::vector<types::global_dof_index> & local_dof_indices,
- const std::vector<types::global_dof_index> & local_neighbor_dof_indices)
+ const FullMatrix<double> &vi_ui_matrix,
+ const FullMatrix<double> &vi_ue_matrix,
+ const FullMatrix<double> &ve_ui_matrix,
+ const FullMatrix<double> &ve_ue_matrix,
+ const std::vector<types::global_dof_index> &local_dof_indices,
+ const std::vector<types::global_dof_index> &local_neighbor_dof_indices)
{
constraints.distribute_local_to_global(vi_ui_matrix,
local_dof_indices,
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,
// 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
// <a href="http://epubs.siam.org/doi/abs/10.1137/S1064827502410657">
// paper</a>. 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<int dim>
void
LDGPoissonProblem<dim>::
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
- // <code>completely_distributed_solution</code> 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,
- // <code>completely_distributed_solution</code>,
- // to solution vector which has some overlap between
- // processors, <code>locally_relevant_solution</code>.
- // 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
+ // <code>completely_distributed_solution</code> 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,
+ // <code>completely_distributed_solution</code>,
+ // to solution vector which has some overlap between
+ // processors, <code>locally_relevant_solution</code>.
+ // 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 <code>solution_names</code> 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<int dim>
void
LDGPoissonProblem<dim>::
output_results() const
{
- std::vector<std::string> solution_names;
- switch(dim)
+ std::vector<std::string> 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<dim> data_out;
- data_out.attach_dof_handler(dof_handler);
- data_out.add_data_vector(locally_relevant_solution,
- solution_names);
+ DataOut<dim> data_out;
+ data_out.attach_dof_handler(dof_handler);
+ data_out.add_data_vector(locally_relevant_solution,
+ solution_names);
- Vector<float> subdomain(triangulation.n_active_cells());
+ Vector<float> subdomain(triangulation.n_active_cells());
- for(unsigned int i=0; i<subdomain.size(); i++)
- subdomain(i) = triangulation.locally_owned_subdomain();
+ for (unsigned int i=0; i<subdomain.size(); i++)
+ subdomain(i) = triangulation.locally_owned_subdomain();
- data_out.add_data_vector(subdomain,"subdomain");
+ data_out.add_data_vector(subdomain,"subdomain");
- data_out.build_patches();
+ data_out.build_patches();
- const std::string filename = ("solution." +
- Utilities::int_to_string(
+ const std::string filename = ("solution." +
+ Utilities::int_to_string(
triangulation.locally_owned_subdomain(),4));
- std::ofstream output((filename + ".vtu").c_str());
- data_out.write_vtu(output);
+ std::ofstream output((filename + ".vtu").c_str());
+ data_out.write_vtu(output);
- if(Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0 )
+ if (Utilities::MPI::this_mpi_process(MPI_COMM_WORLD) == 0 )
{
- std::vector<std::string> filenames;
- for(unsigned int i=0;
- i < Utilities::MPI::n_mpi_processes(MPI_COMM_WORLD);
- i++)
+ std::vector<std::string> 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);
+ }
}
LDGPoissonProblem<dim>::
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;
}
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.
*/
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"));
- }
+ }
}
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"));
- }
+ }
}
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);
break;
default:
Assert(false, ExcMessage("The exact solution for dim != 2 is not provided"));
- }
+ }
}
template <int dim>
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"));
- }
+ }
}
ExcDimensionMismatch (points.size(), values.size()));
for (unsigned int p=0; p<points.size(); ++p)
- {
- values[p].clear ();
-
- const double x = points[p][0];
- const double y = points[p][1];
-
- switch (dim)
{
- case 2:
- values[p][0][0] = pow(x+1.0,2.0)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
- values[p][0][1] = -sin(x*y)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
- values[p][1][0] = -sin(x*y)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
- values[p][1][1] = (x*2.0+x*x+y*y+1.0)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
- break;
- default:
- Assert(false, ExcMessage("The inverse of permeability tensor for dim != 2 is not provided"));
+ values[p].clear ();
+
+ const double x = points[p][0];
+ const double y = points[p][1];
+
+ switch (dim)
+ {
+ case 2:
+ values[p][0][0] = pow(x+1.0,2.0)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
+ values[p][0][1] = -sin(x*y)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
+ values[p][1][0] = -sin(x*y)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
+ values[p][1][1] = (x*2.0+x*x+y*y+1.0)/(x*4.0+(x*x)*(y*y)-pow(sin(x*y),2.0)+x*(y*y)*2.0+(x*x)*6.0+(x*x*x)*4.0+x*x*x*x+y*y+1.0);
+ break;
+ default:
+ Assert(false, ExcMessage("The inverse of permeability tensor for dim != 2 is not provided"));
+ }
}
- }
}
}
#include <deal.II/base/config.h>
#if DEAL_II_VERSION_MAJOR >= 9 && defined(DEAL_II_WITH_TRILINOS)
- #include <deal.II/differentiation/ad.h>
- #define ENABLE_SACADO_FORMULATION
+#include <deal.II/differentiation/ad.h>
+#define ENABLE_SACADO_FORMULATION
#endif
// These must be included below the AD headers so that
// @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
{
// 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,
// @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
// 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 <int dim,typename NumberType>
class Material_Compressible_Neo_Hook_One_Field
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
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<dim>::I;
+ return NumberType(get_dPsi_vol_dJ(det_F) * det_F) * Physics::Elasticity::StandardTensors<dim>::I;
}
// Next, determine the isochoric Kirchhoff stress
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<dim>::IxI
- - (2.0 * get_dPsi_vol_dJ(det_F))*Physics::Elasticity::StandardTensors<dim>::S );
+ // See Holzapfel p265
+ return det_F
+ * ( (get_dPsi_vol_dJ(det_F) + det_F * get_d2Psi_vol_dJ2(det_F))*Physics::Elasticity::StandardTensors<dim>::IxI
+ - (2.0 * get_dPsi_vol_dJ(det_F))*Physics::Elasticity::StandardTensors<dim>::S );
}
// Calculate the isochoric part of the tangent $J
void setup_lqp (const Parameters::AllParameters ¶meters)
{
material.reset(new Material_Compressible_Neo_Hook_One_Field<dim,NumberType>(parameters.mu,
- parameters.nu));
+ parameters.nu));
}
// We offer an interface to retrieve certain data.
// 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;
void
print_conv_footer();
-
+
void
print_vertical_tip_displacement();
};
n_q_points (qf_cell.size()),
n_q_points_f (qf_face.size())
{
-
+
}
// The class destructor simply clears the data held by the DOFHandler
// 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.
//
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...
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();
}
// 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 <int dim>
-Point<dim> grid_y_transform (const Point<dim> &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<dim> pt_out = pt_in;
- pt_out[1] = y_transform;
-
- return pt_out;
-}
+ template <int dim>
+ Point<dim> grid_y_transform (const Point<dim> &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<dim> pt_out = pt_in;
+ pt_out[1] = y_transform;
+
+ return pt_out;
+ }
template <int dim,typename NumberType>
void Solid<dim,NumberType>::make_grid()
// (modelling a plane strain condition)
if (dim == 3)
repetitions[dim-1] = 1;
-
+
const Point<dim> bottom_left = (dim == 3 ? Point<dim>(0.0, 0.0, -0.5) : Point<dim>(0.0, 0.0));
const Point<dim> top_right = (dim == 3 ? Point<dim>(48.0, 44.0, 0.5) : Point<dim>(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<dim>::active_cell_iterator cell =
- triangulation.begin_active(), endc = triangulation.end();
- for (; cell != endc; ++cell)
- for (unsigned int face = 0;
- face < GeometryInfo<dim>::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<dim>::active_cell_iterator cell =
+ triangulation.begin_active(), endc = triangulation.end();
+ for (; cell != endc; ++cell)
+ for (unsigned int face = 0;
+ face < GeometryInfo<dim>::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<dim>, 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;
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,
for (typename Triangulation<dim>::active_cell_iterator cell =
triangulation.begin_active(); cell != triangulation.end(); ++cell)
{
- const std::vector<std::shared_ptr<PointHistory<dim,NumberType> > > lqph =
- quadrature_point_history.get_data(cell);
- Assert(lqph.size() == n_q_points, ExcInternalError());
+ const std::vector<std::shared_ptr<PointHistory<dim,NumberType> > > 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);
}
}
}
// 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 <int dim,typename NumberType>
void Solid<dim,NumberType>::print_vertical_tip_displacement()
for (unsigned int i = 0; i < l_width; ++i)
std::cout << "_";
std::cout << std::endl;
-
+
Point<dim> 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<dim>::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<GeometryInfo<dim>::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<dim> mapping (parameters.poly_degree);
- const Point<dim> qp_unit = mapping.transform_real_to_unit_cell(cell,soln_pt);
- const Quadrature<dim> soln_qrule (qp_unit);
- AssertThrow(soln_qrule.size() == 1, ExcInternalError());
- FEValues<dim> 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<GeometryInfo<dim>::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<dim> mapping (parameters.poly_degree);
+ const Point<dim> qp_unit = mapping.transform_real_to_unit_cell(cell,soln_pt);
+ const Quadrature<dim> soln_qrule (qp_unit);
+ AssertThrow(soln_qrule.size() == 1, ExcInternalError());
+ FEValues<dim> 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
// Determine the true Newton update error for the problem
template <int dim,typename NumberType>
void Solid<dim,NumberType>::get_error_update(const BlockVector<double> &newton_update,
- Errors &error_update)
+ Errors &error_update)
{
BlockVector<double> error_ud(dofs_per_block);
for (unsigned int i = 0; i < dof_handler_ref.n_dofs(); ++i)
ScratchData_ASM(const FiniteElement<dim> &fe_cell,
const QGauss<dim> &qf_cell,
const UpdateFlags uf_cell,
- const QGauss<dim-1> & qf_face,
+ const QGauss<dim-1> & qf_face,
const UpdateFlags uf_face,
const BlockVector<double> &solution_total)
:
};
// 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<dim>::active_cell_iterator &cell,
ScratchData_ASM &scratch,
BlockVector<double> &system_rhs = const_cast<Solid<dim,NumberType> *>(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:
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.
cell->get_dof_indices(data.local_dof_indices);
const std::vector<std::shared_ptr<const PointHistory<dim,NumberType> > > lqph =
- const_cast<const Solid<dim,NumberType> *>(data.solid)->quadrature_point_history.get_data(cell);
+ const_cast<const Solid<dim,NumberType> *>(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
cell->get_dof_indices(data.local_dof_indices);
const std::vector<std::shared_ptr<const PointHistory<dim,ADNumberType> > > lqph =
- const_cast<const Solid<dim,ADNumberType> *>(data.solid)->quadrature_point_history.get_data(cell);
+ const_cast<const Solid<dim,ADNumberType> *>(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<double> 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.
// 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<ADNumberType> 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<SymmetricTensor<2, dim,ADNumberType> > &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<SymmetricTensor<2, dim,ADNumberType> > &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<n_independent_variables; ++I)
- {
- const ADNumberType &residual_I = residual_ad[I];
- data.cell_rhs(I) = -residual_I.val(); // RHS = - residual
- for (unsigned int J=0; J<n_independent_variables; ++J)
{
- // Compute the gradients of the residual entry [forward-mode]
- data.cell_matrix(I,J) = residual_I.dx(J); // linearisation_IJ
+ const ADNumberType &residual_I = residual_ad[I];
+ data.cell_rhs(I) = -residual_I.val(); // RHS = - residual
+ for (unsigned int J=0; J<n_independent_variables; ++J)
+ {
+ // Compute the gradients of the residual entry [forward-mode]
+ data.cell_matrix(I,J) = residual_I.dx(J); // linearisation_IJ
+ }
}
- }
}
};
-
+
template <int dim>
struct Assembler<dim,Sacado::Rad::ADvar<Sacado::Fad::DFad<double> > > : Assembler_Base<dim,Sacado::Rad::ADvar<Sacado::Fad::DFad<double> > >
{
cell->get_dof_indices(data.local_dof_indices);
const std::vector<std::shared_ptr<const PointHistory<dim,ADNumberType> > > 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<double> 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.
// 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:
// 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<n_independent_variables; ++I)
- {
- // This computes the adjoint df/dX_{i} [reverse-mode]
- const ADDerivType residual_I = local_dof_values_ad[I].adj();
- data.cell_rhs(I) = -residual_I.val(); // RHS = - residual
- for (unsigned int J=0; J<n_independent_variables; ++J)
{
- // Compute the gradients of the residual entry [forward-mode]
- data.cell_matrix(I,J) = residual_I.dx(J); // linearisation_IJ
+ // This computes the adjoint df/dX_{i} [reverse-mode]
+ const ADDerivType residual_I = local_dof_values_ad[I].adj();
+ data.cell_rhs(I) = -residual_I.val(); // RHS = - residual
+ for (unsigned int J=0; J<n_independent_variables; ++J)
+ {
+ // Compute the gradients of the residual entry [forward-mode]
+ data.cell_matrix(I,J) = residual_I.dx(J); // linearisation_IJ
+ }
}
- }
}
};
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<dim>(n_components),
- constraints,
- fe.component_mask(z_displacement));
- else
- VectorTools::interpolate_boundary_values(dof_handler_ref,
- boundary_id,
- ZeroFunction<dim>(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<dim>(n_components),
+ constraints,
+ fe.component_mask(z_displacement));
+ else
+ VectorTools::interpolate_boundary_values(dof_handler_ref,
+ boundary_id,
+ ZeroFunction<dim>(n_components),
+ constraints,
+ fe.component_mask(z_displacement));
+ }
constraints.close();
}
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<dim,NumberType> 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<double> NumberType;
- Solid<dim,NumberType> 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<double> > NumberType;
- Solid<dim,NumberType> solid_3d(parameters);
- solid_3d.run();
- }
- #endif
+ typedef double NumberType;
+ Solid<dim,NumberType> 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<double> NumberType;
+ Solid<dim,NumberType> 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<double> > NumberType;
+ Solid<dim,NumberType> 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)
{
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)))
+ );
}
}
}
MatrixType &system_matrix)
{
internal_create_system_matrix<dim>
- (dof_handler, quad, convection_function, parameters, time_step,
- [&constraints, &system_matrix](const std::vector<types::global_dof_index> &local_indices,
- const FullMatrix<double> &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<types::global_dof_index> &local_indices,
+ const FullMatrix<double> &cell_matrix)
+ {
+ constraints.distribute_local_to_global
+ (cell_matrix, local_indices, system_matrix);
+ });
}
template<int dim, typename MatrixType>
MatrixType &system_matrix)
{
internal_create_system_matrix<dim>
- (dof_handler, quad, convection_function, parameters, time_step,
- [&system_matrix](const std::vector<types::global_dof_index> &local_indices,
- const FullMatrix<double> &cell_matrix)
- {
- system_matrix.add(local_indices, cell_matrix);
- });
+ (dof_handler, quad, convection_function, parameters, time_step,
+ [&system_matrix](const std::vector<types::global_dof_index> &local_indices,
+ const FullMatrix<double> &cell_matrix)
+ {
+ system_matrix.add(local_indices, cell_matrix);
+ });
}
}
#endif
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<dim> fe_values(fe, quad, update_values | update_gradients |
update_quadrature_points | update_JxW_values);
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));
}
}
}
}
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);
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);
}
}
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
CDRProblem<dim>::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<dim>()),
- triangulation(mpi_communicator, typename Triangulation<dim>::MeshSmoothing
- (Triangulation<dim>::smoothing_on_refinement |
- Triangulation<dim>::smoothing_on_coarsening)),
- dof_handler(triangulation),
- convection_function
- {
- [](const Point<dim> 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<dim>()),
+triangulation(mpi_communicator, typename Triangulation<dim>::MeshSmoothing
+ (Triangulation<dim>::smoothing_on_refinement |
+ Triangulation<dim>::smoothing_on_coarsening)),
+dof_handler(triangulation),
+convection_function
+{
+ [](const Point<dim> p) -> Tensor<1, dim>
+ {Tensor<1, dim> v; v[0] = -p[1]; v[1] = p[0]; return v;}
+},
+forcing_function
+{
+ [](double t, const Point<dim> p) -> double
{
- [](double t, const Point<dim> 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());
}
// 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<dim, TrilinosWrappers::MPI::Vector>
- 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();
// parallel::distributed::SolutionTransfer::interpolate is called it uses
// those values to populate <code>temporary</code>.
TrilinosWrappers::MPI::Vector temporary
- (locally_owned_dofs, mpi_communicator);
+ (locally_owned_dofs, mpi_communicator);
solution_transfer.interpolate(temporary);
// After <code>temporary</code> has the correct value, this call correctly
// populates <code>completely_distributed_solution</code>, which had its
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);
// ------------- 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());
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_point<n_face_q_points; ++q_point)
{
fe_subface_values_cell.reinit (cell, face_no, subface_no);
fe_subface_values_cell.get_function_gradients (primal_solution,
- cell_grads);
+ cell_grads);
fe_face_values_neighbor.reinit (neighbor_child,
neighbor_neighbor);
fe_face_values_neighbor.get_function_gradients (primal_solution,
- neighbor_grads);
+ neighbor_grads);
for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
{
// ------------- integrate_over_regular_face -----------
fe_face_values_cell.reinit(cell, face_no);
fe_face_values_cell.get_function_gradients (tmp_solution,
- cell_grads);
+ cell_grads);
Assert (cell->neighbor(face_no).state() == IteratorState::valid,
ExcInternalError());
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<n_face_q_points; ++q_point)
{
fe_subface_values_cell.reinit (cell, face_no, subface_no);
fe_subface_values_cell.get_function_gradients (tmp_solution,
- cell_grads);
+ cell_grads);
fe_face_values_neighbor.reinit (neighbor_child,
neighbor_neighbor);
fe_face_values_neighbor.get_function_gradients (tmp_solution,
- neighbor_grads);
+ neighbor_grads);
for (unsigned int q_point=0; q_point<n_face_q_points; ++q_point)
{
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_accessor.h>
-#include <deal.II/dofs/dof_tools.h>
+#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/numerics/vector_tools.h>
//////////////////////////////////////////////////////////
//////////////////// 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 <int dim>
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<types::global_dof_index> &boundary_values_id_u,
- std::vector<double> 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<dim> &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<PETScWrappers::PreconditionBoomerAMG> 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<types::global_dof_index> &indices,
- std::vector<PetscScalar> &values);
- void get_vector_values(PETScWrappers::VectorBase &vector,
- const std::vector<types::global_dof_index> &indices,
- std::map<types::global_dof_index, types::global_dof_index> &map_from_Q1_to_Q2,
- std::vector<PetscScalar> &values);
-
- MPI_Comm mpi_communicator;
-
- //FINITE ELEMENT SPACE
- int degree_MAX;
- int degree_LS;
- DoFHandler<dim> dof_handler_LS;
- FE_Q<dim> fe_LS;
- IndexSet locally_owned_dofs_LS;
- IndexSet locally_relevant_dofs_LS;
-
- int degree_U;
- DoFHandler<dim> dof_handler_U;
- FE_Q<dim> 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<PETScWrappers::PreconditionBoomerAMG> MC_preconditioner;
-
- // BOUNDARIES
- std::vector<types::global_dof_index> boundary_values_id_u;
- std::vector<double> 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<types::global_dof_index, types::global_dof_index> map_from_Q1_to_Q2;
- std::map<types::global_dof_index, std::vector<types::global_dof_index> > 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<types::global_dof_index> &boundary_values_id_u,
+ std::vector<double> 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<dim> &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<PETScWrappers::PreconditionBoomerAMG> 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<types::global_dof_index> &indices,
+ std::vector<PetscScalar> &values);
+ void get_vector_values(PETScWrappers::VectorBase &vector,
+ const std::vector<types::global_dof_index> &indices,
+ std::map<types::global_dof_index, types::global_dof_index> &map_from_Q1_to_Q2,
+ std::vector<PetscScalar> &values);
+
+ MPI_Comm mpi_communicator;
+
+ //FINITE ELEMENT SPACE
+ int degree_MAX;
+ int degree_LS;
+ DoFHandler<dim> dof_handler_LS;
+ FE_Q<dim> fe_LS;
+ IndexSet locally_owned_dofs_LS;
+ IndexSet locally_relevant_dofs_LS;
+
+ int degree_U;
+ DoFHandler<dim> dof_handler_U;
+ FE_Q<dim> 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<PETScWrappers::PreconditionBoomerAMG> MC_preconditioner;
+
+ // BOUNDARIES
+ std::vector<types::global_dof_index> boundary_values_id_u;
+ std::vector<double> 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<types::global_dof_index, types::global_dof_index> map_from_Q1_to_Q2;
+ std::map<types::global_dof_index, std::vector<types::global_dof_index> > sparsity_pattern;
+};
template <int dim>
LevelSetSolver<dim>::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<dim> &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<dim> &triangulation,
+ MPI_Comm &mpi_communicator)
:
mpi_communicator (mpi_communicator),
degree_LS(degree_LS),
////////////////////////////////////////
template<int dim>
void LevelSetSolver<dim>::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;
template<int dim>
void LevelSetSolver<dim>::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;
/////////////////////////////////////////
template <int dim>
void LevelSetSolver<dim>::set_boundary_conditions(std::vector<types::global_dof_index> &boundary_values_id_u,
- std::vector<double> boundary_values_u)
+ std::vector<double> boundary_values_u)
{
this->boundary_values_id_u = boundary_values_id_u;
this->boundary_values_u = boundary_values_u;
//////////////////////////////////
template <int dim>
void LevelSetSolver<dim>::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();
template <int dim>
void LevelSetSolver<dim>::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();
////////// SET AND GET U //////////
///////////////////////////////////
template<int dim>
-void LevelSetSolver<dim>::get_unp1(PETScWrappers::MPI::Vector &unp1){unp1=this->unp1;}
+void LevelSetSolver<dim>::get_unp1(PETScWrappers::MPI::Vector &unp1) {unp1=this->unp1;}
// ------------------------------------------------------------------------------- //
// ------------------------------ COMPUTE SOLUTIONS ------------------------------ //
// ------------------------------------------------------------------------------- //
template <int dim>
void LevelSetSolver<dim>::nth_time_step()
-{
+{
assemble_EntRes_Matrix();
// COMPUTE SOLUTION //
if (TIME_INTEGRATION==FORWARD_EULER)
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();
}
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);
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
// 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);
////////////////////
// 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();
void LevelSetSolver<dim>::assemble_ML()
{
ML_vector=0;
-
+
const QGauss<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<double> cell_ML (dofs_per_cell);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
typename DoFHandler<dim>::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_point<n_q_points; ++q_point)
- {
- const double JxW = fe_values_LS.JxW(q_point);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- cell_ML (i) += fe_values_LS.shape_value(i,q_point)*JxW;
- }
- // distribute
- cell_LS->get_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_point<n_q_points; ++q_point)
+ {
+ const double JxW = fe_values_LS.JxW(q_point);
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_ML (i) += fe_values_LS.shape_value(i,q_point)*JxW;
+ }
+ // distribute
+ cell_LS->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (cell_ML,local_dof_indices,ML_vector);
}
// compress
ML_vector.compress(VectorOperation::add);
{
// 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);
void LevelSetSolver<dim>::assemble_MC()
{
MC_matrix=0;
-
+
const QGauss<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<double> cell_MC (dofs_per_cell, dofs_per_cell);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
std::vector<double> shape_values(dofs_per_cell);
typename DoFHandler<dim>::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_point<n_q_points; ++q_point)
- {
- const double JxW = fe_values_LS.JxW(q_point);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- shape_values[i] = fe_values_LS.shape_value(i,q_point);
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- cell_MC(i,j) += shape_values[i]*shape_values[j]*JxW;
- }
- // distribute
- cell_LS->get_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_point<n_q_points; ++q_point)
+ {
+ const double JxW = fe_values_LS.JxW(q_point);
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ shape_values[i] = fe_values_LS.shape_value(i,q_point);
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ cell_MC(i,j) += shape_values[i]*shape_values[j]*JxW;
+ }
+ // distribute
+ cell_LS->get_dof_indices (local_dof_indices);
+ constraints.distribute_local_to_global (cell_MC,local_dof_indices,MC_matrix);
}
// compress
MC_matrix.compress(VectorOperation::add);
CTy_matrix=0;
Cz_matrix=0;
CTz_matrix=0;
-
+
const QGauss<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<double> cell_Cij_x (dofs_per_cell_LS, dofs_per_cell_LS);
FullMatrix<double> cell_Cij_y (dofs_per_cell_LS, dofs_per_cell_LS);
FullMatrix<double> cell_Cij_z (dofs_per_cell_LS, dofs_per_cell_LS);
FullMatrix<double> cell_Cji_x (dofs_per_cell_LS, dofs_per_cell_LS);
FullMatrix<double> cell_Cji_y (dofs_per_cell_LS, dofs_per_cell_LS);
FullMatrix<double> cell_Cji_z (dofs_per_cell_LS, dofs_per_cell_LS);
-
+
std::vector<Tensor<1, dim> > shape_grads_LS(dofs_per_cell_LS);
std::vector<double> shape_values_LS(dofs_per_cell_LS);
-
+
std::vector<types::global_dof_index> local_dof_indices_LS (dofs_per_cell_LS);
-
- typename DoFHandler<dim>::active_cell_iterator cell_LS, endc_LS;
+
+ typename DoFHandler<dim>::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_point<n_q_points; ++q_point)
- {
- const double JxW = fe_values_LS.JxW(q_point);
- for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
- {
- shape_values_LS[i] = fe_values_LS.shape_value(i,q_point);
- shape_grads_LS [i] = fe_values_LS.shape_grad (i,q_point);
- }
-
- for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
- for (unsigned int j=0; j < dofs_per_cell_LS; j++)
- {
- cell_Cij_x(i,j) += (shape_grads_LS[j][0])*shape_values_LS[i]*JxW;
- cell_Cij_y(i,j) += (shape_grads_LS[j][1])*shape_values_LS[i]*JxW;
- cell_Cji_x(i,j) += (shape_grads_LS[i][0])*shape_values_LS[j]*JxW;
- cell_Cji_y(i,j) += (shape_grads_LS[i][1])*shape_values_LS[j]*JxW;
- if (dim==3)
- {
- cell_Cij_z(i,j) += (shape_grads_LS[j][2])*shape_values_LS[i]*JxW;
- cell_Cji_z(i,j) += (shape_grads_LS[i][2])*shape_values_LS[j]*JxW;
- }
- }
- }
- // Distribute
- constraints.distribute_local_to_global(cell_Cij_x,local_dof_indices_LS,Cx_matrix);
- constraints.distribute_local_to_global(cell_Cji_x,local_dof_indices_LS,CTx_matrix);
- constraints.distribute_local_to_global(cell_Cij_y,local_dof_indices_LS,Cy_matrix);
- constraints.distribute_local_to_global(cell_Cji_y,local_dof_indices_LS,CTy_matrix);
- if (dim==3)
- {
- constraints.distribute_local_to_global(cell_Cij_z,local_dof_indices_LS,Cz_matrix);
- constraints.distribute_local_to_global(cell_Cji_z,local_dof_indices_LS,CTz_matrix);
- }
+ 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_point<n_q_points; ++q_point)
+ {
+ const double JxW = fe_values_LS.JxW(q_point);
+ for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
+ {
+ shape_values_LS[i] = fe_values_LS.shape_value(i,q_point);
+ shape_grads_LS [i] = fe_values_LS.shape_grad (i,q_point);
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
+ for (unsigned int j=0; j < dofs_per_cell_LS; j++)
+ {
+ cell_Cij_x(i,j) += (shape_grads_LS[j][0])*shape_values_LS[i]*JxW;
+ cell_Cij_y(i,j) += (shape_grads_LS[j][1])*shape_values_LS[i]*JxW;
+ cell_Cji_x(i,j) += (shape_grads_LS[i][0])*shape_values_LS[j]*JxW;
+ cell_Cji_y(i,j) += (shape_grads_LS[i][1])*shape_values_LS[j]*JxW;
+ if (dim==3)
+ {
+ cell_Cij_z(i,j) += (shape_grads_LS[j][2])*shape_values_LS[i]*JxW;
+ cell_Cji_z(i,j) += (shape_grads_LS[i][2])*shape_values_LS[j]*JxW;
+ }
+ }
+ }
+ // Distribute
+ constraints.distribute_local_to_global(cell_Cij_x,local_dof_indices_LS,Cx_matrix);
+ constraints.distribute_local_to_global(cell_Cji_x,local_dof_indices_LS,CTx_matrix);
+ constraints.distribute_local_to_global(cell_Cij_y,local_dof_indices_LS,Cy_matrix);
+ constraints.distribute_local_to_global(cell_Cji_y,local_dof_indices_LS,CTy_matrix);
+ if (dim==3)
+ {
+ constraints.distribute_local_to_global(cell_Cij_z,local_dof_indices_LS,Cz_matrix);
+ constraints.distribute_local_to_global(cell_Cji_z,local_dof_indices_LS,CTz_matrix);
+ }
}
// COMPRESS
Cx_matrix.compress(VectorOperation::add);
const QGauss<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<dim> 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<double> cell_K_times_solution (dofs_per_cell);
std::vector<Tensor<1,dim> > un_grads (n_q_points);
std::vector<double> old_vx_values (n_q_points);
- std::vector<double> old_vy_values (n_q_points);
- std::vector<double> old_vz_values (n_q_points);
+ std::vector<double> old_vy_values (n_q_points);
+ std::vector<double> old_vz_values (n_q_points);
std::vector<double> shape_values(dofs_per_cell);
std::vector<Tensor<1,dim> > shape_grads(dofs_per_cell);
Vector<double> un_dofs(dofs_per_cell);
-
+
std::vector<types::global_dof_index> indices_LS (dofs_per_cell);
// loop on cells
typename DoFHandler<dim>::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<dim>::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_point<n_q_points; ++q_point)
- {
- v[0] = old_vx_values[q_point]; v[1] = old_vy_values[q_point];
- if(dim==3) v[2] = old_vz_values[q_point]; //dim=3
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- cell_K_times_solution(i) += (v*un_grads[q_point])
- *fe_values_LS.shape_value(i,q_point)*fe_values_LS.JxW(q_point);
- }
- // distribute
- constraints.distribute_local_to_global (cell_K_times_solution, indices_LS, K_times_solution);
+ 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_point<n_q_points; ++q_point)
+ {
+ v[0] = old_vx_values[q_point];
+ v[1] = old_vy_values[q_point];
+ if (dim==3) v[2] = old_vz_values[q_point]; //dim=3
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_K_times_solution(i) += (v*un_grads[q_point])
+ *fe_values_LS.shape_value(i,q_point)*fe_values_LS.JxW(q_point);
+ }
+ // distribute
+ constraints.distribute_local_to_global (cell_K_times_solution, indices_LS, K_times_solution);
}
K_times_solution.compress(VectorOperation::add);
}
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
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);
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<double> 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
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);
EntRes_matrix=0;
entropy_normalization_factor=0;
SuppSize_matrix=0;
-
+
const QGauss<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<dim> 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();
std::vector<double> vyqn (n_q_points);
std::vector<double> vzqn (n_q_points);
std::vector<double> vxqnm1 (n_q_points);
- std::vector<double> vyqnm1 (n_q_points);
- std::vector<double> vzqnm1 (n_q_points);
-
+ std::vector<double> vyqnm1 (n_q_points);
+ std::vector<double> vzqnm1 (n_q_points);
+
FullMatrix<double> cell_EntRes (dofs_per_cell_LS, dofs_per_cell_LS);
FullMatrix<double> cell_volume (dofs_per_cell_LS, dofs_per_cell_LS);
-
+
std::vector<Tensor<1, dim> > shape_grads_LS(dofs_per_cell_LS);
std::vector<double> shape_values_LS(dofs_per_cell_LS);
-
+
std::vector<types::global_dof_index> local_dof_indices_LS (dofs_per_cell_LS);
-
- typename DoFHandler<dim>::active_cell_iterator cell_LS, endc_LS;
+
+ typename DoFHandler<dim>::active_cell_iterator cell_LS, endc_LS;
cell_LS = dof_handler_LS.begin_active();
endc_LS = dof_handler_LS.end();
typename DoFHandler<dim>::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;
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; q<n_q_points; ++q)
- {
- Rk = 1./time_step*(ENTROPY(uqn[q])-ENTROPY(uqnm1[q]))
- +(vxqn[q]*ENTROPY_GRAD(uqn[q],guqn[q][0])+vyqn[q]*ENTROPY_GRAD(uqn[q],guqn[q][1]))/2.
- +(vxqnm1[q]*ENTROPY_GRAD(uqnm1[q],guqnm1[q][0])+vyqnm1[q]*ENTROPY_GRAD(uqnm1[q],guqnm1[q][1]))/2.;
- if (dim==3)
- Rk += 0.5*(vzqn[q]*ENTROPY_GRAD(uqn[q],guqn[q][2])+vzqnm1[q]*ENTROPY_GRAD(uqnm1[q],guqnm1[q][2]));
-
- const double JxW = fe_values_LS.JxW(q);
- for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
- {
- shape_values_LS[i] = fe_values_LS.shape_value(i,q);
- shape_grads_LS [i] = fe_values_LS.shape_grad (i,q);
- }
-
- for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
- for (unsigned int j=0; j < dofs_per_cell_LS; j++)
- {
- cell_EntRes (i,j) += Rk*shape_values_LS[i]*shape_values_LS[j]*JxW;
- cell_volume (i,j) += JxW;
- }
- cell_entropy_mass += ENTROPY(uqn[q])*JxW;
- cell_volume_double += JxW;
-
- cell_min_entropy = std::min(cell_min_entropy,ENTROPY(uqn[q]));
- cell_max_entropy = std::max(cell_max_entropy,ENTROPY(uqn[q]));
- }
- entropy_mass += cell_entropy_mass;
- volume += cell_volume_double;
-
- min_entropy = std::min(min_entropy,cell_min_entropy);
- max_entropy = std::max(max_entropy,cell_max_entropy);
- // Distribute
- constraints.distribute_local_to_global(cell_EntRes,local_dof_indices_LS,EntRes_matrix);
- constraints.distribute_local_to_global(cell_volume,local_dof_indices_LS,SuppSize_matrix);
+ 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; q<n_q_points; ++q)
+ {
+ Rk = 1./time_step*(ENTROPY(uqn[q])-ENTROPY(uqnm1[q]))
+ +(vxqn[q]*ENTROPY_GRAD(uqn[q],guqn[q][0])+vyqn[q]*ENTROPY_GRAD(uqn[q],guqn[q][1]))/2.
+ +(vxqnm1[q]*ENTROPY_GRAD(uqnm1[q],guqnm1[q][0])+vyqnm1[q]*ENTROPY_GRAD(uqnm1[q],guqnm1[q][1]))/2.;
+ if (dim==3)
+ Rk += 0.5*(vzqn[q]*ENTROPY_GRAD(uqn[q],guqn[q][2])+vzqnm1[q]*ENTROPY_GRAD(uqnm1[q],guqnm1[q][2]));
+
+ const double JxW = fe_values_LS.JxW(q);
+ for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
+ {
+ shape_values_LS[i] = fe_values_LS.shape_value(i,q);
+ shape_grads_LS [i] = fe_values_LS.shape_grad (i,q);
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
+ for (unsigned int j=0; j < dofs_per_cell_LS; j++)
+ {
+ cell_EntRes (i,j) += Rk*shape_values_LS[i]*shape_values_LS[j]*JxW;
+ cell_volume (i,j) += JxW;
+ }
+ cell_entropy_mass += ENTROPY(uqn[q])*JxW;
+ cell_volume_double += JxW;
+
+ cell_min_entropy = std::min(cell_min_entropy,ENTROPY(uqn[q]));
+ cell_max_entropy = std::max(cell_max_entropy,ENTROPY(uqn[q]));
+ }
+ entropy_mass += cell_entropy_mass;
+ volume += cell_volume_double;
+
+ min_entropy = std::min(min_entropy,cell_min_entropy);
+ max_entropy = std::max(max_entropy,cell_max_entropy);
+ // Distribute
+ constraints.distribute_local_to_global(cell_EntRes,local_dof_indices_LS,EntRes_matrix);
+ constraints.distribute_local_to_global(cell_volume,local_dof_indices_LS,SuppSize_matrix);
}
EntRes_matrix.compress(VectorOperation::add);
SuppSize_matrix.compress(VectorOperation::add);
- //ENTROPY NORM FACTOR
+ //ENTROPY NORM FACTOR
volume = Utilities::MPI::sum(volume,mpi_communicator);
entropy_mass = Utilities::MPI::sum(entropy_mass,mpi_communicator)/volume;
min_entropy = Utilities::MPI::min(min_entropy,mpi_communicator);
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;
// 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<int dim>
-void LevelSetSolver<dim>::check_max_principle(PETScWrappers::MPI::Vector &unp1_solution)
+void LevelSetSolver<dim>::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<types::global_dof_index> local_dof_indices (dofs_per_cell);
-
+
double tol=1e-10;
typename DoFHandler<dim>::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; i<dofs_per_cell; i++)
- if (locally_owned_dofs_LS.is_element(local_dof_indices[i]))
- {
- double solni = unp1_solution(local_dof_indices[i]);
- if (solni - umin_vector(local_dof_indices[i]) < -tol || umax_vector(local_dof_indices[i]) - solni < -tol)
- {
- pcout << "MAX Principle violated" << std::endl;
- abort();
- }
- }
+ cell_LS->get_dof_indices(local_dof_indices);
+ for (unsigned int i=0; i<dofs_per_cell; i++)
+ if (locally_owned_dofs_LS.is_element(local_dof_indices[i]))
+ {
+ double solni = unp1_solution(local_dof_indices[i]);
+ if (solni - umin_vector(local_dof_indices[i]) < -tol || umax_vector(local_dof_indices[i]) - solni < -tol)
+ {
+ pcout << "MAX Principle violated" << std::endl;
+ abort();
+ }
+ }
}
}
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 //
/////////////////////////////
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);
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]);
// 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);
// 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);
std::vector<double> 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
{
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<NUM_ITER; iter++)
- {
- 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<types::global_dof_index> gj_indices (gj,gj+ncolumns);
- std::vector<double> 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<types::global_dof_index> gj_indices(gj,gj+ncolumns);
- std::vector<double> Rpos(ncolumns);
- std::vector<double> 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<double> 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<types::global_dof_index> gj_indices (gj,gj+ncolumns);
+ std::vector<double> 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<types::global_dof_index> gj_indices(gj,gj+ncolumns);
+ std::vector<double> Rpos(ncolumns);
+ std::vector<double> 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<double> 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<int dim>
void LevelSetSolver<dim>::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
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();
template<int dim>
void LevelSetSolver<dim>::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
//////////////////
// 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;
/////////////////
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)
std::vector<types::global_dof_index> local_dof_indices_U (dofs_per_cell_U);
typename DoFHandler<dim>::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<dim>::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; i<dofs_per_cell_LS; ++i)
- map_from_Q1_to_Q2[local_dof_indices_LS[i]] = local_dof_indices_U[i];
+ cell_LS->get_dof_indices(local_dof_indices_LS);
+ cell_U->get_dof_indices(local_dof_indices_U);
+ for (unsigned int i=0; i<dofs_per_cell_LS; ++i)
+ map_from_Q1_to_Q2[local_dof_indices_LS[i]] = local_dof_indices_U[i];
}
}
template <int dim>
-void LevelSetSolver<dim>::solve(const ConstraintMatrix &constraints,
- PETScWrappers::MPI::SparseMatrix &Matrix,
- std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> preconditioner,
- PETScWrappers::MPI::Vector &completely_distributed_solution,
- const PETScWrappers::MPI::Vector &rhs)
+void LevelSetSolver<dim>::solve(const ConstraintMatrix &constraints,
+ PETScWrappers::MPI::SparseMatrix &Matrix,
+ std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> 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);
template <int dim>
void LevelSetSolver<dim>::save_old_solution()
{
- unm1 = un;
- un = unp1;
+ unm1 = un;
+ un = unp1;
}
template <int dim>
{
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;
}
// ------------------------------ MY PETSC WRAPPERS ------------------------------ //
// ------------------------------------------------------------------------------- //
template<int dim>
-void LevelSetSolver<dim>::get_vector_values (PETScWrappers::VectorBase &vector,
- const std::vector<types::global_dof_index> &indices,
- std::vector<PetscScalar> &values)
+void LevelSetSolver<dim>::get_vector_values (PETScWrappers::VectorBase &vector,
+ const std::vector<types::global_dof_index> &indices,
+ std::vector<PetscScalar> &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<int dim>
-void LevelSetSolver<dim>::get_vector_values (PETScWrappers::VectorBase &vector,
- const std::vector<types::global_dof_index> &indices,
- std::map<types::global_dof_index, types::global_dof_index> &map_from_Q1_to_Q2,
- std::vector<PetscScalar> &values)
+void LevelSetSolver<dim>::get_vector_values (PETScWrappers::VectorBase &vector,
+ const std::vector<types::global_dof_index> &indices,
+ std::map<types::global_dof_index, types::global_dof_index> &map_from_Q1_to_Q2,
+ std::vector<PetscScalar> &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);
// 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
{
public:
MultiPhase (const unsigned int degree_LS,
- const unsigned int degree_U);
+ const unsigned int degree_U);
~MultiPhase ();
void run ();
void set_boundary_inlet();
void get_boundary_values_U();
void get_boundary_values_phi(std::vector<types::global_dof_index> &boundary_values_id_phi,
- std::vector<double> &boundary_values_phi);
+ std::vector<double> &boundary_values_phi);
void output_results();
void output_vectors();
void output_rho();
MPI_Comm mpi_communicator;
parallel::distributed::Triangulation<dim> triangulation;
-
+
int degree_LS;
DoFHandler<dim> dof_handler_LS;
FE_Q<dim> fe_LS;
FE_Q<dim> fe_P;
IndexSet locally_owned_dofs_P;
IndexSet locally_relevant_dofs_P;
-
+
ConditionalOStream pcout;
// SOLUTION VECTORS
double umax;
double min_h;
- double sharpness;
+ double sharpness;
int sharpness_integer;
unsigned int n_refinement;
};
template <int dim>
-MultiPhase<dim>::MultiPhase (const unsigned int degree_LS,
- const unsigned int degree_U)
+MultiPhase<dim>::MultiPhase (const unsigned int degree_LS,
+ const unsigned int degree_U)
:
mpi_communicator (MPI_COMM_WORLD),
triangulation (mpi_communicator,
- typename Triangulation<dim>::MeshSmoothing
- (Triangulation<dim>::smoothing_on_refinement |
- Triangulation<dim>::smoothing_on_coarsening)),
+ typename Triangulation<dim>::MeshSmoothing
+ (Triangulation<dim>::smoothing_on_refinement |
+ Triangulation<dim>::smoothing_on_coarsening)),
degree_LS(degree_LS),
dof_handler_LS (triangulation),
fe_LS (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))
{}
/////////////////////////////////////////
template <int dim>
void MultiPhase<dim>::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;
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);
// init condition for phi
completely_distributed_solution_phi = 0;
VectorTools::interpolate(dof_handler_LS,
- InitialPhi<dim>(PROBLEM, sharpness),
- completely_distributed_solution_phi);
+ InitialPhi<dim>(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<dim>(),
- completely_distributed_solution_u);
+ ZeroFunction<dim>(),
+ 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<dim>(),
- completely_distributed_solution_v);
+ ZeroFunction<dim>(),
+ 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<dim>(),
- completely_distributed_solution_p);
+ ZeroFunction<dim>(),
+ completely_distributed_solution_p);
constraints.distribute (completely_distributed_solution_p);
locally_relevant_solution_p = completely_distributed_solution_p;
}
-
+
template <int dim>
void MultiPhase<dim>::init_constraints()
{
std::map<types::global_dof_index, double> map_boundary_values_v;
std::map<types::global_dof_index, double> 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<dim>(),map_boundary_values_u);
- VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction<dim>(),map_boundary_values_v);
+ VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction<dim>(),map_boundary_values_v);
// RIGHT
- VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction<dim>(),map_boundary_values_u);
- VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction<dim>(),map_boundary_values_v);
- // BOTTOM
- VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_u);
- VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_v);
+ VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction<dim>(),map_boundary_values_v);
+ // BOTTOM
+ VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_v);
// TOP
- VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_u);
- VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_v);
- }
+ VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),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<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,0,ZeroFunction<dim>(),map_boundary_values_u);
// RIGHT
- VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction<dim>(),map_boundary_values_u);
- // BOTTOM
- VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_u);
- VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_v);
+ VectorTools::interpolate_boundary_values (dof_handler_U,1,ZeroFunction<dim>(),map_boundary_values_u);
+ // BOTTOM
+ VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,2,ZeroFunction<dim>(),map_boundary_values_v);
// TOP
- VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_u);
- VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_v);
+ VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_u);
+ VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),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<dim>(PROBLEM),map_boundary_values_u);
VectorTools::interpolate_boundary_values (dof_handler_U,3,ZeroFunction<dim>(),map_boundary_values_u);
VectorTools::interpolate_boundary_values (dof_handler_U,3,BoundaryV<dim>(PROBLEM),map_boundary_values_v);
}
- else
+ else
{
pcout << "Error in type of PROBLEM at Boundary Conditions" << std::endl;
abort();
boundary_values_v.resize(map_boundary_values_v.size());
std::map<types::global_dof_index,double>::const_iterator boundary_value_u =map_boundary_values_u.begin();
std::map<types::global_dof_index,double>::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;
{
const QGauss<dim-1> face_quadrature_formula(1); // center of the face
FEFaceValues<dim> 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<double> u_value (n_face_q_points);
- std::vector<double> v_value (n_face_q_points);
-
+ std::vector<double> v_value (n_face_q_points);
+
typename DoFHandler<dim>::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<GeometryInfo<dim>::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 <int dim>
void MultiPhase<dim>::get_boundary_values_phi(std::vector<types::global_dof_index> &boundary_values_id_phi,
- std::vector<double> &boundary_values_phi)
+ std::vector<double> &boundary_values_phi)
{
std::map<types::global_dof_index, double> 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<dim>(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<types::global_dof_index,double>::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)
{
void MultiPhase<dim>::output_vectors()
{
DataOut<dim> 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<std::string> filenames;
for (unsigned int i=0;
- i<Utilities::MPI::n_mpi_processes(mpi_communicator);
- ++i)
- filenames.push_back ("sol_vectors-" +
- Utilities::int_to_string (output_number, 3) +
- "." +
- Utilities::int_to_string (i, 4) +
- ".vtu");
-
+ i<Utilities::MPI::n_mpi_processes(mpi_communicator);
+ ++i)
+ filenames.push_back ("sol_vectors-" +
+ Utilities::int_to_string (output_number, 3) +
+ "." +
+ Utilities::int_to_string (i, 4) +
+ ".vtu");
+
std::ofstream master_output ((filename + ".pvtu").c_str());
data_out.write_pvtu_record (master_output, filenames);
}
template <int dim>
void MultiPhase<dim>::output_rho()
{
- Postprocessor<dim> postprocessor(eps,rho_air,rho_fluid);
+ Postprocessor<dim> postprocessor(eps,rho_air,rho_fluid);
DataOut<dim> 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<std::string> filenames;
for (unsigned int i=0;
- i<Utilities::MPI::n_mpi_processes(mpi_communicator);
- ++i)
- filenames.push_back ("sol_rho-" +
- Utilities::int_to_string (output_number, 3) +
- "." +
- Utilities::int_to_string (i, 4) +
- ".vtu");
-
+ i<Utilities::MPI::n_mpi_processes(mpi_communicator);
+ ++i)
+ filenames.push_back ("sol_rho-" +
+ Utilities::int_to_string (output_number, 3) +
+ "." +
+ Utilities::int_to_string (i, 4) +
+ ".vtu");
+
std::ofstream master_output ((filename + ".pvtu").c_str());
data_out.write_pvtu_record (master_output, filenames);
}
//PROBLEM=FILLING_TANK;
//PROBLEM=SMALL_WAVE_PERTURBATION;
//PROBLEM=FALLING_DROP;
-
- ForceTerms<dim> force_function(std::vector<double>{0.0,-1.0});
+
+ ForceTerms<dim> force_function(std::vector<double> {0.0,-1.0});
//////////////////////////////////////
// PARAMETERS FOR TRANSPORT PROBLEM //
//////////////////////////////////////
//ALGORITHM = "NMPP_uH";
ALGORITHM = "MPP_uH";
- // ADJUST PARAMETERS ACCORDING TO PROBLEM
+ // ADJUST PARAMETERS ACCORDING TO PROBLEM
if (PROBLEM==FALLING_DROP)
n_refinement=7;
//////////////
if (PROBLEM==FILLING_TANK)
GridGenerator::hyper_rectangle(triangulation,
- Point<dim>(0.0,0.0), Point<dim>(0.4,0.4), true);
+ Point<dim>(0.0,0.0), Point<dim>(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<dim>(0.0,0.0), Point<dim>(1.0,0.5), true);
+ GridGenerator::subdivided_hyper_rectangle
+ (triangulation, repetitions, Point<dim>(0.0,0.0), Point<dim>(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<dim>(0.0,0.0), Point<dim>(0.3,0.9), true);
+ GridGenerator::subdivided_hyper_rectangle
+ (triangulation, repetitions, Point<dim>(0.0,0.0), Point<dim>(0.3,0.9), true);
}
triangulation.refine_global (n_refinement);
// SETUP
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<dim> 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<dim> 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();
}
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();
}
///////////////////// NAVIER STOKES SOLVER //////////////////////
/////////////////////////////////////////////////////////////////
template<int dim>
-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<dim> &force_function,
- const bool verbose,
- parallel::distributed::Triangulation<dim> &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<dim> &force_function,
+ const bool verbose,
+ parallel::distributed::Triangulation<dim> &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<dim> &force_function,
- Function<dim> &rho_function,
- Function<dim> &nu_function,
- const bool verbose,
- parallel::distributed::Triangulation<dim> &triangulation,
- MPI_Comm &mpi_communicator);
+ NavierStokesSolver(const unsigned int degree_LS,
+ const unsigned int degree_U,
+ const double time_step,
+ Function<dim> &force_function,
+ Function<dim> &rho_function,
+ Function<dim> &nu_function,
+ const bool verbose,
+ parallel::distributed::Triangulation<dim> &triangulation,
+ MPI_Comm &mpi_communicator);
// rho and nu functions
void set_rho_and_nu_functions(const Function<dim> &rho_function,
- const Function<dim> &nu_function);
+ const Function<dim> &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<types::global_dof_index> boundary_values_id_u,
- std::vector<types::global_dof_index> boundary_values_id_v, std::vector<double> boundary_values_u,
- std::vector<double> boundary_values_v);
+ std::vector<types::global_dof_index> boundary_values_id_v, std::vector<double> boundary_values_u,
+ std::vector<double> boundary_values_v);
void set_boundary_conditions(std::vector<types::global_dof_index> boundary_values_id_u,
- std::vector<types::global_dof_index> boundary_values_id_v,
- std::vector<types::global_dof_index> boundary_values_id_w, std::vector<double> boundary_values_u,
- std::vector<double> boundary_values_v, std::vector<double> boundary_values_w);
+ std::vector<types::global_dof_index> boundary_values_id_v,
+ std::vector<types::global_dof_index> boundary_values_id_w, std::vector<double> boundary_values_u,
+ std::vector<double> boundary_values_v, std::vector<double> 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 //
void assemble_system_dpsi_q();
// SOLVERS //
void solve_U(const ConstraintMatrix &constraints, PETScWrappers::MPI::SparseMatrix &Matrix,
- std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> preconditioner,
- PETScWrappers::MPI::Vector &completely_distributed_solution,
- const PETScWrappers::MPI::Vector &rhs);
+ std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> 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<PETScWrappers::PreconditionBoomerAMG> preconditioner,
- PETScWrappers::MPI::Vector &completely_distributed_solution,
- const PETScWrappers::MPI::Vector &rhs);
+ std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> 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();
// CONSTRUCTOR FOR LEVEL SET
template<int dim>
NavierStokesSolver<dim>::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<dim> &force_function,
- const bool verbose,
- parallel::distributed::Triangulation<dim> &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<dim> &force_function,
+ const bool verbose,
+ parallel::distributed::Triangulation<dim> &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)
// CONSTRUCTOR NOT FOR LEVEL SET
template<int dim>
NavierStokesSolver<dim>::NavierStokesSolver(const unsigned int degree_LS,
- const unsigned int degree_U,
- const double time_step,
- Function<dim> &force_function,
- Function<dim> &rho_function,
- Function<dim> &nu_function,
- const bool verbose,
- parallel::distributed::Triangulation<dim> &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<dim> &force_function,
+ Function<dim> &rho_function,
+ Function<dim> &nu_function,
+ const bool verbose,
+ parallel::distributed::Triangulation<dim> &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<int dim>
-NavierStokesSolver<dim>::~NavierStokesSolver() {
+NavierStokesSolver<dim>::~NavierStokesSolver()
+{
dof_handler_LS.clear();
dof_handler_U.clear();
dof_handler_P.clear();
/////////////////////////////////////////////////////////////
template<int dim>
void NavierStokesSolver<dim>::set_rho_and_nu_functions(const Function<dim> &rho_function,
- const Function<dim> &nu_function) {
+ const Function<dim> &nu_function)
+{
this->rho_function=rho_function;
this->nu_function=nu_function;
}
template<int dim>
void NavierStokesSolver<dim>::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();
template<int dim>
void NavierStokesSolver<dim>::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;
template<int dim>
void NavierStokesSolver<dim>::set_boundary_conditions(std::vector<types::global_dof_index> boundary_values_id_u,
- std::vector<types::global_dof_index> boundary_values_id_v,
- std::vector<double> boundary_values_u,
- std::vector<double> boundary_values_v)
+ std::vector<types::global_dof_index> boundary_values_id_v,
+ std::vector<double> boundary_values_u,
+ std::vector<double> boundary_values_v)
{
this->boundary_values_id_u=boundary_values_id_u;
this->boundary_values_id_v=boundary_values_id_v;
template<int dim>
void NavierStokesSolver<dim>::set_boundary_conditions(std::vector<types::global_dof_index> boundary_values_id_u,
- std::vector<types::global_dof_index> boundary_values_id_v,
- std::vector<types::global_dof_index> boundary_values_id_w,
- std::vector<double> boundary_values_u,
- std::vector<double> boundary_values_v,
- std::vector<double> boundary_values_w)
+ std::vector<types::global_dof_index> boundary_values_id_v,
+ std::vector<types::global_dof_index> boundary_values_id_w,
+ std::vector<double> boundary_values_u,
+ std::vector<double> boundary_values_v,
+ std::vector<double> boundary_values_w)
{
this->boundary_values_id_u=boundary_values_id_u;
this->boundary_values_id_v=boundary_values_id_v;
template<int dim>
void NavierStokesSolver<dim>::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<int dim>
void NavierStokesSolver<dim>::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<int dim>
-void NavierStokesSolver<dim>::set_phi(PETScWrappers::MPI::Vector locally_relevant_solution_phi) {
+void NavierStokesSolver<dim>::set_phi(PETScWrappers::MPI::Vector locally_relevant_solution_phi)
+{
this->locally_relevant_solution_phi=locally_relevant_solution_phi;
}
template<int dim>
-void NavierStokesSolver<dim>::get_rho_and_nu(double phi) {
+void NavierStokesSolver<dim>::get_rho_and_nu(double phi)
+{
double H=0;
// get rho, nu
if (phi>eps)
}
template<int dim>
-void NavierStokesSolver<dim>::get_pressure(PETScWrappers::MPI::Vector &locally_relevant_solution_p)
+void NavierStokesSolver<dim>::get_pressure(PETScWrappers::MPI::Vector &locally_relevant_solution_p)
{
locally_relevant_solution_p=this->locally_relevant_solution_p;
}
template<int dim>
void NavierStokesSolver<dim>::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<int dim>
void NavierStokesSolver<dim>::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;
///////////// SETUP AND INITIAL CONDITION /////////////
///////////////////////////////////////////////////////
template<int dim>
-void NavierStokesSolver<dim>::setup() {
+void NavierStokesSolver<dim>::setup()
+{
pcout<<"***** SETUP IN NAVIER STOKES SOLVER *****"<<std::endl;
setup_DOF();
init_constraints();
}
template<int dim>
-void NavierStokesSolver<dim>::setup_DOF() {
+void NavierStokesSolver<dim>::setup_DOF()
+{
rho_min = 1.;
degree_MAX=std::max(degree_LS,degree_U);
// setup system LS
}
template<int dim>
-void NavierStokesSolver<dim>::setup_VECTORS() {
+void NavierStokesSolver<dim>::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);
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);
////////////////////////////
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<int dim>
-void NavierStokesSolver<dim>::init_constraints() {
+void NavierStokesSolver<dim>::init_constraints()
+{
//grl constraints
constraints.clear();
constraints.reinit(locally_relevant_dofs_U);
////////////////// ASSEMBLE SYSTEMS ///////////////////
///////////////////////////////////////////////////////
template<int dim>
-void NavierStokesSolver<dim>::assemble_system_U()
+void NavierStokesSolver<dim>::assemble_system_U()
{
- if (rebuild_Matrix_U==true)
+ if (rebuild_Matrix_U==true)
{
system_Matrix_u=0;
system_Matrix_v=0;
system_rhs_u=0;
system_rhs_v=0;
system_rhs_w=0;
-
+
const QGauss<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<dim> 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<dim> 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<double> cell_A_u(dofs_per_cell,dofs_per_cell);
Vector<double> cell_rhs_u(dofs_per_cell);
Vector<double> cell_rhs_v(dofs_per_cell);
Vector<double> cell_rhs_w(dofs_per_cell);
-
+
std::vector<double> phiqnp1(n_q_points);
-
+
std::vector<double> uqn(n_q_points);
std::vector<double> uqnm1(n_q_points);
std::vector<double> vqn(n_q_points);
std::vector<Tensor<1, dim> > grad_pqn(n_q_points);
std::vector<Tensor<1, dim> > grad_psiqn(n_q_points);
std::vector<Tensor<1, dim> > grad_psiqnm1(n_q_points);
-
+
std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
std::vector<Tensor<1, dim> > shape_grad(dofs_per_cell);
std::vector<double> shape_value(dofs_per_cell);
-
+
double force_u;
double force_v;
double force_w;
double rho;
Vector<double> force_terms(dim);
- typename DoFHandler<dim>::active_cell_iterator
- cell_U=dof_handler_U.begin_active(), endc_U=dof_handler_U.end();
+ typename DoFHandler<dim>::active_cell_iterator
+ cell_U=dof_handler_U.begin_active(), endc_U=dof_handler_U.end();
typename DoFHandler<dim>::active_cell_iterator cell_P=dof_handler_P.begin_active();
typename DoFHandler<dim>::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_point<n_q_points; ++q_point) {
- const double JxW=fe_values_U.JxW(q_point);
- for (unsigned int i=0; i<dofs_per_cell; ++i) {
- shape_grad[i]=fe_values_U.shape_grad(i,q_point);
- shape_value[i]=fe_values_U.shape_value(i,q_point);
- }
-
- pressure_grad_u=(grad_pqn[q_point][0]+4./3*grad_psiqn[q_point][0]-1./3*grad_psiqnm1[q_point][0]);
- pressure_grad_v=(grad_pqn[q_point][1]+4./3*grad_psiqn[q_point][1]-1./3*grad_psiqnm1[q_point][1]);
- if (dim==3)
- pressure_grad_w=(grad_pqn[q_point][2]+4./3*grad_psiqn[q_point][2]-1./3*grad_psiqnm1[q_point][2]);
-
- if (LEVEL_SET==1) // use level set to define rho and nu
- get_rho_and_nu(phiqnp1[q_point]);
- else // rho and nu are defined through functions
- {
- rho_value=rho_function.value(fe_values_U.quadrature_point(q_point));
- nu_value=nu_function.value(fe_values_U.quadrature_point(q_point));
- }
-
- // Non-linearity: for semi-implicit
- u_star=2*uqn[q_point]-uqnm1[q_point];
- v_star=2*vqn[q_point]-vqnm1[q_point];
- if (dim==3)
- w_star=2*wqn[q_point]-wqnm1[q_point];
-
- // for explicit nonlinearity
- //Un[0] = uqn[q_point];
- //Un[1] = vqn[q_point];
- //if (dim==3)
- //Un[2] = wqn[q_point];
-
- //double nonlinearity_u = Un*grad_un[q_point];
- //double nonlinearity_v = Un*grad_vn[q_point];
- //double nonlinearity_w = 0;
- //if (dim==3)
- //nonlinearity_w = Un*grad_wn[q_point];
-
- rho_star=rho_value; // This is because we consider rho*u_t instead of (rho*u)_t
- rho=rho_value;
-
- // FORCE TERMS
- force_function.vector_value(fe_values_U.quadrature_point(q_point),force_terms);
- force_u=force_terms[0];
- force_v=force_terms[1];
- if (dim==3)
- force_w=force_terms[2];
- if (RHO_TIMES_RHS==1)
- {
- force_u*=rho;
- force_v*=rho;
- if (dim==3)
- force_w*=rho;
- }
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- cell_rhs_u(i)+=((4./3*rho*uqn[q_point]-1./3*rho*uqnm1[q_point]
- +2./3*time_step*(force_u-pressure_grad_u)
- //-2./3*time_step*rho*nonlinearity_u
- )*shape_value[i])*JxW;
- cell_rhs_v(i)+=((4./3*rho*vqn[q_point]-1./3*rho*vqnm1[q_point]
- +2./3*time_step*(force_v-pressure_grad_v)
- //-2./3*time_step*rho*nonlinearity_v
- )*shape_value[i])*JxW;
- if (dim==3)
- cell_rhs_w(i)+=((4./3*rho*wqn[q_point]-1./3*rho*wqnm1[q_point]
- +2./3*time_step*(force_w-pressure_grad_w)
- //-2./3*time_step*rho*nonlinearity_w
- )*shape_value[i])*JxW;
- if (rebuild_Matrix_U==true)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- {
- if (dim==2)
- cell_A_u(i,j)+=(rho_star*shape_value[i]*shape_value[j]
- +2./3*time_step*nu_value*(shape_grad[i]*shape_grad[j])
- +2./3*time_step*rho*shape_value[i]
- *(u_star*shape_grad[j][0]+v_star*shape_grad[j][1]) // semi-implicit NL
- )*JxW;
- else //dim==3
- cell_A_u(i,j)+=(rho_star*shape_value[i]*shape_value[j]
- +2./3*time_step*nu_value*(shape_grad[i]*shape_grad[j])
- +2./3*time_step*rho*shape_value[i]
- *(u_star*shape_grad[j][0]+v_star*shape_grad[j][1]+w_star*shape_grad[j][2]) // semi-implicit NL
- )*JxW;
- }
- }
+ 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_point<n_q_points; ++q_point)
+ {
+ const double JxW=fe_values_U.JxW(q_point);
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ shape_grad[i]=fe_values_U.shape_grad(i,q_point);
+ shape_value[i]=fe_values_U.shape_value(i,q_point);
+ }
+
+ pressure_grad_u=(grad_pqn[q_point][0]+4./3*grad_psiqn[q_point][0]-1./3*grad_psiqnm1[q_point][0]);
+ pressure_grad_v=(grad_pqn[q_point][1]+4./3*grad_psiqn[q_point][1]-1./3*grad_psiqnm1[q_point][1]);
+ if (dim==3)
+ pressure_grad_w=(grad_pqn[q_point][2]+4./3*grad_psiqn[q_point][2]-1./3*grad_psiqnm1[q_point][2]);
+
+ if (LEVEL_SET==1) // use level set to define rho and nu
+ get_rho_and_nu(phiqnp1[q_point]);
+ else // rho and nu are defined through functions
+ {
+ rho_value=rho_function.value(fe_values_U.quadrature_point(q_point));
+ nu_value=nu_function.value(fe_values_U.quadrature_point(q_point));
+ }
+
+ // Non-linearity: for semi-implicit
+ u_star=2*uqn[q_point]-uqnm1[q_point];
+ v_star=2*vqn[q_point]-vqnm1[q_point];
+ if (dim==3)
+ w_star=2*wqn[q_point]-wqnm1[q_point];
+
+ // for explicit nonlinearity
+ //Un[0] = uqn[q_point];
+ //Un[1] = vqn[q_point];
+ //if (dim==3)
+ //Un[2] = wqn[q_point];
+
+ //double nonlinearity_u = Un*grad_un[q_point];
+ //double nonlinearity_v = Un*grad_vn[q_point];
+ //double nonlinearity_w = 0;
+ //if (dim==3)
+ //nonlinearity_w = Un*grad_wn[q_point];
+
+ rho_star=rho_value; // This is because we consider rho*u_t instead of (rho*u)_t
+ rho=rho_value;
+
+ // FORCE TERMS
+ force_function.vector_value(fe_values_U.quadrature_point(q_point),force_terms);
+ force_u=force_terms[0];
+ force_v=force_terms[1];
+ if (dim==3)
+ force_w=force_terms[2];
+ if (RHO_TIMES_RHS==1)
+ {
+ force_u*=rho;
+ force_v*=rho;
+ if (dim==3)
+ force_w*=rho;
+ }
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ cell_rhs_u(i)+=((4./3*rho*uqn[q_point]-1./3*rho*uqnm1[q_point]
+ +2./3*time_step*(force_u-pressure_grad_u)
+ //-2./3*time_step*rho*nonlinearity_u
+ )*shape_value[i])*JxW;
+ cell_rhs_v(i)+=((4./3*rho*vqn[q_point]-1./3*rho*vqnm1[q_point]
+ +2./3*time_step*(force_v-pressure_grad_v)
+ //-2./3*time_step*rho*nonlinearity_v
+ )*shape_value[i])*JxW;
+ if (dim==3)
+ cell_rhs_w(i)+=((4./3*rho*wqn[q_point]-1./3*rho*wqnm1[q_point]
+ +2./3*time_step*(force_w-pressure_grad_w)
+ //-2./3*time_step*rho*nonlinearity_w
+ )*shape_value[i])*JxW;
+ if (rebuild_Matrix_U==true)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ if (dim==2)
+ cell_A_u(i,j)+=(rho_star*shape_value[i]*shape_value[j]
+ +2./3*time_step*nu_value*(shape_grad[i]*shape_grad[j])
+ +2./3*time_step*rho*shape_value[i]
+ *(u_star*shape_grad[j][0]+v_star*shape_grad[j][1]) // semi-implicit NL
+ )*JxW;
+ else //dim==3
+ cell_A_u(i,j)+=(rho_star*shape_value[i]*shape_value[j]
+ +2./3*time_step*nu_value*(shape_grad[i]*shape_grad[j])
+ +2./3*time_step*rho*shape_value[i]
+ *(u_star*shape_grad[j][0]+v_star*shape_grad[j][1]+w_star*shape_grad[j][2]) // semi-implicit NL
+ )*JxW;
+ }
+ }
+ }
+ 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);
}
- 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);
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<int dim>
-void NavierStokesSolver<dim>::assemble_system_dpsi_q() {
- if (rebuild_S_M==true) {
- system_S=0;
- system_M=0;
- }
+void NavierStokesSolver<dim>::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<dim> quadrature_formula(degree_MAX+1);
FEValues<dim> 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<dim> 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<dim> 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();
std::vector<double> shape_value(dofs_per_cell);
std::vector<Tensor<1, dim> > shape_grad(dofs_per_cell);
- typename DoFHandler<dim>::active_cell_iterator
- cell_P=dof_handler_P.begin_active(), endc_P=dof_handler_P.end();
+ typename DoFHandler<dim>::active_cell_iterator
+ cell_P=dof_handler_P.begin_active(), endc_P=dof_handler_P.end();
typename DoFHandler<dim>::active_cell_iterator cell_U=dof_handler_U.begin_active();
typename DoFHandler<dim>::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_point<n_q_points; ++q_point) {
- const double JxW=fe_values_P.JxW(q_point);
- double divU = gunp1[q_point][0]+gvnp1[q_point][1];
- if (dim==3) divU += gwnp1[q_point][2];
- for (unsigned int i=0; i<dofs_per_cell; ++i) {
- shape_value[i]=fe_values_P.shape_value(i,q_point);
- shape_grad[i]=fe_values_P.shape_grad(i,q_point);
- }
- if (LEVEL_SET==1) // use level set to define rho and nu
- get_rho_and_nu (phiqnp1[q_point]);
- else // rho and nu are defined through functions
- nu_value=nu_function.value(fe_values_U.quadrature_point(q_point));
-
- for (unsigned int i=0; i<dofs_per_cell; ++i) {
- cell_rhs_psi(i)+=-3./2./time_step*rho_min*divU*shape_value[i]*JxW;
- cell_rhs_q(i)-=nu_value*divU*shape_value[i]*JxW;
- if (rebuild_S_M==true) {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- if (i==j)
- {
- cell_S(i,j)+=shape_grad[i]*shape_grad[j]*JxW+1E-10;
- cell_M(i,j)+=shape_value[i]*shape_value[j]*JxW;
- }
- else
- {
- cell_S(i,j)+=shape_grad[i]*shape_grad[j]*JxW;
- cell_M(i,j)+=shape_value[i]*shape_value[j]*JxW;
- }
- }
- }
+ 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_point<n_q_points; ++q_point)
+ {
+ const double JxW=fe_values_P.JxW(q_point);
+ double divU = gunp1[q_point][0]+gvnp1[q_point][1];
+ if (dim==3) divU += gwnp1[q_point][2];
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ shape_value[i]=fe_values_P.shape_value(i,q_point);
+ shape_grad[i]=fe_values_P.shape_grad(i,q_point);
+ }
+ if (LEVEL_SET==1) // use level set to define rho and nu
+ get_rho_and_nu (phiqnp1[q_point]);
+ else // rho and nu are defined through functions
+ nu_value=nu_function.value(fe_values_U.quadrature_point(q_point));
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ cell_rhs_psi(i)+=-3./2./time_step*rho_min*divU*shape_value[i]*JxW;
+ cell_rhs_q(i)-=nu_value*divU*shape_value[i]*JxW;
+ if (rebuild_S_M==true)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ if (i==j)
+ {
+ cell_S(i,j)+=shape_grad[i]*shape_grad[j]*JxW+1E-10;
+ cell_M(i,j)+=shape_value[i]*shape_value[j]*JxW;
+ }
+ else
+ {
+ cell_S(i,j)+=shape_grad[i]*shape_grad[j]*JxW;
+ cell_M(i,j)+=shape_value[i]*shape_value[j]*JxW;
+ }
+ }
+ }
+ }
+ 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);
}
- 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);
///////////////////////////////////////////////////////
template<int dim>
void NavierStokesSolver<dim>::solve_U(const ConstraintMatrix &constraints,
- PETScWrappers::MPI::SparseMatrix &Matrix,
- std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> preconditioner,
- PETScWrappers::MPI::Vector &completely_distributed_solution,
- const PETScWrappers::MPI::Vector &rhs)
+ PETScWrappers::MPI::SparseMatrix &Matrix,
+ std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> 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);
template<int dim>
void NavierStokesSolver<dim>::solve_P(const ConstraintMatrix &constraints,
- PETScWrappers::MPI::SparseMatrix &Matrix,
- std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> preconditioner,
- PETScWrappers::MPI::Vector &completely_distributed_solution,
- const PETScWrappers::MPI::Vector &rhs) {
+ PETScWrappers::MPI::SparseMatrix &Matrix,
+ std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> 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);
//////////////// get different fields /////////////////
///////////////////////////////////////////////////////
template<int dim>
-void NavierStokesSolver<dim>::get_velocity() {
- assemble_system_U();
+void NavierStokesSolver<dim>::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;
}
template<int dim>
-void NavierStokesSolver<dim>::get_pressure()
+void NavierStokesSolver<dim>::get_pressure()
{
// GET DPSI
assemble_system_dpsi_q();
/////////////////////// DO STEPS //////////////////////
///////////////////////////////////////////////////////
template<int dim>
-void NavierStokesSolver<dim>::nth_time_step() {
+void NavierStokesSolver<dim>::nth_time_step()
+{
get_velocity();
get_pressure();
}
//////////////////////// OTHERS ///////////////////////
///////////////////////////////////////////////////////
template<int dim>
-void NavierStokesSolver<dim>::save_old_solution() {
+void NavierStokesSolver<dim>::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;
// 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"
{
public:
TestLevelSet (const unsigned int degree_LS,
- const unsigned int degree_U);
+ const unsigned int degree_U);
~TestLevelSet ();
void run ();
// BOUNDARY //
void set_boundary_inlet();
void get_boundary_values_phi(std::vector<unsigned int> &boundary_values_id_phi,
- std::vector<double> &boundary_values_phi);
+ std::vector<double> &boundary_values_phi);
// VELOCITY //
void get_interpolated_velocity();
// SETUP AND INIT CONDITIONS //
void init_constraints();
// POST PROCESSING //
void process_solution(parallel::distributed::Triangulation<dim> &triangulation,
- DoFHandler<dim> &dof_handler_LS,
- PETScWrappers::MPI::Vector &solution);
+ DoFHandler<dim> &dof_handler_LS,
+ PETScWrappers::MPI::Vector &solution);
void output_results();
void output_solution();
std::vector<unsigned int> boundary_values_id_phi;
std::vector<double> boundary_values_phi;
- // GENERAL
+ // GENERAL
MPI_Comm mpi_communicator;
parallel::distributed::Triangulation<dim> triangulation;
-
+
int degree;
int degree_LS;
DoFHandler<dim> dof_handler_LS;
double cfl;
double min_h;
- double sharpness;
+ double sharpness;
int sharpness_integer;
unsigned int n_refinement;
// MASS MATRIX
PETScWrappers::MPI::SparseMatrix matrix_MC, matrix_MC_tnm1;
std_cxx1x::shared_ptr<PETScWrappers::PreconditionBoomerAMG> preconditioner_MC;
-
+
};
template <int dim>
-TestLevelSet<dim>::TestLevelSet (const unsigned int degree_LS,
- const unsigned int degree_U)
+TestLevelSet<dim>::TestLevelSet (const unsigned int degree_LS,
+ const unsigned int degree_U)
:
mpi_communicator (MPI_COMM_WORLD),
triangulation (mpi_communicator,
- typename Triangulation<dim>::MeshSmoothing
- (Triangulation<dim>::smoothing_on_refinement |
- Triangulation<dim>::smoothing_on_coarsening)),
+ typename Triangulation<dim>::MeshSmoothing
+ (Triangulation<dim>::smoothing_on_refinement |
+ Triangulation<dim>::smoothing_on_coarsening)),
degree_LS(degree_LS),
dof_handler_LS (triangulation),
fe_LS (degree_LS),
// velocity in x
completely_distributed_solution_u = 0;
VectorTools::interpolate(dof_handler_U,
- ExactU<dim>(PROBLEM,time),
- completely_distributed_solution_u);
+ ExactU<dim>(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<dim>(PROBLEM,time),
- completely_distributed_solution_v);
+ ExactV<dim>(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<dim>(PROBLEM,time),
- completely_distributed_solution_w);
+ ExactW<dim>(PROBLEM,time),
+ completely_distributed_solution_w);
constraints.distribute (completely_distributed_solution_w);
locally_relevant_solution_w = completely_distributed_solution_w;
}
{
const QGauss<dim-1> face_quadrature_formula(1); // center of the face
FEFaceValues<dim> 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<double> u_value (n_face_q_points);
- std::vector<double> v_value (n_face_q_points);
- std::vector<double> w_value (n_face_q_points);
-
+ std::vector<double> v_value (n_face_q_points);
+ std::vector<double> w_value (n_face_q_points);
+
typename DoFHandler<dim>::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<GeometryInfo<dim>::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 <int dim>
void TestLevelSet<dim>::get_boundary_values_phi(std::vector<unsigned int> &boundary_values_id_phi,
- std::vector<double> &boundary_values_phi)
+ std::vector<double> &boundary_values_phi)
{
std::map<unsigned int, double> 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<dim>(),
- map_boundary_values_phi);
+ boundary_id,BoundaryPhi<dim>(),
+ 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<unsigned int,double>::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)
{
//////////////////////////////////
template <int dim>
void TestLevelSet<dim>::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 <int dim>
// init condition for phi
completely_distributed_solution_phi = 0;
VectorTools::interpolate(dof_handler_LS,
- InitialPhi<dim>(PROBLEM, sharpness),
- //ZeroFunction<dim>(),
- completely_distributed_solution_phi);
+ InitialPhi<dim>(PROBLEM, sharpness),
+ //ZeroFunction<dim>(),
+ 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<dim>(PROBLEM,time),
- completely_distributed_solution_u);
+ ExactU<dim>(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<dim>(PROBLEM,time),
- completely_distributed_solution_v);
+ ExactV<dim>(PROBLEM,time),
+ completely_distributed_solution_v);
constraints.distribute (completely_distributed_solution_v);
locally_relevant_solution_v = completely_distributed_solution_v;
}
-
+
template <int dim>
void TestLevelSet<dim>::init_constraints()
{
// POST PROCESSING //
/////////////////////
template <int dim>
-void TestLevelSet<dim>::process_solution(parallel::distributed::Triangulation<dim> &triangulation,
- DoFHandler<dim> &dof_handler_LS,
- PETScWrappers::MPI::Vector &solution)
+void TestLevelSet<dim>::process_solution(parallel::distributed::Triangulation<dim> &triangulation,
+ DoFHandler<dim> &dof_handler_LS,
+ PETScWrappers::MPI::Vector &solution)
{
Vector<double> difference_per_cell (triangulation.n_active_cells());
// error for phi
VectorTools::integrate_difference (dof_handler_LS,
- solution,
- InitialPhi<dim>(PROBLEM,sharpness),
- difference_per_cell,
- QGauss<dim>(degree_LS+3),
- VectorTools::L1_norm);
-
+ solution,
+ InitialPhi<dim>(PROBLEM,sharpness),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(PROBLEM,sharpness),
- difference_per_cell,
- QGauss<dim>(degree_LS+3),
- VectorTools::L2_norm);
+ solution,
+ InitialPhi<dim>(PROBLEM,sharpness),
+ difference_per_cell,
+ QGauss<dim>(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;
}
void TestLevelSet<dim>::output_solution()
{
DataOut<dim> 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<std::string> filenames;
for (unsigned int i=0;
- i<Utilities::MPI::n_mpi_processes(mpi_communicator);
- ++i)
- filenames.push_back ("solution-" +
- Utilities::int_to_string (output_number, 3) +
- "." +
- Utilities::int_to_string (i, 4) +
- ".vtu");
-
+ i<Utilities::MPI::n_mpi_processes(mpi_communicator);
+ ++i)
+ filenames.push_back ("solution-" +
+ Utilities::int_to_string (output_number, 3) +
+ "." +
+ Utilities::int_to_string (i, 4) +
+ ".vtu");
+
std::ofstream master_output ((filename + ".pvtu").c_str());
data_out.write_pvtu_record (master_output, filenames);
}
//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<dim>(0.0,0.0), Point<dim>(1.0,1.0), true);
+ //GridGenerator::hyper_rectangle(triangulation, Point<dim>(0.0,0.0), Point<dim>(1.0,1.0), true);
triangulation.refine_global (n_refinement);
-
+
///////////
// SETUP //
///////////
// TRANSPORT SOLVER //
//////////////////////
LevelSetSolver<dim> 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 //
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)
- {
+ while (time<final_time)
+ {
timestep_number++;
if (time+time_step > 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 //
/////////////////
// 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;
}
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();
}
{
public:
TestNavierStokes (const unsigned int degree_LS,
- const unsigned int degree_U);
+ const unsigned int degree_U);
~TestNavierStokes ();
void run ();
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;
};
template <int dim>
-TestNavierStokes<dim>::TestNavierStokes (const unsigned int degree_LS,
- const unsigned int degree_U)
+TestNavierStokes<dim>::TestNavierStokes (const unsigned int degree_LS,
+ const unsigned int degree_U)
:
mpi_communicator (MPI_COMM_WORLD),
triangulation (mpi_communicator,
- typename Triangulation<dim>::MeshSmoothing
- (Triangulation<dim>::smoothing_on_refinement |
- Triangulation<dim>::smoothing_on_coarsening)),
+ typename Triangulation<dim>::MeshSmoothing
+ (Triangulation<dim>::smoothing_on_refinement |
+ Triangulation<dim>::smoothing_on_coarsening)),
degree_LS(degree_LS),
dof_handler_LS (triangulation),
fe_LS (degree_LS),
/////////////////////////////////////////
template <int dim>
void TestNavierStokes<dim>::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);
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);
//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 <int dim>
// init condition for rho
completely_distributed_solution_rho = 0;
VectorTools::interpolate(dof_handler_LS,
- RhoFunction<dim>(0),
- completely_distributed_solution_rho);
+ RhoFunction<dim>(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<dim>(0,0),
- completely_distributed_solution_u);
+ ExactSolution_and_BC_U<dim>(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<dim>(0,1),
- completely_distributed_solution_v);
+ ExactSolution_and_BC_U<dim>(0,1),
+ completely_distributed_solution_v);
constraints.distribute (completely_distributed_solution_v);
locally_relevant_solution_v = completely_distributed_solution_v;
// init condition for w
{
completely_distributed_solution_w = 0;
VectorTools::interpolate(dof_handler_U,
- ExactSolution_and_BC_U<dim>(0,2),
- completely_distributed_solution_w);
+ ExactSolution_and_BC_U<dim>(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<dim>(0),
- completely_distributed_solution_p);
+ ExactSolution_p<dim>(0),
+ completely_distributed_solution_p);
constraints.distribute (completely_distributed_solution_p);
locally_relevant_solution_p = completely_distributed_solution_p;
}
-
+
template <int dim>
void TestNavierStokes<dim>::init_constraints()
{
// 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<dim>(3),
- locally_relevant_solution_p,
- 0);
+ QGauss<dim>(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;
}
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<float> subdomain (triangulation.n_active_cells());
for (unsigned int i=0; i<subdomain.size(); ++i)
subdomain(i) = triangulation.locally_owned_subdomain();
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);
{
std::vector<std::string> filenames;
for (unsigned int i=0;
- i<Utilities::MPI::n_mpi_processes(mpi_communicator);
- ++i)
- filenames.push_back ("solution-" +
- Utilities::int_to_string (output_number, 3) +
- "." +
- Utilities::int_to_string (i, 4) +
- ".vtu");
+ i<Utilities::MPI::n_mpi_processes(mpi_communicator);
+ ++i)
+ filenames.push_back ("solution-" +
+ Utilities::int_to_string (output_number, 3) +
+ "." +
+ Utilities::int_to_string (i, 4) +
+ ".vtu");
std::ofstream master_output ((filename + ".pvtu").c_str());
data_out.write_pvtu_record (master_output, filenames);
Vector<double> difference_per_cell (triangulation.n_active_cells());
// error for u
VectorTools::integrate_difference (dof_handler_U,
- locally_relevant_solution_u,
- ExactSolution_and_BC_U<dim>(time,0),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::L2_norm);
+ locally_relevant_solution_u,
+ ExactSolution_and_BC_U<dim>(time,0),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time,0),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::H1_norm);
+ locally_relevant_solution_u,
+ ExactSolution_and_BC_U<dim>(time,0),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time,1),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::L2_norm);
+ locally_relevant_solution_v,
+ ExactSolution_and_BC_U<dim>(time,1),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time,1),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::H1_norm);
+ locally_relevant_solution_v,
+ ExactSolution_and_BC_U<dim>(time,1),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time,2),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::L2_norm);
+ locally_relevant_solution_w,
+ ExactSolution_and_BC_U<dim>(time,2),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time,2),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::H1_norm);
+ locally_relevant_solution_w,
+ ExactSolution_and_BC_U<dim>(time,2),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::L2_norm);
+ locally_relevant_solution_p,
+ ExactSolution_p<dim>(time),
+ difference_per_cell,
+ QGauss<dim>(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<dim>(time),
- difference_per_cell,
- QGauss<dim>(degree_U+1),
- VectorTools::H1_norm);
+ locally_relevant_solution_p,
+ ExactSolution_p<dim>(time),
+ difference_per_cell,
+ QGauss<dim>(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);
boundary_values_w.resize(map_boundary_values_w.size());
std::map<unsigned int,double>::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;
for (unsigned int cycle=0; cycle<n_cycles; ++cycle)
{
if (cycle == 0)
- {
- GridGenerator::hyper_cube (triangulation);
- triangulation.refine_global (n_refinement);
- setup();
- initial_condition();
- }
+ {
+ GridGenerator::hyper_cube (triangulation);
+ triangulation.refine_global (n_refinement);
+ setup();
+ initial_condition();
+ }
else
- {
- triangulation.refine_global(1);
- setup();
- initial_condition();
- time_step*=0.5;
- }
+ {
+ triangulation.refine_global(1);
+ setup();
+ initial_condition();
+ time_step*=0.5;
+ }
output_results();
// if (cycle==0)
NavierStokesSolver<dim> 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)
- {
- timestep_number++;
- ///////////////////
- // GET TIME_STEP //
- ///////////////////
- if (time+time_step > 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)
+ {
+ timestep_number++;
+ ///////////////////
+ // GET TIME_STEP //
+ ///////////////////
+ if (time+time_step > 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);
+ }
+ }
}
}
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();
}
{
public:
InitialPhi (unsigned int PROBLEM, double sharpness=0.005) : Function<dim>(),
- sharpness(sharpness),
- PROBLEM(PROBLEM) {}
+ sharpness(sharpness),
+ PROBLEM(PROBLEM) {}
virtual double value (const Point<dim> &p, const unsigned int component=0) const;
double sharpness;
unsigned int PROBLEM;
};
template <int dim>
double InitialPhi<dim>::value (const Point<dim> &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));
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();
// 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();
double BoundaryV<dim>::value (const Point<dim> &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;
}
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;
}
{
public:
InitialPhi (unsigned int PROBLEM, double sharpness=0.005) : Function<dim>(),
- sharpness(sharpness),
- PROBLEM(PROBLEM) {}
+ sharpness(sharpness),
+ PROBLEM(PROBLEM) {}
virtual double value (const Point<dim> &p, const unsigned int component=0) const;
double sharpness;
unsigned int PROBLEM;
};
template <int dim>
double InitialPhi<dim>::value (const Point<dim> &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;
class BoundaryPhi : public Function <dim>
{
public:
- BoundaryPhi (double t=0)
- :
- Function<dim>()
+ BoundaryPhi (double t=0)
+ :
+ Function<dim>()
{this->set_time(t);}
virtual double value (const Point<dim> &p, const unsigned int component=0) const;
};
public:
ExactU (unsigned int PROBLEM, double time=0) : Function<dim>(), PROBLEM(PROBLEM), time(time) {}
virtual double value (const Point<dim> &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;
};
public:
ExactV (unsigned int PROBLEM, double time=0) : Function<dim>(), PROBLEM(PROBLEM), time(time) {}
virtual double value (const Point<dim> &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;
};
public:
ExactW (unsigned int PROBLEM, double time=0) : Function<dim>(), PROBLEM(PROBLEM), time(time) {}
virtual double value (const Point<dim> &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;
};
class RhoFunction : public Function <dim>
{
public:
- RhoFunction (double t=0) : Function<dim>(){this->set_time(t);}
+ RhoFunction (double t=0) : Function<dim>() {this->set_time(t);}
virtual double value (const Point<dim> &p, const unsigned int component=0) const;
};
template <int dim>
double RhoFunction<dim>::value (const Point<dim> &p,
- const unsigned int) const
+ const unsigned int) const
{
double t = this->get_time();
double return_value = 0;
class NuFunction : public Function <dim>
{
public:
- NuFunction (double t=0) : Function<dim>(){this->set_time(t);}
+ NuFunction (double t=0) : Function<dim>() {this->set_time(t);}
virtual double value (const Point<dim> &p, const unsigned int component=0) const;
};
template <int dim>
class ExactSolution_and_BC_U : public Function <dim>
{
public:
- ExactSolution_and_BC_U (double t=0, int field=0)
- :
- Function<dim>(),
+ ExactSolution_and_BC_U (double t=0, int field=0)
+ :
+ Function<dim>(),
field(field)
{
this->set_time(t);
};
template <int dim>
double ExactSolution_and_BC_U<dim>::value (const Point<dim> &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 <int dim>
Tensor<1,dim> ExactSolution_and_BC_U<dim>::gradient (const Point<dim> &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;
}
class ExactSolution_p : public Function <dim>
{
public:
- ExactSolution_p (double t=0) : Function<dim>(){this->set_time(t);}
+ ExactSolution_p (double t=0) : Function<dim>() {this->set_time(t);}
virtual double value (const Point<dim> &p, const unsigned int component=0) const;
virtual Tensor<1,dim> gradient (const Point<dim> &p, const unsigned int component = 0) const;
};
class ForceTerms : public Function <dim>
{
public:
- ForceTerms (double t=0)
- :
- Function<dim>()
+ ForceTerms (double t=0)
+ :
+ Function<dim>()
{
this->set_time(t);
nu = 1.;
template <int dim>
void ForceTerms<dim>::vector_value (const Point<dim> &p, Vector<double> &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
}
}