119 * #include
"PhaseFieldSolver.h"
121 *
void InitialValues::vector_value(
const Point<2> &p,
130<a name=
"ann-PhaseFieldSolver.cpp"></a>
131<h1>Annotated version of PhaseFieldSolver.cpp</h1>
147 * #include
"PhaseFieldSolver.h"
149 * PhaseFieldSolver::PhaseFieldSolver()
150 * : mpi_communicator(MPI_COMM_WORLD)
153 * , pcout(std::cout, (this_mpi_process == 0))
171<a name=
"ann-PhaseFieldSolver.h"></a>
172<h1>Annotated version of PhaseFieldSolver.h</h1>
191 * #ifndef KOBAYASHI_PARALLEL_PHASEFIELDSOLVER_H
192 * #define KOBAYASHI_PARALLEL_PHASEFIELDSOLVER_H
194 * #include <deal.II/base/quadrature_lib.h>
195 * #include <deal.II/base/function.h>
196 * #include <deal.II/base/utilities.h>
197 * #include <deal.II/lac/vector.h>
198 * #include <deal.II/lac/full_matrix.h>
199 * #include <deal.II/lac/sparse_matrix.h>
200 * #include <deal.II/lac/sparse_direct.h>
201 * #include <deal.II/lac/dynamic_sparsity_pattern.h>
202 * #include <deal.II/lac/solver_cg.h>
203 * #include <deal.II/lac/precondition.h>
204 * #include <deal.II/lac/affine_constraints.h>
205 * #include <deal.II/grid/tria.h>
206 * #include <deal.II/grid/grid_generator.h>
207 * #include <deal.II/dofs/dof_handler.h>
208 * #include <deal.II/dofs/dof_tools.h>
209 * #include <deal.II/fe/fe_q.h>
210 * #include <deal.II/fe/fe_values.h>
211 * #include <deal.II/fe/fe_system.h>
212 * #include <deal.II/numerics/vector_tools.h>
213 * #include <deal.II/numerics/matrix_tools.h>
214 * #include <deal.II/numerics/data_out.h>
215 * #include <deal.II/grid/grid_in.h>
219 * For Parallel Computation
222 * #include <deal.II/base/conditional_ostream.h>
223 * #include <deal.II/base/mpi.h>
224 * #include <deal.II/lac/petsc_vector.h>
225 * #include <deal.II/lac/petsc_sparse_matrix.h>
226 * #include <deal.II/lac/petsc_solver.h>
227 * #include <deal.II/lac/petsc_precondition.h>
228 * #include <deal.II/grid/grid_tools.h>
229 * #include <deal.II/dofs/dof_renumbering.h>
231 * #include <deal.II/distributed/solution_transfer.h>
234 * #include <iostream>
238 *
class PhaseFieldSolver {
240 * PhaseFieldSolver();
244 *
void make_grid_and_dofs();
245 *
void assemble_system();
247 *
void output_results(
const unsigned int timestep_number)
const;
248 *
double compute_residual();
249 *
void applying_bc();
250 *
float get_random_number();
265 *
const double final_time, time_step;
266 *
const double theta;
267 *
const double epsilon, tau,
gamma, latent_heat, alpha, t_eq, a;
279 * Initial values
class
282 *
class InitialValues :
public Function<2>
287 * virtual void vector_value(const
Point<2> &p,
296<a name=
"ann-applying_bc.cpp"></a>
297<h1>Annotated version of applying_bc.cpp</h1>
316 * #include
"PhaseFieldSolver.h"
318 *
void PhaseFieldSolver::applying_bc(){
322 *
QGauss<2> quadrature_formula(fe.degree + 1);
324 * quadrature_formula,
330 * std::map<types::global_dof_index,double> boundary_values;
334 * Prescribing p=1 at the left face (
this will be maintained in the subsequent iterations when zero BC is applied in the Newton-Raphson iterations)
340 * boundary_values,p_mask);
344 * To apply the boundary values only to the solution vector without the Jacobian Matrix and RHS
Vector
347 *
for (
auto &boundary_value : boundary_values)
348 * old_solution(boundary_value.
first) = boundary_value.
second;
356<a name=
"ann-assemble_system.cpp"></a>
357<h1>Annotated version of assemble_system.cpp</h1>
373 * #include
"PhaseFieldSolver.h"
376 *
void PhaseFieldSolver::assemble_system() {
379 * Separating each variable as a
scalar to easily call the respective shape
functions
385 *
QGauss<2> quadrature_formula(fe.degree + 1);
387 * quadrature_formula,
390 *
const unsigned int dofs_per_cell = fe.n_dofs_per_cell();
391 *
const unsigned int n_q_points = quadrature_formula.size();
398 * To
copy values and
gradients of solution from previous iteration
399 * Old Newton iteration
402 * std::vector<Tensor<1, 2>> old_newton_solution_gradients_p(n_q_points);
403 * std::vector<double> old_newton_solution_values_p(n_q_points);
404 * std::vector<Tensor<1, 2>> old_newton_solution_gradients_t(n_q_points);
405 * std::vector<double> old_newton_solution_values_t(n_q_points);
408 * Old time step iteration
411 * std::vector<Tensor<1, 2>> old_time_solution_gradients_p(n_q_points);
412 * std::vector<double> old_time_solution_values_p(n_q_points);
413 * std::vector<Tensor<1, 2>> old_time_solution_gradients_t(n_q_points);
414 * std::vector<double> old_time_solution_values_t(n_q_points);
416 * std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
417 * jacobian_matrix.operator=(0.0);
418 * system_rhs.operator=(0.0);
420 *
for (
const auto &cell : dof_handler.active_cell_iterators()){
421 *
if (cell->subdomain_id() == this_mpi_process) {
425 * fe_values.reinit(cell);
429 * Copying old solution values
432 * fe_values[phase_parameter].get_function_values(conv_solution_np,old_newton_solution_values_p);
433 * fe_values[phase_parameter].get_function_gradients(conv_solution_np,old_newton_solution_gradients_p);
434 * fe_values[temperature].get_function_values(conv_solution_np,old_newton_solution_values_t);
435 * fe_values[temperature].get_function_gradients(conv_solution_np,old_newton_solution_gradients_t);
436 * fe_values[phase_parameter].get_function_values(old_solution_np,old_time_solution_values_p);
437 * fe_values[phase_parameter].get_function_gradients(old_solution_np,old_time_solution_gradients_p);
438 * fe_values[temperature].get_function_values(old_solution_np,old_time_solution_values_t);
439 * fe_values[temperature].get_function_gradients(old_solution_np,old_time_solution_gradients_t);
441 *
for (
unsigned int q = 0; q < n_q_points; ++q){
442 *
double khi = get_random_number();
445 * Old solution values
448 *
double p_on = old_newton_solution_values_p[q];
449 *
auto grad_p_on = old_newton_solution_gradients_p[q];
450 *
double p_ot = old_time_solution_values_p[q];
451 *
auto grad_p_ot = old_time_solution_gradients_p[q];
452 *
double t_on = old_newton_solution_values_t[q];
453 *
auto grad_t_on = old_newton_solution_gradients_t[q];
454 *
double t_ot = old_time_solution_values_t[q];
455 *
auto grad_t_ot = old_time_solution_gradients_t[q];
456 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i){
462 *
double psi_i = fe_values[phase_parameter].value(i,q);
463 *
auto grad_psi_i = fe_values[phase_parameter].gradient(i,q);
464 *
double phi_i = fe_values[temperature].value(i,q);
465 *
auto grad_phi_i = fe_values[temperature].gradient(i,q);
466 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j){
472 *
double psi_j = fe_values[phase_parameter].value(j,q);
473 *
auto grad_psi_j = fe_values[phase_parameter].gradient(j,q);
474 *
double phi_j = fe_values[temperature].value(j,q);
475 *
auto grad_phi_j = fe_values[temperature].gradient(j,q);
477 *
double mp = psi_i*(tau*psi_j);
478 *
double kp = grad_psi_i*(
std::pow(epsilon,2)*grad_psi_j);
479 *
double m = (alpha/M_PI)*
std::atan(gamma*(t_eq - t_on));
480 *
double t1 = (1-p_on)*(p_on-0.5+m);
481 *
double t2 = -(p_on)*(p_on-0.5+m);
482 *
double t3 = (p_on)*(1-p_on);
483 *
double nl_p = psi_i*((t1+t2+t3)*psi_j);
486 * Adding
random noise at the interface
489 * nl_p -= a*khi*psi_i*((1.0 - 2*(p_on))*psi_j);
490 *
double f1_p= mp + time_step*theta*kp - time_step*theta*nl_p;
492 *
double t4 = (p_on)*(1-p_on)*(-(alpha*
gamma/(M_PI*(1+
std::pow((gamma*(t_eq-t_on)),2)))));
493 *
double nl_t = psi_i*(t4*phi_j);
494 *
double f1_t = -time_step*theta*nl_t;
496 *
double mpt = phi_i*(latent_heat*psi_j);
497 *
double f2_p = -mpt;
499 *
double mt = phi_i*(phi_j);
500 *
double kt = grad_phi_i*(grad_phi_j);
501 *
double f2_t = mt + time_step*theta*kt;
505 * Assembling Jacobian
matrix
508 *
cell_matrix(i,j) += (f1_p + f1_t + f2_p + f2_t)*fe_values.JxW(q);
513 * Finding f1 and f2 at previous iteration
for rhs vector
516 *
double mp_n = psi_i*(tau*p_on);
517 *
double kp_n = grad_psi_i*(
std::pow(epsilon,2)*grad_p_on);
518 *
double m_n = (alpha/M_PI)*
std::atan(gamma*(t_eq-t_on));
519 *
double nl_n = psi_i*((p_on)*(1-p_on)*(p_on-0.5+m_n));
520 *
double mp_t = psi_i*(tau*p_ot);
521 *
double kp_t = grad_psi_i*(tau*grad_p_ot);
522 *
double m_t = (alpha/M_PI)*
std::atan(gamma*(t_eq-t_ot));
523 *
double nl_t = psi_i*(p_ot)*(1-p_ot)*(p_ot-0.5+m_t);
526 * Adding
random noise at the interface
529 * nl_n -= psi_i*(a*khi*(p_on)*(1-p_on));
530 * nl_t -= psi_i*(a*khi*(p_ot)*(1-p_ot));
532 *
double f1n = mp_n + time_step*theta*kp_n - time_step*theta*nl_n - mp_t + time_step*(1-theta)*kp_t - time_step*(1-theta)*nl_t;
534 *
double mt_n = phi_i*(t_on);
535 *
double kt_n = grad_phi_i*(grad_t_on);
536 *
double mpt_n = phi_i*(latent_heat*p_on);
537 *
double mt_t = phi_i*(t_ot);
538 *
double kt_t = grad_phi_i*(grad_t_ot);
539 *
double mpt_t = phi_i*(latent_heat*p_ot);
541 *
double f2n = mt_n + time_step*theta*kt_n - mpt_n - mt_t + time_step*(1-theta)*kt_t + mpt_t;
545 * Assembling RHS vector
548 * cell_rhs(i) -= (f1n + f2n)*fe_values.JxW(q);
552 * cell->get_dof_indices(local_dof_indices);
553 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
555 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j)
556 * jacobian_matrix.add(local_dof_indices[i],
557 * local_dof_indices[j],
559 * system_rhs(local_dof_indices[i]) += cell_rhs(i);
572 * std::map<types::global_dof_index, double> boundary_values;
580 * system_rhs,
false);
589<a name=
"ann-get_random_number.cpp"></a>
590<h1>Annotated version of get_random_number.cpp</h1>
606 * #include
"PhaseFieldSolver.h"
609 *
float PhaseFieldSolver::get_random_number()
611 *
static std::default_random_engine
e;
612 *
static std::uniform_real_distribution<> dis(-0.5, 0.5);
618<a name=
"ann-grid_dof.cpp"></a>
619<h1>Annotated version of grid_dof.cpp</h1>
635 * #include
"PhaseFieldSolver.h"
637 *
void PhaseFieldSolver::make_grid_and_dofs() {
644 * std::ifstream f(
"mesh/Kobayashi_mesh100x400.msh");
645 * gridin.read_msh(f);
649 * dof_handler.distribute_dofs(fe);
655 *
const std::vector<IndexSet> locally_owned_dofs_per_proc =
657 *
const IndexSet locally_owned_dofs =
659 * jacobian_matrix.reinit(locally_owned_dofs,
660 * locally_owned_dofs,
663 * old_solution.reinit(locally_owned_dofs, mpi_communicator);
664 * system_rhs.reinit(locally_owned_dofs, mpi_communicator);
665 * conv_solution.reinit(locally_owned_dofs, mpi_communicator);
666 * solution_update.reinit(locally_owned_dofs, mpi_communicator);
668 * conv_solution_np.reinit(dof_handler.n_dofs());
669 * old_solution_np.reinit(dof_handler.n_dofs());
674<a name=
"ann-main.cpp"></a>
675<h1>Annotated version of main.cpp</h1>
691 * #include <iostream>
692 * #include
"PhaseFieldSolver.h"
694 *
int main(
int argc,
char **argv) {
696 * PhaseFieldSolver phasefieldsolver;
697 * phasefieldsolver.run();
703<a name=
"ann-output_results.cpp"></a>
704<h1>Annotated version of output_results.cpp</h1>
720 * #include
"PhaseFieldSolver.h"
722 *
void PhaseFieldSolver::output_results(
const unsigned int timestep_number)
const {
727 *
using only one process to output the result
730 *
if (this_mpi_process == 0)
735 * std::vector<std::string> solution_names;
736 * solution_names.emplace_back (
"p");
737 * solution_names.emplace_back (
"T");
739 * data_out.add_data_vector(localized_solution, solution_names);
740 *
const std::string filename =
744 * DataOutBase::VtkFlags::ZlibCompressionLevel::best_speed;
745 * data_out.set_flags(vtk_flags);
746 * std::ofstream output(filename);
748 * data_out.build_patches();
749 * data_out.write_vtk(output);
755<a name=
"ann-run.cpp"></a>
756<h1>Annotated version of
run.cpp</h1>
772 * #include
"PhaseFieldSolver.h"
775 *
void PhaseFieldSolver::run() {
776 * make_grid_and_dofs();
778 * pcout <<
" Number of degrees of freedom: " << dof_handler.n_dofs()
779 * <<
" (by partition:";
781 * pcout << (p == 0 ?
' ' :
'+')
784 * pcout <<
")" << std::endl;
787 * Initialise the solution
790 * InitialValues initial_value;
799 * Applying Boundary Conditions at t=0
812 * Time steps
begin here:
815 *
unsigned int timestep_number = 1;
816 *
for (; time <= final_time; time += time_step, ++timestep_number) {
818 * pcout <<
"Time step " << timestep_number <<
" at t=" << time+time_step
821 * conv_solution.operator=(old_solution);
825 * Newton-Raphson iterations
begin here:
828 *
for (
unsigned int it = 1; it <= 100; ++it) {
829 * pcout <<
"Newton iteration number:" << it << std::endl;
832 * pcout <<
"Convergence Failure!!!!!!!!!!!!!!!" << std::endl;
840 * conv_solution_np = conv_solution;
841 * old_solution_np = old_solution;
844 * Initialise the delta solution as zero
853 * Assemble Jacobian and Residual
859 * Solving to get delta solution
865 * Checking
for convergence
868 *
double residual_norm = system_rhs.l2_norm();
871 * pcout <<
"Nothing wrong till here!!!!!!" << std::endl;
874 * pcout <<
"the residual is:" << residual_norm << std::endl;
875 *
if (residual_norm <= (1e-4)) {
876 * pcout <<
"Solution Converged!" << std::endl;
882 * Transfer the converged solution to the old_solution vector to plot output
885 * old_solution.operator=(conv_solution);
889 * output the solution at only specific number of time steps
892 *
if (timestep_number%10 == 0)
893 * output_results(timestep_number);
899<a name=
"ann-solve.cpp"></a>
900<h1>Annotated version of solve.cpp</h1>
916 * #include
"PhaseFieldSolver.h"
918 *
void PhaseFieldSolver::solve(){
926 * A_direct.solve(jacobian_matrix, solution_update, system_rhs);
929 * Updating the solution by adding the delta solution
932 * conv_solution.add(1, solution_update);
std::vector< bool > component_mask
void attach_dof_handler(const DoFHandler< dim, spacedim > &)
void make_sparsity_pattern(const DoFHandler< dim, spacedim > &dof_handler, SparsityPatternBase &sparsity_pattern, const AffineConstraints< number > &constraints={}, const bool keep_constrained_dofs=true, const types::subdomain_id subdomain_id=numbers::invalid_subdomain_id)
@ update_values
Shape function values.
@ update_JxW_values
Transformed quadrature weights.
@ update_gradients
Shape function gradients.
void subdomain_wise(DoFHandler< dim, spacedim > &dof_handler)
void random(DoFHandler< dim, spacedim > &dof_handler)
@ matrix
Contents is actually a matrix.
void cell_matrix(FullMatrix< double > &M, const FEValuesBase< dim > &fe, const FEValuesBase< dim > &fetest, const ArrayView< const std::vector< double > > &velocity, const double factor=1.)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > epsilon(const Tensor< 2, dim, Number > &Grad_u)
VectorType::value_type * begin(VectorType &V)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
long double gamma(const unsigned int n)
void copy(const T *begin, const T *end, U *dest)
int(& functions)(const void *v1, const void *v2)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
inline ::VectorizedArray< Number, width > atan(const ::VectorizedArray< Number, width > &x)
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
DataOutBase::CompressionLevel compression_level