Dear Daniel,
I'm sorry to make this mistake, (and thank Jean-Paul very much). The newest
code focus on build the sparsity pattern in "setup_dof()", while other
parts (assemble_system(), assemble_rhs(), run() ) need to be left to make
the code work and maintain the structure of 3 components of the blockvector
solution.
Thank you much!
Best,
Chucui
--
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see
https://groups.google.com/d/forum/dealii?hl=en
---
You received this message because you are subscribed to the Google Groups
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/utilities.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/function.h>
#include <deal.II/base/smartpointer.h>
#include <deal.II/base/convergence_table.h>
#include <deal.II/base/timer.h>
#include <deal.II/base/tensor_function.h>
#include <deal.II/lac/block_vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/block_sparse_matrix.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/sparse_direct.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_boundary_lib.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_dgq.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/mapping_q.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/numerics/solution_transfer.h>
#include <math.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/function.h>
#include <deal.II/base/utilities.h>
#include <deal.II/lac/block_vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/block_sparse_matrix.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_boundary_lib.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>
// Then we need to include the header file for the sparse direct solver
// UMFPACK:
#include <deal.II/lac/sparse_direct.h>
// This includes the library for the incomplete LU factorization that will be
// used as a preconditioner in 3D:
#include <deal.II/lac/sparse_ilu.h>
// This is C++:
#include <iostream>
#include <fstream>
#include <sstream>
// As in all programs, the namespace dealii is included:
namespace Step22
{
using namespace dealii;
template <int dim>
class Problem
{
public:
Problem (const unsigned int degree);
void run ();
private:
void setup_dofs ();
void assemble_system (const BlockVector<double> old_solution,
const BlockVector<double> older_solution);
void assemble_rhs (const double time,
const BlockVector<double> old_solution,
const BlockVector<double> older_solution);
void solve ();
double free_energy_compute (const BlockVector<double> solution);
void assemble_system_1 (const Vector<double> phi_0);
void assemble_rhs_1 (const Vector<double> phi_0, const Vector<double> q_0);
void solve_1 ();
const unsigned int degree;
Triangulation<dim> triangulation;
Triangulation<dim> triangulation_active;
FESystem<dim> fe;
FE_Q<dim> fe_phi;
FE_Q<dim> fe_mu;
FE_DGQ<dim> fe_q;
DoFHandler<dim> dof_handler;
DoFHandler<dim> dof_handler_0;
DoFHandler<dim> dof_handler_1;
DoFHandler<dim> dof_handler_2;
ConstraintMatrix constraints;
ConstraintMatrix constraints_phi;
ConstraintMatrix constraints_mu;
ConstraintMatrix constraints_q;
BlockSparsityPattern sparsity_pattern;
BlockSparseMatrix<double> system_matrix;
BlockSparseMatrix<double> system_matrix_1;
BlockSparseMatrix<double> free_energy_matrix;
Vector<double> phi_0, q_0;
BlockVector<double> solution;
BlockVector<double> old_solution;
BlockVector<double> older_solution;
BlockVector<double> system_rhs;
BlockVector<double> system_rhs_1;
BlockVector<double> solution_1;
double time_step, time;
const double D, eps, lambda;//, s;
unsigned int timestep_number;
ConvergenceTable convergence_table;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <int dim>
class SolutionsPhi : public Function<dim>
{
public:
SolutionsPhi () : Function<dim>() {}
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;
};
template <int dim>
double SolutionsPhi<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
//if (component == 0)
double phi_value = 0;
Tensor<1,dim> r;
r[0] = std::sqrt((p[0] - 0.3 + 0.01) * (p[0] - 0.3 + 0.01) + (p[1] - 0.5) * (p[1] - 0.5)) ;
r[1] = std::sqrt((p[0] - 0.7 - 0.01) * (p[0] - 0.7 - 0.01) + (p[1] - 0.5) * (p[1] - 0.5)) ;
if ((r[0] >= (0.2 + 0.01)) && (r[1] >= (0.2 + 0.01)))
{phi_value = -1;
}
else if (r[0] < (0.2 + 0.01))
{phi_value = std::tanh((0.2-std::sqrt((p[0]-0.3+0.01) * (p[0]-0.3+0.01) + (p[1] -0.5) * (p[1] -0.5)))/0.01);
}
else if (r[1] < (0.2 + 0.01))
{phi_value = std::tanh((0.2-std::sqrt((p[0]-0.7-0.01) * (p[0]-0.7-0.01) + (p[1] -0.5) * (p[1] -0.5)))/0.01);
}
else
{phi_value = 0;
}
//phi_value = std::cos(numbers::PI * p[0]) * std::cos(numbers::PI * p[1]);
return phi_value;
}
template <int dim>
Tensor<1,dim> SolutionsPhi<dim>::gradient (const Point<dim> &p,
const unsigned int) const
{
Tensor<1,dim> return_value;
for (unsigned int d=0; d<dim; ++d)
{
return_value[d] = 0;}
return return_value;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <int dim>
class SolutionsMu : public Function<dim>
{
public:
SolutionsMu () : Function<dim>() {}
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;
};
template <int dim>
double SolutionsMu<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
double phi_value = 0;
return phi_value;
}
template <int dim>
Tensor<1,dim> SolutionsMu<dim>::gradient (const Point<dim> &p,
const unsigned int) const
{
Tensor<1,dim> return_value;
for (unsigned int d=0; d<dim; ++d)
{
return_value[d] = 0;}
return return_value;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <int dim>
class SolutionsQ : public Function<dim>
{
public:
SolutionsQ () : Function<dim>() {}
virtual double value (const Point<dim> &p,
const unsigned int component = 0) const;
};
template <int dim>
double SolutionsQ<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
double phi_value = 0, q_value = 0;
Tensor<1,dim> r;
r[0] = std::sqrt((p[0] - 0.3 + 0.01) * (p[0] - 0.3 + 0.01) + (p[1] - 0.5) * (p[1] - 0.5)) ;
r[1] = std::sqrt((p[0] - 0.7 - 0.01) * (p[0] - 0.7 - 0.01) + (p[1] - 0.5) * (p[1] - 0.5)) ;
if ((r[0] >= (0.2 + 0.01)) && (r[1] >= (0.2 + 0.01)))
{phi_value = -1;
}
else if (r[0] < (0.2 + 0.01))
{phi_value = std::tanh((0.2-std::sqrt((p[0]-0.3+0.01) * (p[0]-0.3+0.01) + (p[1] -0.5) * (p[1] -0.5)))/0.01);
}
else if (r[1] < (0.2 + 0.01))
{phi_value = std::tanh((0.2-std::sqrt((p[0]-0.7-0.01) * (p[0]-0.7-0.01) + (p[1] -0.5) * (p[1] -0.5)))/0.01);
}
else
{phi_value = 0;
}
//phi_value = std::cos(numbers::PI * p[0]) * std::cos(numbers::PI * p[1]);
q_value = (1./std::sqrt(2)) * (phi_value * phi_value - 1);
return q_value;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <int dim>
class Solutions : public Function<dim>
{
public:
Solutions () : Function<dim>(3) {}
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 Solutions<dim>::value (const Point<dim> &p,
const unsigned int component) const
{
if (component == 0)
return std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time());
else if (component == 1)
return std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time()) + std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time()) * std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time()) * std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time());
else
return (1 / 2) - (1 / 2) * std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time()) * std::cos(p[0]) * std::cos(p[1]) * std::cos(this->get_time());
}
template <int dim>
void
Solutions<dim>::vector_value (const Point<dim> &p,
Vector<double> &values) const
{
for (unsigned int c=0; c<this->n_components; ++c)
values(c) = Solutions<dim>::value (p, c);
}
double GFunction (const double phi1,
const double phi2)
{ const double eps = 0.01;
return (1.5 * phi1 - 0.5 * phi2) * (std::sqrt(2));
}
template <int dim>
Problem<dim>::Problem (const unsigned int degree)
:
degree (degree),
fe (FE_Q<dim>(degree), 1,
FE_Q<dim>(degree), 1,
FE_DGQ<dim>(degree), 1),
fe_phi (degree),
fe_mu (degree),
fe_q (degree),
dof_handler (triangulation),
dof_handler_0 (triangulation),
dof_handler_1 (triangulation),
dof_handler_2 (triangulation),
time_step (0.001),
timestep_number (1),
D (1),
eps (0.01),
lambda (0.001)
{}
template <int dim>
void Problem<dim>::setup_dofs ()
{
//A_preconditioner.reset ();
system_matrix.clear ();
system_matrix_1.clear ();
free_energy_matrix.clear ();
dof_handler.distribute_dofs (fe);
dof_handler_0.distribute_dofs (fe_phi);
dof_handler_1.distribute_dofs (fe_mu);
dof_handler_2.distribute_dofs (fe_q);
//DoFRenumbering::Cuthill_McKee (dof_handler);
DoFRenumbering::component_wise (dof_handler);
DoFRenumbering::component_wise (dof_handler_0);
DoFRenumbering::component_wise (dof_handler_1);
DoFRenumbering::component_wise (dof_handler_2);
std::vector<unsigned int> block_component (3);
block_component[0] = 0;
block_component[1] = 1;//=3-1
block_component[2] = 2;
DoFRenumbering::component_wise (dof_handler, block_component);
constraints.clear ();
const ComponentMask component_mask = ComponentMask();
DoFTools::make_periodicity_constraints(dof_handler,0,1,0, constraints, component_mask);
DoFTools::make_periodicity_constraints(dof_handler,2,3,1, constraints, component_mask);
constraints.close ();
constraints_phi.close ();
constraints_mu.close ();
constraints_q.close ();
std::vector<types::global_dof_index> dofs_per_block (3);
DoFTools::count_dofs_per_block (dof_handler, dofs_per_block, block_component);
const unsigned int n_phi = dofs_per_block[0],
n_mu = dofs_per_block[1],
n_q = dofs_per_block[2];
std::cout << " Number of active cells: "
<< triangulation.n_active_cells()
<< std::endl
<< " Number of degrees of freedom: "
<< dof_handler.n_dofs()
<< " (" << n_phi << '+' << n_mu << '+' << n_q << ')'
<< std::endl;
{
BlockDynamicSparsityPattern dsp (3,3);
dsp.block(0,0).reinit (n_phi, n_phi);
dsp.block(1,0).reinit (n_mu, n_phi);
dsp.block(2,0).reinit (n_q, n_phi);
dsp.block(0,1).reinit (n_phi, n_mu);
dsp.block(1,1).reinit (n_mu, n_mu);
dsp.block(2,1).reinit (n_q, n_mu);
dsp.block(0,2).reinit (n_phi, n_q);
dsp.block(1,2).reinit (n_mu, n_q);
dsp.block(2,2).reinit (n_q, n_q);
dsp.collect_sizes();
DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints, false);
sparsity_pattern.copy_from (dsp);
}
{
system_matrix.reinit (sparsity_pattern);
system_matrix_1.reinit (sparsity_pattern);
free_energy_matrix.reinit (sparsity_pattern);
solution.reinit (3);
solution.block(0).reinit (n_phi);
solution.block(1).reinit (n_mu);
solution.block(2).reinit (n_q);
solution.collect_sizes ();
old_solution.reinit (3);
old_solution.block(0).reinit (n_phi);
old_solution.block(1).reinit (n_mu);
old_solution.block(2).reinit (n_q);
old_solution.collect_sizes ();
older_solution.reinit (3);
older_solution.block(0).reinit (n_phi);
older_solution.block(1).reinit (n_mu);
older_solution.block(2).reinit (n_q);
older_solution.collect_sizes ();
system_rhs.reinit (3);
system_rhs.block(0).reinit (n_phi);
system_rhs.block(1).reinit (n_mu);
system_rhs.block(2).reinit (n_q);
system_rhs.collect_sizes ();
system_rhs_1.reinit (3);
system_rhs_1.block(0).reinit (n_phi);
system_rhs_1.block(1).reinit (n_mu);
system_rhs_1.block(2).reinit (n_q);
system_rhs_1.collect_sizes ();
solution_1.reinit (3);
solution_1.block(0).reinit (n_phi);
solution_1.block(1).reinit (n_mu);
solution_1.block(2).reinit (n_q);
solution_1.collect_sizes ();
phi_0.reinit (n_phi);
q_0.reinit (n_q);
}
}
template <int dim>
void Problem<dim>::assemble_system (const BlockVector<double> old_solution,
const BlockVector<double> older_solution)
{
system_matrix=0;
QGauss<dim> quadrature_formula(degree+2);
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);
std::vector<Vector<double> > older_solution_values(n_q_points, Vector<double>(3));
std::vector<Vector<double> > old_solution_values(n_q_points, Vector<double>(3));
const FEValuesExtractors::Scalar phase (0);
const FEValuesExtractors::Scalar chemipt (1);
const FEValuesExtractors::Scalar intervarq (2);
typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
fe_values.reinit (cell);
local_matrix = 0;
local_rhs = 0;
fe_values.get_function_values (old_solution, old_solution_values);
fe_values.get_function_values (older_solution, older_solution_values);
for (unsigned int q=0; q<n_q_points; ++q)
{
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
const double older_phi = older_solution_values[q](0);
const double old_phi = old_solution_values[q](0);
const Tensor<1,dim> grad_psi_i_phi = fe_values[phase].gradient (i, q);
const Tensor<1,dim> grad_psi_i_mu = fe_values[chemipt].gradient (i, q);
const double psi_i_phi = fe_values[phase].value (i, q);
const double psi_i_mu = fe_values[chemipt].value (i, q);
const double psi_i_q = fe_values[intervarq].value (i, q);
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
const Tensor<1,dim> grad_psi_j_phi = fe_values[phase].gradient (j, q);
const Tensor<1,dim> grad_psi_j_mu = fe_values[chemipt].gradient (j, q);
const double psi_j_phi = fe_values[phase].value (j, q);
const double psi_j_mu = fe_values[chemipt].value (j, q);
const double psi_j_q = fe_values[intervarq].value (j, q);
local_matrix(i,j) += (psi_i_phi * psi_j_phi
+ time_step * 0.5 * D * grad_psi_i_phi * grad_psi_j_mu
+ psi_i_mu * psi_j_mu
- grad_psi_i_mu * grad_psi_j_phi * eps * lambda
- (lambda / eps) * GFunction(old_phi, older_phi) * psi_i_mu * psi_j_q
+ psi_i_q * psi_j_q
- GFunction(old_phi, older_phi) * psi_i_q * psi_j_phi
) * fe_values.JxW(q);
}
}
}
cell->get_dof_indices (local_dof_indices);
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
system_matrix.add (local_dof_indices[i],
local_dof_indices[j],
local_matrix(i,j));
}
}
}
}
template <int dim>
void Problem<dim>::assemble_rhs (const double time,
const BlockVector<double> old_solution,
const BlockVector<double> older_solution)
{
system_rhs=0;
QGauss<dim> quadrature_formula(degree+2);
FEValues<dim> fe_values (fe, quadrature_formula,
update_values | update_gradients |
update_quadrature_points | update_JxW_values);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
Vector<double> local_rhs (dofs_per_cell);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
std::vector<Vector<double> > older_solution_values(n_q_points, Vector<double>(3));
std::vector<Vector<double> > old_solution_values(n_q_points, Vector<double>(3));
std::vector<Tensor<1, dim> > old_solution_gradients_0(n_q_points);
std::vector<Tensor<1, dim> > old_solution_gradients_1(n_q_points);
const FEValuesExtractors::Scalar phase (0);
const FEValuesExtractors::Scalar chemipt (1);
const FEValuesExtractors::Scalar intervarq (2);
typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
local_rhs = 0;
fe_values.reinit (cell);
fe_values.get_function_values (old_solution, old_solution_values);
fe_values.get_function_values (older_solution, older_solution_values);
fe_values[phase].get_function_gradients(old_solution, old_solution_gradients_0);
fe_values[chemipt].get_function_gradients(old_solution, old_solution_gradients_1);
for (unsigned int q=0; q<n_q_points; ++q)
{
const double older_phi = older_solution_values[q](0);
const double old_phi = old_solution_values[q](0);
const double old_mu = old_solution_values[q](1);
const double old_q = old_solution_values[q](2);
Tensor<1,dim> grad_old_phi;
Tensor<1,dim> grad_old_mu;
for (unsigned int d=0; d<dim; ++d)
{
grad_old_phi[d] = old_solution_gradients_0[q][d];
grad_old_mu[d] = old_solution_gradients_1[q][d];
}
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
const Tensor<1,dim> grad_psi_i_phi = fe_values[phase].gradient (i, q);
const Tensor<1,dim> grad_psi_i_mu = fe_values[chemipt].gradient (i, q);
const double psi_i_phi = fe_values[phase].value (i, q);
const double psi_i_mu = fe_values[chemipt].value (i, q);
const double psi_i_q = fe_values[intervarq].value (i, q);
local_rhs(i) += (//psi_i_phi * new_fright * time_step
+ psi_i_phi * old_phi
- 0.5 * time_step * D * grad_psi_i_phi * grad_old_mu
- psi_i_mu * old_mu
+ grad_psi_i_mu * grad_old_phi * eps * lambda
+ (lambda / eps) * GFunction(old_phi, older_phi) * psi_i_mu * old_q
+ psi_i_q * old_q
- GFunction(old_phi, older_phi) * psi_i_q * old_phi)
* fe_values.JxW(q);
}
}
cell->get_dof_indices (local_dof_indices);
for (unsigned int i=0; i<dofs_per_cell; ++i)
system_rhs(local_dof_indices[i]) += local_rhs(i);
}
}
template <int dim>
void Problem<dim>::solve ()
{
SparseDirectUMFPACK A_direct;
A_direct.initialize(system_matrix);
A_direct.vmult (solution, system_rhs);
}
template <int dim>
void Problem<dim>::assemble_system_1 (const Vector<double> phi_0)
{
system_matrix_1=0;
QGauss<dim> quadrature_formula(degree+2);
QGauss<dim-1> face_quadrature_formula(degree+2);
FEValues<dim> fe_values (fe, quadrature_formula,
update_values |
update_quadrature_points |
update_JxW_values |
update_gradients);
FEValues<dim> fe_phi_values (fe_phi, quadrature_formula,
update_values | update_gradients |
update_quadrature_points | update_JxW_values);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
//const unsigned int n_face_q_points = face_quadrature_formula.size();
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);
std::vector<double> phi_0_values(n_q_points);
const FEValuesExtractors::Scalar phase (0);
const FEValuesExtractors::Scalar chemipt (1);
const FEValuesExtractors::Scalar intervarq (2);
typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
typename DoFHandler<dim>::active_cell_iterator
cell_phi = dof_handler_0.begin_active();
for (; cell!=endc; ++cell, ++cell_phi)
{
fe_values.reinit (cell);
fe_phi_values.reinit (cell_phi);
local_matrix = 0;
local_rhs = 0;
fe_phi_values.get_function_values (phi_0, phi_0_values);
for (unsigned int q=0; q<n_q_points; ++q)
{
const double old_phi = phi_0_values[q];
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
const Tensor<1,dim> grad_psi_i_phi = fe_values[phase].gradient (i, q);
const Tensor<1,dim> grad_psi_i_mu = fe_values[chemipt].gradient (i, q);
const double psi_i_phi = fe_values[phase].value (i, q);
const double psi_i_mu = fe_values[chemipt].value (i, q);
const double psi_i_q = fe_values[intervarq].value (i, q);
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
const Tensor<1,dim> grad_psi_j_phi = fe_values[phase].gradient (j, q);
const Tensor<1,dim> grad_psi_j_mu = fe_values[chemipt].gradient (j, q);
const double psi_j_phi = fe_values[phase].value (j, q);
const double psi_j_mu = fe_values[chemipt].value (j, q);
const double psi_j_q = fe_values[intervarq].value (j, q);
local_matrix(i,j) += (psi_i_phi * psi_j_phi * (1./time_step )
+ (grad_psi_i_phi * grad_psi_j_mu)
+ psi_i_mu * psi_j_mu
- grad_psi_i_mu * grad_psi_j_phi * eps * lambda
- (lambda / eps) * GFunction(old_phi, old_phi) * psi_i_mu * psi_j_q
+ psi_i_q * psi_j_q
- GFunction(old_phi, old_phi) * psi_i_q * psi_j_phi
)
* fe_values.JxW(q);
}
}
}
cell->get_dof_indices (local_dof_indices);
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
system_matrix_1.add (local_dof_indices[i],
local_dof_indices[j],
local_matrix(i,j));
}
}
}
}
template <int dim>
void Problem<dim>::assemble_rhs_1 (const Vector<double> phi_0,
const Vector<double> q_0)
{
system_rhs_1=0;
QGauss<dim> quadrature_formula(degree+2);
QGauss<dim-1> face_quadrature_formula(degree+2);
FEValues<dim> fe_values (fe, quadrature_formula,
update_values | update_gradients |
update_quadrature_points | update_JxW_values);
FEValues<dim> fe_phi_values (fe_phi, quadrature_formula,
update_values | update_gradients |
update_quadrature_points | update_JxW_values);
FEValues<dim> fe_q_values (fe_q, quadrature_formula,
update_values | update_gradients |
update_quadrature_points | update_JxW_values);
const unsigned int dofs_per_cell = fe.dofs_per_cell;
const unsigned int n_q_points = quadrature_formula.size();
Vector<double> local_rhs (dofs_per_cell);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
std::vector<double> phi_0_values(n_q_points);
std::vector<double> q_0_values(n_q_points);
const SolutionsPhi<dim> neumann_phi;
const SolutionsMu<dim> neumann_mu;
const FEValuesExtractors::Scalar phase (0);
const FEValuesExtractors::Scalar chemipt (1);
const FEValuesExtractors::Scalar intervarq (2);
typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
typename DoFHandler<dim>::active_cell_iterator
cell_phi = dof_handler_0.begin_active();
typename DoFHandler<dim>::active_cell_iterator
cell_q = dof_handler_2.begin_active();
for (; cell!=endc; ++cell, ++cell_phi, ++cell_q)
{
local_rhs = 0;
fe_values.reinit (cell);
fe_phi_values.reinit (cell_phi);
fe_q_values.reinit (cell_q);
fe_phi_values.get_function_values (phi_0, phi_0_values);
fe_q_values.get_function_values (q_0, q_0_values);
for (unsigned int q=0; q<n_q_points; ++q)
{
const double old_phi = phi_0_values[q];
const double old_q = q_0_values[q];
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
const double psi_i_phi = fe_values[phase].value (i, q);
const double psi_i_q = fe_values[intervarq].value (i, q);
local_rhs(i) += (psi_i_phi * old_phi * (1./time_step)
+ psi_i_q * old_q
- GFunction(old_phi, old_phi) * psi_i_q * old_phi)
* fe_values.JxW(q);
}
}
cell->get_dof_indices (local_dof_indices);
for (unsigned int i=0; i<dofs_per_cell; ++i)
system_rhs_1(local_dof_indices[i]) += local_rhs(i);
}
}
template <int dim>
void Problem<dim>::solve_1 ()
{
SparseDirectUMFPACK A_direct;
A_direct.initialize(system_matrix_1);
A_direct.vmult (solution_1, system_rhs_1);
}
template <int dim>
double Problem<dim>::free_energy_compute (const BlockVector<double> solution)
{
free_energy_matrix=0;
QGauss<dim> quadrature_formula(degree+2);
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_free_energy_matrix (dofs_per_cell, dofs_per_cell);
std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);
std::vector<Vector<double> > solution_values(n_q_points, Vector<double>(3));
std::vector<Tensor<1, dim> > solution_gradients_0(n_q_points);
const FEValuesExtractors::Scalar phase (0);
const FEValuesExtractors::Scalar chemipt (1);
const FEValuesExtractors::Scalar intervarq (2);
typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler.begin_active(),
endc = dof_handler.end();
for (; cell!=endc; ++cell)
{
fe_values.reinit (cell);
local_free_energy_matrix = 0;
fe_values.get_function_values (solution, solution_values);
fe_values[phase].get_function_gradients(solution, solution_gradients_0);
for (unsigned int q=0; q<n_q_points; ++q)
{
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
const Tensor<1,dim> grad_psi_i_phi = fe_values[phase].gradient (i, q);
const double psi_i_q = fe_values[intervarq].value (i, q);
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
const Tensor<1,dim> grad_psi_j_phi = fe_values[phase].gradient (j, q);
const double psi_j_q = fe_values[intervarq].value (j, q);
local_free_energy_matrix(i,j) += (0.5 * lambda * eps * grad_psi_i_phi * grad_psi_j_phi
+ psi_i_q * psi_j_q * 0.5 * (lambda / eps))
* fe_values.JxW(q);
}
}
}
cell->get_dof_indices (local_dof_indices);
for (unsigned int i=0; i<dofs_per_cell; ++i)
{
for (unsigned int j=0; j<dofs_per_cell; ++j)
{
free_energy_matrix.add (local_dof_indices[i],
local_dof_indices[j],
local_free_energy_matrix(i,j));
}
}
}
double free_energy = 0;
free_energy = free_energy_matrix.matrix_norm_square(solution);
//std::cout << "dof 11-4-8 "<< free_energy << std::endl;
return free_energy;
}
template <int dim>
void Problem<dim>::run ()
{
const unsigned int n_cycles = 1;
double free_energy = 0;
for (unsigned int cycle=0; cycle<n_cycles; ++cycle)
{
if (cycle == 0)
{
GridGenerator::hyper_cube (triangulation_active, 0, 1);
triangulation_active.refine_global (7);
GridGenerator::flatten_triangulation (triangulation_active, triangulation);
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->face(f)->at_boundary())
{
if (std::fabs(cell->face(f)->center()(0) - (1)) < 1e-12)
cell->face(f)->set_boundary_id (1);
else if(std::fabs(cell->face(f)->center()(1) - (0)) < 1e-12)
cell->face(f)->set_boundary_id (2);
else if(std::fabs(cell->face(f)->center()(1) - (1)) < 1e-12)
cell->face(f)->set_boundary_id (3);
else if(std::fabs(cell->face(f)->center()(0) - (0)) < 1e-12)
{
cell->face(f)->set_boundary_id (0);
}
}
}
}
}
else
{
//triangulation.refine_global (1);
}
setup_dofs ();
VectorTools::project (dof_handler_0, constraints_phi, QGauss<dim>(degree+2),
SolutionsPhi<dim>(),
phi_0);
VectorTools::project (dof_handler_2, constraints_q, QGauss<dim>(degree+2),
SolutionsQ<dim>(),
q_0);
assemble_system_1 (phi_0);
assemble_rhs_1 (phi_0, q_0);
solve_1 ();
older_solution = solution_1;
old_solution = solution_1;
assemble_system (old_solution, older_solution);
time = time_step * 2;
timestep_number = 2;
for (; time<=300.01; time+=time_step, ++timestep_number) //time<=/ 1./16
{
assemble_rhs (time - 0.5 * time_step, old_solution, older_solution);
solve ();
free_energy = free_energy_compute (solution);
older_solution = old_solution;
old_solution = solution;
std::cout << "Time step " << timestep_number << " at t=" << time << "free energy is " << free_energy << std::endl;
assemble_system (old_solution, older_solution);
}
}
}
}
int main ()
{
try
{
using namespace dealii;
using namespace Step22;
Problem<2> flow_problem(1);
flow_problem.run ();
}
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;
}