Plugins
Loading...
Searching...
No Matches
turbulent_viscosity_fv1_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013: G-CSC, Goethe University Frankfurt
3 * Author: Christian Wehner
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef __H__UG__NAVIER_STOKES_TURBULENT_VISCOSITY_FV1_DATA_IMPL_H_
34#define __H__UG__NAVIER_STOKES_TURBULENT_VISCOSITY_FV1_DATA_IMPL_H_
35
37
38namespace ug{
39namespace NavierStokes{
40
41// transfer by injection
42template <typename TData, int dim, typename TImpl,typename TGridFunction>
44 for(int si = 0; si < approximationSpace.domain()->subset_handler()->num_subsets(); ++si){
45 // transfer to lower levels, averaging over child edges (2d) / child faces (3d)
46 for (size_t lev=approximationSpace.num_levels()-2; ;lev--){
47 const DoFDistribution& lDD = *approximationSpace.dof_distribution(GridLevel(lev, GridLevel::LEVEL));
48 const MultiGrid& grid = *lDD.multi_grid();
49 typedef typename DoFDistribution::traits<Vertex>::const_iterator coarseLevelVertexIter;
50 coarseLevelVertexIter clvIter, clvIterEnd;
51 clvIter = lDD.template begin<Vertex>(si);
52 clvIterEnd = lDD.template end<Vertex>(si);
53 for (;clvIter != clvIterEnd;clvIter++){
54 Vertex* vertex = *clvIter;
55 aaData[vertex] += aaData[grid.get_child<Vertex>(vertex, 0)];
56 }
57 if (lev==0) break;
58 }
59 }
60}
61
62template <typename TData, int dim, typename TImpl,typename TGridFunction>
64 // get domain
65 domain_type& domain = *u->domain().get();
66 // create Multiindex
67 std::vector<DoFIndex> multInd;
68 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
69 ElemIterator iter = u->template begin<Vertex>(si);
70 ElemIterator iterEnd = u->template end<Vertex>(si);
71 for( ;iter !=iterEnd; ++iter)
72 {
73 Vertex* vertex = iter;
74 for (int d=0;d<dim;d++){
75 u->dof_indices(vertex, d, multInd);
76 aaU[vertex][d]=DoFRef(*u,multInd[0]);
77 }
78 }
79 }
80}
81
82// go over all elements, interpolate data to barycenter, average by multiplying with corresponding element volume and deviding by complete adjacent element volume
83template <typename TData, int dim, typename TImpl,typename TGridFunction>
84template <typename VType>
86 // get domain of grid function
87 domain_type& domain = *m_uInfo->domain().get();
89
90 // set attachment values to zero
91 SetAttachmentValues(aaUHat , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
92 SetAttachmentValues(aaVol , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
93
94 // coord and vertex array
97
98 // get position accessor
99 typedef typename domain_type::position_accessor_type position_accessor_type;
100 const position_accessor_type& posAcc = domain.position_accessor();
101
102 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
103 {
104 // get iterators
105 ElemIterator iter = m_uInfo->template begin<elem_type>(si);
106 ElemIterator iterEnd = m_uInfo->template end<elem_type>(si);
107
108 // loop elements of dimension
109 for( ;iter !=iterEnd; ++iter)
110 {
111 // get Elem
112 elem_type* elem = *iter;
113 // get vertices and extract corner coordinates
114 const size_t numVertices = elem->num_vertices();
115 MathVector<dim> bary,localBary;
116 bary = 0;
117
118 for(size_t i = 0; i < numVertices; ++i){
119 vVrt[i] = elem->vertex(i);
120 coCoord[i] = posAcc[vVrt[i]];
121 bary += coCoord[i];
122 };
123 bary /= numVertices;
124
125 // reference object id
126 ReferenceObjectID roid = elem->reference_object_id();
127
128 // get trial space
129 const LocalShapeFunctionSet<dim>& rTrialSpace =
130 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
131
132 // get Reference Mapping
133 DimReferenceMapping<dim, dim>& map = ReferenceMappingProvider::get<dim, dim>(roid, coCoord);
134
135 map.global_to_local(localBary,bary);
136
137 UG_ASSERT(dynamic_cast<elem_type*>(elem) != NULL, "Only elements of type elem_type are currently supported");
138
139 // memory for shapes
140 std::vector<number> vShape;
141
142 // evaluate finite volume geometry
143 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
144
145 rTrialSpace.shapes(vShape, localBary);
146
147 size_t noc = elem->num_vertices();
148
149 VType value;
150 value = 0;
151 number elementVolume = 0;
152
154 for (size_t co=0;co<noc;co++){
155 const typename DimFV1Geometry<dim>::SCV& scv = geo.scv(co);
156 VType localValue = aaU[elem->vertex(co)];
157 //for debug UG_LOG(localValue << "\n");
158 localValue *= vShape[co];
159 value += localValue;
160 elementVolume += scv.volume();
161 }
162 value *= elementVolume;
163 for (size_t co=0;co<noc;co++){
164 aaUHat[elem->vertex(co)] += value;
165 aaVol[elem->vertex(co)] += elementVolume;
166 }
168 }
169 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
170 // average
171 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
172 {
173 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
174 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
175 for( ;vertexIter !=vertexIterEnd; vertexIter++)
176 {
177 Vertex* vertex = *vertexIter;
178 if (pbm && pbm->is_slave(vertex)) continue;
179 aaUHat[vertex]/=(number)aaVol[vertex];
180 }
181 }
182}
183
184// go over all elements, interpolate data to barycenter, average by multiplying with corresponding element volume and deviding by complete adjacent element volume
185template <typename TData, int dim, typename TImpl,typename TGridFunction>
187 // get domain of grid function
188 domain_type& domain = *m_uInfo->domain().get();
190
191 std::vector<DoFIndex> multInd;
192
193 // set attachment values to zero
194 SetAttachmentValues(aaUHat , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
195 SetAttachmentValues(aaVol , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
196
197 // coord and vertex array
200
201 // get position accessor
202 typedef typename domain_type::position_accessor_type position_accessor_type;
203 const position_accessor_type& posAcc = domain.position_accessor();
204
205 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
206 {
207 // get iterators
208 ElemIterator iter = m_uInfo->template begin<elem_type>(si);
209 ElemIterator iterEnd = m_uInfo->template end<elem_type>(si);
210
211 // loop elements of dimension
212 for( ;iter !=iterEnd; ++iter)
213 {
214 // get Elem
215 elem_type* elem = *iter;
216 // get vertices and extract corner coordinates
217 const size_t numVertices = elem->num_vertices();
218 MathVector<dim> bary,localBary;
219 bary = 0;
220
221 for(size_t i = 0; i < numVertices; ++i){
222 vVrt[i] = elem->vertex(i);
223 coCoord[i] = posAcc[vVrt[i]];
224 bary += coCoord[i];
225 };
226 bary /= numVertices;
227
228 // reference object id
229 ReferenceObjectID roid = elem->reference_object_id();
230
231 // get trial space
232 const LocalShapeFunctionSet<dim>& rTrialSpace =
233 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
234
235 // get Reference Mapping
236 DimReferenceMapping<dim, dim>& map = ReferenceMappingProvider::get<dim, dim>(roid, coCoord);
237
238 map.global_to_local(localBary,bary);
239
240 // memory for shapes
241 std::vector<number> vShape;
242
243 // evaluate finite volume geometry
244 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
245
246 rTrialSpace.shapes(vShape, localBary);
247
248 size_t noc = elem->num_vertices();
249
250 MathVector<dim> value;
251 value = 0;
252 number elementVolume = 0;
253 for (size_t co=0;co<noc;co++){
254 const typename DimFV1Geometry<dim>::SCV& scv = geo.scv(co);
255 MathVector<dim> localValue;
256 for (int d=0;d<dim;d++){
257 u->dof_indices(elem->vertex(co), d, multInd);
258 localValue[d]=DoFRef(*u,multInd[0]);
259 }
260 //for debug UG_LOG("localValue=" << localValue << "\n");
261 //for debug UG_LOG("vShape=" << vShape[s] << "\n");
262 localValue *= vShape[co];
263 value += localValue;
264 elementVolume += scv.volume();
265 }
266 //for debug UG_LOG("value=" << value << " vol=" << elementVolume << "\n");
267 value *= elementVolume;
268 for (size_t co=0;co<noc;co++){
269 aaVol[elem->vertex(co)]+=elementVolume;
270 aaUHat[elem->vertex(co)] += value;
271 }
272 }
273 }
274 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
275 // average
276 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
277 {
278 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
279 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
280 for( ;vertexIter !=vertexIterEnd; vertexIter++)
281 {
282 Vertex* vertex = *vertexIter;
283 if (pbm && pbm->is_slave(vertex)) continue;
284 aaUHat[vertex]/=(number)aaVol[vertex];
285 }
286 }
287}
288
289// go over all elements, interpolate data to scv barycenter, average by multiplying with corresponding scv volume and deviding by volume of complete control volume
290template <typename TData, int dim, typename TImpl,typename TGridFunction>
291template <typename VType>
293 // get domain of grid function
294 domain_type& domain = *m_uInfo->domain().get();
296
297 // set attachment values to zero
298 SetAttachmentValues(aaUHat , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
299 SetAttachmentValues(aaVol , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
300
301 // coord and vertex array
304
305 // get position accessor
306 typedef typename domain_type::position_accessor_type position_accessor_type;
307 const position_accessor_type& posAcc = domain.position_accessor();
308
309 // assemble deformation tensor fluxes
310 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
311 {
312 // get iterators
313 ElemIterator iter = m_uInfo->template begin<elem_type>(si);
314 ElemIterator iterEnd = m_uInfo->template end<elem_type>(si);
315
316 // loop elements of dimension
317 for( ;iter !=iterEnd; ++iter)
318 {
319 // get Elem
320 elem_type* elem = *iter;
321 // get vertices and extract corner coordinates
322 const size_t numVertices = elem->num_vertices();
323 MathVector<dim> bary,localBary;
324 bary = 0;
325
326 for(size_t i = 0; i < numVertices; ++i){
327 vVrt[i] = elem->vertex(i);
328 coCoord[i] = posAcc[vVrt[i]];
329 bary += coCoord[i];
330 };
331 bary /= numVertices;
332
333 // reference object id
334 ReferenceObjectID roid = elem->reference_object_id();
335
336 // get trial space
337 const LocalShapeFunctionSet<dim>& rTrialSpace =
338 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
339
340 // get Reference Mapping
341 DimReferenceMapping<dim, dim>& map = ReferenceMappingProvider::get<dim, dim>(roid, coCoord);
342
343 map.global_to_local(localBary,bary);
344
345 // evaluate finite volume geometry
346 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
347
348 size_t noc = elem->num_vertices();
349
350 MathVector<dim> scvLocalBary;
351 for (size_t co=0;co<noc;co++){
352 const typename DimFV1Geometry<dim>::SCV& scv = geo.scv(co);
353
354 scvLocalBary = 0;
355 // compute barycenter of scv
356 for (size_t i=0;i<scv->num_corners();i++){
357 scvLocalBary += scv->loal_corner(i);
358 }
359 scvLocalBary/=(number)(scv->num_corners());
360 // memory for shapes
361 std::vector<number> vShape;
362 rTrialSpace.shapes(vShape, scvLocalBary);
363 VType localValue = 0;
364
365 for (size_t j=0;j<noc;j++){
366 localValue += vShape[j]*aaU[elem->vertex(j)];
367 }
368
369 localValue *= scv.volume();
370 aaVol[elem->vertex(co)] += scv.volume();
371 aaUHat[elem->vertex(co)] += localValue;
372 }
373 }
374 }
375 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
376 // average
377 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
378 {
379 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
380 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
381 for( ;vertexIter !=vertexIterEnd; vertexIter++)
382 {
383 Vertex* vertex = *vertexIter;
384 if (pbm && pbm->is_slave(vertex)) continue;
385 aaUHat[vertex]/=(number)aaVol[vertex];
386 }
387 }
388}
389
390// go over all elements, interpolate data to scv barycenter, average by multiplying with corresponding scv volume and deviding by volume of complete control volume
391template <typename TData, int dim, typename TImpl,typename TGridFunction>
393 // get domain of grid function
394 domain_type& domain = *m_uInfo->domain().get();
396
397 // set attachment values to zero
398 SetAttachmentValues(aaUHat , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
399 SetAttachmentValues(aaVol , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
400
401 // coord and vertex array
404
405 // get position accessor
406 typedef typename domain_type::position_accessor_type position_accessor_type;
407 const position_accessor_type& posAcc = domain.position_accessor();
408
409 // create Multiindex
410 std::vector<DoFIndex> multInd;
411
412 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
413 {
414 // get iterators
415 ElemIterator iter = m_uInfo->template begin<elem_type>(si);
416 ElemIterator iterEnd = m_uInfo->template end<elem_type>(si);
417
418 // loop elements of dimension
419 for( ;iter !=iterEnd; ++iter)
420 {
421 // get Elem
422 elem_type* elem = *iter;
423 // get vertices and extract corner coordinates
424 const size_t numVertices = elem->num_vertices();
425 MathVector<dim> bary,localBary;
426 bary = 0;
427
428 for(size_t i = 0; i < numVertices; ++i){
429 vVrt[i] = elem->vertex(i);
430 coCoord[i] = posAcc[vVrt[i]];
431 bary += coCoord[i];
432 };
433 bary /= numVertices;
434
435 // reference object id
436 ReferenceObjectID roid = elem->reference_object_id();
437
438 // get trial space
439 const LocalShapeFunctionSet<dim>& rTrialSpace =
440 LocalFiniteElementProvider::get<dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
441
442 // get Reference Mapping
443 DimReferenceMapping<dim, dim>& map = ReferenceMappingProvider::get<dim, dim>(roid, coCoord);
444
445 map.global_to_local(localBary,bary);
446
447 // evaluate finite volume geometry
448 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
449
450 size_t noc = elem->num_vertices();
451
452 static const size_t MaxNumVerticesOfElem = 10;
453
454 typedef MathVector<dim> MVD;
455 std::vector<MVD> uValue(MaxNumVerticesOfElem);
456
457 for (size_t co=0;co<noc;co++){
458 for (int d=0;d<dim;d++){
459 u->dof_indices(elem->vertex(co), d, multInd);
460 uValue[co][d]=DoFRef(*u,multInd[0]);
461 }
462 };
463
464 MathVector<dim> scvLocalBary;
465 for (size_t co=0;co<noc;co++){
466 const typename DimFV1Geometry<dim>::SCV& scv = geo.scv(co);
467 scvLocalBary = 0;
468 // compute barycenter of scv
469 for (size_t i=0;i<scv.num_corners();i++){
470 scvLocalBary += scv.local_corner(i);
471 }
472 scvLocalBary/=(number)(scv.num_corners());
473 // memory for shapes
474 std::vector<number> vShape;
475 rTrialSpace.shapes(vShape, scvLocalBary);
476 MathVector<dim> localValue = 0;
477
478 for (size_t j=0;j<noc;j++)
479 for (int d=0;d<dim;d++)
480 localValue += vShape[j]*uValue[j];
481
482 localValue *= scv.volume();
483 aaVol[elem->vertex(co)] += scv.volume();
484 aaUHat[elem->vertex(co)] += localValue;
485 }
486 }
487 }
488 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
489 // average
490 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
491 {
492 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
493 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
494 for( ;vertexIter !=vertexIterEnd; vertexIter++)
495 {
496 Vertex* vertex = *vertexIter;
497 if (pbm && pbm->is_slave(vertex)) continue;
498 aaUHat[vertex]/=(number)aaVol[vertex];
499 }
500 }
501}
502
503template <typename TData, int dim, typename TImpl,typename TGridFunction>
505 // get domain
506 domain_type& domain = *u->domain().get();
507 // get periodic boundary manager
508 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
509
510 // create Multiindex
511 std::vector<DoFIndex> multInd;
512
514
515 // add boundary subsets to enforce boundary subset computations in geo.update()
516 for(size_t i = 0; i < this->m_turbZeroSg.size(); ++i){
517 geo.add_boundary_subset(this->m_turbZeroSg[i]);
518 }
519
520 // set attachment values to zero
521 SetAttachmentValues(aaDefTensor , u->template begin<Vertex>(), u->template end<Vertex>(), 0);
522 SetAttachmentValues(aaVol , u->template begin<Vertex>(), u->template end<Vertex>(), 0);
523
524 // coord and vertex array
527
528 // get position accessor
529 typedef typename domain_type::position_accessor_type position_accessor_type;
530 const position_accessor_type& posAcc = domain.position_accessor();
531
532 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
533 // get iterators
534 ElemIterator iter = u->template begin<elem_type>(si);
535 ElemIterator iterEnd = u->template end<elem_type>(si);
536
537 // loop elements of dimension
538 for( ;iter !=iterEnd; ++iter)
539 {
540 // get Elem
541 elem_type* elem = *iter;
542 // get vertices and extract corner coordinates
543 const size_t numVertices = elem->num_vertices();
544 for(size_t i = 0; i < numVertices; ++i){
545 vVrt[i] = elem->vertex(i);
546 coCoord[i] = posAcc[vVrt[i]];
547 };
548
549 // evaluate finite volume geometry
550 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
551
552 static const size_t MaxNumVerticesOfElem = 10;
553
554 typedef MathVector<dim> MVD;
555 std::vector<MVD> uValue(MaxNumVerticesOfElem);
556 MVD ipVelocity;
557
558 size_t noc = elem->num_vertices();
559
560 size_t nip = geo.num_scvf();
561
562 for (size_t co=0;co < noc;co++)
563 {
564 const typename DimFV1Geometry<dim>::SCV& scv = geo.scv(co);
565 for (int d=0;d<dim;d++){
566 u->dof_indices(elem->vertex(co), d, multInd);
567 uValue[co][d]=DoFRef(*u,multInd[0]);
568 }
569 aaVol[elem->vertex(co)] += scv.volume();
570 }
571
572 for (size_t ip=0;ip<nip;ip++){
573 // get current SCVF
574 ipVelocity = 0;
575 const typename DimFV1Geometry<dim>::SCVF& scvf = geo.scvf(ip);
576 for (size_t co=0;co < noc;co++){
577 for (int d=0;d<dim;d++){
578 ipVelocity[d] += scvf.shape(co)*uValue[co][d];
579 };
580 };
581 dimMat ipDefTensorFlux;
582 ipDefTensorFlux = 0;
583 for (int i=0;i<dim;i++){
584 for (int j=0;j<dim;j++){
585 ipDefTensorFlux[i][j]= 0.5 * (ipVelocity[i] * scvf.normal()[j] + ipVelocity[j] * scvf.normal()[i]);
586 }
587 }
588 aaDefTensor[elem->vertex(scvf.from())]+=ipDefTensorFlux;
589 aaDefTensor[elem->vertex(scvf.to())]-=ipDefTensorFlux;
590 }
591 for(size_t sgi = 0; sgi < this->m_turbZeroSg.size(); ++sgi){
592 const size_t sgsi=this->m_turbZeroSg[sgi];
593 if (geo.num_bf(sgsi) == 0) continue;
594 for(size_t bfi = 0; bfi < geo.num_bf(sgsi); ++bfi){
595 const typename DimFV1Geometry<dim>::BF& bf = geo.bf(sgsi, bfi);
596 const size_t nodeID = bf.node_id();
597 for (int i=0;i<dim;i++)
598 for (int j=0;j<dim;j++){
599 aaDefTensor[elem->vertex(nodeID)][i][j] += 0.5 * (uValue[nodeID][i] * bf.normal()[j] + uValue[nodeID][j] * bf.normal()[i]);
600 }
601 }
602 }
603 }
604 }
605 // average
606 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
607 VertexIterator vertexIter = u->template begin<Vertex>(si);
608 VertexIterator vertexIterEnd = u->template end<Vertex>(si);
609 for( ;vertexIter !=vertexIterEnd; vertexIter++)
610 {
611 Vertex* vertex = *vertexIter;
612 if (pbm && pbm->is_slave(vertex)) continue;
613 aaDefTensor[vertex]/=(number)aaVol[vertex];
614 }
615 }
616}
617
618template <typename TData, int dim, typename TImpl,typename TGridFunction>
620 // get domain of grid function
621 domain_type& domain = *m_uInfo->domain().get();
622 // get periodic boundary manager
623 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
624 // average
625 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
626 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
627 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
628 for( ;vertexIter !=vertexIterEnd; vertexIter++)
629 {
630 Vertex* vertex = *vertexIter;
631 if (pbm && pbm->is_slave(vertex)) continue;
632 aaTensor[vertex]*=(number)FNorm(aaTensor[vertex]);
633 }
634 }
635}
636
637template <typename TData, int dim, typename TImpl,typename TGridFunction>
639 // get domain of grid function
640 domain_type& domain = *m_uInfo->domain().get();
641 // get periodic boundary manager
642 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
643 // create Multiindex
644 std::vector<DoFIndex> multInd;
645
647
648 // add boundary subsets to enforce boundary subset computations in geo.update()
649 for(size_t i = 0; i < this->m_turbZeroSg.size(); ++i){
650 geo.add_boundary_subset(this->m_turbZeroSg[i]);
651 }
652
653 SetAttachmentValues(aaDefTensor , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
654 SetAttachmentValues(aaVol , m_uInfo->template begin<Vertex>(), m_uInfo->template end<Vertex>(), 0);
655
656 // coord and vertex array
659
660 // get position accessor
661 typedef typename domain_type::position_accessor_type position_accessor_type;
662 const position_accessor_type& posAcc = domain.position_accessor();
663
664 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
665 // get iterators
666 ElemIterator iter = m_uInfo->template begin<elem_type>(si);
667 ElemIterator iterEnd = m_uInfo->template end<elem_type>(si);
668
669 //for debug UG_LOG("|||||||||||||||||||| si = " << si << "\n");
670
671 // loop elements of dimension
672 for( ;iter !=iterEnd; ++iter)
673 {
674 // get Elem
675 elem_type* elem = *iter;
676 // get vertices and extract corner coordinates
677 const size_t numVertices = elem->num_vertices();
678 for(size_t i = 0; i < numVertices; ++i){
679 vVrt[i] = elem->vertex(i);
680 coCoord[i] = posAcc[vVrt[i]];
681 // //for debug UG_LOG("co_coord(" << i<< "+1,:)=" << coCoord[i] << "\n");
682 };
683
684 // evaluate finite volume geometry
685 geo.update(elem, &(coCoord[0]), domain.subset_handler().get());
686
687 static const size_t MaxNumVerticesOfElem = 10;
688
689 typedef MathVector<dim> MVD;
690 std::vector<MVD> uValue(MaxNumVerticesOfElem);
691 MVD ipVelocity;
692
693 UG_ASSERT(dynamic_cast<elem_type*>(elem) != NULL, "Only elements of type elem_type are currently supported");
694
695 size_t noc = elem->num_vertices();
696
697 size_t nip = geo.num_scvf();
698
699 for (size_t co=0;co < noc;co++)
700 {
701 const typename DimFV1Geometry<dim>::SCV& scv = geo.scv(co);
702 uValue[co]=aaU[elem->vertex(co)];
703 //for debug UG_LOG("uvalue(" << s << ")=" << uValue[s] << "\n");
704 aaVol[elem->vertex(co)] += scv.volume();
705 }
706
707 for (size_t ip=0;ip<nip;ip++){
708 // get current SCVF
709 ipVelocity = 0;
710 const typename DimFV1Geometry<dim>::SCVF& scvf = geo.scvf(ip);
711 for (size_t co=0;co < noc;co++){
712 for (int d=0;d<dim;d++){
713 ipVelocity[d] += scvf.shape(co)*uValue[co][d];
714 };
715 };
716 dimMat ipDefTensorFlux;
717 ipDefTensorFlux = 0;
718 for (int d=0;d<dim;d++){
719 for (int j=0;j<dim;j++){
720 ipDefTensorFlux[d][j]= 0.5 * (ipVelocity[d] * scvf.normal()[j] + ipVelocity[j] * scvf.normal()[d]);
721 }
722 }
723 aaDefTensor[elem->vertex(scvf.from())]+=ipDefTensorFlux;
724 aaDefTensor[elem->vertex(scvf.to())]-=ipDefTensorFlux;
725 }
726 for(size_t sgi = 0; sgi < this->m_turbZeroSg.size(); ++sgi){
727 const size_t sgsi=this->m_turbZeroSg[sgi];
728 if (geo.num_bf(sgsi) == 0) continue;
729 for(size_t bfi = 0; bfi < geo.num_bf(sgsi); ++bfi){
730 const typename DimFV1Geometry<dim>::BF& bf = geo.bf(sgsi, bfi);
731 const size_t nodeID = bf.node_id();
732 for (int i=0;i<dim;i++)
733 for (int j=0;j<dim;j++){
734 aaDefTensor[elem->vertex(nodeID)][i][j] += 0.5 * (uValue[nodeID][i] * bf.normal()[j] + uValue[nodeID][j] * bf.normal()[i]);
735 }
736 }
737 }
738 }
739 }
740 // average
741 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
742 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
743 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
744 for( ;vertexIter !=vertexIterEnd; vertexIter++)
745 {
746 Vertex* vertex = *vertexIter;
747 if (pbm && pbm->is_slave(vertex)) continue;
748 aaDefTensor[vertex]/=(number)aaVol[vertex];
749 }
750 }
751}
752
753// Frobenius norm of dim x dim matrix
754template <typename TData, int dim, typename TImpl,typename TGridFunction>
756 number norm=0;
757 for (int d1=0;d1<dim;d1++)
758 for (int d2=0;d2<dim;d2++){
759 norm += M[d1][d2] * M[d1][d2];
760 }
761 return sqrt(2.0*norm);
762}
763
764template <typename TData, int dim, typename TImpl,typename TGridFunction>
766 // get domain of grid function
767 domain_type& domain = *m_uInfo->domain().get();
768 // get periodic boundary manager
769 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
770 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
771 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
772 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
773 for( ;vertexIter !=vertexIterEnd; vertexIter++)
774 {
775 Vertex* vertex = *vertexIter;
776 if (pbm && pbm->is_slave(vertex)) continue;
777 dimMat Tij;
778 for (int d1=0;d1 < dim;d1++)
779 for (int d2=0;d2 < dim;d2++)
780 Tij[d1][d2] = aaU[vertex][d1]*aaU[vertex][d2];
781 Tij*=factor;
782 aaResult[vertex]+=Tij;
783 }
784 }
785}
786
787template <typename TData, int dim, typename TImpl,typename TGridFunction>
789 // get domain of grid function
790 domain_type& domain = *m_uInfo->domain().get();
791 // get periodic boundary manager
792 PeriodicBoundaryManager* pbm = (domain.grid())->periodic_boundary_manager();
793 // create Multiindex
794 std::vector<DoFIndex> multInd;
795
796 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si){
797 VertexIterator vertexIter = m_uInfo->template begin<Vertex>(si);
798 VertexIterator vertexIterEnd = m_uInfo->template end<Vertex>(si);
799 for( ;vertexIter !=vertexIterEnd; vertexIter++)
800 {
801 Vertex* vertex = *vertexIter;
802 if (pbm && pbm->is_slave(vertex)) continue;
803 dimMat Tij;
804 MathVector<dim> uValue;
805 for (int d=0;d<dim;d++){
806 u->dof_indices(vertex, d, multInd);
807 uValue[d]=DoFRef(*u,multInd[0]);
808 }
809 for (int d1=0;d1 < dim;d1++)
810 for (int d2=0;d2 < dim;d2++)
811 Tij[d1][d2] = uValue[d1]*uValue[d2];
812 Tij*=factor;
813 aaResult[vertex]+=Tij;
814 }
815 }
816}
817
818template<typename TGridFunction>
820 // get domain of grid function
821 domain_type& domain = *m_u->domain().get();
822 SetAttachmentValues(m_acTurbulentViscosity, m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
823
824 // coord and vertex array
825// MathVector<dim> coCoord[domain_traits<dim>::MaxNumVerticesOfElem];
826// Vertex* vVrt[domain_traits<dim>::MaxNumVerticesOfElem];
827
828 // assemble deformation tensor fluxes
829 this->assembleDeformationTensor(m_acDeformation,m_acVolume,m_u);
830 // compute turbulent viscosity , loop over vertices
831 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
832 {
833 if ((this->m_turbZeroSg.size()!=0) && (this->m_turbZeroSg.contains(si)==true)) continue;
834 VertexIterator vertexIter = m_u->template begin<Vertex>(si);
835 VertexIterator vertexIterEnd = m_u->template end<Vertex>(si);
836 for( ;vertexIter !=vertexIterEnd; vertexIter++)
837 {
838 // get Elem
839 Vertex* vertex = *vertexIter;
840 if (m_pbm && m_pbm->is_slave(vertex)){
841 continue;
842 }
843 number delta = m_acVolume[vertex];
844 // for possible other choices of delta see Fr�hlich p 160
845 delta = pow(delta,(number)1.0/(number)dim);
846 number tensorNorm = this->FNorm(m_acDeformation[vertex]);
847 m_acTurbulentViscosity[vertex] = m_c * delta*delta * tensorNorm;
848 }
849 }
850 // transfer attachment data to lower levels
851 this->transferToLowerLevels(m_acTurbulentViscosity,*m_spApproxSpace);
852}
853
854template<typename TGridFunction>
856 // get domain of grid function
857 domain_type& domain = *m_u->domain().get();
858
859 // get position accessor
860 // for debug typedef typename domain_type::position_accessor_type position_accessor_type;
861 // for debug const position_accessor_type& posAcc = domain.position_accessor();
862
863 // initialize attachment values with 0
864// SetAttachmentValues(m_acDeformation , m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
865 SetAttachmentValues(m_acTurbulentViscosity, m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
866// SetAttachmentValues(m_acVolume,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
867 SetAttachmentValues(m_acTurbulentC,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
868// SetAttachmentValues(m_acVolumeHat,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
869// SetAttachmentValues(m_acUHat,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
870// SetAttachmentValues(m_acDeformationHat,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
871// SetAttachmentValues(m_acLij,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
872 SetAttachmentValues(m_acMij,m_grid->template begin<Vertex>(), m_grid->template end<Vertex>(), 0);
873
874 // compute Lij term \hat{u_i u_j} - \hat{u_i} \hat{u_j}
875 // \hat{u}
876 this->elementFilter(m_acUHat,m_acVolumeHat,m_u);
877 // use Mij attachment to store first Lij part
878 // u_i u_j
879 this->addUiUjTerm(m_acMij,1.0,m_u);
880 // \hat{u_i u_j}
881 this->elementFilter(m_acLij,m_acVolumeHat,m_acMij);
882 // \hat{u_i u_j} - \hat{u_i} \hat{u_j}
883 this->addUiUjTerm(m_acLij,-1.0,m_acUHat);
884
885 // Mij term
886 // first term |\hat{S}| \hat{S}
887 // assemble \hat{S} using \hat{u}
888 this->assembleDeformationTensor(m_acDeformationHat,m_acVolume,m_acUHat);
889 // normalize \hat{S}
890 this->scaleTensorByNorm(m_acDeformationHat);
891 // Mij second term \hat{|S|S}
892 // compute S
893 this->assembleDeformationTensor(m_acDeformation,m_acVolumeHat,m_u);
894 // compute |S| S
895 this->scaleTensorByNorm(m_acDeformation);
896 // filter |S| S
897 //for debug UG_LOG("------------------------------------------------------\n");
898 this->elementFilter(m_acMij,m_acVolumeHat,m_acDeformation);
899
900 bool use_filter = false;
901
902 // create Multiindex
903 std::vector<DoFIndex> multInd;
904
905 // complete Mij term computation by scaling and adding the two terms,
906 // solve the local least squares problem and compute local c and local turbulent viscosity
907 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
908 {
909 if (use_filter==false)
910 if ((this->m_turbZeroSg.size()!=0) && (this->m_turbZeroSg.contains(si)==true)) continue;
911 VertexIterator vertexIter = m_u->template begin<Vertex>(si);
912 VertexIterator vertexIterEnd = m_u->template end<Vertex>(si);
913 for( ;vertexIter !=vertexIterEnd; vertexIter++){
914 Vertex* vertex = *vertexIter;
915 if (m_pbm && m_pbm->is_slave(vertex)) continue;
916 // use c to compute turbulent viscosity
917 number delta = m_acVolume[vertex];
918 delta = pow(delta,(number)1.0/(number)dim);
919 number deltaHat = m_acVolumeHat[vertex];
920 deltaHat = pow(deltaHat,(number)1.0/(number)dim);
921 m_u->dof_indices(vertex, 0, multInd);
922 m_u->dof_indices(vertex, 1, multInd);
923 m_acDeformationHat[vertex] *= -2*deltaHat*deltaHat;
924 m_acMij[vertex] *= 2*delta*delta;
925 m_acMij[vertex] += m_acDeformationHat[vertex];
926 //for debug UG_LOG("Mij " << FNorm(m_acMij[vertex]) << "\n");
927 for (int d1=0;d1<dim;d1++){
928 for (int d2=0;d2<dim;d2++){
929 //for debug UG_LOG(m_acMij[vertex][d1][d2] << " ");
930 }
931 //for debug UG_LOG("\n");
932 }
933 //for debug UG_LOG("Lij " << FNorm(m_acLij[vertex]) << "\n");
934 for (int d1=0;d1<dim;d1++){
935 for (int d2=0;d2<dim;d2++){
936 //for debug UG_LOG(m_acLij[vertex][d1][d2] << " ");
937 }
938 //for debug UG_LOG("\n");
939 }
940 // compute local c
941 // solve least squares problem
942 number c = 0;
943 for (int d1=0;d1<dim;d1++)
944 for (int d2=0;d2<dim;d2++)
945 c += m_acLij[vertex][d1][d2]*m_acMij[vertex][d1][d2];
946 number denom=0;
947 //for debug UG_LOG("c=" << c << "\n");
948 for (int d1=0;d1<dim;d1++)
949 for (int d2=0;d2<dim;d2++)
950 denom += m_acMij[vertex][d1][d2]*m_acMij[vertex][d1][d2];
951 if (denom>1e-15)
952 c/=(number)denom;
953 else c=0;
954
955 if (m_spaceFilter==false){
956 if (m_timeFilter==false){
957 m_acTurbulentViscosity[vertex] = c * delta*delta * this->FNorm(m_acDeformation[vertex]);
958 } else {
959 m_acTurbulentC[vertex]= (m_timeFilterEps * c + (1-m_timeFilterEps)*m_acTurbulentC[vertex]);
960 m_acTurbulentViscosity[vertex] = m_acTurbulentC[vertex] * delta*delta * this->FNorm(m_acDeformation[vertex]);
961 }
962 if (m_acTurbulentViscosity[vertex]+m_viscosityNumber<m_small) m_acTurbulentViscosity[vertex] = m_viscosityNumber + m_small; }
963 else{
964 // store c in viscosity array
965 m_acTurbulentViscosity[vertex] = c;
966 }
967 }
968 }
969 if (m_spaceFilter==true){
970 // filter c
971 if (m_timeFilter==false)
972 this->elementFilter(m_acTurbulentC,m_acVolumeHat,m_acTurbulentViscosity);
973 else
974 // store c in volumeHat array
975 this->elementFilter(m_acVolumeHat,m_acVolumeHat,m_acTurbulentViscosity);
976 // compute turbulent viscosity
977 for(int si = 0; si < domain.subset_handler()->num_subsets(); ++si)
978 {
979 //for debug UG_LOG("si = " << si << "\n");
980 if ((this->m_turbZeroSg.size()!=0) && (this->m_turbZeroSg.contains(si)==true)) continue;
981 VertexIterator vertexIter = m_u->template begin<Vertex>(si);
982 VertexIterator vertexIterEnd = m_u->template end<Vertex>(si);
983 for( ;vertexIter !=vertexIterEnd; vertexIter++){
984 Vertex* vertex = *vertexIter;
985 if (m_pbm && m_pbm->is_slave(vertex)) continue;
986 number delta = m_acVolume[vertex];
987 delta = pow(delta,(number)1.0/(number)dim);
988 if (m_timeFilter==true)
989 // time averaging, note that c has been stored in m_acVolumeHat
990 m_acTurbulentC[vertex]= (m_timeFilterEps * m_acVolumeHat[vertex] + (1-m_timeFilterEps)*m_acTurbulentC[vertex]);
991 m_acTurbulentViscosity[vertex] = m_acTurbulentC[vertex] * delta*delta * this->FNorm(m_acDeformation[vertex]);
992 if (m_acTurbulentViscosity[vertex]+m_viscosityNumber<m_small) m_acTurbulentViscosity[vertex] = m_viscosityNumber+m_small;
993 //for debug UG_LOG("nu_t = " << m_acTurbulentViscosity[vertex] << " c = " << m_acTurbulentC[vertex] << " delta = " << delta << " co=[" << 0.5*(posAcc[vertex->vertex(0)][0] + posAcc[vertex->vertex(1)][0]) << "," << 0.5*(posAcc[vertex->vertex(0)][1] + posAcc[vertex->vertex(1)][1]) << "]\n");
994 }
995 }
996 }
997}
998
999} // namespace NavierStokes
1000} // end namespace ug
1001
1002#endif /* __H__UG__NAVIER_STOKES_TURBULENT_VISCOSITY_FV1_DATA_IMPL_H_ */
function NavierStokes(fcts, subsets, discType)
T * get()
SmartPtr< TDomain > domain()
size_t node_id() const
const MathVector< worldDim > & normal() const
const MathVector< worldDim > & normal() const
number shape(size_t sh) const
const MathVector< dim > & local_corner(size_t co) const
number volume() const
size_t num_corners() const
const SCVF & scvf(size_t i) const
size_t num_bf() const
void update(GridObject *elem, const MathVector< worldDim > *vCornerCoords, const ISubsetHandler *ish=NULL)
const std::vector< BF > & bf(int si) const
void add_boundary_subset(int subsetIndex)
const SCV & scv(size_t i) const
size_t num_scvf() const
virtual void global_to_local(MathVector< dim > &locPos, const MathVector< worldDim > &globPos, const size_t maxIter=1000, const number tol=1e-10) const=0
SmartPtr< MultiGrid > multi_grid()
size_t num_levels() const
SmartPtr< DoFDistribution > dof_distribution(const GridLevel &gl, bool bCreate=true)
virtual void shapes(std::vector< std::vector< shape_type > > &vvShape, const std::vector< MathVector< dim > > &vLocPos) const=0
void update()
Definition turbulent_viscosity_fv1_impl.h:855
TGridFunction::domain_type domain_type
domain type
Definition turbulent_viscosity_fv1.h:393
TGridFunction::template traits< Vertex >::const_iterator VertexIterator
vertex iterator
Definition turbulent_viscosity_fv1.h:414
TGridFunction::domain_type domain_type
domain type
Definition turbulent_viscosity_fv1.h:205
void update()
Definition turbulent_viscosity_fv1_impl.h:819
TGridFunction::template traits< Vertex >::const_iterator VertexIterator
vertex iterator
Definition turbulent_viscosity_fv1.h:226
domain_type::position_accessor_type position_accessor_type
position accessor type
Definition turbulent_viscosity_fv1.h:70
void fillAttachment(aVertexDimVector &aaU, SmartPtr< TGridFunction > u)
Definition turbulent_viscosity_fv1_impl.h:63
void addUiUjTerm(aVertexTensor &aaDefTensor, const number factor, aVertexDimVector aaU)
Definition turbulent_viscosity_fv1_impl.h:765
void transferToLowerLevels(aVertexNumber &aaData, ApproximationSpace< domain_type > &approximationSpace)
Definition turbulent_viscosity_fv1_impl.h:43
void assembleDeformationTensor(aVertexTensor &aaDefTensor, aVertexNumber &aaVol, SmartPtr< TGridFunction > u)
Definition turbulent_viscosity_fv1_impl.h:504
number FNorm(MathMatrix< dim, dim > M)
Definition turbulent_viscosity_fv1_impl.h:755
TGridFunction::domain_type domain_type
domain type
Definition turbulent_viscosity_fv1.h:64
void elementFilter(PeriodicAttachmentAccessor< Vertex, Attachment< VType > > &aaUHat, aVertexNumber &aaVol, const PeriodicAttachmentAccessor< Vertex, Attachment< VType > > &aaU)
Definition turbulent_viscosity_fv1_impl.h:85
void scaleTensorByNorm(aVertexTensor &aaTensor)
Definition turbulent_viscosity_fv1_impl.h:619
void scvFilter(PeriodicAttachmentAccessor< Vertex, Attachment< VType > > &aaUHat, aVertexNumber &aaVol, const PeriodicAttachmentAccessor< Vertex, Attachment< VType > > &aaU)
Definition turbulent_viscosity_fv1_impl.h:292
TGridFunction::template dim_traits< dim >::const_iterator ElemIterator
element iterator
Definition turbulent_viscosity_fv1.h:79
TGridFunction::template dim_traits< dim >::grid_base_object elem_type
element type
Definition turbulent_viscosity_fv1.h:76
TGridFunction::template traits< Vertex >::const_iterator VertexIterator
vertex iterator
Definition turbulent_viscosity_fv1.h:82
bool is_slave(TElem *) const
SmartPtr< TSubsetHandler > subset_handler()
SmartPtr< TGrid > grid()
size_t num_subsets() const
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
#define UG_ASSERT(expr, msg)
double number
ReferenceObjectID
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)