Nektar++
Loading...
Searching...
No Matches
ALEHelper.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: ALEHelper.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// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Helper class for ALE process
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include "ALEHelper.h"
38
39namespace Nektar::SolverUtils
40{
41
43 [[maybe_unused]] int spaceDim,
44 [[maybe_unused]] Array<OneD, MultiRegions::ExpListSharedPtr> &fields)
45{
46}
47
49 [[maybe_unused]] int spaceDim,
50 [[maybe_unused]] Array<OneD, MultiRegions::ExpListSharedPtr> &fields)
51{
52 // Create ALE objects for each interface zone
53 if (fields[0]->GetGraph() !=
54 nullptr) // homogeneous graphs are missing the graph data
55 {
56 for (auto &zone : fields[0]->GetGraph()->GetMovement()->GetZones())
57 {
58 switch (zone.second->GetMovementType())
59 {
61 m_ALEs.emplace_back(ALEFixedShPtr(
63 zone.second)));
64 break;
66 m_ALEs.emplace_back(ALETranslateShPtr(
68 zone.second)));
69 m_ALESolver = true;
70 break;
72 m_ALEs.emplace_back(ALERotateShPtr(
74 zone.second)));
75 m_ALESolver = true;
76 break;
78 WARNINGL0(false,
79 "Zone cannot have movement type of 'None'.");
80 default:
81 break;
82 }
83 }
84 }
85
86 // Update grid velocity
88
89 // Updates trace grid velocity
90 for (int i = 0; i < m_gridVelocityTrace.size(); ++i)
91 {
92 m_fieldsALE[0]->ExtractTracePhys(m_gridVelocity[i],
93 m_gridVelocityTrace[i], true);
94 }
95}
96
98{
99
100 // Reset grid velocity to 0
101 for (int i = 0; i < m_spaceDim; ++i)
102 {
103 std::fill(m_gridVelocity[i].begin(), m_gridVelocity[i].end(), 0.0);
104 }
105 if (m_ALESolver)
106 {
107 // Now update for each movement zone, adding the grid velocities
108 for (auto &ALE : m_ALEs)
109 {
110 ALE->UpdateGridVel(time, m_fieldsALE, m_gridVelocity);
111 }
112 }
113}
114
117{
118 const int nm = m_fieldsALE[0]->GetNcoeffs();
120
121 // Premultiply each field by the mass matrix
122 for (int i = 0; i < m_fieldsALE.size(); ++i)
123 {
124 fields[i] = Array<OneD, NekDouble>(nm);
125 m_fieldsALE[i]->GeneralMatrixOp(mkey, m_fieldsALE[i]->GetCoeffs(),
126 fields[i]);
127 }
128}
129
130/**
131* @brief Update m_fields with u^n by multiplying by inverse mass
132 matrix. That's then used in e.g. checkpoint output and L^2 error
133 calculation.
134*/
136 [[maybe_unused]] Array<OneD, Array<OneD, NekDouble>> &traceNormals,
138 [[maybe_unused]] NekDouble time)
139{
140 // @TODO: Look at geometric factor and junk only what is needed
141 // @TODO: Look at collections and see if they offer a speed up
142 for (int i = 0; i < m_fieldsALE.size(); ++i)
143 {
144 m_fieldsALE[i]->MultiplyByElmtInvMass(
145 fields[i],
146 m_fieldsALE[i]->UpdateCoeffs()); // @TODO: Potentially matrix free?
147 m_fieldsALE[i]->BwdTrans(m_fieldsALE[i]->GetCoeffs(),
148 m_fieldsALE[i]->UpdatePhys());
149 }
150}
151
153 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
155{
156 const int nc = m_fieldsALE[0]->GetNcoeffs();
157 int nVariables = inarray.size();
158
159 // General idea is that we are time-integrating the quantity (Mu), so we
160 // need to multiply input by inverse mass matrix to get coefficients u,
161 // and then backwards transform to physical space so we can apply the DG
162 // operator.
164 for (int i = 0; i < nVariables; ++i)
165 {
166 outarray[i] = Array<OneD, NekDouble>(m_fieldsALE[0]->GetNpoints());
167 m_fieldsALE[i]->MultiplyByElmtInvMass(inarray[i], tmp);
168 m_fieldsALE[i]->BwdTrans(tmp, outarray[i]);
169 }
170}
171
173 Array<OneD, Array<OneD, NekDouble>> &traceNormals)
174{
175 // Only move if timestepped
176 if (time == m_prevStageTime)
177 {
178 return;
179 }
180
181 auto curvedEdges = m_fieldsALE[0]->GetGraph()->GetCurvedEdges();
182 auto curvedFaces = m_fieldsALE[0]->GetGraph()->GetCurvedFaces();
183
185 timer.Start();
186 m_fieldsALE[0]->GetGraph()->GetMovement()->PerformMovement(
187 time); // @TODO: Moved out of loop!
188 timer.Stop();
189 timer.AccumulateRegion("Movement::PerformMovement");
190
191 ResetMatricesNormal(traceNormals);
193 // Recompute grid velocity.
195
196 // Updates trace grid velocity
197 for (int i = 0; i < m_gridVelocityTrace.size(); ++i)
198 {
199 m_fieldsALE[0]->ExtractTracePhys(m_gridVelocity[i],
200 m_gridVelocityTrace[i], true);
201 }
202
203 // Set the flag to exchange coords in InterfaceMapDG to true
204 m_fieldsALE[0]->GetGraph()->GetMovement()->GetCoordExchangeFlag() = true;
205
206 m_prevStageTime = time;
207}
208
210 Array<OneD, Array<OneD, NekDouble>> &traceNormals)
211{
212 // Now update matrices and normal for each movement zone
213 for (auto &ALE : m_ALEs)
214 {
215 ALE->ResetMatricesNormal(traceNormals, m_fieldsALE);
216 }
217}
218
220{
221 // check all update nromal definitions and return true if any are true
222 for (auto &ALE : m_ALEs)
223 {
224 if (ALE->UpdateNormalsFlag())
225 {
226 m_updateNormals = ALE->UpdateNormalsFlag();
227 break;
228 }
229 }
230}
231
237
239 : m_zone(std::static_pointer_cast<SpatialDomains::ZoneFixed>(zone))
240{
241}
242
244 [[maybe_unused]] NekDouble time,
245 [[maybe_unused]] Array<OneD, MultiRegions::ExpListSharedPtr> &fields,
246 [[maybe_unused]] Array<OneD, Array<OneD, NekDouble>> &gridVelocity)
247{
248}
249
251 [[maybe_unused]] Array<OneD, Array<OneD, NekDouble>> &traceNormals,
252 [[maybe_unused]] Array<OneD, MultiRegions::ExpListSharedPtr> &fields)
253{
254}
255
257 : m_zone(std::static_pointer_cast<SpatialDomains::ZoneTranslate>(zone))
258{
259}
260
262 [[maybe_unused]] NekDouble time,
264 Array<OneD, Array<OneD, NekDouble>> &gridVelocity)
265{
266 auto vel = m_zone->GetVel(time);
267 auto exp = fields[0]->GetExp();
268
269 auto elements = m_zone->GetElements();
270 for (auto &el : elements)
271 {
272 int indx = fields[0]->GetElmtToExpId(el->GetGlobalID());
273 int offset = fields[0]->GetPhys_Offset(indx);
274 auto expansion = (*exp)[indx];
275
276 int nq = expansion->GetTotPoints();
277 for (int i = 0; i < nq; ++i)
278 {
279 for (int j = 0; j < gridVelocity.size(); ++j)
280 {
281 gridVelocity[j][offset + i] += vel[j];
282 }
283 }
284 }
285}
286
288 [[maybe_unused]] Array<OneD, Array<OneD, NekDouble>> &traceNormals,
290{
291 auto curvedEdges = fields[0]->GetGraph()->GetCurvedEdges();
292 auto curvedFaces = fields[0]->GetGraph()->GetCurvedFaces();
293
294 // The order of the resets below is v important to avoid errors
295 if (m_meshDistorted)
296 {
297 for (auto &field : fields)
298 {
299 field->ResetMatrices();
300 }
301 }
302
303 // Loop over all elements and faces and edges and reset geometry
304 // information. Only need to do this on the first field as the geometry
305 // information is shared.
306
307 if (m_zone->GetMoved())
308 {
309 auto conEl = m_zone->GetConstituentElements();
310 for (const auto &i : conEl)
311 {
312 for (const auto &j : i)
313 {
314 j->ResetNonRecursive(curvedEdges, curvedFaces);
315 }
316 }
317
318 // We need to rebuild geometric factors on the trace elements
319 for (const auto &i : conEl[fields[0]->GetShapeDimension() -
320 1]) // This only takes the trace elements
321 {
322 fields[0]->GetTrace()->GetExpFromGeomId(i->GetGlobalID())->Reset();
323 }
324 }
325
326 if (m_zone->GetMoved())
327 {
328 auto conEl = m_zone->GetConstituentElements();
329 // Loop over zone elements expansions and rebuild geometric
330 // factors
331 for (const auto &i :
332 conEl[0]) // This only takes highest dimensioned elements
333 {
334 fields[0]->GetExpFromGeomId(i->GetGlobalID())->Reset();
335 }
336 }
337
338 for (auto &field : fields)
339 {
340 // Reset collections (despite the default being eNoCollection it does
341 // remember the last auto-tuned values), eNoImpType gives lots of output
342 field->CreateCollections(Collections::eNoCollection);
343 }
344}
345
347 : m_zone(std::static_pointer_cast<SpatialDomains::ZoneRotate>(zone))
348{
349}
350
352 [[maybe_unused]] NekDouble time,
353 [[maybe_unused]] Array<OneD, MultiRegions::ExpListSharedPtr> &fields,
354 [[maybe_unused]] Array<OneD, Array<OneD, NekDouble>> &gridVelocity)
355{
356
357 auto angVel = m_zone->GetAngularVel(time);
358 auto axis = m_zone->GetAxis();
359 auto origin = m_zone->GetOrigin();
360
361 auto exp = fields[0]->GetExp();
362
363 auto elements = m_zone->GetElements();
364 for (auto &el : elements)
365 {
366 int indx = fields[0]->GetElmtToExpId(el->GetGlobalID());
367 int offset = fields[0]->GetPhys_Offset(indx);
368 auto expansion = (*exp)[indx];
369
370 int nq = expansion->GetTotPoints();
371
372 Array<OneD, NekDouble> xc(nq, 0.0), yc(nq, 0.0), zc(nq, 0.0);
373 Array<OneD, NekDouble> norm(3, 0.0);
374 expansion->GetCoords(xc, yc, zc);
375 for (int i = 0; i < nq; ++i)
376 {
377 // Vector from origin to point
378 NekDouble xpointMinOrigin = xc[i] - origin(0);
379 NekDouble ypointMinOrigin = yc[i] - origin(1);
380 NekDouble zpointMinOrigin = zc[i] - origin(2);
381
382 // Vector orthogonal to plane formed by axis and point
383 // We negate angVel here as by convention a positive angular
384 // velocity is counter-clockwise
385 norm[0] = (ypointMinOrigin * axis[2] - zpointMinOrigin * axis[1]) *
386 (-angVel);
387 norm[1] = (zpointMinOrigin * axis[0] - xpointMinOrigin * axis[2]) *
388 (-angVel);
389 norm[2] = (xpointMinOrigin * axis[1] - ypointMinOrigin * axis[0]) *
390 (-angVel);
391 for (int j = 0; j < gridVelocity.size(); ++j)
392 {
393 gridVelocity[j][offset + i] = norm[j];
394 }
395 }
396 }
397}
398
400 Array<OneD, Array<OneD, NekDouble>> &traceNormals,
402{
403
404 auto curvedEdges = fields[0]->GetGraph()->GetCurvedEdges();
405 auto curvedFaces = fields[0]->GetGraph()->GetCurvedFaces();
406
407 // The order of the resets below is v important to avoid errors
408 if (m_meshDistorted)
409 {
410 for (auto &field : fields)
411 {
412 field->ResetMatrices();
413 }
414 }
415
416 // Loop over all elements and faces and edges and reset geometry
417 // information. Only need to do this on the first field as the geometry
418 // information is shared.
419 if (m_zone->GetMoved() && m_zone->v_GetAngle() != 0)
420 {
421 auto conEl = m_zone->GetConstituentElements();
422 for (const auto &i : conEl)
423 {
424 for (const auto &j : i)
425 {
426 j->ResetNonRecursive(curvedEdges, curvedFaces);
427 }
428 }
429
430 // We need to rebuild geometric factors on the trace elements
431 for (const auto &i : conEl[fields[0]->GetShapeDimension() -
432 1]) // This only takes the trace elements
433 {
434 fields[0]->GetTrace()->GetExpFromGeomId(i->GetGlobalID())->Reset();
435 }
436 }
437
438 if (m_zone->GetMoved() && m_zone->v_GetAngle() != 0)
439 {
440 auto conEl = m_zone->GetConstituentElements();
441 // Loop over zone elements expansions and rebuild geometric
442 // factors
443 for (const auto &i :
444 conEl[0]) // This only takes highest dimensioned elements
445 {
446 fields[0]->GetExpFromGeomId(i->GetGlobalID())->Reset();
447 }
448 }
449
450 if (m_zone->GetMoved() && m_zone->v_GetAngle() != 0)
451 {
452 auto conEl = m_zone->GetConstituentElements();
453 // Loop over zone elements expansions and rebuild geometric factors
454 // and recalc trace normals
455 for (const auto &i :
456 conEl[0]) // This only takes highest dimensioned elements
457 {
458 int nfaces =
459 fields[0]->GetExpFromGeomId(i->GetGlobalID())->GetNtraces();
460 for (int j = 0; j < nfaces; ++j)
461 {
462 fields[0]
463 ->GetExpFromGeomId(i->GetGlobalID())
464 ->ComputeTraceNormal(j);
465 }
466 }
467 }
468
469 for (auto &field : fields)
470 {
471 // Reset collections (despite the default being eNoCollection it does
472 // remember the last auto-tuned values), eNoImpType gives lots of output
473 field->CreateCollections(Collections::eNoCollection);
474 }
475
476 // Reload new trace normals in to the solver cache
477 fields[0]->GetTrace()->GetNormals(traceNormals);
478}
479
481 std::vector<Array<OneD, NekDouble>> &fieldcoeffs,
482 std::vector<std::string> &variables)
483
484{
485 int nCoeffs = m_fieldsALE[0]->GetNcoeffs();
486 // Adds extra output variables for grid velocity
487 std::string gridVarName[3] = {"gridVx", "gridVy", "gridVz"};
488 for (int i = 0; i < m_spaceDim; ++i)
489 {
490 Array<OneD, NekDouble> gridVel(nCoeffs, 0.0);
491 m_fieldsALE[0]->FwdTransLocalElmt(m_gridVelocity[i], gridVel);
492 fieldcoeffs.emplace_back(gridVel);
493 variables.emplace_back(gridVarName[i]);
494 }
495}
496
498 std::vector<Array<OneD, NekDouble>> &fieldcoeffs,
499 std::vector<std::string> &variables)
500
501{
502 int nCoeffs = m_fieldsALE[0]->GetNcoeffs();
503 int nPhys = m_fieldsALE[0]->GetTotPoints();
504 // Adds extra output variables for grid velocity
505 std::string gridXName[3] = {"gridX", "gridY", "gridZ"};
507 for (int i = 0; i < m_spaceDim; ++i)
508 {
509 Xc[i] = Array<OneD, NekDouble>(nPhys, 0.0);
510 }
511
512 switch (m_spaceDim)
513 {
514 case 1:
515 {
516 m_fieldsALE[0]->GetCoords(Xc[0]);
517 break;
518 }
519 case 2:
520 {
521 m_fieldsALE[0]->GetCoords(Xc[0], Xc[1]);
522 break;
523 }
524 case 3:
525 {
526 m_fieldsALE[0]->GetCoords(Xc[0], Xc[1], Xc[2]);
527 break;
528 }
529 }
530
531 for (int i = 0; i < m_spaceDim; ++i)
532 {
533 Array<OneD, NekDouble> coeffs(nCoeffs);
534 m_fieldsALE[0]->FwdTransLocalElmt(Xc[i], coeffs);
535 fieldcoeffs.emplace_back(coeffs);
536 variables.emplace_back(gridXName[i]);
537 }
538}
539
540} // namespace Nektar::SolverUtils
#define WARNINGL0(condition, msg)
void AccumulateRegion(std::string, int iolevel=0)
Accumulate elapsed time for a region.
Definition Timer.cpp:70
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
Describes a matrix with ordering defined by a local to global map.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fieldsALE
Definition ALEHelper.h:140
SOLVER_UTILS_EXPORT void UpdateNormalsFlag()
virtual SOLVER_UTILS_EXPORT void v_ALEPreMultiplyMass(Array< OneD, Array< OneD, NekDouble > > &fields)
SOLVER_UTILS_EXPORT void ExtraFldOutputGrid(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables)
virtual SOLVER_UTILS_EXPORT void v_ALEInitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields)
Definition ALEHelper.cpp:42
SOLVER_UTILS_EXPORT void ALEDoElmtInvMass(Array< OneD, Array< OneD, NekDouble > > &traceNormals, Array< OneD, Array< OneD, NekDouble > > &fields, NekDouble time)
Update m_fields with u^n by multiplying by inverse mass matrix. That's then used in e....
SOLVER_UTILS_EXPORT void InitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields)
Definition ALEHelper.cpp:48
Array< OneD, Array< OneD, NekDouble > > m_gridVelocityTrace
Definition ALEHelper.h:142
SOLVER_UTILS_EXPORT void ALEDoElmtInvMassBwdTrans(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
SOLVER_UTILS_EXPORT void ResetMatricesNormal(Array< OneD, Array< OneD, NekDouble > > &traceNormals)
SOLVER_UTILS_EXPORT void ExtraFldOutputGridVelocity(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables)
SOLVER_UTILS_EXPORT void MoveMesh(const NekDouble &time, Array< OneD, Array< OneD, NekDouble > > &traceNormals)
virtual SOLVER_UTILS_EXPORT void v_UpdateGridVelocity(const NekDouble &time)
Definition ALEHelper.cpp:97
SOLVER_UTILS_EXPORT const Array< OneD, const Array< OneD, NekDouble > > & GetGridVelocityTrace()
Array< OneD, Array< OneD, NekDouble > > m_gridVelocity
Definition ALEHelper.h:141
std::vector< ALEBaseShPtr > m_ALEs
Definition ALEHelper.h:143
std::shared_ptr< ALETranslate > ALETranslateShPtr
Definition ALEHelper.h:225
std::shared_ptr< ALERotate > ALERotateShPtr
Definition ALEHelper.h:226
std::shared_ptr< ALEFixed > ALEFixedShPtr
Definition ALEHelper.h:224
std::shared_ptr< ZoneBase > ZoneBaseShPtr
Definition Zones.h:177
STL namespace.
void v_UpdateGridVel(const NekDouble time, Array< OneD, MultiRegions::ExpListSharedPtr > &fields, Array< OneD, Array< OneD, NekDouble > > &gridVelocity) final
ALEFixed(SpatialDomains::ZoneBaseShPtr zone)
void v_ResetMatricesNormal(Array< OneD, Array< OneD, NekDouble > > &traceNormals, Array< OneD, MultiRegions::ExpListSharedPtr > &fields) final
SpatialDomains::ZoneRotateShPtr m_zone
Definition ALEHelper.h:221
void v_ResetMatricesNormal(Array< OneD, Array< OneD, NekDouble > > &traceNormals, Array< OneD, MultiRegions::ExpListSharedPtr > &fields) final
ALERotate(SpatialDomains::ZoneBaseShPtr zone)
void v_UpdateGridVel(const NekDouble time, Array< OneD, MultiRegions::ExpListSharedPtr > &fields, Array< OneD, Array< OneD, NekDouble > > &gridVelocity) final
SpatialDomains::ZoneTranslateShPtr m_zone
Definition ALEHelper.h:199
ALETranslate(SpatialDomains::ZoneBaseShPtr zone)
void v_ResetMatricesNormal(Array< OneD, Array< OneD, NekDouble > > &traceNormals, Array< OneD, MultiRegions::ExpListSharedPtr > &fields) final
void v_UpdateGridVel(const NekDouble time, Array< OneD, MultiRegions::ExpListSharedPtr > &fields, Array< OneD, Array< OneD, NekDouble > > &gridVelocity) final