2 #include "libmesh/mesh.h" 3 #include "libmesh/quadrature.h" 4 #include "libmesh/dense_matrix.h" 5 #include "libmesh/dense_vector.h" 6 #include "libmesh/sparse_matrix.h" 7 #include "libmesh/fourth_error_estimators.h" 8 #include "libmesh/dof_map.h" 9 #include "libmesh/numeric_vector.h" 10 #include "libmesh/periodic_boundaries.h" 11 #include "libmesh/periodic_boundary.h" 12 #include "libmesh/elem.h" 20 const std::string & name_in,
21 const unsigned int number_in) :
26 #ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES 27 libmesh_error_msg(
"Must have second derivatives enabled");
30 #ifdef LIBMESH_ENABLE_PERIODIC 32 DofMap & dof_map = get_dof_map();
74 #endif // LIBMESH_ENABLE_PERIODIC 81 attach_init_object(*
this);
84 nonlinear_solver->residual_and_jacobian_object =
this;
87 nonlinear_solver->mffd_residual_object =
this;
90 nonlinear_solver->bounds_object =
this;
99 if (_biharmonic._verbose)
103 params.
set<
Point>(
"center") = _biharmonic._initialCenter;
104 params.
set<
Real>(
"width") = _biharmonic._initialWidth;
116 *(old_local_solution) = *(current_local_solution);
118 if (_biharmonic._verbose)
137 return (r < width) ? 1.0 : -0.5;
156 return (r < width) ? 1.0 : -0.5;
171 Real r = sqrt((p(0)-center(0))*(p(0)-center(0)));
172 return (r < width) ? 1.0 : -0.5;
190 residual_and_jacobian(u, &R,
nullptr, sys);
200 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 205 PerfLog perf_log (
"Biharmonic Residual and Jacobian",
false);
211 const DofMap & dof_map = get_dof_map();
221 std::unique_ptr<FEBase> fe (FEBase::build(_biharmonic._dim, fe_type));
229 fe->attach_quadrature_rule (qrule.get());
235 const std::vector<Real> & JxW = fe->get_JxW();
238 const std::vector<std::vector<Real>> & phi = fe->get_phi();
241 const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi();
244 const std::vector<std::vector<RealTensor>> & d2phi = fe->get_d2phi();
248 std::vector<Real> Laplacian_phi_qp;
260 std::vector<dof_id_type> dof_indices;
268 for (
const auto & elem : _biharmonic._mesh.active_local_element_ptr_range())
276 const unsigned int n_dofs =
277 cast_int<unsigned int>(dof_indices.size());
293 Laplacian_phi_qp.resize(
n_dofs);
295 for (
unsigned int qp=0; qp<qrule->n_points(); qp++)
305 Laplacian_u_qp = 0.0,
306 Laplacian_u_old_qp = 0.0;
309 grad_u_qp(0.0, 0.0, 0.0),
310 grad_u_old_qp(0.0, 0.0, 0.0);
316 M_prime_old_qp = 0.0;
318 for (
unsigned int i=0; i<
n_dofs; i++)
320 Laplacian_phi_qp[i] = d2phi[i][qp](0, 0);
321 grad_u_qp(0) += u(dof_indices[i])*dphi[i][qp](0);
322 grad_u_old_qp(0) += u_old(dof_indices[i])*dphi[i][qp](0);
324 if (_biharmonic._dim > 1)
326 Laplacian_phi_qp[i] += d2phi[i][qp](1, 1);
327 grad_u_qp(1) += u(dof_indices[i])*dphi[i][qp](1);
328 grad_u_old_qp(1) += u_old(dof_indices[i])*dphi[i][qp](1);
330 if (_biharmonic._dim > 2)
332 Laplacian_phi_qp[i] += d2phi[i][qp](2, 2);
333 grad_u_qp(2) += u(dof_indices[i])*dphi[i][qp](2);
334 grad_u_old_qp(2) += u_old(dof_indices[i])*dphi[i][qp](2);
336 u_qp += phi[i][qp]*u(dof_indices[i]);
337 u_old_qp += phi[i][qp]*u_old(dof_indices[i]);
338 Laplacian_u_qp += Laplacian_phi_qp[i]*u(dof_indices[i]);
339 Laplacian_u_old_qp += Laplacian_phi_qp[i]*u_old(dof_indices[i]);
342 if (_biharmonic._degenerate)
344 M_qp = 1.0 - u_qp*u_qp;
345 M_old_qp = 1.0 - u_old_qp*u_old_qp;
346 M_prime_qp = -2.0*u_qp;
347 M_prime_old_qp = -2.0*u_old_qp;
351 for (
unsigned int i=0; i<
n_dofs; i++)
356 Number ri = 0.0, ri_old = 0.0;
357 ri -= Laplacian_phi_qp[i]*M_qp*_biharmonic._kappa*Laplacian_u_qp;
358 ri_old -= Laplacian_phi_qp[i]*M_old_qp*_biharmonic._kappa*Laplacian_u_old_qp;
360 if (_biharmonic._degenerate)
362 ri -= (dphi[i][qp]*grad_u_qp)*M_prime_qp*(_biharmonic._kappa*Laplacian_u_qp);
363 ri_old -= (dphi[i][qp]*grad_u_old_qp)*M_prime_old_qp*(_biharmonic._kappa*Laplacian_u_old_qp);
366 if (_biharmonic._cahn_hillard)
370 ri += Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp;
371 ri_old += Laplacian_phi_qp[i]*M_old_qp*_biharmonic._theta_c*(u_old_qp*u_old_qp - 1.0)*u_old_qp;
372 if (_biharmonic._degenerate)
374 ri += (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp;
375 ri_old += (dphi[i][qp]*grad_u_old_qp)*M_prime_old_qp*_biharmonic._theta_c*(u_old_qp*u_old_qp - 1.0)*u_old_qp;
381 ri -= Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*u_qp;
382 ri_old -= Laplacian_phi_qp[i]*M_old_qp*_biharmonic._theta_c*u_old_qp;
383 if (_biharmonic._degenerate)
385 ri -= (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*u_qp;
386 ri_old -= (dphi[i][qp]*grad_u_old_qp)*M_prime_old_qp*_biharmonic._theta_c*u_old_qp;
392 switch(_biharmonic._log_truncation)
403 Re(i) += JxW[qp]*((u_qp-u_old_qp)*phi[i][qp]-_biharmonic._dt*0.5*((2.0-_biharmonic._cnWeight)*ri + _biharmonic._cnWeight*ri_old));
409 Number M_prime_prime_qp = 0.0;
410 if (_biharmonic._degenerate) M_prime_prime_qp = -2.0;
411 for (
unsigned int j=0; j<
n_dofs; j++)
414 ri_j -= Laplacian_phi_qp[i]*M_qp*_biharmonic._kappa*Laplacian_phi_qp[j];
415 if (_biharmonic._degenerate)
418 Laplacian_phi_qp[i]*M_prime_qp*phi[j][qp]*_biharmonic._kappa*Laplacian_u_qp +
419 (dphi[i][qp]*dphi[j][qp])*M_prime_qp*(_biharmonic._kappa*Laplacian_u_qp) +
420 (dphi[i][qp]*grad_u_qp)*(M_prime_prime_qp*phi[j][qp])*(_biharmonic._kappa*Laplacian_u_qp) +
421 (dphi[i][qp]*grad_u_qp)*(M_prime_qp)*(_biharmonic._kappa*Laplacian_phi_qp[j]);
424 if (_biharmonic._cahn_hillard)
429 Laplacian_phi_qp[i]*M_prime_qp*phi[j][qp]*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp +
430 Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*(3.0*u_qp*u_qp - 1.0)*phi[j][qp] +
431 (dphi[i][qp]*dphi[j][qp])*M_prime_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp +
432 (dphi[i][qp]*grad_u_qp)*M_prime_prime_qp*_biharmonic._theta_c*(u_qp*u_qp - 1.0)*u_qp +
433 (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*(3.0*u_qp*u_qp - 1.0)*phi[j][qp];
439 Laplacian_phi_qp[i]*M_prime_qp*phi[j][qp]*_biharmonic._theta_c*u_qp +
440 Laplacian_phi_qp[i]*M_qp*_biharmonic._theta_c*phi[j][qp] +
441 (dphi[i][qp]*dphi[j][qp])*M_prime_qp*_biharmonic._theta_c*u_qp +
442 (dphi[i][qp]*grad_u_qp)*M_prime_prime_qp*_biharmonic._theta_c*u_qp +
443 (dphi[i][qp]*grad_u_qp)*M_prime_qp*_biharmonic._theta_c*phi[j][qp];
448 switch(_biharmonic._log_truncation)
459 Je(i,j) += JxW[qp]*(phi[i][qp]*phi[j][qp] - 0.5*_biharmonic._dt*(2.0-_biharmonic._cnWeight)*ri_j);
491 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES 508 PerfLog perf_log (
"Biharmonic bounds",
false);
514 const DofMap & dof_map = get_dof_map();
524 std::unique_ptr<FEBase> fe (FEBase::build(_biharmonic._dim, fe_type));
532 std::vector<dof_id_type> dof_indices;
534 for (
const auto & elem : _biharmonic._mesh.active_local_element_ptr_range())
537 const std::vector<std::vector<Real>> & phi = fe->get_phi();
544 const unsigned int n_dofs =
545 cast_int<unsigned int>(dof_indices.size());
552 std::vector<Point> nodes;
553 fe->get_refspace_nodes(elem->type(), nodes);
556 fe->reinit(elem, &nodes);
569 for (
unsigned int i=0; i<
n_dofs; ++i)
572 Real infinity = 1.0e20;
573 Real bound = infinity;
574 for (
unsigned int j = 0; j < nodes.size(); ++j)
578 bound = 1.0/std::abs(phi[i][j]);
592 XL.
insert(XLe, dof_indices);
593 XU.
insert(XUe, dof_indices);
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices)
Inserts the entries of v in *this at the locations specified by v.
This is the EquationSystems class.
void initialize() override
static Number InitialDensityStrip(const Point &p, const Parameters ¶ms, const std::string &, const std::string &)
void residual_and_jacobian(const NumericVector< Number > &u, NumericVector< Number > *R, SparseMatrix< Number > *J, NonlinearImplicitSystem &) override
The residual and Jacobian assembly function for the Biharmonic system.
void add_periodic_boundary(const PeriodicBoundaryBase &periodic_boundary)
Adds a copy of the specified periodic boundary to the system.
JR(EquationSystems &eqSys, const std::string &name, const unsigned int number)
Constructor.
This class provides the ability to map between arbitrary, user-defined strings and several data types...
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
VectorValue< Real > RealVectorValue
Useful typedefs to allow transparent switching between Real and Complex data types.
std::size_t n_dofs() const
void resize(const unsigned int n)
Resize the vector.
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i]...
const FEType & variable_type(const unsigned int c) const
boundary_id_type pairedboundary
Manages storage and variables for transient systems.
The Biharmonic class encapsulates most of the data structures necessary to calculate the biharmonic r...
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
The libMesh namespace provides an interface to certain functionality in the library.
The definition of a periodic boundary.
The PerfLog class allows monitoring of specific events.
This class handles the numbering of degrees of freedom on a mesh.
std::unique_ptr< QBase > default_quadrature_rule(const unsigned int dim, const int extraorder=0) const
void libmesh_ignore(const Args &...)
boundary_id_type myboundary
The boundary ID of this boundary and its counterpart.
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
const T & get(std::string_view) const
static Gradient InitialGradientZero(const Point &, const Parameters &, const std::string &, const std::string &)
void bounds(NumericVector< Number > &XL, NumericVector< Number > &XU, NonlinearImplicitSystem &) override
Function defining the bounds of the Biharmonic system.
NumberVectorValue Gradient
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and non-linear solv...
static Number InitialDensityRod(const Point &p, const Parameters ¶ms, const std::string &, const std::string &)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void constrain_element_vector(DenseVector< Number > &rhs, std::vector< dof_id_type > &dofs, bool asymmetric_constraint_rows=true) const
Constrains the element vector.
T & set(const std::string &)
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
A Point defines a location in LIBMESH_DIM dimensional Real space.
void residual(const NumericVector< Number > &u, NumericVector< Number > &R, NonlinearImplicitSystem &sys) override
The residual assembly function for the Biharmonic system.
static Number InitialDensityBall(const Point &p, const Parameters ¶ms, const std::string &, const std::string &)
Static functions to be used for initialization.
void constrain_element_matrix(DenseMatrix< Number > &matrix, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix.