34 template <
int spacedim, class
Value>
58 std::shared_ptr< FiniteElement<0> > fe0_ptr = std::make_shared< FE_P_disc<0> >(0);
59 std::shared_ptr< FiniteElement<1> > fe1_ptr = std::make_shared< FE_P_disc<1> >(0);
60 std::shared_ptr< FiniteElement<2> > fe2_ptr = std::make_shared< FE_P_disc<2> >(0);
61 std::shared_ptr< FiniteElement<3> > fe3_ptr = std::make_shared< FE_P_disc<3> >(0);
69 std::shared_ptr< FiniteElement<0> > fe0_ptr = std::make_shared< FE_P_disc<0> >(0);
70 std::shared_ptr< FiniteElement<1> > fe1_ptr = std::make_shared< FE_P_disc<1> >(0);
71 std::shared_ptr< FiniteElement<2> > fe2_ptr = std::make_shared< FE_P_disc<2> >(0);
72 std::shared_ptr< FiniteElement<3> > fe3_ptr = std::make_shared< FE_P_disc<3> >(0);
80 ASSERT(
false).error(
"Should not happen!\n");
84 std::shared_ptr<DOFHandlerMultiDim> dh_par = std::make_shared<DOFHandlerMultiDim>(mesh);
85 std::shared_ptr<DiscreteSpace> ds = std::make_shared<EqualOrderDiscreteSpace>( &mesh, fe0, fe1, fe2, fe3);
86 dh_par->distribute_dofs(ds);
89 std::shared_ptr< FieldFE<spacedim, Value> > field_ptr = std::make_shared< FieldFE<spacedim, Value> >();
90 field_ptr->set_fe_data( dh_par, 0, dh_par->create_vector() );
98 "Record with data for iterative coupling of flow and mechanics.\n")
102 "Flow equation, provides the velocity field as a result.")
104 "Mechanics, provides the displacement field.")
106 "Time governor setting for the HM coupling.")
109 .make_field_descriptor_type(
"Coupling_Iterative")),
111 "Input fields of the HM coupling.")
113 "Tuning parameter for iterative splitting. Its default value" 114 "corresponds to a theoretically optimal value with fastest convergence." )
116 "Maximal count of HM iterations." )
118 "Minimal count of HM iterations." )
120 "Absolute tolerance for difference in HM iteration." )
122 "Relative tolerance for difference in HM iteration." )
127 const int HM_Iterative::registrar = Input::register_class< HM_Iterative, Mesh &, const Input::Record >(
"Coupling_Iterative")
133 *
this += alpha.name(
"biot_alpha")
134 .units(
UnitSI().dimensionless())
135 .input_default(
"0.0")
138 *
this += density.name(
"fluid_density")
139 .units(
UnitSI().kg().m(-3))
140 .input_default(
"0.0")
143 *
this += gravity.name(
"gravity")
144 .units(
UnitSI().m().s(-2))
145 .input_default(
"9.81")
148 *
this += beta.name(
"relaxation_beta")
149 .units(
UnitSI().dimensionless())
152 *
this += pressure_potential.name(
"pressure_potential")
156 *
this += flow_source.name(
"extra_flow_source")
167 potential_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, -1);
168 pressure_potential.set_field(mesh.region_db().get_region_set(
"ALL"), potential_ptr_);
170 beta_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, 1);
171 beta.set_field(mesh.region_db().get_region_set(
"ALL"), beta_ptr_);
173 flow_source_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, 1);
174 flow_source.set_field(mesh.region_db().get_region_set(
"ALL"), flow_source_ptr_);
176 old_pressure_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, 1);
177 old_iter_pressure_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, 1);
178 div_u_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, 1);
179 old_div_u_ptr_ = create_field<3, FieldValue<3>::Scalar>(
mesh, 1);
188 using namespace Input;
197 std::stringstream ss;
204 mechanics_->data()[
"cross_section"].copy_from(flow_->data()[
"cross_section"]);
205 mechanics_->initialize();
208 beta_ = in_record.
val<
double>(
"iteration_parameter");
209 min_it_ = in_record.
val<
unsigned int>(
"min_it");
210 max_it_ = in_record.
val<
unsigned int>(
"max_it");
229 template<
int dim,
class Value>
235 for (
auto cell : dh->own_range() )
236 vec[cell.local_idx()] = from_field.
value(cell.elm().centre(), cell.elm());
243 template<
int dim,
class Value>
249 for (
auto cell : dh->own_range() )
251 auto elm = cell.elm();
262 std::stringstream ss;
266 flow_->zero_time_step();
279 double difference = 0;
287 (it < max_it_ && difference >
a_tol_ && difference/norm >
r_tol_)
295 flow_->solve_time_step(
false);
308 MessageOut().fmt(
"HM Iteration {} abs. difference: {} rel. difference: {}\n" 309 "--------------------------------------------------------",
310 it, difference, difference/norm);
314 flow_->output_data();
326 double difference2 = 0, norm2 = 0;
328 for (
auto ele : dh->local_range() )
330 auto elm = ele.elm();
331 ele.get_loc_dof_indices(dof_indices);
332 for (
auto side : ele.side_range() )
337 double pressure =
flow_->get_mh_dofhandler().side_scalar(side.side());
338 double potential = -alpha*density*gravity*pressure;
342 difference2 += pow(potential_vec_[dof_indices[side.side_idx()]] - potential,2);
343 norm2 += pow(potential,2);
346 potential_vec_[dof_indices[side.side_idx()]] = potential;
350 double send_data[] = { difference2, norm2 };
353 difference2 = recv_data[0];
354 norm2 = recv_data[1];
358 dif2norm = (difference2 == 0)?0:numeric_limits<double>::max();
360 dif2norm = sqrt(difference2/norm2);
361 DebugOut() <<
"Relative potential difference: " << dif2norm << endl;
363 if (dif2norm > numeric_limits<double>::epsilon())
376 double beta_diff2 = 0, beta_norm2 = 0, src_diff2 = 0, src_norm2 = 0;
377 for (
auto ele : dh->local_range() )
379 auto elm = ele.elm();
382 double young =
mechanics_->data().young_modulus.value(elm.centre(), elm);
383 double poisson =
mechanics_->data().poisson_ratio.value(elm.centre(), elm);
387 double p =
flow_->get_mh_dofhandler().element_scalar(elm);
390 double src = (beta*(p-old_p) + alpha*(old_div_u - div_u)) /
time_->
dt();
394 beta_diff2 += pow(beta_vec[ele.local_idx()] - beta,2);
395 beta_norm2 += pow(beta,2);
396 src_diff2 += pow(src_vec[ele.local_idx()] - src,2);
397 src_norm2 += pow(src,2);
400 beta_vec[ele.local_idx()] = beta;
401 src_vec[ele.local_idx()] = src;
404 double send_data[] = { beta_diff2, beta_norm2, src_diff2, src_norm2 };
407 beta_diff2 = recv_data[0];
408 beta_norm2 = recv_data[1];
409 src_diff2 = recv_data[2];
410 src_norm2 = recv_data[3];
412 double beta_dif2norm, src_dif2norm;
414 beta_dif2norm = (beta_diff2 == 0)?0:numeric_limits<double>::max();
416 beta_dif2norm = sqrt(beta_diff2/beta_norm2);
418 src_dif2norm = (src_diff2 == 0)?0:numeric_limits<double>::max();
420 src_dif2norm = sqrt(src_diff2/src_norm2);
421 DebugOut() <<
"Relative difference in beta: " << beta_dif2norm << endl;
422 DebugOut() <<
"Relative difference in extra_source: " << src_dif2norm << endl;
424 if (beta_dif2norm > numeric_limits<double>::epsilon())
429 if (src_dif2norm > numeric_limits<double>::epsilon())
440 double p_dif2 = 0, p_norm2 = 0;
441 for (
auto cell : dh->own_range())
443 auto elm = cell.elm();
444 double new_p =
flow_->get_mh_dofhandler().element_scalar(elm);
446 p_dif2 += pow(new_p - old_p, 2)*elm.measure();
447 p_norm2 += pow(old_p, 2)*elm.measure();
450 double send_data[] = { p_dif2, p_norm2 };
453 difference = sqrt(recv_data[0]);
454 norm = sqrt(recv_data[1]);
461 return flow_->get_mh_dofhandler();
unsigned int max_it_
Maximal number of iterations.
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > old_div_u_ptr_
double beta_
Tuning parameter for iterative splitting.
void update_field_from_mh_dofhandler(const MH_DofHandler &mh_dh, FieldFE< dim, Value > &field)
double r_tol_
Relative tolerance for difference between two succeeding iterations.
static const int registrar
#define MessageOut()
Macro defining 'message' record of log.
VectorMPI get_data_vec() const
Class template representing a field with values dependent on: point, element, and region...
void initialize(Mesh &mesh)
void next_time()
Proceed to the next time according to current estimated time step.
static const Input::Type::Record & get_input_type()
Declare input record type for the equation TransportDG.
const MH_DofHandler & get_mh_dofhandler() override
void update_flow_fields()
double lame_mu(double young, double poisson)
void zero_time_step() override
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > potential_ptr_
FieldFE for pressure_potential field.
const TimeStep & step(int index=-1) const
Basic time management functionality for unsteady (and steady) solvers (class Equation).
double a_tol_
Absolute tolerance for difference between two succeeding iterations.
static const Input::Type::Record & get_input_type()
Define input record.
void view(const char *name="") const
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > old_pressure_ptr_
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > div_u_ptr_
double element_scalar(ElementAccessor< 3 > &ele) const
temporary replacement for DofHandler accessor, scalar (pressure) on element
void update_solution() override
static constexpr Mask equation_result
Match result fields. These are never given by input or copy of input.
Compound finite element on dim dimensional simplex.
Field< 3, FieldValue< 3 >::Scalar > pressure_potential
Potential -alpha*pressure whose gradient is passed to mechanics as additional load.
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > flow_source_ptr_
static constexpr Mask equation_external_output
Match an output field, that can be also copy of other field.
void set_time_result_changed()
Manually mark flag that the field has been changed.
void copy_field(const Field< dim, Value > &from_field, FieldFE< dim, Value > &to_field)
Field< 3, FieldValue< 3 >::Scalar > alpha
Biot coefficient.
std::shared_ptr< Elasticity > mechanics_
solute transport with chemistry through operator splitting
#define START_TIMER(tag)
Starts a timer with specified tag.
virtual Value::return_type const & value(const Point &p, const ElementAccessor< spacedim > &elm) const
Field< 3, FieldValue< 3 >::Scalar > gravity
Standard gravity.
static Input::Type::Abstract & get_input_type()
static constexpr Mask in_rhs
A field is part of the right hand side of the equation.
Field< 3, FieldValue< 3 >::Scalar > flow_source
void initialize() override
std::shared_ptr< FieldFE< spacedim, Value > > create_field(Mesh &mesh, int n_comp)
Field< 3, FieldValue< 3 >::Scalar > beta
std::shared_ptr< DOFHandlerMultiDim > get_dofhandler() const
#define MPI_Allreduce(sendbuf, recvbuf, count, datatype, op, comm)
void set_input_list(Input::Array input_list, const TimeGovernor &tg)
unsigned int min_it_
Minimal number of iterations to perform.
static const Input::Type::Record & get_input_type()
HM_Iterative(Mesh &mesh, Input::Record in_record)
bool set_time(const TimeStep &time, LimitSide limit_side)
double lame_lambda(double young, double poisson)
static const Input::Type::Record & get_input_type()
#define WarningOut()
Macro defining 'warning' record of log.
Class for representation SI units of Fields.
std::shared_ptr< RichardsLMH > flow_
steady or unsteady water flow simulator based on MH scheme
void compute_iteration_error(double &difference, double &norm)
#define DebugOut()
Macro defining 'debug' record of log.
static bool print_message_table(ostream &stream, std::string equation_name)
Crouzeix-Raviart finite element on dim dimensional simplex.
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > old_iter_pressure_ptr_
Field< 3, FieldValue< 3 >::Scalar > density
Density of fluid.
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
std::shared_ptr< FieldFE< 3, FieldValue< 3 >::Scalar > > beta_ptr_