Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
stokes-darcy.cc

Commented version of this example This example on gitlab

1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#include <config.h>
8
9#include <cstddef>
10#include <cmath>
11#include <iostream>
12#include <string>
13
23
25#include <dune/grid/uggrid.hh>
26#include <dune/grid/common/gridfactory.hh>
27
29#include <dune/istl/bvector.hh>
31#include <dune/istl/solvers.hh>
32#include <dune/istl/umfpack.hh>
33
41
42#include <dune/assembler/backends/istlmatrixbackend.hh>
43#include <dune/assembler/backends/istlvectorbackend.hh>
44#include <dune/assembler/defaultglobalassembler.hh>
45
46#include <dune/vtk/datacollectors/discontinuouslagrangedatacollector.hh>
47#include <dune/vtk/datacollectors/lagrangedatacollector.hh>
48#include <dune/vtk/vtkwriter.hh>
49
57#include <dune/fufem/logger.hh>
58
59int main (int argc, char *argv[]) try
60{
61
62 auto log = Dune::Fufem::makeLogger(std::cout, "[% 8.3f] [% 8.3f] ");
63
64 Dune::MPIHelper::instance(argc, argv);
65
66 log("MPI initialized");
67 auto parameters = Dune::ParameterTree();
68 Dune::ParameterTreeParser::readOptions(argc, argv, parameters);
69
70 auto nu = parameters.get<double>("viscosity", 1.0);
71 auto K = parameters.get<double>("permeability", 1.0e-2);
72 auto alpha_BJS = parameters.get<double>("alpha_BJS", 1.0);
73 auto g = parameters.get<double>("gravity", 1.0);
74 auto meshFile = parameters.get<std::string>("meshFile", "stokes-darcy.msh");
75 auto StokesID = parameters.get<int>("StokesID", 1);
76 auto DarcyID = parameters.get<int>("DarcyID", 2);
77 auto refinements = parameters.get<std::size_t>("refinements", 2);
78
79 log("Command line processed");
80 constexpr std::size_t dim = 2;
81
82 auto stokesVelocityDirichletValues = [](auto x)
83 {
84 return Dune::FieldVector<double,dim>{1.0, 0.0};
85 };
86
87 auto darcyDirichletValues = [](auto x)
88 {
89 return 0;
90 };
91 using Grid = Dune::UGGrid<dim>;
92
93 auto factory = Dune::GridFactory<Grid>();
94 auto reader = Dune::GmshReader<Grid>(meshFile, factory);
95 auto gridPtr = factory.createGrid();
96 auto& grid = *gridPtr;
97 auto elementData = Dune::Fufem::ElementData(reader, factory, grid);
98 auto boundaryData = Dune::Fufem::BoundaryData(reader, factory, grid);
99 grid.globalRefine(refinements);
100
101 auto gridView = grid.leafGridView();
102
103 elementData.update(gridView);
104
105 log("Grid refined");
108
109 auto stokesDomain = SubDomain(gridView);
110 for(auto&& element : elements(gridView))
111 if (elementData(element) == StokesID)
112 stokesDomain.insertElement(element);
113
114 log(Dune::formatString("Stokes domain contains %d elements", stokesDomain.indexSet().size(0)));
115
116 auto darcyDomain = SubDomain(gridView);
117 for(auto&& element : elements(gridView))
118 if (elementData(element) == DarcyID)
119 darcyDomain.insertElement(element);
120
121 log(Dune::formatString("Darcy domain contains %d elements", darcyDomain.indexSet().size(0)));
122 auto interface = SubDomainInterface(stokesDomain, darcyDomain);
123
124 log("Interface created");
125 auto stokesDirichletBoundary = Dune::Fufem::BoundaryPatch(gridView);
126 for (const auto& intersection : Dune::Fufem::Boundary(gridView))
127 if (boundaryData(intersection) == StokesID)
128 stokesDirichletBoundary.insertFace(intersection);
129
130 auto darcyDirichletBoundary = Dune::Fufem::BoundaryPatch(gridView);
131 for (const auto& intersection : Dune::Fufem::Boundary(gridView))
132 if (boundaryData(intersection) == DarcyID)
133 darcyDirichletBoundary.insertFace(intersection);
134
135 log("Dirichlet boundaries created");
136 using namespace Dune::Functions::BasisFactory;
138
139 constexpr std::size_t maxOrder = 2;
140 auto basis = makeBasis(gridView,
141 composite(
142 restrict(
143 composite(
144 power<dim>(lagrange<maxOrder>(), flatInterleaved()),
145 lagrange<maxOrder-1>(),
146 flatLexicographic()
147 ), stokesDomain),
148 restrict(lagrange<maxOrder+1>(), darcyDomain),
149 flatLexicographic()
150 )
151 );
152
153 log(Dune::formatString("Basis created with dimension %d", basis.dimension()));
154 using namespace Dune::Indices;
155
156 auto stokesVelocityBasis = Dune::Functions::subspaceBasis(basis, _0, _0);
157 auto stokesPressureBasis = Dune::Functions::subspaceBasis(basis, _0, _1);
158 auto darcyBasis = Dune::Functions::subspaceBasis(basis, _1);
159 using Vector = Dune::BlockVector<double>;
161
162 auto sol = Vector();
163 auto rhs = Vector();
164 auto stiffnessMatrix = Matrix();
165 auto constraints = Dune::Fufem::makeAffineConstraints(basis);
166 computeBoundaryConstraints(constraints, stokesVelocityBasis, stokesVelocityDirichletValues, stokesDirichletBoundary);
167 computeBoundaryConstraints(constraints, darcyBasis, darcyDirichletValues, darcyDirichletBoundary);
168
169 log("Boundary constraints computed");
170 using namespace Dune::Fufem::Forms;
171
172 auto u = trialFunction(stokesVelocityBasis);
173 auto p = trialFunction(stokesPressureBasis);
174 auto phi = trialFunction(darcyBasis);
175
176 auto v = testFunction(stokesVelocityBasis);
177 auto q = testFunction(stokesPressureBasis);
178 auto psi = testFunction(darcyBasis);
179 auto E = [&](const auto& v) {
180 return symmetrize(grad(v));
181 };
182
183 auto normal = faceNormal(gridView);
184 auto P_tangent = compose([&](auto n) {
186 for(auto i : Dune::range(dim))
187 for(auto j : Dune::range(dim))
188 T[i][j] = (i==j) - n[i]*n[j];
189 return T;
190 }, normal);
191 double alpha = alpha_BJS/std::sqrt(K);
192
193 auto A = integrate( 2*nu*dot(E(u), E(v)) - div(u)*q - div(v)*p, stokesDomain )
194 + integrate( dot(K*grad(phi), grad(psi)), darcyDomain )
195 + integrate( alpha*dot(P_tangent*u, v), interface )
196 + integrate( g*outside(phi)*dot(v, normal), interface )
197 + integrate( - outside(psi)*dot(u, normal), interface );
198 auto assembler = Dune::Assembler::Assembler(basis, basis);
199
200 log("Assembler set up");
201 auto matrixBackend = Dune::Assembler::ISTLMatrixBackend(stiffnessMatrix);
202 auto rhsBackend = Dune::Assembler::ISTLVectorBackend(rhs);
203 auto patternBuilder = matrixBackend.patternBuilder();
204 patternBuilder.resize(basis, basis);
205 assembler.assembleMatrixPattern(A, patternBuilder);
206
207 log("Matrix pattern assembled");
208
209 patternBuilder.setupMatrix();
210
211 log("Matrix set up");
212 assembler.assembleMatrixEntries(A, matrixBackend);
213
214 log("Matrix assembled");
215 rhsBackend.resize(basis);
216 rhsBackend.setZero();
217
218 log("RHS assembled");
219 constraints.constrainLinearSystem(stiffnessMatrix, rhs);
220
221 log("Boundary condition incorporated into system");
222 auto solBackend = Dune::Assembler::ISTLVectorBackend(sol);
223 solBackend.resize(basis);
224 solBackend.setZero();
225#if HAVE_UMFPACK
226 auto solver = Dune::UMFPack<Matrix>();
227 solver.setMatrix(stiffnessMatrix);
228#else
229 auto matrixOperator = Dune::MatrixAdapter<Matrix,Vector,Vector>(stiffnessMatrix);
230 auto preconditioner = Dune::SeqILU<Matrix,Vector,Vector>(stiffnessMatrix,1.0);
232 matrixOperator,
233 preconditioner,
234 1e-6,
235 1000,
236 1000,
237 2);
238#endif
239
240 log("Solver created");
241
242 auto solverStatistics = Dune::InverseOperatorResult();
243
244 solver.apply(sol, rhs, solverStatistics);
245
246 log("Linear system solved");
247 constraints.interpolate(sol);
248
249 log("Constrained solution interpolated");
250 auto vtkWriter = Dune::Vtk::UnstructuredGridWriter(Dune::Vtk::DiscontinuousLagrangeDataCollector(basis.gridView(), maxOrder));
251 vtkWriter.addPointData(u|sol, Dune::VTK::FieldInfo("stokes_velocity", Dune::VTK::FieldInfo::Type::vector, dim));
252 vtkWriter.addPointData(p|sol, Dune::VTK::FieldInfo("stokes_pressure", Dune::VTK::FieldInfo::Type::scalar, 1));
253 vtkWriter.addPointData(phi|sol, Dune::VTK::FieldInfo("darcy_pressure", Dune::VTK::FieldInfo::Type::scalar, 1));
254 vtkWriter.addPointData(-K*jacobian(phi)|sol, Dune::VTK::FieldInfo("darcy_velocity", Dune::VTK::FieldInfo::Type::vector, dim));
255 vtkWriter.addPointData((p+phi)|sol, Dune::VTK::FieldInfo("pressure", Dune::VTK::FieldInfo::Type::scalar, 1));
256 vtkWriter.addPointData((u-K*jacobian(phi))|sol, Dune::VTK::FieldInfo("velocity", Dune::VTK::FieldInfo::Type::vector, dim));
257 vtkWriter.write("stokes-darcy");
258
259 log("Solution written to vtk file");
260}
261catch (Dune::Exception& e)
262{
263 std::cout << e.what() << std::endl;
264 return 1;
265}
int main(int argc, char **argv)
field_type dot(const type &newv) const
double alpha() const
Y & rhs()
auto subspaceBasis(const RootBasis &rootBasis, const TypeTree::TreePath< PrefixTreeIndices... > &prefixPath)
static std::string formatString(const std::string &s, const T &... args)
size_type dim() const
const char * what() const noexcept override
auto makeAffineConstraints(const Basis &basis)
Create and initialize an AffineConstraints object for a basis.
Definition affineconstraints.hh:825
auto outside(const Op &op)
Construct outside version of a given operator.
Definition userfunctions.hh:862
auto faceNormal(const GridView &gridView)
Construct operator representing the face normals.
Definition userfunctions.hh:965
auto jacobian(const FEFunctionOperator< B, TP, argIndex > &op)
Obtain the jacobian of an operator.
Definition userfunctions.hh:1063
auto grad(const Op &op)
Obtain the gradient of an operator.
Definition userfunctions.hh:1186
auto compose(const OuterOp &outerOp, const InnerOp &innerOp)
Generic composition of a multilinear operators with a pointwise outer operator.
Definition userfunctions.hh:483
::value auto integrate(MultilinearOperator op, const Domain &domain)
Integrate a k-linear operator to obtain a k-linear form.
Definition integrate.hh:53
auto makeLogger(std::ostream &stream, std::string format)
Create a simple logger callback.
Definition logger.hh:42
Definition baseclass.hh:22
static DUNE_EXPORT MPIHelper & instance(int &argc, char **&argv)
static void readOptions(int argc, char *argv[], ParameterTree &pt)
LeafGridView leafGridView() const
void globalRefine(int refCount)
Encapsulate a subset of the boundary intersections of a GridView.
Definition domains/boundarypatch.hh:37
Class for storing data associated to boundary segments.
Definition boundarydata.hh:44
Class for storing data associated to elements.
Definition elementdata.hh:47
T div(T... args)
T endl(T... args)
T log(T... args)
T sqrt(T... args)