libMesh
Loading...
Searching...
No Matches
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
13using 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"))
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
232void 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
253void 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.
283void 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 ErrorVector unsigned int
void viewParameters()
Definition biharmonic.C:165
std::unique_ptr< ExodusII_IO > _exio
Definition biharmonic.h:106
Real _cnWeight
Definition biharmonic.h:103
int _log_truncation
Definition biharmonic.h:97
InitialStateEnum _initialState
Definition biharmonic.h:99
void output(int timestep, const Real &t, Real &o_t, bool force=false)
Definition biharmonic.C:253
Point _initialCenter
Definition biharmonic.h:100
void init()
Initialize all the systems.
Definition biharmonic.C:212
void step(const Real &dt=-1.0)
Definition biharmonic.C:232
bool _cahn_hillard
Definition biharmonic.h:95
std::string _ofile_base
Definition biharmonic.h:105
@ LOG_DOUBLE_OBSTACLE
Definition biharmonic.h:57
@ LOG_DOUBLE_WELL
Definition biharmonic.h:56
@ DOUBLE_OBSTACLE
Definition biharmonic.h:55
bool _degenerate
Definition biharmonic.h:95
bool _netforce
Definition biharmonic.h:95
Real _theta_c
Definition biharmonic.h:93
unsigned int _N
Definition biharmonic.h:92
Real _kappa
Definition biharmonic.h:93
ReplicatedMesh & _mesh
Definition biharmonic.h:112
bool _growth
Definition biharmonic.h:95
Biharmonic(ReplicatedMesh &mesh)
Constructor retrieves command-line options, setting defaults, if necessary.
Definition biharmonic.C:16
void run()
Definition biharmonic.C:289
Real _initialWidth
Definition biharmonic.h:101
std::string _ofile
Definition biharmonic.h:105
bool _verbose
Definition biharmonic.h:98
FreeEnergyEnum _energy
Definition biharmonic.h:96
Real _theta
Definition biharmonic.h:93
unsigned int _dim
Definition biharmonic.h:92
This is the EquationSystems class.
virtual void init()
Initialize all the systems.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The ReplicatedMesh class is derived from the MeshBase class, and is used to store identical copies of...
MeshBase & mesh
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.
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.
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.
The libMesh namespace provides an interface to certain functionality in the library.
void command_line_vector(const std::string &, std::vector< T > &)
Definition libmesh.C:1044
OStreamProxy out
T command_line_value(const std::string &, T)
Definition libmesh.C:971
bool on_command_line(std::string arg)
Definition libmesh.C:934
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real