Daniel,

Let me explain the problem more. I heve parallelized a code based on 
step-40. The non-parallel code works for all the initial values and 
boundary conditions But the parallel one fails at the first call to 
solverCG with this error:  "[0]PETSC ERROR: Caught signal number 11 SEGV: 
Segmentation Violation, probably memory access out of range" and the same 
story when I run the code on cluster.

For a couple of specific boundary conditions and initial values the problem 
resolves when I just replace the PreconditioerAMG with PreconditionerJacobi 
!! 
I feel the problem is with Petsc solver, that's why I want to examine if 
the code works with Trilinos. But I failed to implement trilinos as I 
mentioned previously.

I am submitting my code along with a Parameter.prm file which includes all 
the parameters of the code. 

I appreciate if you could run the code on your machine and see if you can 
find out what's wrong with it.

Thanks

For example the following is the number of SolverCG iteration for the 20 
Newoton-Raphson iterations after which   

On Sunday, October 16, 2016 at 10:39:49 AM UTC-5, Daniel Arndt wrote:
>
> In case there is an error with Trilinos, what is it?
>
> Am Sonntag, 16. Oktober 2016 17:27:26 UTC+2 schrieb Daniel Arndt:
>>
>> Hamed,
>>
>>
>>>>> It still works with Petsc and Trilinos is not implemented at all. I 
>>>>> appreciate it if you could let me know what changes should be made in 
>>>>> step-40 to make it work with Trilinos.
>>>>>
>>>> What exactly, do you mean by that? So you have both PETSc and Trilinos 
>> installed and step-40 works. Are you saying that PETSc objects are used 
>> even if you use 
>> "using namespace ::LinearAlgebraTrilinos;" ? How did you find out?
>>
>> Best,
>> Daniel
>>
>

-- 
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 dealii+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
#include <deal.II/base/function.h>
#include <deal.II/base/parameter_handler.h>
#include <deal.II/base/point.h>
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/symmetric_tensor.h>
#include <deal.II/base/tensor.h>
#include <deal.II/base/timer.h>
#include <deal.II/base/work_stream.h>
#include <deal.II/base/conditional_ostream.h>
#include <deal.II/base/std_cxx11/shared_ptr.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/utilities.h>
#include <deal.II/base/index_set.h>

#include <deal.II/lac/generic_linear_algebra.h>

namespace LA
{
#if defined(DEAL_II_WITH_PETSC) && !(defined(DEAL_II_WITH_TRILINOS) && defined(FORCE_USE_OF_TRILINOS))
  using namespace dealii::LinearAlgebraPETSc;
#  define USE_PETSC_LA
#elif defined(DEAL_II_WITH_TRILINOS)
  using namespace dealii::LinearAlgebraTrilinos;
#else
#  error DEAL_II_WITH_PETSC or DEAL_II_WITH_TRILINOS required
#endif
}

#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/dynamic_sparsity_pattern.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/compressed_sparsity_pattern.h>
#include <deal.II/lac/precondition_selector.h>
#include <deal.II/lac/sparse_direct.h>
#include <deal.II/lac/sparsity_tools.h>

#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/lac/trilinos_vector.h>
#include <deal.II/lac/trilinos_precondition.h>
#include <deal.II/lac/trilinos_solver.h>

#include <deal.II/lac/petsc_parallel_sparse_matrix.h>
#include <deal.II/lac/petsc_parallel_vector.h>
#include <deal.II/lac/petsc_solver.h>
#include <deal.II/lac/petsc_precondition.h>

#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/grid_in.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_boundary_lib.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>

#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_accessor.h>

#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_dgq.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_tools.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/mapping_q_eulerian.h>
#include <deal.II/fe/mapping_q.h>

#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>

#include <deal.II/distributed/tria.h>
#include <deal.II/distributed/grid_refinement.h>

#include <iostream>
#include <fstream>
//////////////////////////////////////////////////////////////////
namespace PhaseField
{
  using namespace dealii;
// INPUT OF PARAMETERS
  namespace Parameters
  {
    struct FESystem
    {
      unsigned int poly_degree;
      unsigned int quad_order;
      static void
      declare_parameters(ParameterHandler &prm);

      void
      parse_parameters(ParameterHandler &prm);
    };

    void FESystem::declare_parameters(ParameterHandler &prm)
    {
      prm.enter_subsection("Finite element system");
      {
        prm.declare_entry("Polynomial degree", "1",
                          Patterns::Integer(0),
                          "Displacement system polynomial order");
        prm.declare_entry("Quadrature order", "2",
                          Patterns::Integer(0),
                          "Gauss quadrature order");
      }
      prm.leave_subsection();
    }

    void FESystem::parse_parameters(ParameterHandler &prm)
    {
      prm.enter_subsection("Finite element system");
      {
        poly_degree = prm.get_integer("Polynomial degree");
        quad_order = prm.get_integer("Quadrature order");
      }
      prm.leave_subsection();
    }
////////////////////////////////////////////////////
    struct Geometry
    {
      unsigned int refinement;
      double       scale;
      static void
      declare_parameters(ParameterHandler &prm);
      void
      parse_parameters(ParameterHandler &prm);
    };
    void Geometry::declare_parameters(ParameterHandler &prm)
    {
      prm.enter_subsection("Geometry");
      {
        prm.declare_entry("Global refinement", "4",
                            Patterns::Integer(0),
                          "Global refinement level");
        prm.declare_entry("Grid scale", "1e-9",
                          Patterns::Double(0.0),
                          "Global grid scaling factor");
      }
      prm.leave_subsection();
    }
    void Geometry::parse_parameters(ParameterHandler &prm)
    {
      prm.enter_subsection("Geometry");
      {
    	refinement = prm.get_integer("Global refinement");
        scale = prm.get_double("Grid scale");
      }
      prm.leave_subsection();
    }

 /////////////////////////////////////////////////
        struct Materials
            {
              double lambda0; // austenite phase
              double mu0;     // austenite phase
              double lambda1;  // martensite phase
              double mu1;      // martensite phase
              double L;        // interface mobility
              double beta;     // gradient energy coefficient
              double A0;       // parameter for barrier height
              double theta;    // temperature
              double thetac;   // critical temperature
              double thetae;   // equilibrium temperature
              double thetan;   // Crank-Nicolson parameter

              static void
              declare_parameters(ParameterHandler &prm);
              void
              parse_parameters(ParameterHandler &prm);
            };
            void Materials::declare_parameters(ParameterHandler &prm)
            {
              prm.enter_subsection("Material properties");
              {
                prm.declare_entry("lambda austenite", "144.0e9",
                                  Patterns::Double(),
                                  "lambda austenite");

                prm.declare_entry("mu austenite", "74.0e9",
                                  Patterns::Double(0.0),
                                  "mu austenite");

                prm.declare_entry("lambda martensite", "379.0e9",
                                  Patterns::Double(),
                                  "lambda martensite");

                prm.declare_entry("mu martensite", "134.0e9",
                                  Patterns::Double(0.0),
                                  "mu martensite");

                prm.declare_entry("kinetic coeff", "2600.0",
                                  Patterns::Double(0.0),
                                  "kinetic coeff");

                prm.declare_entry("energy coeff", "2.59e-10",
                                  Patterns::Double(0.0),
                                  "energy coeff");

                prm.declare_entry("barrier height", "28.0e6",
                                  Patterns::Double(),
                                  "barrier height");

                prm.declare_entry("temperature", "50.0",
                                  Patterns::Double(0.0),
                                  "temperature");

                prm.declare_entry("temperature crit", "-183.0",
                                  Patterns::Double(),
                                  "temperature crit");

                prm.declare_entry("temperature eql", "215.0",
                                  Patterns::Double(),
                                  "temperature eql");

                prm.declare_entry("crank-nicolson parameter", "0.5",
                                   Patterns::Double(),
                                  "crank-nicolson parameter");
              }
              prm.leave_subsection();
            }

            void Materials::parse_parameters(ParameterHandler &prm)
            {
              prm.enter_subsection("Material properties");
              {
                lambda0 = prm.get_double("lambda austenite");
                mu0 = prm.get_double("mu austenite");
                lambda1 = prm.get_double("lambda martensite");
                mu1 = prm.get_double("mu martensite");
                L = prm.get_double("kinetic coeff");
                beta = prm.get_double("energy coeff");
                A0 = prm.get_double("barrier height");
                theta = prm.get_double("temperature");
                thetac = prm.get_double("temperature crit");
                thetae = prm.get_double("temperature eql");
                thetan = prm.get_double("crank-nicolson parameter");
                 }
              prm.leave_subsection();
            }


    /////////////////////////////////////////////////
    struct Time
    {
      double delta_t;
      double end_time;
      static void
      declare_parameters(ParameterHandler &prm);
      void
      parse_parameters(ParameterHandler &prm);
    };
    void Time::declare_parameters(ParameterHandler &prm)
    {
      prm.enter_subsection("Time");
      {
        prm.declare_entry("End time", "2e-12",
                          Patterns::Double(),
                          "End time");
        prm.declare_entry("Time step size", "1e-14",
                          Patterns::Double(),
                          "Time step size");
      }
      prm.leave_subsection();
    }
    void Time::parse_parameters(ParameterHandler &prm)
    {
      prm.enter_subsection("Time");
      {
        end_time = prm.get_double("End time");
        delta_t = prm.get_double("Time step size");
      }
      prm.leave_subsection();
    }
 ///////////////////////////////////////////////////////
    struct AllParameters : public FESystem,
      public Geometry,
      public Materials,
      public Time
    {
      AllParameters(const std::string &input_file);
      static void
      declare_parameters(ParameterHandler &prm);
      void
      parse_parameters(ParameterHandler &prm);
    };
    AllParameters::AllParameters(const std::string &input_file)
    {
      ParameterHandler prm;
      declare_parameters(prm);
      prm.read_input(input_file);
      parse_parameters(prm);
    }
    void AllParameters::declare_parameters(ParameterHandler &prm)
    {
      FESystem::declare_parameters(prm);
      Geometry::declare_parameters(prm);
      Materials::declare_parameters(prm);
      Time::declare_parameters(prm);
    }
    void AllParameters::parse_parameters(ParameterHandler &prm)
    {
      FESystem::parse_parameters(prm);
      Geometry::parse_parameters(prm);
      Materials::parse_parameters(prm);
      Time::parse_parameters(prm);
    }
  }

 //  DEFINE SECOND ORDER IDENTITY, AND TWO FOURTH ORDER IDENTITY TENSORS
  template <int dim>
  class StandardTensors
  {
  public:
    static const SymmetricTensor<2, dim> I;
    static const SymmetricTensor<4, dim> IxI;
    static const SymmetricTensor<4, dim> II;
   //   static const SymmetricTensor<2, dim> transformation_strain;
  };
  template <int dim>
  const SymmetricTensor<2, dim>
  StandardTensors<dim>::I = unit_symmetric_tensor<dim>();
  template <int dim>
  const SymmetricTensor<4, dim>
  StandardTensors<dim>::IxI = outer_product(I, I);
  template <int dim>
  const SymmetricTensor<4, dim>
  StandardTensors<dim>::II = identity_tensor<dim>();

// DEFINE TIME STEP, CURRENT TIME ETC.
  class Time
  {
  public:
    Time (const double time_end,
          const double delta_t)
      :
      timestep(0),
      time_current(0.0),
      time_end(time_end),
      delta_t(delta_t)
    {}

    virtual ~Time()
    {}
    double current() const
    {
      return time_current;
    }
    double end() const
    {
      return time_end;
    }
    double get_delta_t() const
    {
      return delta_t;
    }
    unsigned int get_timestep() const
    {
      return timestep;
    }
    void increment()
    {
      time_current += delta_t;
      ++timestep;
    }
  private:
    unsigned int timestep;
    double       time_current;
    const double time_end;
    const double delta_t;
  };

//////////////////////////////////////////////////////////
    template <int dim>
     class Material_Compressible_Neo_Hook_Three_Field
     {
     public:
       Material_Compressible_Neo_Hook_Three_Field(const double lambda0,
                                                  const double mu0,
                                                  const double lambda1,
                                                  const double mu1,
                                                  const double A0,
                                                  const double theta,
                                                  const double thetac,
                                                  const double thetae)
         :
         det_F(1.0),
         I1(0.0),   // I1 = trace(Be)
         ge(StandardTensors<dim>::I),  // = Fe.Fe^T
         Be(SymmetricTensor<2, dim>()),   // = 0.5(Fe.Fe^T-I)
         lambda00(lambda0),
         mu00(mu0),
         lambda11(lambda1),
         mu11(mu1),
         A00(A0),
         theta1(theta),
         thetac1(thetac),
         thetae1(thetae)
       {}

       ~Material_Compressible_Neo_Hook_Three_Field()
       {}

       void update_material_data (const Tensor<2, dim> &F, const Tensor<2, dim> &Fe,
                      const double phi, const double dphi,const double ddphi,
					  const double dPotentialBarrier, const double ddPotentialBarrier)
       {
         det_F = determinant(F);    // determinant of total F
         ge = symmetrize(Fe*transpose(Fe));  // ge = Fe.Fe^T
         Be = 0.5*(ge-StandardTensors<dim>::I);  // Be = 1/2(ge-I)
         I1 = trace(Be);                         // first invariant of Be
         lambda = lambda00+(lambda11-lambda00)*phi;  // definition of the Lame constants are obvious
         mu = mu00+(mu11-mu00)*phi;
         deltaG = A00*(theta1-thetae1)/3.0;   // difference in thermal energy
         A = A00*(theta1-thetac1);            // compute barrier height
         dphi1 = dphi;                        // d_phi/d_eta
         ddphi1 = ddphi;
         dPotentialBarrier1 = dPotentialBarrier;
         ddPotentialBarrier1 = ddPotentialBarrier;
         Assert(det_F > 0, ExcInternalError());
       }
       SymmetricTensor<2, dim> get_tau()    // tau is the Kirchhoff stress := J*Cauchy stress
       {
            return get_tau_kirchhoff();
       }
       SymmetricTensor<4, dim> get_Jc() const // comupte the fourth order modulus tensor in the deformed config.
       {
           return get_Jc_modulus();
       }
        double get_det_F() const
       {
         return det_F;
       }
       double get_driving_force_noStress() const  // driving force excluding the transformational work
       {
         return get_driv_forc_noStress ();
       }
       double get_deri_driving_force_noStress() const  // driving force excluding the transformational work
       {
         return get_deri_driv_forc_noStress ();
       }
     protected:
       double det_F;
       double I1;
       SymmetricTensor<2, dim> ge;
       SymmetricTensor<2, dim> Be;
       double lambda00;
       double mu00;
       double lambda11;
       double mu11;
       double A00;
       double theta1;
       double thetac1;
       double thetae1;
       double lambda;
       double mu;
       double deltaG;
       double A;
       double dphi1;
       double ddphi1;
       double dPotentialBarrier1;
       double ddPotentialBarrier1;
// compute the Kirchhoff stress
       SymmetricTensor<2, dim> get_tau_kirchhoff() const
       {
        SymmetricTensor<2, dim> kirchhoff_stress = lambda*I1*ge +
                         mu*symmetrize(Tensor<2, dim>(ge) * Tensor<2, dim>(ge))-mu*ge;
       return kirchhoff_stress;
       }
// compute the modulus J*d_ijkl
       SymmetricTensor<4, dim> get_Jc_modulus() const
       {
       SymmetricTensor<4,dim> elasticityTensor;
          for (unsigned int i=0; i<dim; ++i)
            for (unsigned int j=0; j<dim; ++j)
              for (unsigned int k=0; k<dim; ++k)
                for (unsigned int l=0; l<dim; ++l)
                  elasticityTensor[i][j][k][l] =
                     lambda*ge[i][j]*ge[k][l]+mu*(ge[i][l]*ge[j][k]+ge[i][k]*ge[j][l]);
          return elasticityTensor;
       }
       // compute the driving force excluding the transformational work
       double get_driv_forc_noStress () const
       {
        return  -A*dPotentialBarrier1-deltaG*dphi1;
       }
       double get_deri_driv_forc_noStress () const
       {
        return  -A*ddPotentialBarrier1-deltaG*ddphi1;
       }
     };

// updates the quadrature point history

  template <int dim>
    class PointHistory
    {
    public:
      PointHistory()
        :
        material(NULL),
        F_inv(StandardTensors<dim>::I),
        tau(SymmetricTensor<2, dim>()),
        Jc(SymmetricTensor<4, dim>())
      {}

      virtual ~PointHistory()
      {
        delete material;
        material = NULL;
      }

      void setup_lqp (const Parameters::AllParameters &parameters)
      {
        material = new Material_Compressible_Neo_Hook_Three_Field<dim>(parameters.lambda0,
            parameters.mu0, parameters.lambda1, parameters.mu1, parameters.A0,
            parameters.theta, parameters.thetac, parameters.thetae);

        update_values(Tensor<2, dim>(), double (), double (), double());
      }

      void update_values (const Tensor<2, dim> &Grad_u_n,
    		              const double new_eta,
			              const double old_eta,
						  const double thetan)
      {


        double eta = thetan*new_eta +(1-thetan)*old_eta;


        const double phi = 3*eta*eta-2*eta*eta*eta;   // interpolation function
        const double dphi = 6*eta-6*eta*eta;  // derivative of interpolation fn
        const double ddphi = 6-12*eta;
        const double dPotentialBarrier = 2*eta-6*eta*eta+4*eta*eta*eta;
        const double ddPotentialBarrier =2-12*eta+12*eta*eta;

//        double strectch1 = 0.8;
//        double strectch2 = 1.2;

        Tensor<2, dim> tmp;  // transformation strain tensor
//                tmp[0][0] = pow(strectch1, 1.5)/(1.0+strectch1) + pow(strectch2, 1.5)/(1.0+strectch2)-1.0;
//                tmp[1][1] = pow(strectch1, 0.5)/(1.0+strectch1) + pow(strectch2, 0.5)/(1.0+strectch2)-1.0;
//                tmp[2][2] = 0.0;
//                tmp[0][1] = -strectch1/(1.0+strectch1) + strectch2/(1.0+strectch2);
//                tmp[1][0] = -strectch1/(1.0+strectch1) + strectch2/(1.0+strectch2);
//                tmp[0][2] = 0.0;
//                tmp[2][0] = 0.0;
//                tmp[1][2] = 0.0;
//                tmp[2][1] = 0.0;

//
        tmp[0][0] = 0.1;
        tmp[1][1] = -0.05;
        tmp[2][2] = -0.05;
        tmp[0][1] = 0.0;
        tmp[1][0] = 0.0;
        tmp[0][2] = 0.0;
        tmp[2][0] = 0.0;
        tmp[1][2] = 0.0;
        tmp[2][1] = 0.0;

        SymmetricTensor<2, dim> transStrain = symmetrize(tmp);

        const Tensor<2, dim> Ft = (Tensor<2, dim>(StandardTensors<dim>::I) +
                        Tensor<2, dim>(transStrain)*phi);  // transformation deformation gradient
        F = (Tensor<2, dim>(StandardTensors<dim>::I) +  Grad_u_n);  // total F
        Fe = F * invert(Ft); // elastic part of deformation grad
        material->update_material_data(F, Fe, phi, dphi, ddphi, dPotentialBarrier, ddPotentialBarrier);
        F_inv = invert(F);
        tau = material->get_tau(); // extracting kirchhoff stress
        Jc = material->get_Jc();  // extracting J*d_ijkl
        driving_force_noStress = material->get_driving_force_noStress(); // extracting driving force with no stress
        deri_driving_force_noStress = material->get_deri_driving_force_noStress();

        const Tensor<2, dim> temp_tensor = F_inv*Tensor<2, dim>(tau);
        const Tensor<2, dim> temp_tensor1 = temp_tensor * Fe;
        get_driv_forc = scalar_product(temp_tensor1, tmp)*dphi + driving_force_noStress; // computing total driving force
        get_deri_driv_forc = scalar_product(temp_tensor1, tmp)*ddphi + deri_driving_force_noStress;

        Assert(determinant(F_inv) > 0, ExcInternalError());
      }


      const Tensor<2, dim> &get_F() const
      {
        return F;
      }
      double get_det_F() const
      {
        return material->get_det_F();
      }

      const Tensor<2, dim> &get_F_inv() const
      {
        return F_inv;
      }

      const SymmetricTensor<2, dim> &get_tau() const
      {
        return tau;
      }

      const SymmetricTensor<4, dim> &get_Jc() const
      {
        return Jc;
      }

      double get_driving_force() const
      {
        return get_driv_forc;
      }

      double get_deri_driving_force() const
      {
        return get_deri_driv_forc;
      }


    private:
      Material_Compressible_Neo_Hook_Three_Field<dim> *material;
      Tensor<2, dim> F_inv;
      Tensor<2, dim> F;
      SymmetricTensor<2, dim> tau;
      SymmetricTensor<4, dim> Jc;
      Tensor<2, dim> Fe;
      double driving_force_noStress;
      double deri_driving_force_noStress;
      double dphi;
      double ddphi;
      double get_driv_forc;
      double get_deri_driv_forc;
    };
///////////////////////////////////////////////////////////////

  template <int dim>
  class Solid
  {
  public:
    Solid(const std::string &input_file);

    virtual
    ~Solid();

    void
    run();

  private:

    void    make_grid();
    void    system_setup();
    void    assemble_system();
    void    make_constraints(const int &it_nr);
    void    solve_nonlinear_timestep();
    unsigned int    solve();
    void    assemble_system_eta();
    void    solve_nonlinear_timestep_eta();
    unsigned int    solve_eta();
    void    setup_qph();
    void    update_qph_incremental();
    void    output_results() const;


    Parameters::AllParameters        parameters;

    double                           vol_reference; // volume of the reference config
    double                           vol_current;  // volume of the current config

    Time                             time;  // variable of type class 'Time'
    TimerOutput                      timer;


    MPI_Comm                         mpi_communicator;
    parallel::distributed::Triangulation<dim> triangulation;
    ConditionalOStream               pcout;

    const unsigned int               degree; // degree of polynomial of shape functions
    const FESystem<dim>              fe; // fe object
    DoFHandler<dim>                  dof_handler; // we have used two dof_handler: one for mechanics another for order parameter
    const unsigned int               dofs_per_cell;   // no of dofs per cell for the mechanics problem
    const FEValuesExtractors::Vector u_fe;
    const QGauss<dim>                qf_cell;  // quadrature points in the cell
    const QGauss<dim - 1>            qf_face;  // quadrature points at the face
    const unsigned int               n_q_points;  // no of quadrature points in the cell
    const unsigned int               n_q_points_f; // no of quadrature points at the face
    ConstraintMatrix                 constraints;  // constraint object

    FE_DGQ<dim>          		     history_fe;
    DoFHandler<dim>     			 history_dof_handler;

    std::vector<PointHistory<dim> >  quadrature_point_history;

    IndexSet                         locally_owned_dofs;
    IndexSet                         locally_relevant_dofs;


    LA::MPI::SparseMatrix      	     tangent_matrix;  // tangent stiffenss matrix
    LA::MPI::Vector                  system_rhs;  // system right hand side or residual of mechanics problem
    LA::MPI::Vector                  solution;  // solution vector for displacement
    LA::MPI::Vector                  solution_update; // another vector containing the displacement soln
    LA::MPI::Vector                  tmp;

    const unsigned int               degree_eta; // degree of polynomial for eta
    FE_Q<dim>                        fe_eta;  // fe object for eta
    DoFHandler<dim>                  dof_handler_eta; //another dof_handler for eta
    const unsigned int               dofs_per_cell_eta; // dof per eta cell
    const QGauss<dim>                qf_cell_eta;
    const unsigned int               n_q_points_eta;

    IndexSet                         locally_owned_dofs_eta;
    IndexSet                         locally_relevant_dofs_eta;

    LA::MPI::SparseMatrix            mass_matrix;  // mass matrix out of Ginxburg-Landau eqn
    LA::MPI::SparseMatrix            laplace_matrix; // Laplace matrix out of Ginxburg-Landau eqn
    LA::MPI::SparseMatrix            system_matrix_eta;
    LA::MPI::SparseMatrix            nl_matrix;
    LA::MPI::SparseMatrix            tmp_matrix;
    LA::MPI::Vector                  nl_term;
    LA::MPI::Vector                  system_rhs_eta;
    LA::MPI::Vector                  solution_eta;  // solution vector for eta
    LA::MPI::Vector                  old_solution_eta;
    LA::MPI::Vector                  solution_update_eta;
    LA::MPI::Vector                  tmp_vector;   // a vector used for solving eta
    LA::MPI::Vector                  tmp_eta;

  };
/////////////////////////////////////////////////////////

 // defines the initial condition for the order parameter
           template <int dim>
           class InitialValues : public Function<dim>
           {
           public:
             InitialValues () : Function<dim>() {}
             virtual double value(const Point<dim>   &p,
                                   const unsigned int  /*component = 0*/) const;
           };

           template <int dim>
           double InitialValues<dim>::value (const Point<dim>  &p,
                                      const unsigned int /*component*/) const
           {
          // return 0.01;
         	return  (rand()%100+0.0)*0.01;

//               if ((p[0] > 2.5e-9) && (p[1] > 2.5e-9) && (p[0] < 7.5e-9) && (p[1] < 7.5e-9))
//                 return 1;
//               else
//                 return 0;
////
//       return
//       -std::max(std::min(-tanh((sqrt((p[0]-3.0e-9)*(p[0]-3.0e-9)+(p[1]-3.0e-9)*(p[1]-3.0e-9))-1.0e-9)/0.4e-9),0.0),
//       std::min(-tanh((sqrt((p[0]-7.0e-9)*(p[0]-7.0e-9)+(p[1]-3.0e-9)*(p[1]-3.0e-9))-1.0e-9)/0.4e-9),0.0));


  // return   std::max(tanh((1e-9-sqrt((p[0]-5.0e-9)*(p[0]-5.0e-9)+(p[1]-5.0e-9)*(p[1]-5.0e-9)))/0.4e-9),0.0);

    //return (0.5*std::tanh(3.0*(p[0]-5.0e-9)/7.07e-10)+0.5);
   //return  0.1 * std::max(tanh((p[0]-5.0e-9)/(0.4e-9)), 0.0);
    //  return 0.5*std::tanh(p[0]/(0.4e-9))+0.5;
           }
   /////////////////////////////////////////////////
     template <int dim>
     class BoundaryDisplacement :  public Function<dim>
     {
     public:
  	  BoundaryDisplacement (const int direction, const int time_step);
       virtual
       void
       vector_value (const Point<dim> &p,
                     Vector<double>   &values) const;
       virtual
       void
       vector_value_list (const std::vector<Point<dim> > &points,
                          std::vector<Vector<double> >   &value_list) const;
     private:
       const int direction;
       const int time_step;
     };
     template <int dim>
     BoundaryDisplacement<dim>::BoundaryDisplacement (const int direction,const int time_step)
       :
       Function<dim> (dim),
  	  direction(direction),
  	  time_step(time_step)
     {}
     template <int dim>
     inline
     void
  	BoundaryDisplacement<dim>::vector_value (const Point<dim> &/*p*/,
                                   Vector<double>   &values) const
     {
       Assert (values.size() == dim,
               ExcDimensionMismatch (values.size(), dim));

       values = 0;
       if (time_step <3)
        values(direction) = 0.1e-9;
       else
        values(direction)= 0.001e-9;

     }
     template <int dim>
     void
  	BoundaryDisplacement<dim>::vector_value_list (const std::vector<Point<dim> > &points,
                                        std::vector<Vector<double> >   &value_list) const
     {
       const unsigned int n_ooints = points.size();
       Assert (value_list.size() == n_ooints,
               ExcDimensionMismatch (value_list.size(), n_ooints));
       for (unsigned int p=0; p<n_ooints; ++p)
     	  BoundaryDisplacement<dim>::vector_value (points[p],
                                       value_list[p]);
     }

///////////////////////////////////////////////////
// constructor
  template <int dim>
  Solid<dim>::Solid(const std::string &input_file)
    :
    mpi_communicator (MPI_COMM_WORLD),
    triangulation (mpi_communicator,
                   typename Triangulation<dim>::MeshSmoothing
                   (Triangulation<dim>::smoothing_on_refinement |
                    Triangulation<dim>::smoothing_on_coarsening)),

    parameters(input_file),
    time(parameters.end_time, parameters.delta_t),

	pcout (std::cout,
		  (Utilities::MPI::this_mpi_process(mpi_communicator)
		   == 0)),
    timer(mpi_communicator,
          pcout,
          TimerOutput::summary,
          TimerOutput::wall_times),

    degree(parameters.poly_degree),
    fe(FE_Q<dim>(parameters.poly_degree), dim), // displacement
    dof_handler(triangulation),
    dofs_per_cell (fe.dofs_per_cell),
	u_fe(0),
    qf_cell(parameters.quad_order),
    qf_face(parameters.quad_order),
    n_q_points (qf_cell.size()),
    n_q_points_f (qf_face.size()),

    degree_eta(parameters.poly_degree),
    fe_eta (parameters.poly_degree),
    dof_handler_eta (triangulation),
    dofs_per_cell_eta(fe_eta.dofs_per_cell),
	qf_cell_eta(parameters.quad_order),
	n_q_points_eta (qf_cell_eta.size()),

	history_dof_handler (triangulation),
	history_fe (parameters.poly_degree)
  {}

//destructor
  template <int dim>
  Solid<dim>::~Solid()
  {
    dof_handler.clear();
    dof_handler_eta.clear();
  }

  //////////////////////////////////////////////////
    template <int dim>
    void Solid<dim>::run()
    {
      make_grid(); // generates the geometry and mesh
      system_setup(); // sets up the system matrices

      VectorTools::interpolate(dof_handler_eta, InitialValues<dim>(), tmp_eta); //initial eta
      solution_eta= tmp_eta;
      old_solution_eta = solution_eta;
      update_qph_incremental();

  // this is the zeroth iteration for compute the initial distorted solution
  //of the body due to arbitrary distribution of initial eta

      solve_nonlinear_timestep();
      output_results();

      time.increment();

   // computed actual time integration to update displacement and eta
      while (time.current() <= time.end())
        {
    	  pcout << std::endl
    	        << "Time step #" << time.get_timestep() << "; "
    	        << "advancing to t = " << time.current() << "."
    	        << std::endl;
       solve_nonlinear_timestep_eta();
       solve_nonlinear_timestep();
       output_results();
       time.increment();

        }
     }
///////////////////////////////////
  template <int dim>
  void Solid<dim>::solve_nonlinear_timestep()
   {
	 double initial_rhs_norm = 0.;
     unsigned int newton_iteration = 0;
       for (; newton_iteration < 20;   ++newton_iteration)
         {
       	  assemble_system ();
       	  make_constraints(newton_iteration);

       	  if (newton_iteration == 0)
       	     initial_rhs_norm = system_rhs.l2_norm();

       	  const unsigned int n_iterations
       	      = solve ();

       	   tmp += solution_update;
       	   solution = tmp;
         update_qph_incremental();

       	 if (newton_iteration == 0)
       	   std::cout << " Solving for Displacement:   " << n_iterations;
       	 else
       	   std::cout << '+' << n_iterations;

       	 if (newton_iteration > 0 && system_rhs.l2_norm() <= 1e-6 * initial_rhs_norm)
       	  {
       	   std::cout << " CG iterations per nonlinear step.     CONVERGED! " << std::endl;
       	   break;
       	  }
       	AssertThrow (newton_iteration < 19,
       	ExcMessage("No convergence in nonlinear solver!"));

        }
   }

  /////////////////////////////////////////
  template <int dim>
    void Solid<dim>::solve_nonlinear_timestep_eta()
     {
	  old_solution_eta = solution_eta;
  	  double initial_rhs_norm = 0.;
      unsigned int newton_iteration = 0;
         for (; newton_iteration < 20;   ++newton_iteration)
           {
         	  assemble_system_eta ();

         	  if (newton_iteration == 0)
         	     initial_rhs_norm = system_rhs_eta.l2_norm();

         	  const unsigned int n_iterations
         	      = solve_eta ();

         	 tmp_eta += solution_update_eta;
         	 solution_eta= tmp_eta;
         	 update_qph_incremental();

         	 if (newton_iteration == 0)
         	   std::cout << " Solving for Order Parameter:   " << n_iterations;
         	 else
         	   std::cout << '+' << n_iterations;

         	 if (newton_iteration > 0 && system_rhs_eta.l2_norm() <= 1e-6 * initial_rhs_norm)
         	  {
         	   std::cout << " CG iterations per nonlinear step.     CONVERGED! " << std::endl;
         	   break;
         	  }
         	AssertThrow (newton_iteration < 19,
         	ExcMessage("No convergence in nonlinear solver!"));

          }
     }

///////////////////////////////////////////////////////
  template <int dim>
  void Solid<dim>::make_grid()
  {
//    // Divide the beam, but only along the x- and y-coordinate directions
//    std::vector< unsigned int > repetitions(dim, 32);
//    // Only allow one element through the thickness
//    // (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>(10.0, 10.0, 0.5) : Point<dim>(10.0, 10.0));
//
//    GridGenerator::subdivided_hyper_rectangle(triangulation,
//                                              repetitions,
//                                              bottom_left,
//                                              top_right,
//											  true);


	  GridGenerator::hyper_rectangle(triangulation,
	                                 Point<dim>(0.0, 0.0, 0.0),
	                                 Point<dim>(10.0, 10.0, 10.0),
	                                 true);
	  triangulation.refine_global (parameters.refinement);

    GridTools::scale(parameters.scale, triangulation);


  }


///////////////////////////////////////////////////
  template <int dim>
  void Solid<dim>::system_setup()
  {
    dof_handler.distribute_dofs(fe);
    dof_handler_eta.distribute_dofs (fe_eta);
    history_dof_handler.distribute_dofs (history_fe);

    const unsigned int n_dofs = dof_handler.n_dofs(),
         		       n_dofs_eta  = dof_handler_eta.n_dofs();

         std::cout     << "   Number of active cells: "
                       << triangulation.n_active_cells()
                       << std::endl
                       << "   Total number of cells: "
                       << triangulation.n_cells()
                       << std::endl
   					   << "   Number of degrees of freedom: "
                       << n_dofs + n_dofs_eta
                       << " (" << n_dofs << '+' << n_dofs_eta << ')'
                       << std::endl;

    locally_owned_dofs = dof_handler.locally_owned_dofs ();
    DoFTools::extract_locally_relevant_dofs (dof_handler  ,  locally_relevant_dofs);

    DynamicSparsityPattern dsp(locally_relevant_dofs);
    DoFTools::make_sparsity_pattern (dof_handler, dsp);
    SparsityTools::distribute_sparsity_pattern (dsp,
                                                dof_handler.n_locally_owned_dofs_per_processor(),
                                                mpi_communicator,
                                                locally_relevant_dofs);

    tangent_matrix.reinit(locally_owned_dofs,
                          locally_owned_dofs,
                          dsp,
                          mpi_communicator);

    solution.reinit(locally_owned_dofs,
                      locally_relevant_dofs,
	                  mpi_communicator);
    solution_update.reinit(locally_owned_dofs,
                           locally_relevant_dofs,
	                       mpi_communicator);

    system_rhs.reinit(locally_owned_dofs,
                      mpi_communicator);
    tmp.reinit(locally_owned_dofs,
                          mpi_communicator);

    locally_owned_dofs_eta = dof_handler_eta.locally_owned_dofs ();
    DoFTools::extract_locally_relevant_dofs (dof_handler_eta  ,  locally_relevant_dofs_eta);

    DynamicSparsityPattern dsp_eta(locally_relevant_dofs_eta);
    DoFTools::make_sparsity_pattern (dof_handler_eta, dsp_eta);
    SparsityTools::distribute_sparsity_pattern (dsp_eta,
                                                dof_handler_eta.n_locally_owned_dofs_per_processor(),
                                                mpi_communicator,
                                                locally_relevant_dofs_eta);

    mass_matrix.reinit (locally_owned_dofs_eta,
                        locally_owned_dofs_eta,
                        dsp_eta,
                        mpi_communicator);
    laplace_matrix.reinit (locally_owned_dofs_eta,
                           locally_owned_dofs_eta,
                           dsp_eta,
                           mpi_communicator);
    system_matrix_eta.reinit (locally_owned_dofs_eta,
                              locally_owned_dofs_eta,
                              dsp_eta,
                              mpi_communicator);
    nl_matrix.reinit (locally_owned_dofs_eta,
                      locally_owned_dofs_eta,
                      dsp_eta,
                      mpi_communicator);
    tmp_matrix.reinit (locally_owned_dofs_eta,
                       locally_owned_dofs_eta,
                       dsp_eta,
                       mpi_communicator);

//    MatrixCreator::create_mass_matrix(dof_handler_eta,
//                                      QGauss<dim>(fe_eta.degree+1),
//                                      mass_matrix);
//    MatrixCreator::create_laplace_matrix(dof_handler_eta,
//                                         QGauss<dim>(fe_eta.degree+1),
//                                         laplace_matrix);

    solution_eta.reinit(locally_owned_dofs_eta,
                        locally_relevant_dofs_eta,
                        mpi_communicator);
    old_solution_eta.reinit(locally_owned_dofs_eta,
                            locally_relevant_dofs_eta,
                            mpi_communicator);
    solution_update_eta.reinit(locally_owned_dofs_eta,
                               locally_relevant_dofs_eta,
                               mpi_communicator);

    system_rhs_eta.reinit(locally_owned_dofs_eta,
                          mpi_communicator);
    nl_term.reinit(locally_owned_dofs_eta,
                   mpi_communicator);
    tmp_vector.reinit(locally_owned_dofs_eta,
                      mpi_communicator);
    tmp_eta.reinit(locally_owned_dofs_eta,
                          mpi_communicator);
// sets up the quadrature point history
   setup_qph();


  }

  //////////////////////////////////
  template <int dim>
      void Solid<dim>::make_constraints(const int &it_nr)
      {
        if (it_nr > 1)
          return;

        constraints.clear();
        constraints.reinit (locally_relevant_dofs);

        const bool apply_dirichlet_bc = (it_nr == 0);
        const int  timestep = time.get_timestep();

        const FEValuesExtractors::Scalar x_displacement(0);
        const FEValuesExtractors::Scalar y_displacement(1);
        const FEValuesExtractors::Scalar z_displacement(2);
        {
          const int boundary_id = 0;

          if (apply_dirichlet_bc == true)
            VectorTools::interpolate_boundary_values(dof_handler,
                                                     boundary_id,
                                                     ZeroFunction<dim>(dim),
                                                     constraints,
                                                     fe.component_mask(x_displacement)/*|
                                                     fe.component_mask(y_displacement) |
                                                     fe.component_mask(z_displacement)*/);
          else
            VectorTools::interpolate_boundary_values(dof_handler,
                                                     boundary_id,
                                                     ZeroFunction<dim>(dim),
                                                     constraints,
                                                     fe.component_mask(x_displacement)/* |
                                                     fe.component_mask(y_displacement) |
                                                     fe.component_mask(z_displacement)*/);
        }

        {
      	  const int boundary_id = 1;

         if (apply_dirichlet_bc == true)
          VectorTools::interpolate_boundary_values(dof_handler,
                                                   boundary_id,
  												 BoundaryDisplacement<dim>(0, timestep),
                                                   constraints,
                                                   fe.component_mask(x_displacement));
        else
          VectorTools::interpolate_boundary_values(dof_handler,
                                                   boundary_id,
  												 ZeroFunction<dim>(dim),
                                                   constraints,
                                                   fe.component_mask(x_displacement));
        }
//
////
        {
         const int boundary_id = 2;

        if (apply_dirichlet_bc == true)
         VectorTools::interpolate_boundary_values(dof_handler,
                                                  boundary_id,
                                                  ZeroFunction<dim>(dim),
                                                  constraints,
                                                  fe.component_mask(y_displacement));
       else
         VectorTools::interpolate_boundary_values(dof_handler,
                                                  boundary_id,
                                                  ZeroFunction<dim>(dim),
                                                  constraints,
                                                  fe.component_mask(y_displacement));
        }
  //
  //      {
  //    	const int boundary_id = 3;
  //
  //      if (apply_dirichlet_bc == true)
  //       VectorTools::interpolate_boundary_values(dof_handler,
  //                                                boundary_id,
  //                                                ZeroFunction<dim>(dim),
  //                                                constraints,
  //                                                fe.component_mask(y_displacement));
  //     else
  //       VectorTools::interpolate_boundary_values(dof_handler,
  //                                                boundary_id,
  //                                                ZeroFunction<dim>(dim),
  //                                                constraints,
  //                                                fe.component_mask(y_displacement));
  //      }


        {
          const int boundary_id = 4;

           if (apply_dirichlet_bc == true)
            VectorTools::interpolate_boundary_values(dof_handler,
                                                     boundary_id,
                                                     ZeroFunction<dim>(dim),
                                                     constraints,
                                                     fe.component_mask(z_displacement));
          else
            VectorTools::interpolate_boundary_values(dof_handler,
                                                     boundary_id,
                                                     ZeroFunction<dim>(dim),
                                                     constraints,
                                                     fe.component_mask(z_displacement));
        }

//        {
//      	const int boundary_id = 5;
//
//        if (apply_dirichlet_bc == true)
//          VectorTools::interpolate_boundary_values(dof_handler,
//                                                   boundary_id,
//                                                   ZeroFunction<dim>(dim),
//                                                   constraints,
//                                                   fe.component_mask(z_displacement));
//        else
//          VectorTools::interpolate_boundary_values(dof_handler,
//                                                   boundary_id,
//                                                   ZeroFunction<dim>(dim),
//                                                   constraints,
//                                                   fe.component_mask(z_displacement));
//        }
        constraints.close();
      }
  /////////////////////////////////////////////////////////////////////////////////////
  template <int dim>
  void Solid<dim>::assemble_system ()
  {
	tangent_matrix = 0;
	system_rhs = 0;

   FEValues<dim> fe_values (fe, qf_cell,
                            update_values   | update_gradients |
                            update_quadrature_points | update_JxW_values);


   FEFaceValues<dim> fe_face_values (fe, qf_face,
                                     update_values         | update_quadrature_points  |
                                     update_normal_vectors | update_JxW_values);

   FullMatrix<double>   cell_matrix (dofs_per_cell, dofs_per_cell);
   Vector<double>       cell_rhs (dofs_per_cell);

   std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);

   std::vector<double>                    Nx(dofs_per_cell);
   std::vector<Tensor<2, dim> >           grad_Nx(dofs_per_cell);
   std::vector<SymmetricTensor<2, dim> >  symm_grad_Nx(dofs_per_cell);



   typename DoFHandler<dim>::active_cell_iterator
   cell = dof_handler.begin_active(),
   endc = dof_handler.end();
   for (; cell!=endc;  ++cell)
	   if (cell->is_locally_owned())
       {
   	    fe_values.reinit (cell);
   	    cell_matrix = 0;
        cell_rhs = 0;

       PointHistory<dim> *lqph =
             reinterpret_cast<PointHistory<dim>*>(cell->user_pointer());

        for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
           {
      	  const Tensor<2, dim> F_inv = lqph[q_point].get_F_inv();
      	  const Tensor<2, dim> tau         = lqph[q_point].get_tau();
      	  const SymmetricTensor<2, dim> symm_tau         = lqph[q_point].get_tau();
      	  const SymmetricTensor<4, dim> Jc = lqph[q_point].get_Jc();
      	  const double JxW = fe_values.JxW(q_point);

      	  for (unsigned int k=0; k<dofs_per_cell; ++k)
               {
      		    grad_Nx[k] = fe_values[u_fe].gradient(k, q_point)  * F_inv;
      		    symm_grad_Nx[k] = symmetrize(grad_Nx[k]);
               }


          for (unsigned int i=0; i<dofs_per_cell; ++i)
             {
          	 const unsigned int component_i = fe.system_to_component_index(i).first;

           	 for (unsigned int j=0; j<dofs_per_cell; ++j)
               {
           		  const unsigned int component_j = fe.system_to_component_index(j).first;

           		   cell_matrix(i, j) += symm_grad_Nx[i] * Jc // The material contribution:
           		                               * symm_grad_Nx[j] * JxW;
           		  if (component_i == component_j) // geometrical stress contribution
           		   cell_matrix(i, j) += grad_Nx[i][component_i] * tau
           		                               * grad_Nx[j][component_j] * JxW;
              }

           	       cell_rhs(i) -= symm_grad_Nx[i] * symm_tau * JxW;
            }
       }

//
//
//       for (unsigned int face_number=0; face_number<GeometryInfo<dim>::faces_per_cell; ++face_number)
//         if (cell->face(face_number)->at_boundary()
//             &&
//             (cell->face(face_number)->boundary_id() == 1))
//           {
//             fe_face_values.reinit (cell, face_number);
//             for (unsigned int q_point=0; q_point<n_q_points_f; ++q_point)
//               {
//           	  double magnitude;
//
//           	  if (cell->face(face_number)->center()[1]>= -0.2e-9 && cell->face(face_number)->center()[1]<= 0.2e-9)
//           	     magnitude = -10e8;
//           	  else
//           	     magnitude = 0.0;
//
//           	  static const Tensor<1, dim> dir ({1.0,0.0,0.0});
//           	  const Tensor<1, dim> traction  = magnitude*dir;
//
//
//                 for (unsigned int i=0; i<dofs_per_cell; ++i)
//                 {
//                     const unsigned int
//                   component_i = fe.system_to_component_index(i).first;
//                   cell_rhs(i) += (traction[component_i] *
//                                   fe_face_values.shape_value(i,q_point) *
//                                   fe_face_values.JxW(q_point));
//                 }
//               }
//           }

//

      cell->get_dof_indices (local_dof_indices);
      constraints.distribute_local_to_global (cell_matrix,
                                              cell_rhs,
                                              local_dof_indices,
                                              tangent_matrix,
                                              system_rhs);

     }

   tangent_matrix.compress (VectorOperation::add);
   system_rhs.compress (VectorOperation::add);
  }



  //////////////////////////////////////////////////////
  template <int dim>
  void Solid<dim>::assemble_system_eta ()
  {
    system_matrix_eta = 0;
    system_rhs_eta = 0;
    mass_matrix = 0;
    laplace_matrix = 0;
    nl_matrix = 0;
    nl_term = 0;

    FEValues<dim> fe_values_eta (fe_eta, qf_cell_eta,
                             update_values  | update_gradients |
							 update_quadrature_points | update_JxW_values);

    FullMatrix<double>   cell_mass_matrix            (dofs_per_cell_eta, dofs_per_cell_eta);
    FullMatrix<double>   cell_laplace_matrix         (dofs_per_cell_eta, dofs_per_cell_eta);
    FullMatrix<double>   cell_nl_matrix              (dofs_per_cell_eta, dofs_per_cell_eta);
    Vector    <double>   cell_nl_term                (dofs_per_cell_eta);

    std::vector<types::global_dof_index> local_dof_indices(dofs_per_cell_eta);

    std::vector<double> phi (dofs_per_cell_eta);
    std::vector<Tensor<1,dim> >   grad_phi (dofs_per_cell_eta);

    typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler_eta.begin_active(),
    endc = dof_handler_eta.end();
    for (; cell!=endc; ++cell)
      if (cell->is_locally_owned())
      {
        fe_values_eta.reinit(cell);

        cell_mass_matrix = 0;
        cell_laplace_matrix = 0;
        cell_nl_matrix = 0;
        cell_nl_term = 0;

        PointHistory<dim> *lqph =
                      reinterpret_cast<PointHistory<dim>*>(cell->user_pointer());

	        for (unsigned int q=0; q<n_q_points_eta; ++q)
          {
	        	const double driving_force = lqph[q].get_driving_force();
	        	const double deri_driving_force = lqph[q].get_deri_driving_force();

        	for (unsigned int k=0; k<dofs_per_cell_eta; ++k)
              {
            	phi[k]      = fe_values_eta.shape_value (k, q);
            	grad_phi[k] = fe_values_eta.shape_grad  (k, q);
              }

            for (unsigned int i=0; i<dofs_per_cell_eta; ++i)
              {
                for (unsigned int j=0; j<dofs_per_cell_eta; ++j)
                {
                	cell_mass_matrix(i,j)    += (phi[i]      * phi[j])      * fe_values_eta.JxW(q);
                	cell_laplace_matrix(i,j) += (grad_phi[i] * grad_phi[j]) * fe_values_eta.JxW(q);

                	cell_nl_matrix(i,j) += deri_driving_force * phi[i] * phi[j] * fe_values_eta.JxW(q);
                }

                    cell_nl_term(i)     +=  driving_force * phi[i] * fe_values_eta.JxW (q);
              }
          }


        cell->get_dof_indices (local_dof_indices);

        for (unsigned int i=0; i<dofs_per_cell_eta; ++i)
          {
            for (unsigned int j=0; j<dofs_per_cell_eta; ++j)
              {
            	mass_matrix.  add (local_dof_indices[i],
            	  	               local_dof_indices[j],
            	  	               cell_mass_matrix(i,j));

               laplace_matrix.add (local_dof_indices[i],
            	     	           local_dof_indices[j],
            	  	               cell_laplace_matrix(i,j));

               nl_matrix.     add (local_dof_indices[i],
                   			        local_dof_indices[j],
                   	                cell_nl_matrix(i,j));

              }
                nl_term (local_dof_indices[i]) += cell_nl_term(i);
          }
     }


    mass_matrix.compress (VectorOperation::add);
    laplace_matrix.compress (VectorOperation::add);
    nl_matrix.compress (VectorOperation::add);
    nl_term.compress (VectorOperation::add);

    system_matrix_eta.copy_from (mass_matrix);
    system_matrix_eta.add (  laplace_matrix, parameters.L * parameters.beta * parameters.delta_t * parameters.thetan);
    system_matrix_eta.add ( nl_matrix,  -parameters.L * parameters.delta_t * parameters.thetan);

    tmp_matrix.copy_from (mass_matrix);
    tmp_matrix.add (  laplace_matrix, parameters.L * parameters.beta * parameters.delta_t * parameters.thetan);


    tmp_matrix.vmult (tmp_vector, solution_eta);
    system_rhs_eta += tmp_vector;

    tmp_matrix.add(  laplace_matrix, -parameters.L * parameters.beta * parameters.delta_t);

    tmp_matrix.vmult (tmp_vector, old_solution_eta);
    system_rhs_eta -= tmp_vector;
    system_rhs_eta.add (-parameters.L * parameters.delta_t, nl_term);

    system_rhs_eta *= -1;

    system_matrix_eta.compress (VectorOperation::add);
    system_rhs_eta.compress (VectorOperation::add);

  }

///////////////////////////////////////////////////////////////////////
  template <int dim>
  void Solid<dim>::setup_qph()
  {

    {
    unsigned int our_cells = 0;
    for (typename Triangulation<dim>::active_cell_iterator
         cell = triangulation.begin_active();
         cell != triangulation.end(); ++cell)
      if (cell->is_locally_owned())
        ++our_cells;
    triangulation.clear_user_data();
    {
      std::vector<PointHistory<dim> > tmp;
      tmp.swap (quadrature_point_history);
    }
    quadrature_point_history.resize (our_cells * n_q_points);

      unsigned int history_index = 0;
      for (typename Triangulation<dim>::active_cell_iterator
    		  cell = triangulation.begin_active();
    		  cell != triangulation.end(); ++cell)
       if (cell->is_locally_owned())
        {
          cell->set_user_pointer(&quadrature_point_history[history_index]);
          history_index += n_q_points;
        }

      Assert(history_index == quadrature_point_history.size(),
             ExcInternalError());
    }

    for (typename Triangulation<dim>::active_cell_iterator
    		cell = triangulation.begin_active();
    		cell != triangulation.end(); ++cell)
     if (cell->is_locally_owned())
      {
        PointHistory<dim> *lqph =
          reinterpret_cast<PointHistory<dim>*>(cell->user_pointer());

        Assert(lqph >= &quadrature_point_history.front(), ExcInternalError());
        Assert(lqph <= &quadrature_point_history.back(), ExcInternalError());

        for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
          lqph[q_point].setup_lqp(parameters);
      }
  }

// Updates the data at all quadrature points over a loop run by WorkStream::run
  template <int dim>
  void Solid<dim>::update_qph_incremental()

  {
    FEValues<dim> fe_values (fe, qf_cell,
                                 update_values | update_gradients);
    FEValues<dim> fe_values_eta (fe_eta, qf_cell,
                                     update_values | update_gradients);

    std::vector<Tensor<2, dim> > solution_grads_total (qf_cell.size());
    std::vector<double> solution_eta_total (qf_cell.size());
    std::vector<double> old_solution_eta_total (qf_cell.size());

    typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
    typename DoFHandler<dim>::active_cell_iterator
    cell_eta = dof_handler_eta.begin_active();
    for (; cell!=endc; ++cell, ++cell_eta)
    	if (cell->is_locally_owned())
        {
    	    PointHistory<dim> *lqph =
    	      reinterpret_cast<PointHistory<dim>*>(cell->user_pointer());

    	    Assert(lqph >= &quadrature_point_history.front(), ExcInternalError());
    	    Assert(lqph <= &quadrature_point_history.back(), ExcInternalError());

    	    Assert(solution_grads_total.size() == n_q_points,
    	           ExcInternalError());
    	    Assert(solution_eta_total.size() == n_q_points,
    	           ExcInternalError());

    	    fe_values.reinit(cell);
    	    fe_values_eta.reinit (cell_eta);

    	    fe_values[u_fe].get_function_gradients(solution,  solution_grads_total);
    	    fe_values_eta.get_function_values(solution_eta,   solution_eta_total);
    	    fe_values_eta.get_function_values(old_solution_eta,   old_solution_eta_total);

    	   for (unsigned int q_point = 0; q_point < n_q_points; ++q_point)
    	          lqph[q_point].update_values(solution_grads_total[q_point],
    	                                      solution_eta_total[q_point],
											  old_solution_eta_total[q_point],
											  parameters.thetan);
       }

  }
  //////////////////////////////

  template <int dim>
  unsigned int
  Solid<dim>::solve ()
    {

      LA::MPI::Vector
      completely_distributed_solution (locally_owned_dofs, mpi_communicator);

      SolverControl solver_control (dof_handler.n_dofs(), 1e-12*system_rhs.l2_norm());

      #ifdef USE_PETSC_LA
      LA::SolverCG solver(solver_control, mpi_communicator);
      #else
      LA::SolverCG solver(solver_control);
      #endif

      LA::MPI::PreconditionAMG preconditioner;
      LA::MPI::PreconditionAMG::AdditionalData data;
      #ifdef USE_PETSC_LA
      data.symmetric_operator = true;
      //data.strong_threshold = 0.5;
      #else
      /* Trilinos defaults are good */
      #endif
        preconditioner.initialize(tangent_matrix, data);
   //  LA::MPI::PreconditionJacobi preconditioner(tangent_matrix);


      solver.solve (tangent_matrix, completely_distributed_solution, system_rhs,
                    preconditioner);

      constraints.distribute (completely_distributed_solution);

      solution_update = completely_distributed_solution;

      return solver_control.last_step();
    }

///////////////////////////////////////////////////////////////////////////

  template <int dim>
  unsigned int
  Solid<dim>::solve_eta ()
   {
	  LA::MPI::Vector
      completely_distributed_solution_eta (locally_owned_dofs_eta, mpi_communicator);

      SolverControl solver_control (dof_handler_eta.n_dofs(), 1e-12*system_rhs_eta.l2_norm());

      #ifdef USE_PETSC_LA
      LA::SolverCG solver(solver_control, mpi_communicator);
      #else
      LA::SolverCG solver(solver_control);
      #endif

      LA::MPI::PreconditionAMG preconditioner;
      LA::MPI::PreconditionAMG::AdditionalData data;
      #ifdef USE_PETSC_LA
      data.symmetric_operator = true;
      #else
      /* Trilinos defaults are good */
      #endif
      preconditioner.initialize(system_matrix_eta, data);
      //LA::MPI::PreconditionJacobi preconditioner(system_matrix_eta);

      solver.solve (system_matrix_eta, completely_distributed_solution_eta, system_rhs_eta,
                    preconditioner);

      solution_update_eta = completely_distributed_solution_eta;

      return solver_control.last_step();
   }
///////////////////////////////////////////////////////////
  template <int dim>
  void Solid<dim>::output_results() const
  {
	DataOut<dim> data_out;

	std::vector<std::string> displacement_names;
		 switch (dim)
		   {
		   case 1:
	    	 displacement_names.push_back ("displacement");
		  	 break;
		   case 2:
		  	 displacement_names.push_back ("x_displacement");
		  	 displacement_names.push_back ("y_displacement");
		  	 break;
		   case 3:
		  	 displacement_names.push_back ("x_displacement");
		  	 displacement_names.push_back ("y_displacement");
		  	 displacement_names.push_back ("z_displacement");
		  	 break;
		  default:
		  	 Assert (false, ExcNotImplemented());
	      }

	 data_out.add_data_vector (dof_handler, solution, displacement_names);
     data_out.add_data_vector (dof_handler_eta, solution_eta, "order_parameter");

     /////////////////////////
     Vector<double> norm_of_stress (triangulation.n_active_cells());
     {
       typename Triangulation<dim>::active_cell_iterator
       cell = triangulation.begin_active(),
       endc = triangulation.end();
       for (; cell!=endc; ++cell)
    	   if (cell->is_locally_owned())
           {
             SymmetricTensor<2,dim> accumulated_stress;
             for (unsigned int q=0; q<qf_cell.size(); ++q)
               accumulated_stress +=
                 reinterpret_cast<PointHistory<dim>*>(cell->user_pointer())[q].get_tau();
             norm_of_stress(cell->active_cell_index())
               = (accumulated_stress /
                  qf_cell.size()).norm();
           }
    	   else
    	    norm_of_stress(cell->active_cell_index()) = -1e+20;
      }
data_out.add_data_vector (norm_of_stress, "norm_of_stress");

std::vector< std::vector< Vector<double> > >
                 history_field (dim, std::vector< Vector<double> >(dim)),
                 local_history_values_at_qpoints (dim, std::vector< Vector<double> >(dim)),
                 local_history_fe_values (dim, std::vector< Vector<double> >(dim)),

                 history_field_stress (dim, std::vector< Vector<double> >(dim)),
                 local_history_values_at_qpoints_stress (dim, std::vector< Vector<double> >(dim)),
                 local_history_fe_values_stress (dim, std::vector< Vector<double> >(dim));

    for (unsigned int i=0; i<dim; i++)
      for (unsigned int j=0; j<dim; j++)
      {
        history_field[i][j].reinit(history_dof_handler.n_dofs());
        local_history_values_at_qpoints[i][j].reinit(qf_cell.size());
        local_history_fe_values[i][j].reinit(history_fe.dofs_per_cell);

        history_field_stress[i][j].reinit(history_dof_handler.n_dofs());
        local_history_values_at_qpoints_stress[i][j].reinit(qf_cell.size());
        local_history_fe_values_stress[i][j].reinit(history_fe.dofs_per_cell);
      }
    FullMatrix<double> qpoint_to_dof_matrix (history_fe.dofs_per_cell,
    		qf_cell.size());
    FETools::compute_projection_from_quadrature_points_matrix
              (history_fe,
            		  qf_cell, qf_cell,
               qpoint_to_dof_matrix);
    typename DoFHandler<dim>::active_cell_iterator
	cell = dof_handler.begin_active(),
    endc = dof_handler.end(),
    dg_cell = history_dof_handler.begin_active();
    for (; cell!=endc; ++cell, ++dg_cell)
      if (cell->is_locally_owned())
      {
        PointHistory<dim> *lqph
               = reinterpret_cast<PointHistory<dim> *>(cell->user_pointer());
        Assert (lqph >=
                    &quadrature_point_history.front(),
                    ExcInternalError());
        Assert (lqph <
                    &quadrature_point_history.back(),
                    ExcInternalError());
        for (unsigned int i=0; i<dim; i++)
          for (unsigned int j=0; j<dim; j++)
          {
            for (unsigned int q=0; q<qf_cell.size(); ++q)
              {
            	local_history_values_at_qpoints[i][j](q)
                       = lqph[q].get_F()[i][j];

              qpoint_to_dof_matrix.vmult (local_history_fe_values[i][j],
                                        local_history_values_at_qpoints[i][j]);
              dg_cell->set_dof_values (local_history_fe_values[i][j],
                                     history_field[i][j]);


              local_history_values_at_qpoints_stress[i][j](q)
                                          = lqph[q].get_tau()[i][j];
                        qpoint_to_dof_matrix.vmult (local_history_fe_values_stress[i][j],
                                                    local_history_values_at_qpoints_stress[i][j]);
                        dg_cell->set_dof_values (local_history_fe_values_stress[i][j],
                                                 history_field_stress[i][j]);
             }
         }
      }

    std::vector<DataComponentInterpretation::DataComponentInterpretation>
                  data_component_interpretation(1, DataComponentInterpretation::component_is_scalar);

    data_out.add_data_vector(history_dof_handler, history_field[1][1], "F_22",
                             data_component_interpretation);

    data_out.add_data_vector(history_dof_handler, history_field_stress[0][0], "sigma_11",
                                 data_component_interpretation);
    data_out.add_data_vector(history_dof_handler, history_field_stress[1][1], "sigma_22",
                                 data_component_interpretation);
    data_out.add_data_vector(history_dof_handler, history_field_stress[0][1], "sigma_12",
                                 data_component_interpretation);


     //////////////////////////
    LA::MPI::Vector soln ;
    soln.reinit(locally_owned_dofs,mpi_communicator);
    for (unsigned int i = 0; i < soln.size(); ++i)
      soln(i) = solution(i);
    MappingQEulerian<dim, LA::MPI::Vector > q_mapping(degree, dof_handler, soln);

    Vector<float> subdomain (triangulation.n_active_cells());
    for (unsigned int i=0; i<subdomain.size(); ++i)
      subdomain(i) = triangulation.locally_owned_subdomain();
    data_out.add_data_vector (subdomain, "subdomain");

    data_out.build_patches(q_mapping, degree);

    const unsigned int cycle = time.get_timestep();

    const std::string filename = ("solution-" +
                                  Utilities::int_to_string (cycle, 2) +
                                  "." +
                                  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 (cycle, 2) +
                               "." +
                               Utilities::int_to_string (i, 4) +
                               ".vtu");
         std::ofstream master_output (("solution-" +
                                      Utilities::int_to_string (cycle, 2) +
                                      ".pvtu").c_str());
        data_out.write_pvtu_record (master_output, filenames);
      }

   }
}
/////////////////////////////////////////////////////////
  int main (int argc, char *argv[])
  {
    try
      {
    	using namespace dealii;
    	using namespace PhaseField;

        //deallog.depth_console(0);

        Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv, 1);

        Solid<3> solid_3d("parameters.prm");
        solid_3d.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;
  }

Attachment: parameters.prm
Description: Binary data

Reply via email to