Alamo
HeatConduction.H
Go to the documentation of this file.
1 //
2 // This implements a basic heat conduction method in Alamo.
3 // The partial differential equation to be solved is
4 //
5 // .. math::
6 //
7 // \frac{\partial T}{\partial t} = \alpha\,\Delta T
8 //
9 // where :math:`T` is temperature, :math:`t` is time, and :math:`alpha`
10 // is the thermal diffusivity.
11 // Integration is performed explicitly in time using forward Euler, and
12 // differentiation is performed using the finite difference method.
13 //
14 
15 #ifndef INTEGRATOR_HEATCONDUCTION_H // Include guards
16 #define INTEGRATOR_HEATCONDUCTION_H //
17 
18 // Standard library includes
19 #include <iostream>
20 #include <fstream>
21 #include <iomanip>
22 
23 // AMReX Includes
24 #include "AMReX.H"
25 #include "AMReX_ParallelDescriptor.H"
26 #include "AMReX_ParmParse.H"
27 
28 // Alamo Includes
29 #include "IO/ParmParse.H"
30 #include "Integrator/Integrator.H"
31 #include "BC/Constant.H"
32 #include "BC/Expression.H"
33 #include "IC/IC.H"
34 #include "IC/Sphere.H"
35 #include "IC/Constant.H"
36 #include "IC/Expression.H"
37 #include "Numeric/Stencil.H"
38 
39 namespace Integrator
40 {
41 class HeatConduction : virtual public Integrator
42 {
43 public:
44  // Empty constructor
45  HeatConduction(int a_nghost = 2) :
46  Integrator(),
47  number_of_ghost_cells(a_nghost)
48  {}
49 
50  // Constructor that triggers parse
52  {
53  Parse(*this, pp);
54  }
55 
56  virtual ~HeatConduction()
57  {
58  delete ic;
59  delete bc;
60  }
61 
62  // The Parse function initializes the HeatConduction object using
63  // a parser, pp.
64  // Note that this is a static function, which means it does not have
65  // direct access to member variables. Instead, it initializes the variables
66  // inside the argument, "value", and so all references to member items are
67  // prefixed by "value."
68  static void Parse(HeatConduction& value, IO::ParmParse& pp)
69  {
70  // Diffusion coefficient :math:`\alpha`.
71  // *This is an example of a required input variable -
72  // - program will terminate unless it is provided.*
73  pp_query_required("heat.alpha", value.alpha);
74 
75  // Criterion for mesh refinement.
76  // *This is an example of a default input variable.
77  // The default value is provided here, not in the
78  // definition of the variable.*
79  pp_query_default("heat.refinement_threshold", value.refinement_threshold, 0.01);
80 
81  std::string type;
82 
83  // Initial condition type.
84  // *This is an example of type validation:
85  // the input variable must be one of the three provided values,
86  // and will error if not. The default selection is the first
87  // argument.*
88  pp_query_validate("ic.type", type, {"constant", "sphere","expression"});
89  if (type == "sphere") value.ic = new IC::Sphere(value.geom, pp, "ic.sphere");
90  else if (type == "constant") value.ic = new IC::Constant(value.geom, pp, "ic.constant");
91  else if (type == "expression") value.ic = new IC::Expression(value.geom, pp, "ic.expression");
92  else Util::Abort(INFO, "Invalid ic.type ", type);
93 
94  std::string bc_type;
95  // Select BC object for temperature
96  pp_query_validate("bc.temp.type",bc_type,{"constant","expression"});
97  if (bc_type == "expression") value.bc = new BC::Expression(1, pp, "bc.temp.expression");
98  else if (bc_type == "constant") value.bc = new BC::Constant(1, pp, "bc.temp");
99 
100  // Register the temperature and old temperature fields.
101  // temp_mf and temp_old_mf are defined near the bottom of this Header file.
102  value.RegisterNewFab(value.temp_mf, value.bc, value.number_of_components, value.number_of_ghost_cells, "Temp", true);
103  value.RegisterNewFab(value.temp_old_mf, value.bc, value.number_of_components, value.number_of_ghost_cells, "Temp_old", false);
104  }
105 
106 protected:
107 
108  // Use the ic object to initialize the temperature field
109  void Initialize(int lev)
110  {
111  ic->Initialize(lev, temp_old_mf);
112  }
113 
114  // Integrate the heat equation
115  void Advance(int lev, Set::Scalar /*time*/, Set::Scalar dt)
116  {
117  // Swap the old temp fab and the new temp fab so we use
118  // the new one.
119  std::swap(*temp_mf[lev], *temp_old_mf[lev]);
120 
121  // Get the cell size corresponding to this level
122  const Set::Scalar* DX = geom[lev].CellSize();
123 
124  // Iterate over all of the patches on this level
125  for (amrex::MFIter mfi(*temp_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
126  {
127  // Get the box (index dimensions) for this patch
128  const amrex::Box& bx = mfi.tilebox();
129 
130  // Get an array-accessible handle to the data on this patch.
131  // amrex::Array4<const Set::Scalar> const& temp_old = (*temp_old_mf[lev]).array(mfi);
132  // amrex::Array4<Set::Scalar> const& temp = temp_mf.Patch(lev,mfi);//(*temp_mf[lev]).array(mfi);
133  Set::Patch<const Set::Scalar> temp_old = temp_old_mf.Patch(lev,mfi);
134  Set::Patch<Set::Scalar> temp = temp_mf.Patch(lev,mfi);
135 
136  // Iterate over the grid on this patch
137  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
138  {
139  // Do the physics!
140  // Note that Numeric::Laplacian is an inlined function so there is no overhead.
141  // You can calculate the derivatives yourself if you want.
142  temp(i, j, k) = temp_old(i, j, k) + dt * alpha * Numeric::Laplacian(temp_old, i, j, k, 0, DX);
143  });
144  }
145  }
146 
147  // Tag cells for mesh refinement based on temperature gradient
148  void TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar /*time*/, int /*ngrow*/)
149  {
150  // Get cell dimensions as done above.
151  const Set::Scalar* DX = geom[lev].CellSize();
152  // Calculate the diagonal.
153  Set::Scalar dr = sqrt(AMREX_D_TERM(DX[0] * DX[0], +DX[1] * DX[1], +DX[2] * DX[2]));
154 
155  // Iterate over the patches on this level
156  for (amrex::MFIter mfi(*temp_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
157  {
158  // Get the box and handles as done above.
159  const amrex::Box& bx = mfi.tilebox();
160  amrex::Array4<char> const& tags = a_tags.array(mfi);
161  amrex::Array4<Set::Scalar> const& temp = (*temp_mf[lev]).array(mfi);
162 
163  // Iterate over the grid as done above.
164  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
165  {
166  // Calculate the temperature gradient.
167  Set::Vector grad = Numeric::Gradient(temp, i, j, k, 0, DX);
168 
169  // Is the gradient * cell_size too big? If so, then
170  // mark this cell as needing refinement.
171  if (grad.lpNorm<2>() * dr > refinement_threshold)
172  tags(i, j, k) = amrex::TagBox::SET;
173  });
174  }
175  }
176 
177 protected:
178  Set::Field<Set::Scalar> temp_mf; // Temperature field variable (current timestep)
179  Set::Field<Set::Scalar> temp_old_mf; // Temperature field variable (previous timestep)
180 
181 private:
182 
183  //
184  // Definition of parameters set only at instantiation by
185  // constructors.
186  //
187  const int number_of_components = 1; // Number of components
188  const int number_of_ghost_cells = 2; // Number of ghost cells
189 
190  //
191  // Definition of user-determined variables.
192  //
193  // Instantiate all variables to NAN if possible.
194  // Default values may be set in Parse using query_default.
195  //
196 
197  Set::Scalar alpha = NAN; // Thermal diffusivity
198  Set::Scalar refinement_threshold = NAN ; // Criterion for cell refinement
199 
200  //
201  // Definition of user-determined pointer variables.
202  //
203  // These should be set to nullptr. Make sure that they are deleted
204  // in the ~HeatConduction destructor.
205  //
206 
207  IC::IC* ic = nullptr; // Object used to initialize temperature field
208  BC::BC<Set::Scalar>* bc = nullptr; // Object used to update temp field boundary ghost cells
209 };
210 } // namespace Integrator
211 #endif
Integrator::HeatConduction::bc
BC::BC< Set::Scalar > * bc
Definition: HeatConduction.H:208
IC::IC::Initialize
void Initialize(const int &a_lev, Set::Field< Set::Scalar > &a_field, Set::Scalar a_time=0.0)
Definition: IC.H:26
BC::BC< Set::Scalar >
IC::IC
Pure abstract IC object from which all other IC objects inherit.
Definition: IC.H:12
Integrator::HeatConduction::~HeatConduction
virtual ~HeatConduction()
Definition: HeatConduction.H:56
Integrator::HeatConduction::TagCellsForRefinement
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int)
Definition: HeatConduction.H:148
Sphere.H
Integrator.H
Set::Field< Set::Scalar >
Definition: Set.H:236
Integrator::HeatConduction::HeatConduction
HeatConduction(int a_nghost=2)
Definition: HeatConduction.H:45
Integrator::HeatConduction::ic
IC::IC * ic
Definition: HeatConduction.H:207
Expression.H
Set::Vector
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition: Base.H:20
Constant.H
ParmParse.H
Numeric::Gradient
AMREX_FORCE_INLINE Set::Vector Gradient(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType)
Definition: Stencil.H:655
Constant.H
Set::Scalar
amrex::Real Scalar
Definition: Base.H:19
Integrator::Integrator::RegisterNewFab
void RegisterNewFab(Set::Field< Set::Scalar > &new_fab, BC::BC< Set::Scalar > *new_bc, int ncomp, int nghost, std::string name, bool writeout)
Definition: Integrator.cpp:292
Numeric::Laplacian
AMREX_FORCE_INLINE Set::Scalar Laplacian(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM])
Definition: Stencil.H:530
Integrator::HeatConduction::Advance
void Advance(int lev, Set::Scalar, Set::Scalar dt)
Definition: HeatConduction.H:115
Integrator::HeatConduction::temp_mf
Set::Field< Set::Scalar > temp_mf
Definition: HeatConduction.H:178
pp_query_default
#define pp_query_default(...)
Definition: ParmParse.H:100
Integrator::HeatConduction::alpha
Set::Scalar alpha
Definition: HeatConduction.H:197
Util::Abort
void Abort(const char *msg)
Definition: Util.cpp:165
Integrator
Collection of numerical integrator objects.
Definition: AllenCahn.H:39
IC::Constant
Definition: Constant.H:18
Integrator::HeatConduction::Initialize
void Initialize(int lev)
Definition: HeatConduction.H:109
BC::Constant
Definition: Constant.H:89
IC::Expression
Definition: Expression.H:44
pp_query_validate
#define pp_query_validate(...)
Definition: ParmParse.H:101
Integrator::HeatConduction::number_of_ghost_cells
const int number_of_ghost_cells
Definition: HeatConduction.H:188
pp_query_required
#define pp_query_required(...)
Definition: ParmParse.H:99
Integrator::HeatConduction::refinement_threshold
Set::Scalar refinement_threshold
Definition: HeatConduction.H:198
IO::ParmParse
Definition: ParmParse.H:110
Integrator::HeatConduction
Definition: HeatConduction.H:41
Expression.H
Set::Patch
amrex::Array4< T > const & Patch
Definition: Set.H:88
Integrator::HeatConduction::temp_old_mf
Set::Field< Set::Scalar > temp_old_mf
Definition: HeatConduction.H:179
Integrator::HeatConduction::HeatConduction
HeatConduction(IO::ParmParse &pp)
Definition: HeatConduction.H:51
INFO
#define INFO
Definition: Util.H:20
Integrator::Integrator::dt
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
Definition: Integrator.H:303
IC.H
Set::Field< Set::Scalar >::Patch
amrex::Array4< Set::Scalar > Patch(int lev, amrex::MFIter &mfi) const &
Definition: Set.H:263
BC::Expression
Definition: Expression.H:20
Integrator::HeatConduction::number_of_components
const int number_of_components
Definition: HeatConduction.H:187
IC::Sphere
Definition: Sphere.H:13
Integrator::HeatConduction::Parse
static void Parse(HeatConduction &value, IO::ParmParse &pp)
Definition: HeatConduction.H:68