libMesh
biharmonic.C
Go to the documentation of this file.
1 // Libmesh includes
2 #include "libmesh/mesh_generation.h"
3 #include "libmesh/numeric_vector.h"
4 #include "libmesh/replicated_mesh.h"
5 
6 // Example includes
7 #include "biharmonic.h"
8 #include "biharmonic_jr.h"
9 
10 // C++ includes
11 #include <memory>
12 
13 using namespace libMesh;
14 
15 // Constructor
18  _mesh(mesh)
19 {
20  // Retrieve parameters and set defaults
21  _verbose = false;
22  _growth = false;
23  _degenerate = false;
24  _cahn_hillard = false;
25  _netforce = false;
26 
27  if (on_command_line("--verbose"))
28  _verbose = true;
29  if (on_command_line("--growth"))
30  _growth = true;
31  if (on_command_line("--degenerate"))
32  _degenerate = true;
33  if (on_command_line("--cahn_hillard"))
34  _cahn_hillard = true;
35  if (on_command_line("--netforce"))
36  _netforce = true;
37 
38  _kappa = command_line_value("kappa", 1.0);
39 
40  // "type of energy (double well, double obstacle, logarithmic+double well, logarithmic+double obstacle)"
41  std::string energy = command_line_value("energy", std::string("double_well"));
42 
43  if (energy == "double_well")
45  else if (energy == "double_obstacle")
47  else if (energy == "log_double_well")
49  else if (energy == "log_double_obstacle")
51  else
52  libmesh_error_msg("Unknown energy type: " << energy);
53 
54  _tol = command_line_value("tol", 1.0e-8);
55  _theta = command_line_value("theta", .001);
56  _theta_c = command_line_value("theta_c", 1.0);
57 
58  // "order of log truncation (0=none, 2=quadratic, 3=cubic)"
59  _log_truncation = command_line_value("log_truncation", 2);
60 
61  if (!_log_truncation)
62  libMesh::out << "WARNING: no truncation is being used for the logarithmic free energy term.\nWARNING: division by zero possible!\n";
63 
64 
65  // Dimension
66  _dim = command_line_value("dim", 1);
67 
68  libmesh_assert_msg((_dim <= 3) && (_dim > 0), "Invalid mesh dimension");
69 
70  // Build the mesh
71  // Yes, it's better to make a coarse mesh and then refine it. We'll get to it later.
72  _N = command_line_value("N", 8);
73  libmesh_assert_msg(_N > 0, "Invalid mesh size");
74 
75  switch (_dim)
76  {
77  case 1:
79  break;
80  case 2:
81  MeshTools::Generation::build_square(_mesh, _N, _N, 0.0, 1.0, 0.0, 1.0, QUAD4);
82  break;
83  case 3:
84  MeshTools::Generation::build_cube(_mesh, _N, _N, _N, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, HEX8);
85  break;
86  default:
87  libmesh_assert_msg((_dim <= 3) && (_dim > 0), "Invalid mesh dimension");
88  break;
89  }
90 
91  // Determine the initial timestep size
92  _dt0 = command_line_value("dt", 1.0/(10*_kappa*_N*_N*_N*_N));
93  libmesh_assert_msg(_dt0>=0, "Negative initial timestep");
94 
95  _t0 = command_line_value("min_time", 0.0);
96  _t1 = command_line_value("max_time", _t0 + 50.0*_dt0);
97  libmesh_assert_msg(_t1 >= _t0, "Final time less than initial time");
98  _T = _t1 - _t0;
99 
100  _cnWeight = command_line_value("crank_nicholson_weight", 1.0);
101  libmesh_assert_msg(_cnWeight <= 1 && _cnWeight >= 0, "Crank-Nicholson weight must be between 0 and 1");
102 
103  // Initial state
105  std::string initialState = command_line_value("initial_state", std::string("strip"));
106 
107  if (initialState == std::string("ball"))
109  else if (initialState == std::string("strip"))
111  else if (initialState == std::string("rod"))
112  _initialState = ROD;
113  else
114  libmesh_error_msg("Unknown initial state: neither ball nor rod nor strip");
115 
116  std::vector<Real> icenter;
117  command_line_vector("initial_center", icenter);
118 
119  // Check that the point defining the center was in the right spatial dimension
120  if (icenter.size() > _dim)
121  libmesh_assert_msg(icenter.size() > _dim, "Invalid dimension for the initial state center of mass");
122 
123  // Pad
124  icenter.resize(3);
125  for (std::size_t i = icenter.size(); i < _dim; ++i)
126  icenter[i] = 0.5;
127 
128  for (unsigned int i = _dim; i < 3; ++i)
129  icenter[i] = 0.0;
130 
131  _initialCenter = Point(icenter[0], icenter[1], icenter[2]);
132  _initialWidth = command_line_value("initial_width", 0.125);
133 
134  // Output options
135 #ifdef LIBMESH_HAVE_EXODUS_API
136  if (on_command_line("output_base"))
137  _ofile_base = command_line_value("output_base", std::string("bih"));
138 
139  else
140  {
141  switch(_dim)
142  {
143  case 1:
144  _ofile_base = std::string("bih.1");
145  break;
146  case 2:
147  _ofile_base = std::string("bih.2");
148  break;
149  case 3:
150  _ofile_base = std::string("bih.3");
151  break;
152  default:
153  _ofile_base = std::string("bih");
154  break;
155  }
156  }
157  _ofile = _ofile_base + ".e";
158  _exio = std::make_unique<ExodusII_IO>(_mesh);
159  _o_dt = command_line_value("output_dt", 0.0);
160 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
161 } // constructor
162 
163 
164 
166 {
167  libMesh::out << "Biharmonic parameters:\n";
168 
169  // Print verbosity status
170  if (_verbose)
171  libMesh::out << "verbose mode is on\n";
172  else
173  libMesh::out << "verbose mode is off\n";
174 
175  // Print parameters
176  libMesh::out << "mesh dimension = " << _dim << "\n";
177  libMesh::out << "initial linear mesh size = " << _N << "\n";
178  libMesh::out << "kappa = " << _kappa << "\n";
179  libMesh::out << "growth = " << (int)_growth << "\n";
180  libMesh::out << "degenerate = " << (int)_degenerate << "\n";
181  libMesh::out << "Cahn-Hillard = " << (int)_cahn_hillard << "\n";
182  libMesh::out << "netforce = " << (int)_netforce << "\n";
183  libMesh::out << "energy = " << _energy << "\n";
184  libMesh::out << "tol = " << _tol << "\n";
185  libMesh::out << "theta = " << _theta << "\n";
186  libMesh::out << "theta_c = " << _theta_c << "\n";
187  libMesh::out << "log truncation = " << _log_truncation << "\n";
188  libMesh::out << "initial timestep size = " << _dt0 << "\n";
189 
190  if (_initialState == STRIP)
191  libMesh::out << "initial state: strip\n";
192 
193  if (_initialState == ROD)
194  libMesh::out << "initial state: rod\n";
195 
196  if (_initialState == BALL)
197  libMesh::out << "initial state: ball\n";
198 
199  libMesh::out << "initial state center = " << _initialCenter(0) << "\n";
200  libMesh::out << "initial state width = " << _initialWidth << "\n";
201  libMesh::out << "initial time (min_time) = " << _t0 << "\n";
202  libMesh::out << "integration time = " << _T << "\n";
203  libMesh::out << "final time (max_time) = " << _t1 << "\n";
204  libMesh::out << "Crank-Nicholson weight = " << _cnWeight << "\n";
205  libMesh::out << "Output timestep = " << _o_dt << "\n";
206  libMesh::out << "Output filename base: " << _ofile_base << "\n";
207 }
208 
209 
210 
211 
213 {
214  // Build the main equation encapsulated in the JR (Jacobian-Residual or J(R) "jet of R") object
215  _jr = &(add_system<Biharmonic::JR>(std::string("Biharmonic::JR")));
216 
217  if (_verbose)
218  libMesh::out << ">>> Initializing Biharmonic\n";
219 
220  _dt = 0;
221  _o_count = 0;
223 
224  if (_verbose)
225  libMesh::out << "<<< Initializing Biharmonic\n";
226 }
227 
228 
229 
230 
231 
232 void Biharmonic::step(const Real & dt_in)
233 {
234  // We need to update the old solution vector.
235  // The old solution vector will be the current solution vector from the
236  // previous time step. We use vector assignment. Only TransientSystems
237  // (and systems derived from them) contain old solutions.
238  if (dt_in < 0)
239  _dt = _dt0;
240  else
241  _dt = dt_in;
242 
243  *(_jr->old_local_solution) = *(_jr->current_local_solution);
244 
245  // this will localize the current solution, resulting in a
246  // current_local_solution with correct ghost values
247  _jr->solve();
248 }
249 
250 
251 
252 #ifdef LIBMESH_HAVE_EXODUS_API
253 void Biharmonic::output(int timestep,
254  const Real & t,
255  Real & o_t,
256  bool force)
257 {
258  if (!force && t - o_t < _o_dt)
259  return;
260 
261  ++_o_count;
262 
263  if (_verbose)
264  libMesh::out << "Writing state "
265  << timestep
266  << " at time "
267  << t
268  << " to file "
269  << _ofile
270  << "; output a total of "
271  << _o_count
272  << " states so far\n";
273 
274  _exio->write_timestep(_ofile, *this, timestep, t);
275 
276  if (!force)
277  o_t = t;
278 }
279 
280 #else
281 
282 // Avoid compiler warnings in non-standard build configurations.
283 void Biharmonic::output(int, const Real &, Real &, bool) {}
284 
285 #endif // #ifdef LIBMESH_HAVE_EXODUS_API
286 
287 
288 
290 {
291  Real t = _t0, o_t = 0.0;
292  int timestep = 1;
293 
294  // Force-write the initial timestep
295  output(timestep, t, o_t, true);
296 
297  while (t < _t1)
298  {
299  ++timestep;
300 
301  // A pretty update message
302  if (_verbose)
303  libMesh::out << "Solving for state " << timestep << ", time " << t << "\n";
304 
305  // Move biharmonic one timestep forward
306  step();
307 
308  // Keep track of time and timestep
309  t += _dt;
310 
311  // Output
312  output(timestep, t, o_t);
313  } // while(t < _t1)
314 
315  // Force-write the final timestep
316  output(timestep, t, o_t, true);
317 }
void run()
Definition: biharmonic.C:289
This is the EquationSystems class.
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
std::string _ofile
Definition: biharmonic.h:105
std::unique_ptr< ExodusII_IO > _exio
Definition: biharmonic.h:106
bool _verbose
Definition: biharmonic.h:98
Biharmonic(ReplicatedMesh &mesh)
Constructor retrieves command-line options, setting defaults, if necessary.
Definition: biharmonic.C:16
Real _cnWeight
Definition: biharmonic.h:103
MeshBase & mesh
void init()
Initialize all the systems.
Definition: biharmonic.C:212
Real _kappa
Definition: biharmonic.h:93
Real _theta_c
Definition: biharmonic.h:93
void output(int timestep, const Real &t, Real &o_t, bool force=false)
Definition: biharmonic.C:253
void build_square(UnstructuredMesh &mesh, const unsigned int nx, const unsigned int ny, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 2D meshes.
The libMesh namespace provides an interface to certain functionality in the library.
Point _initialCenter
Definition: biharmonic.h:100
Real _tol
Definition: biharmonic.h:94
bool _netforce
Definition: biharmonic.h:95
int _o_count
Definition: biharmonic.h:108
void viewParameters()
Definition: biharmonic.C:165
bool _cahn_hillard
Definition: biharmonic.h:95
T command_line_value(const std::string &, T)
Definition: libmesh.C:1024
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
FreeEnergyEnum _energy
Definition: biharmonic.h:96
int _log_truncation
Definition: biharmonic.h:97
unsigned int _dim
Definition: biharmonic.h:92
void step(const Real &dt=-1.0)
Definition: biharmonic.C:232
Real _initialWidth
Definition: biharmonic.h:101
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void command_line_vector(const std::string &, std::vector< T > &)
Definition: libmesh.C:1097
OStreamProxy out
bool _growth
Definition: biharmonic.h:95
void build_line(UnstructuredMesh &mesh, const unsigned int nx, const Real xmin=0., const Real xmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
A specialized build_cube() for 1D meshes.
bool on_command_line(std::string arg)
Definition: libmesh.C:987
Real _o_dt
Definition: biharmonic.h:107
unsigned int _N
Definition: biharmonic.h:92
ReplicatedMesh & _mesh
Definition: biharmonic.h:111
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
std::string _ofile_base
Definition: biharmonic.h:105
InitialStateEnum _initialState
Definition: biharmonic.h:99
void ErrorVector unsigned int
Definition: adjoints_ex3.C:360
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
Real _theta
Definition: biharmonic.h:93
bool _degenerate
Definition: biharmonic.h:95