### Implement outflow BC in Richards model

* Outflow BC is a variant of the Dirichlet BC where only negative fluxes
(out of the domain) are applied. Positive fluxes are ignored and
effectively yield a no flow BC.
* Enable "Outflow" as Richards model BC.
parent 24d28d96
 ... ... @@ -37,6 +37,7 @@ * Control negative transport solution by a check policy !181 * DG solver for solute transport model !112 * Cookbook tutorial on using the random field generator !184 * Outflow boundary condition for Richards model !191 ### Changed * Data structures for storing and accessing parameter information !55 ... ...
 ... ... @@ -98,85 +98,99 @@ A boundary condition has the following template: value: # .. option:: Dirichlet Dirichlet ^^^^^^^^^ A Dirichlet boundary conditions determines the exact value of the solution at the boundary. A Dirichlet boundary conditions determines the exact value of the solution at the boundary. **Richards Model** Quantity: Matric head :math:h_m \, [\text{m}]. Richards Model Quantity: Matric head :math:h_m \, [\text{m}]. .. tip:: Typical use cases for Dirichlet conditions in a Richards Model include: Typical use cases for Dirichlet conditions in a Richards Model include: * Height above a fixed water table at the lower boundary. * Evaporative potential at upper boundary, if :math:h_m < z_\text{wt}, where :math:z_\text{wt} is the height above the water table. **Transport Model** Quantity: Total concentration :math:C_t\,[\text{kg}\,\text{m}^{-d}] or concentration in the water phase :math:C_w\,[\text{kg}\,\text{m}^{-d}], depending on the value of concentration_type. The integer :math:d denotes the spatial dimension. Transport Model Quantity: Total concentration :math:C_t\,[\text{kg}\,\text{m}^{-d}] or concentration in the water phase :math:C_w\,[\text{kg}\,\text{m}^{-d}], depending on the value of concentration_type. The integer :math:d denotes the spatial dimension. Variables: * type: Dirichlet * value: Quantity as specified above. * concentration_type **(Transport only)**: Switch between total (:math:C_t) or water_phase (:math:C_w) concentration as defined above. Variables * type: Dirichlet * value: Quantity as specified above. * concentration_type **(Transport only)**: Switch between total (:math:C_t) or water_phase (:math:C_w) concentration as defined above. .. option:: Neumann Neumann ^^^^^^^ A Neumann boundary condition determines the value of target quantity flux at the boundary. A Neumann boundary condition determines the value of target quantity flux at the boundary. **Richards Model** Quantity: Water flux :math:\mathbf{j}_w \, [\text{ms}^{-1}]. Richards Model Quantity: Water flux :math:\mathbf{j}_w \, [\text{ms}^{-1}]. Precipitation and evapotranspiration fluxes are typically measured with respect to a flat surface. For modeling these fluxes, the horizontal_projection key is used, which scales the flux applied to the boundary with its inclination with respect to the direction of gravitational force, Precipitation and evapotranspiration fluxes are typically measured with respect to a flat surface. For modeling these fluxes, the horizontal_projection key is used, which scales the flux applied to the boundary with its inclination with respect to the direction of gravitational force, .. math:: .. math:: j_{N, \text{scaled}} = \left| \mathbf{\hat{n}} \cdot \mathbf{\hat{g}} \right| j_N . j_{N, \text{scaled}} = \left| \mathbf{\hat{n}} \cdot \mathbf{\hat{g}} \right| j_N . .. note:: Hydraulic conductivity decreases with water content. Evaporation fluxes must not infinitely exceed the stable limit, or else the solver will inevitably fail. **Transport Model** Quantity: Solute flux :math:\mathbf{j}_s \, [\text{kg}\,\text{m}^{-d+1}\,\text{s}^{-1}], where :math:d indicates the spatial dimensions. Transport Model Quantity: Solute flux :math:\mathbf{j}_s \, [\text{kg}\,\text{m}^{-d+1}\,\text{s}^{-1}], where :math:d indicates the spatial dimensions. Variables * type: Neumann * value: Flux perpendicular to the surface :math:j_N, in the quantities defined above. Fluxes into the domain are negative, fluxes out of the domain positive. * horizontal_projection **(Richards only)**: Boolean if the actual boundary flux should be scaled with the surface inclination against the direction of gravity. Outflow ^^^^^^^ An outflow boundary condition only allows flow out of the domain. Variables: * type: Neumann * value: Flux perpendicular to the surface :math:j_N, in the quantities defined above. Fluxes into the domain are negative, fluxes out of the domain positive. * horizontal_projection **(Richards only)**: Boolean if the actual boundary flux should be scaled with the surface inclination against the direction of gravity. Richards Model Quantity: Matric head :math:h_m \, [\text{m}] . .. option:: Outflow (Transport only) The outflow boundary condition is a variant of the Dirichlet boundary condition. It applies the specified matric head only if it leads to a net flux out of the domain. Otherwise, the flux is set to zero (no flow boundary condition). An outflow boundary condition allows solute be transported throw the Transport Model Quantity: Solute flux :math:\mathbf{j}_s \, [\text{kg}\,\text{m}^{-d+1}\,\text{s}^{-1}], where :math:d indicates the spatial dimensions. The outflow boundary condition allows solute be transported throw the boundary by the water flux. As solute concentration and water flux are only modelled inside the domain, this effectively only allows the solute to leave the domain and be discarded. The boundary condition value is an additional solute flux for which all considerations of a Neumann boundary condition apply (see above). Quantity: Solute flux :math:\mathbf{j}_s \, [\text{kg}\,\text{m}^{-d+1}\,\text{s}^{-1}], where :math:d indicates the spatial dimensions. additional solute flux for which all considerations of a Neumann boundary condition apply (see above). The total solute flux through the boundary is then given by ... ... @@ -185,15 +199,16 @@ A boundary condition has the following template: j_s = \left| \mathbf{j}_s \cdot \mathbf{\hat{n}} \right| + j_N , where :math:\mathbf{j}_s = C_w \mathbf{j}_w is the solute flux at the boundary, :math:\mathbf{\hat{n}} is the boundary unit normal vector and :math:j_N is the given boundary condition value, as defined below. Variables: * type: Outflow * value: Flux perpendicular to the surface :math:j_N, as in :option:Neumann. This flux is applied in addition to regular seepage through the boundary. It is recommended to set this value to 0 (zero). boundary, :math:\mathbf{\hat{n}} is the boundary unit normal vector and :math:j_N is the flux perpendicular to the surface as specified in the boundary condition value. This flux is applied in addition to regular seepage through the boundary. It is recommended to set this value to 0 (zero). Variables * type: Outflow * value: Matric head :math:h_m or solute flux perpendicular to the surface :math:j_N in quantities defined above, depending on the model. Example Files ------------- ... ...
 ... ... @@ -62,24 +62,11 @@ private: }; /// Return the type strings of permitted boundary conditions /** Currently, both models support all boundary condition types. */ static constexpr auto get_permitted_type_strs () { if constexpr (mode == BCMMode::richards) { return std::array{ DirichletBoundaryCondition::type_str, NeumannBoundaryCondition::type_str }; } else if constexpr (mode == BCMMode::transport) { return std::array{ DirichletBoundaryCondition::type_str, NeumannBoundaryCondition::type_str, OutflowBoundaryCondition::type_str }; } else { return known_type_strs; } return known_type_strs; } /// Return true of the given BC type is permitted for this model ... ...
 ... ... @@ -602,6 +602,7 @@ public: // query the boundary condition const auto bc = boundary->bc(ig.intersection()); const auto bc_type = bc->type(); // loop over quadrature points and integrate normal flux for (const auto& it : quadratureRule(gtface,intorder)) ... ... @@ -654,7 +655,7 @@ public: u_s += x_s(lfsu_s,i) * phiu_s[i]; // update residual according to byType flag if (bc->type() == BCType::Neumann) if (bc_type == BCType::Neumann) { // flux is given parallel to gravity vector RF normal_flux = bc->evaluate(time); ... ... @@ -673,7 +674,7 @@ public: continue; } else if (bc->type() == BCType::Dirichlet) else if (bc_type == BCType::Dirichlet or bc_type == BCType::Outflow) { // compute gradient of u Vector gradu_s(0.); ... ... @@ -718,6 +719,11 @@ public: relCond = 2 * relCond_s * relCond_n / (relCond_s + relCond_n); } // Avoid accumulating inflow for outflow BC if (bc_type == BCType::Outflow and FloatCmp::lt(double(numFlux), 0.0)) { continue; } if constexpr (lopcase != LOPCase::RTVolume) { ... ...
 #ifndef DUNE_DORIE_RICHARDS_OPERATOR_FV_HH #define DUNE_DORIE_RICHARDS_OPERATOR_FV_HH #include #include #include ... ... @@ -261,7 +263,8 @@ public: const auto saturation_f_i = _param->saturation_f(); const auto conductivity_f_i = _param->conductivity_f(); if (bc->type() == BCType::Dirichlet) const auto bc_type = bc->type(); if (bc_type == BCType::Dirichlet or bc_type == BCType::Outflow) { const auto geo_i = entity_i.geometry(); const auto center_position_i_g = geo_i.center(); ... ... @@ -291,10 +294,16 @@ public: // Water flux in normal direction w.r.t the intersection const auto water_flux_n = - cond_i*dudn; // Avoid accumulation of inflow for outflow BC if (bc_type == BCType::Outflow and FloatCmp::lt(double(water_flux_n), 0.0)) { return; } // Contribution to residual from Dirichlet boundary r_i.accumulate(lfsv_i, 0, water_flux_n*volume_f); } else if (bc->type() == BCType::Neumann) else if (bc_type == BCType::Neumann) { // Contribution to residual from Neumann boundary RangeFieldU water_flux_f = bc->evaluate(_time); ... ...
 ... ... @@ -122,7 +122,7 @@ TEST_F(BCFactory, Outflow) "time: 0.0" "}"); EXPECT_NO_THROW(_bcf_none->create("name", config, 1.0)); EXPECT_THROW(_bcf_richards->create("name", config, 1.0), Dune::IOError); EXPECT_NO_THROW(_bcf_richards->create("name", config, 1.0)); EXPECT_NO_THROW(_bcf_transport->create("name", config, 1.0)); } ... ...
 ... ... @@ -4,6 +4,7 @@ message(STATUS "Handling system tests") dorie_add_metaini_test(TARGET dorie_test METAINI ode_homogeneous_sand.mini.in) dorie_add_metaini_test(TARGET dorie_test METAINI ode_homogeneous_silt.mini.in) dorie_add_metaini_test(TARGET dorie_test METAINI ode_layered.mini.in) dorie_add_metaini_test(TARGET dorie_test METAINI ode_outflow.mini.in) # add target for ODE tests add_custom_target(test_run_ode ... ...
 upper: index: 1 conditions: infiltration: type: Neumann time: 0 value: -5.55e-6 lower: index: 0 conditions: water_table: type: Dirichlet time: 0 value: 0 default: type: Outflow value: 2
 include ${CMAKE_BINARY_DIR}/doc/default_files/config.ini _test_command = run _asset_path = "${CMAKE_CURRENT_LIST_DIR}" _evaluation = ode _order = 0, 1 | expand prec _upwind = none, semiUpwind, fullUpwind | expand _ic_mode = trans, stat | expand ic_mode __name = ode_outflow_{_order}_{_upwind}_{_ic_mode} [grid] gridType = rectangular initialLevel = 0 cells = 1 320, 1 160 | expand prec [richards] output.fileName = {__name} output.outputPath = {__name} output.vertexData = false initial.type = analytic, stationary | expand ic_mode initial.equation = -y boundary.file = "{_asset_path}/bcs/outflow.yml" parameters.file = "{_asset_path}/param/richards_param.yml" time.end = 1E7, 0 | expand ic_mode time.maxTimestep = 1E7 time.startTimestep = 1E4 NewtonParameters.AbsoluteLimit = 1E-10 NewtonParameters.Reduction = 1E-10 numerics.penaltyFactor = 10 numerics.FEorder = {_order} numerics.upwinding = {_upwind} [_ode] headLower = 0. flux = -5.55e-6 head_abstol = 3E-4, 3.2E-5 | expand prec flux_abstol = 1E100, 3.1E-9 | expand prec flux_rt_abstol = 4E-14 # Error tolerance multipliers for stationary solution head_eps_stat = 1.0, 1.0 | expand prec flux_eps_stat = 1.0, 1.0 | expand prec flux_rt_eps_stat = 1E3
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!