118 *
#include
"PhaseFieldSolver.h"
120 *
void InitialValues::vector_value(
const Point<2> &,
129<a name=
"ann-PhaseFieldSolver.cpp"></a>
130<h1>Annotated version of PhaseFieldSolver.cpp</h1>
146 *
#include
"PhaseFieldSolver.h"
148 *
PhaseFieldSolver::PhaseFieldSolver()
149 *
: mpi_communicator(MPI_COMM_WORLD)
152 *
, pcout(std::cout, (this_mpi_process == 0))
154 *
, dof_handler(triangulation)
170<a name=
"ann-PhaseFieldSolver.h"></a>
171<h1>Annotated version of PhaseFieldSolver.h</h1>
190 *
#ifndef KOBAYASHI_PARALLEL_PHASEFIELDSOLVER_H
191 *
#define KOBAYASHI_PARALLEL_PHASEFIELDSOLVER_H
193 *
#include <deal.II/base/quadrature_lib.h>
194 *
#include <deal.II/base/function.h>
195 *
#include <deal.II/base/utilities.h>
196 *
#include <deal.II/lac/vector.h>
197 *
#include <deal.II/lac/full_matrix.h>
198 *
#include <deal.II/lac/sparse_matrix.h>
199 *
#include <deal.II/lac/sparse_direct.h>
200 *
#include <deal.II/lac/dynamic_sparsity_pattern.h>
201 *
#include <deal.II/lac/solver_cg.h>
202 *
#include <deal.II/lac/precondition.h>
203 *
#include <deal.II/lac/affine_constraints.h>
204 *
#include <deal.II/grid/tria.h>
205 *
#include <deal.II/grid/grid_generator.h>
206 *
#include <deal.II/dofs/dof_handler.h>
207 *
#include <deal.II/dofs/dof_tools.h>
208 *
#include <deal.II/fe/fe_q.h>
209 *
#include <deal.II/fe/fe_values.h>
210 *
#include <deal.II/fe/fe_system.h>
211 *
#include <deal.II/numerics/vector_tools.h>
212 *
#include <deal.II/numerics/matrix_tools.h>
213 *
#include <deal.II/numerics/data_out.h>
214 *
#include <deal.II/grid/grid_in.h>
218 * For Parallel Computation
221 *
#include <deal.II/base/conditional_ostream.h>
222 *
#include <deal.II/base/mpi.h>
223 *
#include <deal.II/lac/petsc_vector.h>
224 *
#include <deal.II/lac/petsc_sparse_matrix.h>
225 *
#include <deal.II/lac/petsc_solver.h>
226 *
#include <deal.II/lac/petsc_precondition.h>
227 *
#include <deal.II/grid/grid_tools.h>
228 *
#include <deal.II/dofs/dof_renumbering.h>
231 *
#include <iostream>
235 *
class PhaseFieldSolver {
237 *
PhaseFieldSolver();
241 *
void make_grid_and_dofs();
242 *
void assemble_system();
244 *
void output_results(
const unsigned int timestep_number)
const;
245 *
double compute_residual();
246 *
void applying_bc();
247 *
float get_random_number();
262 *
const double final_time, time_step;
263 *
const double theta;
264 *
const double epsilon, tau,
gamma, latent_heat, alpha, t_eq, a;
279 *
class InitialValues :
public Function<2>
284 *
virtual void vector_value(
const Point<2> &p,
293<a name=
"ann-applying_bc.cpp"></a>
294<h1>Annotated version of applying_bc.cpp</h1>
313 *
#include
"PhaseFieldSolver.h"
315 *
void PhaseFieldSolver::applying_bc(){
319 *
QGauss<2> quadrature_formula(fe.degree + 1);
321 *
quadrature_formula,
327 *
std::map<types::global_dof_index,double> boundary_values;
331 * 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)
337 *
boundary_values,p_mask);
341 * To
apply the boundary
values only to the solution vector without the Jacobian Matrix and RHS
Vector
344 *
for (
auto &boundary_value : boundary_values)
345 *
old_solution(boundary_value.
first) = boundary_value.
second;
353<a name=
"ann-assemble_system.cpp"></a>
354<h1>Annotated version of assemble_system.cpp</h1>
370 *
#include
"PhaseFieldSolver.h"
373 *
void PhaseFieldSolver::assemble_system() {
376 * Separating each variable as a
scalar to easily call the respective shape
functions
382 *
QGauss<2> quadrature_formula(fe.degree + 1);
384 *
quadrature_formula,
387 *
const unsigned int dofs_per_cell = fe.n_dofs_per_cell();
388 *
const unsigned int n_q_points = quadrature_formula.size();
396 * Old Newton iteration
399 *
std::vector<Tensor<1, 2>> old_newton_solution_gradients_p(n_q_points);
400 *
std::vector<double> old_newton_solution_values_p(n_q_points);
401 *
std::vector<Tensor<1, 2>> old_newton_solution_gradients_t(n_q_points);
402 *
std::vector<double> old_newton_solution_values_t(n_q_points);
405 * Old time step iteration
408 *
std::vector<Tensor<1, 2>> old_time_solution_gradients_p(n_q_points);
409 *
std::vector<double> old_time_solution_values_p(n_q_points);
410 *
std::vector<Tensor<1, 2>> old_time_solution_gradients_t(n_q_points);
411 *
std::vector<double> old_time_solution_values_t(n_q_points);
413 *
std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell);
414 *
jacobian_matrix.operator=(0.0);
415 *
system_rhs.operator=(0.0);
417 *
for (
const auto &cell : dof_handler.active_cell_iterators()){
418 *
if (cell->subdomain_id() == this_mpi_process) {
422 *
fe_values.reinit(cell);
426 * Copying old solution
values
429 *
fe_values[phase_parameter].get_function_values(conv_solution_np,old_newton_solution_values_p);
430 *
fe_values[phase_parameter].get_function_gradients(conv_solution_np,old_newton_solution_gradients_p);
431 *
fe_values[
temperature].get_function_values(conv_solution_np,old_newton_solution_values_t);
432 *
fe_values[
temperature].get_function_gradients(conv_solution_np,old_newton_solution_gradients_t);
433 *
fe_values[phase_parameter].get_function_values(old_solution_np,old_time_solution_values_p);
434 *
fe_values[phase_parameter].get_function_gradients(old_solution_np,old_time_solution_gradients_p);
435 *
fe_values[
temperature].get_function_values(old_solution_np,old_time_solution_values_t);
436 *
fe_values[
temperature].get_function_gradients(old_solution_np,old_time_solution_gradients_t);
438 *
for (
unsigned int q = 0; q < n_q_points; ++q){
439 *
double khi = get_random_number();
445 *
double p_on = old_newton_solution_values_p[q];
446 *
auto grad_p_on = old_newton_solution_gradients_p[q];
447 *
double p_ot = old_time_solution_values_p[q];
448 *
auto grad_p_ot = old_time_solution_gradients_p[q];
449 *
double t_on = old_newton_solution_values_t[q];
450 *
auto grad_t_on = old_newton_solution_gradients_t[q];
451 *
double t_ot = old_time_solution_values_t[q];
452 *
auto grad_t_ot = old_time_solution_gradients_t[q];
453 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i){
459 *
double psi_i = fe_values[phase_parameter].value(i,q);
460 *
auto grad_psi_i = fe_values[phase_parameter].gradient(i,q);
461 *
double phi_i = fe_values[
temperature].value(i,q);
462 *
auto grad_phi_i = fe_values[
temperature].gradient(i,q);
463 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j){
469 *
double psi_j = fe_values[phase_parameter].value(j,q);
470 *
auto grad_psi_j = fe_values[phase_parameter].gradient(j,q);
471 *
double phi_j = fe_values[
temperature].value(j,q);
472 *
auto grad_phi_j = fe_values[
temperature].gradient(j,q);
474 *
double mp = psi_i*(tau*psi_j);
475 *
double kp = grad_psi_i*(
std::pow(epsilon,2)*grad_psi_j);
476 *
double m = (alpha/M_PI)*
std::atan(gamma*(t_eq - t_on));
477 *
double t1 = (1-p_on)*(p_on-0.5+m);
478 *
double t2 = -(p_on)*(p_on-0.5+m);
479 *
double t3 = (p_on)*(1-p_on);
480 *
double nl_p = psi_i*((t1+t2+t3)*psi_j);
483 * Adding
random noise at the interface
486 *
nl_p -= a*khi*psi_i*((1.0 - 2*(p_on))*psi_j);
487 *
double f1_p= mp + time_step*
theta*kp - time_step*
theta*nl_p;
489 *
double t4 = (p_on)*(1-p_on)*(-(alpha*
gamma/(M_PI*(1+
std::pow((gamma*(t_eq-t_on)),2)))));
490 *
double nl_t = psi_i*(t4*phi_j);
491 *
double f1_t = -time_step*
theta*nl_t;
493 *
double mpt = phi_i*(latent_heat*psi_j);
494 *
double f2_p = -mpt;
496 *
double mt = phi_i*(phi_j);
497 *
double kt = grad_phi_i*(grad_phi_j);
498 *
double f2_t = mt + time_step*
theta*kt;
502 * Assembling Jacobian
matrix
505 *
cell_matrix(i,j) += (f1_p + f1_t + f2_p + f2_t)*fe_values.JxW(q);
510 * Finding f1 and f2 at previous iteration
for rhs vector
513 *
double mp_n = psi_i*(tau*p_on);
514 *
double kp_n = grad_psi_i*(
std::pow(epsilon,2)*grad_p_on);
515 *
double m_n = (alpha/M_PI)*
std::atan(gamma*(t_eq-t_on));
516 *
double nl_n = psi_i*((p_on)*(1-p_on)*(p_on-0.5+m_n));
517 *
double mp_t = psi_i*(tau*p_ot);
518 *
double kp_t = grad_psi_i*(tau*grad_p_ot);
519 *
double m_t = (alpha/M_PI)*
std::atan(gamma*(t_eq-t_ot));
520 *
double nl_t = psi_i*(p_ot)*(1-p_ot)*(p_ot-0.5+m_t);
523 * Adding
random noise at the interface
526 *
nl_n -= psi_i*(a*khi*(p_on)*(1-p_on));
527 *
nl_t -= psi_i*(a*khi*(p_ot)*(1-p_ot));
529 *
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;
531 *
double mt_n = phi_i*(t_on);
532 *
double kt_n = grad_phi_i*(grad_t_on);
533 *
double mpt_n = phi_i*(latent_heat*p_on);
534 *
double mt_t = phi_i*(t_ot);
535 *
double kt_t = grad_phi_i*(grad_t_ot);
536 *
double mpt_t = phi_i*(latent_heat*p_ot);
538 *
double f2n = mt_n + time_step*
theta*kt_n - mpt_n - mt_t + time_step*(1-
theta)*kt_t + mpt_t;
542 * Assembling RHS vector
545 *
cell_rhs(i) -= (f1n + f2n)*fe_values.JxW(q);
549 *
cell->get_dof_indices(local_dof_indices);
550 *
for (
unsigned int i = 0; i < dofs_per_cell; ++i)
552 *
for (
unsigned int j = 0; j < dofs_per_cell; ++j)
553 *
jacobian_matrix.add(local_dof_indices[i],
554 *
local_dof_indices[j],
556 *
system_rhs(local_dof_indices[i]) += cell_rhs(i);
569 *
std::map<types::global_dof_index, double> boundary_values;
577 *
system_rhs,
false);
586<a name=
"ann-get_random_number.cpp"></a>
587<h1>Annotated version of get_random_number.cpp</h1>
603 *
#include
"PhaseFieldSolver.h"
606 *
float PhaseFieldSolver::get_random_number()
608 *
static std::default_random_engine
e;
609 *
static std::uniform_real_distribution<> dis(-0.5, 0.5);
615<a name=
"ann-grid_dof.cpp"></a>
616<h1>Annotated version of grid_dof.cpp</h1>
632 *
#include
"PhaseFieldSolver.h"
634 *
void PhaseFieldSolver::make_grid_and_dofs() {
640 *
gridin.attach_triangulation(triangulation);
641 *
std::ifstream f(
"mesh/Kobayashi_mesh100x400.msh");
642 *
gridin.read_msh(f);
646 *
dof_handler.distribute_dofs(fe);
652 *
const std::vector<IndexSet> locally_owned_dofs_per_proc =
654 *
const IndexSet locally_owned_dofs =
656 *
jacobian_matrix.reinit(locally_owned_dofs,
657 *
locally_owned_dofs,
660 *
old_solution.reinit(locally_owned_dofs, mpi_communicator);
661 *
system_rhs.reinit(locally_owned_dofs, mpi_communicator);
662 *
conv_solution.reinit(locally_owned_dofs, mpi_communicator);
663 *
solution_update.reinit(locally_owned_dofs, mpi_communicator);
665 *
conv_solution_np.reinit(dof_handler.n_dofs());
666 *
old_solution_np.reinit(dof_handler.n_dofs());
671<a name=
"ann-main.cpp"></a>
672<h1>Annotated version of
main.cpp</h1>
688 *
#include <iostream>
689 *
#include
"PhaseFieldSolver.h"
691 *
int main(
int argc,
char **argv) {
693 *
PhaseFieldSolver phasefieldsolver;
694 *
phasefieldsolver.run();
700<a name=
"ann-output_results.cpp"></a>
701<h1>Annotated version of output_results.cpp</h1>
717 *
#include
"PhaseFieldSolver.h"
719 *
void PhaseFieldSolver::output_results(
const unsigned int timestep_number)
const {
724 *
using only
one process to output the result
727 *
if (this_mpi_process == 0)
732 *
std::vector<std::string> solution_names;
733 *
solution_names.emplace_back (
"p");
734 *
solution_names.emplace_back (
"T");
736 *
data_out.add_data_vector(localized_solution, solution_names);
737 *
const std::string filename =
742 *
data_out.set_flags(vtk_flags);
743 *
std::ofstream output(filename);
745 *
data_out.build_patches();
746 *
data_out.write_vtk(output);
752<a name=
"ann-run.cpp"></a>
753<h1>Annotated version of
run.cpp</h1>
769 *
#include
"PhaseFieldSolver.h"
772 *
void PhaseFieldSolver::run() {
773 *
make_grid_and_dofs();
775 *
pcout <<
" Number of degrees of freedom: " << dof_handler.n_dofs()
776 *
<<
" (by partition:";
778 *
pcout << (p == 0 ?
' ' :
'+')
781 *
pcout <<
")" << std::endl;
784 * Initialise the solution
787 *
InitialValues initial_value;
796 * Applying Boundary Conditions at t=0
809 * Time steps
begin here:
812 *
unsigned int timestep_number = 1;
813 *
for (; time <= final_time; time += time_step, ++timestep_number) {
815 *
pcout <<
"Time step " << timestep_number <<
" at t=" << time+time_step
818 *
conv_solution.operator=(old_solution);
822 * Newton-Raphson iterations
begin here:
825 *
for (
unsigned int it = 1; it <= 100; ++it) {
826 *
pcout <<
"Newton iteration number:" << it << std::endl;
829 *
pcout <<
"Convergence Failure!!!!!!!!!!!!!!!" << std::endl;
837 *
conv_solution_np = conv_solution;
838 *
old_solution_np = old_solution;
841 * Initialise the delta solution as
zero
850 * Assemble Jacobian and Residual
856 * Solving to get delta solution
862 * Checking
for convergence
865 *
double residual_norm = system_rhs.l2_norm();
868 * pcout <<
"Nothing wrong till here!!!!!!" << std::endl;
871 *
pcout <<
"the residual is:" << residual_norm << std::endl;
872 *
if (residual_norm <= (1e-4)) {
873 *
pcout <<
"Solution Converged!" << std::endl;
879 * Transfer the converged solution to the old_solution vector to plot output
882 *
old_solution.operator=(conv_solution);
886 * output the solution at only specific number of time steps
889 *
if (timestep_number%10 == 0)
890 *
output_results(timestep_number);
896<a name=
"ann-solve.cpp"></a>
897<h1>Annotated version of solve.cpp</h1>
913 *
#include
"PhaseFieldSolver.h"
915 *
void PhaseFieldSolver::solve(){
923 *
A_direct.solve(jacobian_matrix, solution_update, system_rhs);
926 * Updating the solution by adding the delta solution
929 *
conv_solution.add(1, solution_update);
* * int main(int argc, char **argv)
* * * struct InterferenceTaperTransform *
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.
constexpr types::blas_int zero
constexpr types::blas_int one
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)
* const Number temperature
* * * * std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters const
void apply(const Kokkos::TeamPolicy< MemorySpace::Default::kokkos_space::execution_space >::member_type &team_member, const Kokkos::View< Number *, ShapeDataMemorySpace > shape_data, const ViewTypeIn in, ViewTypeOut out)
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)
DataOutBase::CompressionLevel compression_level