Plugins
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 
38 namespace ug{
39 namespace NavierStokes{
40 
41 // transfer by injection
42 template <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 
62 template <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
83 template <typename TData, int dim, typename TImpl,typename TGridFunction>
84 template <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
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 
153 
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  }
167  }
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
185 template <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
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
290 template <typename TData, int dim, typename TImpl,typename TGridFunction>
291 template <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
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
391 template <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
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 
503 template <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
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 
618 template <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 
637 template <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
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
754 template <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 
764 template <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 
787 template <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 
818 template<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 
854 template<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)
TGridFunction * get()
SmartPtr< TDomain > domain()
const MathVector< worldDim > & normal() const
number shape(size_t sh) const
number volume() const
const MathVector< dim > & local_corner(size_t co) const
size_t num_corners() const
const std::vector< BF > & bf(int si) const
const SCVF & scvf(size_t i) const
const SCV & scv(size_t i) const
size_t num_bf() const
void update(GridObject *elem, const MathVector< worldDim > *vCornerCoords, const ISubsetHandler *ish=NULL)
void add_boundary_subset(int subsetIndex)
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
Grid::VertexAttachmentAccessor< position_attachment_type > position_accessor_type
SmartPtr< TSubsetHandler > subset_handler()
SmartPtr< TGrid > grid()
static const int dim
size_t num_subsets() const
void SetAttachmentValues(TAttachmentAccessor &aaVal, TIter elemsBegin, TIter elemsEnd, const TVal &val)
#define UG_ASSERT(expr, msg)
double number
const number & DoFRef(const TMatrix &mat, const DoFIndex &iInd, const DoFIndex &jInd)
ReferenceObjectID
SurfaceView::traits< TElem >::const_iterator const_iterator