Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DisContField3DHomogeneous1D.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // File DisContField3DHomogeneous1D.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Field definition for 3D domain with boundary
33 // conditions using LDG flux and a 1D homogeneous direction
34 //
35 ///////////////////////////////////////////////////////////////////////////////
36 
40 
41 
42 namespace Nektar
43 {
44  namespace MultiRegions
45  {
46 
49  m_bndCondExpansions(),
50  m_bndConditions()
51  {
52  }
53 
56  const LibUtilities::BasisKey &HomoBasis,
57  const NekDouble lhom,
58  const bool useFFT,
59  const bool dealiasing)
60  : ExpList3DHomogeneous1D(pSession,HomoBasis,lhom,useFFT,dealiasing),
61  m_bndCondExpansions(),
62  m_bndConditions()
63  {
64  }
65 
68  const bool DeclarePlanesSetCoeffPhys)
69  : ExpList3DHomogeneous1D (In,false),
70  m_bndCondExpansions (In.m_bndCondExpansions),
71  m_bndConditions (In.m_bndConditions)
72  {
73  if (DeclarePlanesSetCoeffPhys)
74  {
75  DisContField2DSharedPtr zero_plane =
76  boost::dynamic_pointer_cast<DisContField2D> (In.m_planes[0]);
77 
78  for(int n = 0; n < m_planes.num_elements(); ++n)
79  {
80  m_planes[n] =
82  AllocateSharedPtr(*zero_plane, false);
83  }
84 
85  SetCoeffPhys();
86  }
87  }
88 
91  const LibUtilities::BasisKey &HomoBasis,
92  const NekDouble lhom,
93  const bool useFFT,
94  const bool dealiasing,
96  const std::string &variable)
97  : ExpList3DHomogeneous1D(pSession, HomoBasis, lhom, useFFT,
98  dealiasing),
99  m_bndCondExpansions(),
100  m_bndConditions()
101  {
102  int i, n, nel;
103  DisContField2DSharedPtr plane_zero;
105 
106  // note that nzplanes can be larger than nzmodes
107  m_planes[0] = plane_zero = MemoryManager<DisContField2D>::
108  AllocateSharedPtr(pSession, graph2D, variable, true, false);
109 
112 
113  nel = m_planes[0]->GetExpSize();
114 
115  for (i = 0; i < nel; ++i)
116  {
117  (*m_exp).push_back(m_planes[0]->GetExp(i));
118  }
119 
120  for (n = 1; n < m_planes.num_elements(); ++n)
121  {
123  AllocateSharedPtr(*plane_zero, graph2D,
124  variable, true, false);
125  for(i = 0; i < nel; ++i)
126  {
127  (*m_exp).push_back((*m_exp)[i]);
128  }
129  }
130 
131  // Set up trace object.
132  Array<OneD, ExpListSharedPtr> trace(m_planes.num_elements());
133  for (n = 0; n < m_planes.num_elements(); ++n)
134  {
135  trace[n] = m_planes[n]->GetTrace();
136  }
137 
139  pSession, HomoBasis, lhom, useFFT, dealiasing, trace);
140 
141  // Setup default optimisation information
142  nel = GetExpSize();
143 
145  AllocateSharedPtr(nel);
146 
147  SetCoeffPhys();
148 
149  // Do not set up BCs if default variable
150  if(variable.compare("DefaultVar") != 0)
151  {
152  SetupBoundaryConditions(HomoBasis, lhom, bcs, variable);
153  }
154 
155  SetUpDG();
156  }
157 
158  /**
159  * @brief Default destructor
160  */
162  {
163  }
164 
166  const LibUtilities::BasisKey &HomoBasis,
167  const NekDouble lhom,
169  const std::string variable)
170  {
171  int n;
172 
173  // Setup an ExpList2DHomogeneous1D expansion for boundary
174  // conditions and link to class declared in m_planes
176  bcs.GetBoundaryRegions();
178  bcs.GetBoundaryConditions();
179  SpatialDomains::BoundaryRegionCollection::const_iterator it;
180 
181  // count the number of non-periodic boundary regions
182  int cnt = 0;
183  for (it = bregions.begin(); it != bregions.end(); ++it)
184  {
185  SpatialDomains::BoundaryConditionShPtr boundaryCondition =
186  GetBoundaryCondition(bconditions, it->first, variable);
187  if (boundaryCondition->GetBoundaryConditionType()
189  {
190  cnt++;
191  }
192  }
193 
195  ExpListSharedPtr>(cnt);
196  m_bndConditions = m_planes[0]->UpdateBndConditions();
197 
198  int nplanes = m_planes.num_elements();
199  Array<OneD, MultiRegions::ExpListSharedPtr>
200  PlanesBndCondExp(nplanes);
201 
202  cnt = 0;
203  for (it = bregions.begin(); it != bregions.end(); ++it)
204  {
205  SpatialDomains::BoundaryConditionShPtr boundaryCondition =
206  GetBoundaryCondition(bconditions, it->first, variable);
207  if(boundaryCondition->GetBoundaryConditionType() !=
209  {
210  for (n = 0; n < nplanes; ++n)
211  {
212  PlanesBndCondExp[n] = m_planes[n]->
214  }
215 
216  m_bndCondExpansions[cnt++] =
218  AllocateSharedPtr(m_session, HomoBasis, lhom,
219  m_useFFT, false,
220  PlanesBndCondExp);
221  }
222  }
223  EvaluateBoundaryConditions(0.0, variable);
224  }
225 
227  const NekDouble time,
228  const std::string varName)
229  {
230  int n;
231  const Array<OneD, const NekDouble> z = m_homogeneousBasis->GetZ();
232  Array<OneD, NekDouble> local_z(m_planes.num_elements());
233 
234  for (n = 0; n < m_planes.num_elements(); n++)
235  {
236  local_z[n] = z[m_transposition->GetPlaneID(n)];
237  }
238 
239  for (n = 0; n < m_planes.num_elements(); ++n)
240  {
241  m_planes[n]->EvaluateBoundaryConditions(
242  time, varName, 0.5*m_lhom*(1.0+local_z[n]));
243  }
244 
245  // Fourier transform coefficient space boundary values
246  // This will only be undertaken for time dependent
247  // boundary conditions unless time == 0.0 which is the
248  // case when the method is called from the constructor.
249  for (n = 0; n < m_bndCondExpansions.num_elements(); ++n)
250  {
251  if (time == 0.0 || m_bndConditions[n]->GetUserDefined() ==
253  {
254  m_bndCondExpansions[n]->HomogeneousFwdTrans(
257  }
258  }
259  }
260 
262  const Array<OneD, const NekDouble> &inarray,
263  Array<OneD, NekDouble> &outarray,
264  const FlagList &flags,
265  const StdRegions::ConstFactorMap &factors,
266  const StdRegions::VarCoeffMap &varcoeff,
267  const Array<OneD, const NekDouble> &dirForcing)
268  {
269  int n;
270  int cnt = 0;
271  int cnt1 = 0;
272  NekDouble beta;
273  StdRegions::ConstFactorMap new_factors;
274 
275  Array<OneD, NekDouble> e_out;
276  Array<OneD, NekDouble> fce(inarray.num_elements());
277 
278  // Transform forcing function in half-physical space if required
279  if (m_WaveSpace)
280  {
281  fce = inarray;
282  }
283  else
284  {
285  HomogeneousFwdTrans(inarray,fce);
286  }
287 
288  for (n = 0; n < m_planes.num_elements(); ++n)
289  {
290  if (n != 1 || m_transposition->GetK(n) != 0)
291  {
292  beta = 2*M_PI*(m_transposition->GetK(n))/m_lhom;
293  new_factors = factors;
294  // add in Homogeneous Fourier direction and SVV if turned on
295  new_factors[StdRegions::eFactorLambda] +=
296  beta*beta*(1+GetSpecVanVisc(n));
297  m_planes[n]->HelmSolve(
298  fce + cnt,
299  e_out = outarray + cnt1,
300  flags, new_factors, varcoeff, dirForcing);
301  }
302 
303  cnt += m_planes[n]->GetTotPoints();
304  cnt1 += m_planes[n]->GetNcoeffs();
305  }
306  }
307 
309  const NekDouble time,
310  const std::string varName,
311  const NekDouble x2_in,
312  const NekDouble x3_in)
313  {
314  EvaluateBoundaryConditions(time, varName);
315  }
316 
317  boost::shared_ptr<ExpList> &DisContField3DHomogeneous1D::
319  {
320  return UpdateBndCondExpansion(i);
321  }
322 
323  Array<OneD, SpatialDomains::BoundaryConditionShPtr>
325  {
326  return UpdateBndConditions();
327  }
328 
330  Array<OneD, int> &ElmtID,
331  Array<OneD,int> &EdgeID)
332  {
333 
334  if(m_BCtoElmMap.num_elements() == 0)
335  {
336  Array<OneD, int> ElmtID_tmp;
337  Array<OneD, int> EdgeID_tmp;
338 
339  m_planes[0]->GetBoundaryToElmtMap(ElmtID_tmp, EdgeID_tmp);
340  int nel_per_plane = m_planes[0]->GetExpSize();
341  int nplanes = m_planes.num_elements();
342 
343  int MapSize = ElmtID_tmp.num_elements();
344 
345  ElmtID = Array<OneD, int>(nplanes*MapSize);
346  EdgeID = Array<OneD, int>(nplanes*MapSize);
347 
348  // If this mesh (or partition) has no BCs, skip this step
349  if (MapSize > 0)
350  {
351  for(int i = 0; i < nplanes; i++)
352  {
353  for(int j = 0; j < MapSize; j++)
354  {
355  ElmtID[j+i*MapSize] = ElmtID_tmp[j]+i*nel_per_plane;
356  EdgeID[j+i*MapSize] = EdgeID_tmp[j];
357  }
358  }
359  m_BCtoElmMap = Array<OneD, int>(nplanes*MapSize);
360  m_BCtoEdgMap = Array<OneD, int>(nplanes*MapSize);
361 
362  Vmath::Vcopy(nplanes*MapSize,ElmtID,1,m_BCtoElmMap,1);
363  Vmath::Vcopy(nplanes*MapSize,EdgeID,1,m_BCtoEdgMap,1);
364  }
365  }
366  else
367  {
368  int MapSize = m_BCtoElmMap.num_elements();
369 
370  ElmtID = Array<OneD, int>(MapSize);
371  EdgeID = Array<OneD, int>(MapSize);
372 
373  Vmath::Vcopy(MapSize, m_BCtoElmMap, 1, ElmtID, 1);
374  Vmath::Vcopy(MapSize, m_BCtoEdgMap, 1, EdgeID, 1);
375  }
376  }
377 
379  Array<OneD, NekDouble> &BndVals,
380  const Array<OneD, NekDouble> &TotField,
381  int BndID)
382  {
385 
386  Array<OneD, const NekDouble> tmp_Tot;
387  Array<OneD, NekDouble> tmp_BC;
388 
389  int cnt = 0;
390  int pos = 0;
391  int exp_size, exp_size_per_plane, elmtID, boundaryID;
392  int offset, exp_dim;
393 
394  for (int k = 0; k < m_planes.num_elements(); k++)
395  {
396  for (int n = 0; n < m_bndConditions.num_elements(); ++n)
397  {
398  exp_size = m_bndCondExpansions[n]->GetExpSize();
399  exp_size_per_plane = exp_size/m_planes.num_elements();
400 
401  for (int i = 0; i < exp_size_per_plane; i++)
402  {
403  if(n == BndID)
404  {
405  elmtID = m_BCtoElmMap[cnt];
406  boundaryID = m_BCtoEdgMap[cnt];
407  exp_dim = m_bndCondExpansions[n]->
408  GetExp(i+k*exp_size_per_plane)->GetTotPoints();
409  offset = GetPhys_Offset(elmtID);
410  elmt = GetExp(elmtID);
411  temp_BC_exp = boost::dynamic_pointer_cast<
413  m_bndCondExpansions[n]->GetExp(
414  i+k*exp_size_per_plane));
415 
416  elmt->GetEdgePhysVals(boundaryID, temp_BC_exp,
417  tmp_Tot = TotField + offset,
418  tmp_BC = BndVals + pos);
419  pos += exp_dim;
420  }
421  cnt++;
422  }
423  }
424  }
425  }
426 
428  Array<OneD, const NekDouble> &V1,
429  Array<OneD, const NekDouble> &V2,
430  Array<OneD, NekDouble> &outarray,
431  int BndID)
432  {
435 
436  Array<OneD, NekDouble> tmp_V1;
437  Array<OneD, NekDouble> tmp_V2;
438  Array<OneD, NekDouble> tmp_outarray;
439 
440  int cnt = 0;
441  int exp_size, exp_size_per_plane, elmtID, Phys_offset, Coef_offset;
442 
443  for(int k = 0; k < m_planes.num_elements(); k++)
444  {
445  for(int n = 0; n < m_bndConditions.num_elements(); ++n)
446  {
447  exp_size = m_bndCondExpansions[n]->GetExpSize();
448  exp_size_per_plane = exp_size/m_planes.num_elements();
449 
450  for(int i = 0; i < exp_size_per_plane; i++)
451  {
452  if(n == BndID)
453  {
454  elmtID = m_BCtoElmMap[cnt];
455 
456  Phys_offset = m_bndCondExpansions[n]->
457  GetPhys_Offset(i+k*exp_size_per_plane);
458  Coef_offset = m_bndCondExpansions[n]->
459  GetCoeff_Offset(i+k*exp_size_per_plane);
460 
461  elmt = GetExp(elmtID);
462  temp_BC_exp = boost::dynamic_pointer_cast<
464  m_bndCondExpansions[n]->GetExp(
465  i+k*exp_size_per_plane));
466 
467  temp_BC_exp->NormVectorIProductWRTBase(
468  tmp_V1 = V1 + Phys_offset,
469  tmp_V2 = V2 + Phys_offset,
470  tmp_outarray = outarray + Coef_offset);
471  }
472  cnt++;
473  }
474  }
475  }
476  }
477 
479  Array<OneD, NekDouble> &outarray)
480  {
481  ASSERTL1(m_physState == true,
482  "Field must be in physical state to extract trace space.");
483 
484  v_ExtractTracePhys(m_phys, outarray);
485  }
486 
487  /**
488  * @brief This method extracts the trace (edges in 2D) for each plane
489  * from the field @a inarray and puts the values in @a outarray.
490  *
491  * It assumes the field is C0 continuous so that it can overwrite the
492  * edge data when visited by the two adjacent elements.
493  *
494  * @param inarray An array containing the 2D data from which we wish
495  * to extract the edge data.
496  * @param outarray The resulting edge information.
497  */
499  const Array<OneD, const NekDouble> &inarray,
500  Array<OneD, NekDouble> &outarray)
501  {
502  int nPoints_plane = m_planes[0]->GetTotPoints();
503  int nTracePts = m_planes[0]->GetTrace()->GetTotPoints();
504 
505  for (int i = 0; i < m_planes.num_elements(); ++i)
506  {
507  Array<OneD, NekDouble> inarray_plane(nPoints_plane, 0.0);
508  Array<OneD, NekDouble> outarray_plane(nPoints_plane, 0.0);
509 
510  Vmath::Vcopy(nPoints_plane,
511  &inarray[i*nPoints_plane], 1,
512  &inarray_plane[0], 1);
513 
514  m_planes[i]->ExtractTracePhys(inarray_plane, outarray_plane);
515 
516  Vmath::Vcopy(nTracePts,
517  &outarray_plane[0], 1,
518  &outarray[i*nTracePts], 1);
519  }
520  }
521 
522  /**
523  * @brief Set up all DG member variables and maps.
524  */
526  {
527  const int nPlanes = m_planes.num_elements();
528  const int nTracePlane = m_planes[0]->GetTrace()->GetExpSize();
529 
530  // Get trace map from first plane.
531  AssemblyMapDGSharedPtr traceMap = m_planes[0]->GetTraceMap();
532  const Array<OneD, const int> &traceBndMap
533  = traceMap->GetBndCondTraceToGlobalTraceMap();
534  int mapSize = traceBndMap.num_elements();
535 
536  // Set up trace boundary map
537  m_traceBndMap = Array<OneD, int>(nPlanes * mapSize);
538 
539  int i, n, e, cnt = 0, cnt1 = 0;
540 
541  for (i = 0; i < m_bndCondExpansions.num_elements(); ++i)
542  {
543  int nExp = m_bndCondExpansions[i]->GetExpSize();
544  int nPlaneExp = nExp / nPlanes;
545 
546  for (n = 0; n < nPlanes; ++n)
547  {
548  const int offset = n * nTracePlane;
549  for (e = 0; e < nPlaneExp; ++e)
550  {
551  m_traceBndMap[cnt++] = offset + traceBndMap[cnt1+e];
552  }
553  }
554 
555  cnt1 += nPlaneExp;
556  }
557  }
558  } // end of namespace
559 } //end of namespace