Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
bulk-surface.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 <vector>
10#include <cmath>
11#include <numbers>
12#include <thread>
13
19
20#include <dune/geometry/type.hh>
21
23#include <dune/grid/uggrid.hh>
24#include <dune/grid/common/gridfactory.hh>
25
26#include <dune/istl/bvector.hh>
29#include <dune/istl/solvers.hh>
30
39
40#include <dune/vtk/vtkwriter.hh>
41#include <dune/vtk/datacollectors/discontinuouslagrangedatacollector.hh>
42
43#include <dune/assembler/backends/istlvectorbackend.hh>
44#include <dune/assembler/backends/istlmatrixbackend.hh>
45#include <dune/assembler/defaultglobalassembler.hh>
46#include <dune/assembler/parallel/gridcoloring.hh>
47#include <dune/assembler/parallel/coloredrangeexecutor.hh>
48
50#include <dune/fufem/logger.hh>
54
55#include "utilities.hh"
56
57
58
72template<class Constraints, class Basis, class IntersectionSet>
73void computeTraceConstraints(Constraints& constraints, const Basis& basis, const IntersectionSet& intersectionSet)
74{
76 auto isIntersectionDOF = constraints.isConstrained();
77 auto isIntersectionDOFBackend = istlVectorBackend(isIntersectionDOF);
78 Dune::Fufem::markIntersectionDofs(intersectionSet, basis, isIntersectionDOFBackend);
79
80 auto&& isConstrainedBackend = istlVectorBackend(constraints.isConstrained());
81 auto&& constraintValuesBackend = istlVectorBackend(constraints.constantTerm());
82
83 auto localView = basis.localView();
84 const auto& gridView = basis.gridView();
85 for(auto&& element : elements(gridView))
86 {
87 localView.bind(element);
88 for(auto i : Dune::range(localView.tree().size()))
89 {
90 auto i_local = localView.tree().localIndex(i);
91 auto i_global = localView.index(i_local);
92 if (not isIntersectionDOFBackend[i_global])
93 {
94 isConstrainedBackend[i_global] = true;
95 constraintValuesBackend[i_global] = 0;
96 }
97 }
98 }
99 constraints.resolveDependencies();
100}
105int main (int argc, char *argv[]) try
106{
107
108 auto log = Dune::Fufem::makeLogger(std::cout, "[% 8.3f] [% 8.3f] ");
109
110 Dune::MPIHelper::instance(argc, argv);
111
112 log("MPI initialized");
113 auto parameters = Dune::ParameterTree();
114 Dune::ParameterTreeParser::readOptions(argc, argv, parameters);
115
116 auto meshFile = parameters.get<std::string>("meshFile", "bulk-surface.msh");
117 auto refinements = parameters.get<std::size_t>("refinements", 0);
118 auto tol = parameters.get<double>("tol", 1e-4);
119 auto maxIter = parameters.get<std::size_t>("maxIter", 1000);
120 auto verbosity = parameters.get<std::size_t>("verbosity", 2);
121 auto alpha = parameters.get<double>("alpha", 10.0);
122 auto delta = parameters.get<double>("delta", 2.0);
123
124 log("Command line processed");
125
126 auto rhs_A = [] (const auto& x) {
127 if (x[0]>1)
128 return 10;
129 else
130 return 0;
131 };
132 auto rhs_B = [] (const auto& x) { return 0; };
133 auto rhs_I = [] (const auto& x) { return 0; };
134
135 auto dirichletValues = [] (const auto& x) { return 0; };
136 using Grid = Dune::UGGrid<2>;
137
138 auto factory = Dune::GridFactory<Grid>();
139 auto reader = Dune::GmshReader<Grid>(meshFile, factory);
140 auto gridPtr = factory.createGrid();
141 auto& grid = *gridPtr;
142 auto elementData = Dune::Fufem::ElementData(reader, factory, grid);
143
144 log("Grid created");
145
146 grid.globalRefine(refinements);
147 auto gridView = grid.leafGridView();
148 elementData.update(gridView);
149
150 log("Grid refined");
153
154 auto subDomain_A = SubDomain(gridView);
155 for(auto&& element : elements(gridView))
156 if (elementData(element) == 1)
157 subDomain_A.insertElement(element);
158
159 log(Dune::formatString("SubDomain A contains %d elements", subDomain_A.indexSet().size(0)));
160
161 auto subDomain_B = SubDomain(gridView);
162 for(auto&& element : elements(gridView))
163 if (elementData(element) == 2)
164 subDomain_B.insertElement(element);
165
166 log(Dune::formatString("SubDomain B contains %d elements", subDomain_B.indexSet().size(0)));
167
168 auto interface = SubDomainInterface(subDomain_A, subDomain_B);
169 using namespace Dune::Functions::BasisFactory;
171
172 auto basis = makeBasis(gridView,
173 composite(
174 restrict(lagrange<1>(), subDomain_A),
175 restrict(lagrange<1>(), subDomain_B),
176 restrict(lagrange<1>(), subDomain_A),
178
179 using namespace Dune::Indices;
180 auto subDomainBasis_A = Dune::Functions::subspaceBasis(basis, _0);
181 auto subDomainBasis_B = Dune::Functions::subspaceBasis(basis, _1);
182 auto interfaceBasis = Dune::Functions::subspaceBasis(basis, _2);
183
184 log(Dune::formatString("Basis created with dimension %d", basis.dimension()));
187
188 auto sol = Vector();
189 auto rhs = Vector();
190 auto stiffnessMatrix = Matrix();
191 auto constraints = Dune::Fufem::makeAffineConstraints(basis);
192
193 computeBoundaryConstraints(constraints, subDomainBasis_B, dirichletValues);
194
195 log("Boundary constraints computed");
196
197 computeTraceConstraints(constraints, interfaceBasis, interface);
198
199 log("Trace constraints computed");
200 using namespace Dune::Fufem::Forms;
201
202 auto normal = faceNormal(gridView);
203 auto P = compose([&](auto n) {
204 constexpr auto dim = decltype(n)::size();
206 for(auto i : Dune::range(dim))
207 for(auto j : Dune::range(dim))
208 T[i][j] = (i==j) - n[i]*n[j];
209 return T;
210 }, normal);
211
212 auto u_A = trialFunction(subDomainBasis_A);
213 auto v_A = testFunction(subDomainBasis_A);
214
215 auto u_B = trialFunction(subDomainBasis_B);
216 auto v_B = testFunction(subDomainBasis_B);
217
218 auto u_I = trialFunction(interfaceBasis);
219 auto v_I = testFunction(interfaceBasis);
220
221 auto f_A = Coefficient(Dune::Functions::makeGridViewFunction(rhs_A, gridView));
222 auto f_B = Coefficient(Dune::Functions::makeGridViewFunction(rhs_B, gridView));
223 auto f_I = Coefficient(Dune::Functions::makeGridViewFunction(rhs_I, gridView));
224
225 auto a_A = integrate(dot(grad(u_A), grad(v_A)), subDomain_A);
226 auto a_B = integrate(dot(grad(u_B), grad(v_B)), subDomain_B);
227 auto a_I = integrate(delta*dot(P * grad(u_I), grad(v_I)), interface);
228
229 auto a_coupling = integrate(alpha*(u_A - u_I)*(v_A - v_I) + alpha*(outside(u_B) - u_I)*(outside(v_B) - v_I), interface);
230
231 auto a = a_A + a_B + a_I + a_coupling;
232
233 auto l_A = integrate(f_A*v_A, subDomain_A);
234 auto l_B = integrate(f_B*v_B, subDomain_B);
235 auto l_I = integrate(f_I*v_I, interface);
236
237 auto l = l_A + l_B + l_I;
238 auto matrixBackend = Dune::Assembler::ISTLMatrixBackend(stiffnessMatrix);
239 auto rhsBackend = Dune::Assembler::ISTLVectorBackend(rhs);
240 auto assembler = Dune::Assembler::Assembler(basis, basis);
241
242 log("Assembler set up");
243
244 auto patternBuilder = matrixBackend.patternBuilder();
245 patternBuilder.resize(basis, basis);
246
247 assembler.assembleMatrixPattern(a, patternBuilder);
248
249 log("Matrix pattern assembled");
250
251 patternBuilder.setupMatrix();
252
253 log("Matrix set up");
254
255 assembler.assembleMatrixEntries(a, matrixBackend);
256
257 log("Matrix assembled");
258
259 rhsBackend.resize(basis);
260 rhsBackend.setZero();
261 assembler.assembleVectorEntries(l, rhsBackend);
262
263 log("RHS assembled");
264 constraints.constrainLinearSystem(stiffnessMatrix, rhs);
265
266 log("Boundary condition incorporated into system");
267 Dune::Assembler::ISTLVectorBackend(sol).resize(basis);
268 Dune::Assembler::ISTLVectorBackend(sol).setZero();
269
270 auto matrixOperator = Dune::MatrixAdapter<Matrix,Vector,Vector>(stiffnessMatrix);
271
272 auto preconditioner = makeAMGPreconditioner<Vector>(stiffnessMatrix);
273
274 log("Preconditioner created");
275
276 auto solver = Dune::CGSolver<Vector>(
277 matrixOperator,
278 preconditioner,
279 tol,
280 maxIter,
281 verbosity
282 );
283
284 log("Solver created");
285
286 auto solverStatistics = Dune::InverseOperatorResult();
287
288 solver.apply(sol, rhs, solverStatistics);
289
290 log("Linear system solved");
291
292 constraints.interpolate(sol);
293 auto vtkWriter = Dune::Vtk::UnstructuredGridWriter(Dune::Vtk::DiscontinuousLagrangeDataCollector(basis.gridView(), 1));
294 vtkWriter.addPointData(u_A|sol, Dune::VTK::FieldInfo("sol_A", Dune::VTK::FieldInfo::Type::scalar, 1));
295 vtkWriter.addPointData(u_B|sol, Dune::VTK::FieldInfo("sol_B", Dune::VTK::FieldInfo::Type::scalar, 1));
296 vtkWriter.addPointData((u_A + u_B)|sol, Dune::VTK::FieldInfo("sol_bulk", Dune::VTK::FieldInfo::Type::scalar, 1));
297 vtkWriter.addPointData(u_I|sol, Dune::VTK::FieldInfo("sol_I", Dune::VTK::FieldInfo::Type::scalar, 1));
298 vtkWriter.write("bulk-surface");
299
300 log("Solution written to vtk file");
301}
302catch (Dune::Exception& e)
303{
304 std::cout << e.what() << std::endl;
305 return 1;
306}
int main(int argc, char **argv)
field_type dot(const type &newv) const
double alpha() const
Y & rhs()
constexpr FlatLexicographic flatLexicographic()
auto istlVectorBackend(Vector &v)
std::decay_t< F > makeGridViewFunction(F &&f, const GridView &gridView)
auto subspaceBasis(const RootBasis &rootBasis, const TypeTree::TreePath< PrefixTreeIndices... > &prefixPath)
auto makeBasis(const GridView &gridView, PreBasisFactory &&preBasisFactory)
int size() const
static std::string formatString(const std::string &s, const T &... args)
size_type dim() const
const char * what() const noexcept override
void markIntersectionDofs(const IntersectionSet &intersectionSet, const Basis &basis, Vector &vector)
For a given basis and intersection set, determine all degrees of freedom on the patch.
Definition boundarydofs.hh:45
void computeBoundaryConstraints(AffineConstraints< BV, V, MI, C > &constraints, const Basis &basis, Function &&f, const IntersectionSet &intersectionSet)
Compute constraints for essential boundary conditions.
Definition boundaryconstraints.hh:51
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 testFunction(const Basis &basis)
Create unary identity operator on test function space.
Definition userfunctions.hh:694
auto trialFunction(const Basis &basis)
Create unary identity operator on trial function space.
Definition userfunctions.hh:773
auto faceNormal(const GridView &gridView)
Construct operator representing the face normals.
Definition userfunctions.hh:965
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
const Grid & grid() const
IteratorRange<... > elements(const GV &gv)
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)
Coefficient function.
Definition coefficient.hh:42
Class for storing data associated to elements.
Definition elementdata.hh:47
T endl(T... args)
T log(T... args)