Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
Nektar::SolverUtils::FilterAeroForces Class Reference

#include <FilterAeroForces.h>

Inheritance diagram for Nektar::SolverUtils::FilterAeroForces:
[legend]

Public Member Functions

SOLVER_UTILS_EXPORT FilterAeroForces (const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const std::map< std::string, std::string > &pParams)
 
SOLVER_UTILS_EXPORT ~FilterAeroForces () override
 
SOLVER_UTILS_EXPORT void GetForces (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, NekDouble > &Aeroforces, const NekDouble &time)
 
SOLVER_UTILS_EXPORT void GetMoments (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, Array< OneD, NekDouble > &moments, const NekDouble &time)
 
- Public Member Functions inherited from Nektar::SolverUtils::Filter
SOLVER_UTILS_EXPORT Filter (const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation)
 
virtual SOLVER_UTILS_EXPORT ~Filter ()
 
SOLVER_UTILS_EXPORT void Initialise (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
 
SOLVER_UTILS_EXPORT void Update (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
 
SOLVER_UTILS_EXPORT void Finalise (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
 
SOLVER_UTILS_EXPORT bool IsTimeDependent ()
 

Static Public Member Functions

static FilterSharedPtr create (const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const std::map< std::string, std::string > &pParams)
 Creates an instance of this class. More...
 

Static Public Attributes

static std::string className
 Name of the class. More...
 

Protected Member Functions

void v_Initialise (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time) override
 
void v_Update (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time) override
 
void v_Finalise (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time) override
 
bool v_IsTimeDependent () override
 
virtual void v_Initialise (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)=0
 
virtual void v_Update (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)=0
 
virtual void v_Finalise (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)=0
 
virtual bool v_IsTimeDependent ()=0
 

Private Member Functions

void CalculateForces (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
 
void CalculateForcesMapping (const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
 

Private Attributes

std::vector< unsigned int > m_boundaryRegionsIdList
 ID's of boundary regions where we want the forces. More...
 
std::vector< bool > m_boundaryRegionIsInList
 Determines if a given Boundary Region is in m_boundaryRegionsIdList. More...
 
unsigned int m_index
 
unsigned int m_outputFrequency
 
bool m_outputAllPlanes
 if using a homogeneous1D expansion, determine if should output all planes or just the average More...
 
bool m_isHomogeneous1D
 
std::string m_outputFile
 
std::ofstream m_outputStream
 
LibUtilities::BasisSharedPtr m_homogeneousBasis
 
std::string m_BoundaryString
 
Array< OneD, int > m_BCtoElmtID
 
Array< OneD, int > m_BCtoTraceID
 
int m_nPlanes
 number of planes for homogeneous1D expansion More...
 
Array< OneD, int > m_planesID
 
NekDouble m_startTime
 
Array< OneD, Array< OneD, NekDouble > > m_directions0
 
Array< OneD, Array< OneD, NekDouble > > m_directions
 
Array< OneD, NekDoublem_pivotPoint
 
Array< OneD, Array< OneD, NekDouble > > m_Fpplane
 
Array< OneD, Array< OneD, NekDouble > > m_Fvplane
 
Array< OneD, Array< OneD, NekDouble > > m_Ftplane
 
Array< OneD, NekDoublem_Fp
 
Array< OneD, NekDoublem_Fv
 
Array< OneD, NekDoublem_Ft
 
Array< OneD, NekDoublem_Mp
 
Array< OneD, NekDoublem_Mv
 
Array< OneD, NekDoublem_Mt
 
Array< OneD, Array< OneD, NekDouble > > m_Mpplane
 
Array< OneD, Array< OneD, NekDouble > > m_Mvplane
 
Array< OneD, Array< OneD, NekDouble > > m_Mtplane
 
NekDouble m_lastTime
 
GlobalMapping::MappingSharedPtr m_mapping
 

Friends

class MemoryManager< FilterAeroForces >
 

Additional Inherited Members

- Public Types inherited from Nektar::SolverUtils::Filter
typedef std::map< std::string, std::string > ParamMap
 
- Protected Attributes inherited from Nektar::SolverUtils::Filter
LibUtilities::SessionReaderSharedPtr m_session
 
const std::weak_ptr< EquationSystemm_equ
 

Detailed Description

Definition at line 51 of file FilterAeroForces.h.

Constructor & Destructor Documentation

◆ FilterAeroForces()

Nektar::SolverUtils::FilterAeroForces::FilterAeroForces ( const LibUtilities::SessionReaderSharedPtr pSession,
const std::weak_ptr< EquationSystem > &  pEquation,
const std::map< std::string, std::string > &  pParams 
)

Definition at line 58 of file FilterAeroForces.cpp.

61 : Filter(pSession, pEquation)
62{
63 // OutputFile
64 auto it = pParams.find("OutputFile");
65 if (it == pParams.end())
66 {
67 m_outputFile = m_session->GetSessionName();
68 }
69 else
70 {
71 ASSERTL0(it->second.length() > 0, "Missing parameter 'OutputFile'.");
72 m_outputFile = it->second;
73 }
74
75 if (!(m_outputFile.length() >= 4 &&
76 m_outputFile.substr(m_outputFile.length() - 4) == ".fce"))
77 {
78 m_outputFile += ".fce";
79 }
80
81 // OutputFrequency
82 it = pParams.find("OutputFrequency");
83 if (it == pParams.end())
84 {
86 }
87 else
88 {
89 LibUtilities::Equation equ(m_session->GetInterpreter(), it->second);
90 m_outputFrequency = round(equ.Evaluate());
91 }
92
93 // Time after which we need to calculate the forces
94 it = pParams.find("StartTime");
95 if (it == pParams.end())
96 {
97 m_startTime = 0;
98 }
99 else
100 {
101 LibUtilities::Equation equ(m_session->GetInterpreter(), it->second);
102 m_startTime = equ.Evaluate();
103 }
104
105 // For 3DH1D, OutputAllPlanes or just average forces?
106 m_session->MatchSolverInfo("Homogeneous", "1D", m_isHomogeneous1D, false);
108 {
109 it = pParams.find("OutputAllPlanes");
110 if (it == pParams.end())
111 {
112 m_outputAllPlanes = false;
113 }
114 else
115 {
116 std::string sOption = it->second.c_str();
117 m_outputAllPlanes = (boost::iequals(sOption, "true")) ||
118 (boost::iequals(sOption, "yes"));
119 }
120 }
121 else
122 {
123 m_outputAllPlanes = false;
124 }
125
126 // Boundary (to calculate forces on)
127 it = pParams.find("Boundary");
128 ASSERTL0(it != pParams.end(), "Missing parameter 'Boundary");
129 ASSERTL0(it->second.length() > 0, "Empty parameter 'Boundary'.");
130 m_BoundaryString = it->second;
131
132 //
133 // Directions (to project forces)
134 //
135
136 // Allocate m_directions and m_directions0
137 // m_directions0 is to save the original direction defined by the user
138 // and projected every time to the new orientation which is then be saved
139 // in the m_direction, note if moving reference frame is not being used,
140 // m_directions and m_directions0 will be the same
141 m_directions = Array<OneD, Array<OneD, NekDouble>>(3);
142 m_directions0 = Array<OneD, Array<OneD, NekDouble>>(3);
143 // Initialise directions to default values (ex, ey, ez)
144 for (int i = 0; i < 3; ++i)
145 {
146 m_directions[i] = Array<OneD, NekDouble>(3, 0.0);
147 m_directions[i][i] = 1.0;
148
149 m_directions0[i] = Array<OneD, NekDouble>(3, 0.0);
150 m_directions0[i][i] = 1.0;
151 }
152 std::stringstream directionStream;
153 std::string directionString;
154 // Override with input from xml file (if defined)
155 for (int i = 0; i < 3; ++i)
156 {
157 std::stringstream tmp;
158 tmp << i + 1;
159 std::string dir = "Direction" + tmp.str();
160 it = pParams.find(dir);
161 if (it != pParams.end())
162 {
163 ASSERTL0(!(it->second.empty()), "Missing parameter '" + dir + "'.");
164 directionStream.str(it->second);
165 // Guarantee the stream is in its start position
166 // before extracting
167 directionStream.clear();
168 // normalisation factor
169 NekDouble norm = 0.0;
170 for (int j = 0; j < 3; j++)
171 {
172 directionStream >> directionString;
173 if (!directionString.empty())
174 {
175 LibUtilities::Equation equ(m_session->GetInterpreter(),
176 directionString);
177 m_directions[i][j] = equ.Evaluate();
178 norm += m_directions[i][j] * m_directions[i][j];
179 }
180 }
181 // Normalise direction
182 for (int j = 0; j < 3; j++)
183 {
184 m_directions[i][j] /= sqrt(norm);
185 }
186 }
187 }
188
189 for (int i = 0; i < 3; ++i)
190 {
191 for (int j = 0; j < 3; ++j)
192 {
193 m_directions0[i][j] = m_directions[i][j];
194 }
195 }
196
197 // Point around which we compute the moments (default to the origin)
198 m_pivotPoint = Array<OneD, NekDouble>(3, 0.0);
199 it = pParams.find("PivotPoint");
200 if (it == pParams.end())
201 {
202 it = pParams.find("MomentPoint");
203 }
204
205 if (it != pParams.end())
206 {
207 ASSERTL0(!(it->second.empty()), "Missing parameter 'PivotPoint'.");
208 std::stringstream pivotPointStream;
209 std::string pivotPointString;
210 pivotPointStream.str(it->second);
211
212 for (int j = 0; j < 3; ++j)
213 {
214 pivotPointStream >> pivotPointString;
215 if (!pivotPointString.empty())
216 {
217 LibUtilities::Equation equ(m_session->GetInterpreter(),
218 pivotPointString);
219 m_pivotPoint[j] = equ.Evaluate();
220 }
221 }
222 }
223}
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
Array< OneD, NekDouble > m_pivotPoint
bool m_outputAllPlanes
if using a homogeneous1D expansion, determine if should output all planes or just the average
Array< OneD, Array< OneD, NekDouble > > m_directions
Array< OneD, Array< OneD, NekDouble > > m_directions0
LibUtilities::SessionReaderSharedPtr m_session
Definition: Filter.h:83
SOLVER_UTILS_EXPORT Filter(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation)
Definition: Filter.cpp:45
double NekDouble
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294

References ASSERTL0, Nektar::LibUtilities::Equation::Evaluate(), m_BoundaryString, m_directions, m_directions0, m_isHomogeneous1D, m_outputAllPlanes, m_outputFile, m_outputFrequency, m_pivotPoint, Nektar::SolverUtils::Filter::m_session, m_startTime, and tinysimd::sqrt().

◆ ~FilterAeroForces()

Nektar::SolverUtils::FilterAeroForces::~FilterAeroForces ( )
override

Definition at line 228 of file FilterAeroForces.cpp.

229{
230}

Member Function Documentation

◆ CalculateForces()

void Nektar::SolverUtils::FilterAeroForces::CalculateForces ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
const NekDouble time 
)
private

This function calculates the forces

Definition at line 755 of file FilterAeroForces.cpp.

758{
759 // Store time so we can check if result is up-to-date
760 m_lastTime = time;
761
762 // If a mapping is defined, call specific function
763 // Note: CalculateForcesMapping should work without a mapping,
764 // but since it is not very efficient the way it is now,
765 // it is only used when actually required
766 if (m_mapping->IsDefined())
767 {
768 CalculateForcesMapping(pFields, time);
769 return;
770 }
771
772 // Lock equation system weak pointer
773 auto equ = m_equ.lock();
774 ASSERTL0(equ, "Weak pointer expired");
775
776 auto fluidEqu = std::dynamic_pointer_cast<FluidInterface>(equ);
777 ASSERTL0(fluidEqu, "Aero forces filter is incompatible with this solver.");
778
779 // update the direction vectors
780 // only effective if we use moving reference frame
781 {
782 bnu::matrix<NekDouble> projMat = bnu::identity_matrix<NekDouble>(3, 3);
783 // get the projection matrix to transform between moving frame and
784 // inertial stationary frame
785 // note: it will be unity in case we are not using the moving frame
786 fluidEqu->GetMovingFrameProjectionMat(projMat);
787 // update the direction vectors
788 // loop over the directions (ex, ey, ez)
789 for (int idir = 0; idir < 3; ++idir)
790 {
791 bnu::vector<NekDouble> v0 = bnu::zero_vector<NekDouble>(3);
792 bnu::vector<NekDouble> v1 = bnu::zero_vector<NekDouble>(3);
793 // copy the directions
794 for (int j = 0; j < 3; ++j)
795 {
796 v0(j) = m_directions0[idir][j];
797 }
798
799 v1 = bnu::prec_prod(projMat, v0);
800 // update the direction matrix
801 for (int j = 0; j < 3; ++j)
802 {
803 m_directions[idir][j] = v1(j);
804 }
805 }
806 }
807
808 int cnt, elmtid, nq, offset, boundary;
809 // Get number of quadrature points and dimensions
810 int physTot = pFields[0]->GetNpoints();
811 int expdim = pFields[0]->GetGraph()->GetMeshDimension();
812 int momdim = (expdim == 2) ? 1 : 3;
813 int nVel = expdim;
815 {
816 nVel = nVel + 1;
817 }
818
820
821 // Fields used to calculate forces (a single plane for 3DH1D)
822 Array<OneD, MultiRegions::ExpListSharedPtr> fields(pFields.size());
823
824 // Arrays of variables in field
825 Array<OneD, Array<OneD, NekDouble>> physfields(pFields.size());
826 Array<OneD, Array<OneD, NekDouble>> velocity(nVel);
827 Array<OneD, NekDouble> pressure;
828
829 // Arrays of variables in the element
830 Array<OneD, Array<OneD, NekDouble>> velElmt(expdim);
831 Array<OneD, NekDouble> pElmt(physTot);
832
833 // Velocity gradient
834 Array<OneD, Array<OneD, NekDouble>> grad(expdim * expdim);
835 Array<OneD, NekDouble> div;
836
837 Array<OneD, Array<OneD, NekDouble>> coords(3);
838
839 // Values at the boundary
840 Array<OneD, NekDouble> Pb;
841 Array<OneD, Array<OneD, NekDouble>> gradb(expdim * expdim);
842 Array<OneD, Array<OneD, NekDouble>> coordsb(3);
843
844 // Communicators to exchange results
845 LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
846 LibUtilities::CommSharedPtr rowComm = vComm->GetRowComm();
848 m_session->DefinesSolverInfo("HomoStrip")
849 ? vComm->GetColumnComm()->GetColumnComm()
850 : vComm->GetColumnComm();
851
852 // Arrays with forces in each plane
853 m_Fp = Array<OneD, NekDouble>(expdim, 0.0);
854 m_Fv = Array<OneD, NekDouble>(expdim, 0.0);
855 m_Ft = Array<OneD, NekDouble>(expdim, 0.0);
856 m_Mp = Array<OneD, NekDouble>(momdim, 0.0);
857 m_Mv = Array<OneD, NekDouble>(momdim, 0.0);
858 m_Mt = Array<OneD, NekDouble>(momdim, 0.0);
859
860 m_Fpplane = Array<OneD, Array<OneD, NekDouble>>(expdim);
861 m_Fvplane = Array<OneD, Array<OneD, NekDouble>>(expdim);
862 m_Ftplane = Array<OneD, Array<OneD, NekDouble>>(expdim);
863 for (int i = 0; i < expdim; i++)
864 {
865 m_Fpplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
866 m_Fvplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
867 m_Ftplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
868 }
869
870 // Arrays with moments in each plane
871 m_Mpplane = Array<OneD, Array<OneD, NekDouble>>(momdim);
872 m_Mvplane = Array<OneD, Array<OneD, NekDouble>>(momdim);
873 m_Mtplane = Array<OneD, Array<OneD, NekDouble>>(momdim);
874 for (int i = 0; i < momdim; ++i)
875 {
876 m_Mpplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
877 m_Mvplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
878 m_Mtplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
879 }
880
881 // Forces per element length in a boundary
882 Array<OneD, Array<OneD, NekDouble>> fp(expdim);
883 Array<OneD, Array<OneD, NekDouble>> fv(expdim);
884
885 // Moments per element length in a boundary
886 Array<OneD, Array<OneD, NekDouble>> mp(momdim);
887 Array<OneD, Array<OneD, NekDouble>> mv(momdim);
888
889 // Get viscosity
890 NekDouble mu{1}, rho{1.};
891 if (m_session->DefinesParameter("Kinvis"))
892 {
893 rho = (m_session->DefinesParameter("rho"))
894 ? (m_session->GetParameter("rho"))
895 : 1;
896 mu = rho * m_session->GetParameter("Kinvis");
897 }
898 else
899 {
900 mu = m_session->GetParameter("mu");
901 }
902 NekDouble lambda = -2.0 / 3.0;
903
904 // Perform BwdTrans: when we only want the mean force in a 3DH1D
905 // we work in wavespace, otherwise we use physical space
906 for (int i = 0; i < pFields.size(); ++i)
907 {
909 {
910 pFields[i]->SetWaveSpace(false);
911 }
912 pFields[i]->BwdTrans(pFields[i]->GetCoeffs(), pFields[i]->UpdatePhys());
913 pFields[i]->SetPhysState(true);
914 }
915
916 // Define boundary expansions
917 Array<OneD, const SpatialDomains::BoundaryConditionShPtr> BndConds;
918 Array<OneD, MultiRegions::ExpListSharedPtr> BndExp;
920 {
921 BndConds = pFields[0]->GetPlane(0)->GetBndConditions();
922 BndExp = pFields[0]->GetPlane(0)->GetBndCondExpansions();
923 }
924 else
925 {
926 BndConds = pFields[0]->GetBndConditions();
927 BndExp = pFields[0]->GetBndCondExpansions();
928 }
929
930 // For Homogeneous, calculate force on each 2D plane
931 // Otherwise, m_nPlanes = 1, and loop only runs once
932 for (int plane = 0; plane < m_nPlanes; plane++)
933 {
934 // Check if plane is in this proc
935 if (m_planesID[plane] != -1)
936 {
937 // For Homogeneous, consider the 2D expansion
938 // on the current plane
940 {
941 for (int n = 0; n < pFields.size(); n++)
942 {
943 fields[n] = pFields[n]->GetPlane(m_planesID[plane]);
944 }
945 }
946 else
947 {
948 for (int n = 0; n < pFields.size(); n++)
949 {
950 fields[n] = pFields[n];
951 }
952 }
953
954 // Get velocity and pressure values
955 for (int n = 0; n < physfields.size(); ++n)
956 {
957 physfields[n] = fields[n]->GetPhys();
958 }
959 for (int n = 0; n < nVel; ++n)
960 {
961 velocity[n] = Array<OneD, NekDouble>(fields[n]->GetTotPoints());
962 }
963 pressure = Array<OneD, NekDouble>(fields[0]->GetTotPoints());
964 fluidEqu->GetVelocity(physfields, velocity);
965 fluidEqu->GetPressure(physfields, pressure);
966
967 // Loop all the Boundary Regions
968 for (int n = cnt = 0; n < BndConds.size(); n++)
969 {
970 if (m_boundaryRegionIsInList[n] == 1)
971 {
972 for (int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++)
973 {
974 elmtid = m_BCtoElmtID[cnt];
975 elmt = fields[0]->GetExp(elmtid);
976 nq = elmt->GetTotPoints();
977 offset = fields[0]->GetPhys_Offset(elmtid);
978
979 // Extract fields on this element
980 for (int j = 0; j < expdim; j++)
981 {
982 velElmt[j] = velocity[j] + offset;
983 }
984 pElmt = pressure + offset;
985
986 // Compute the velocity gradients
987 div = Array<OneD, NekDouble>(nq, 0.0);
988 for (int j = 0; j < expdim; j++)
989 {
990 for (int k = 0; k < expdim; k++)
991 {
992 grad[j * expdim + k] =
993 Array<OneD, NekDouble>(nq, 0.0);
994 elmt->PhysDeriv(k, velElmt[j],
995 grad[j * expdim + k]);
996
997 if (j == k)
998 {
999 Vmath::Vadd(nq, grad[j * expdim + k], 1,
1000 div, 1, div, 1);
1001 }
1002 }
1003 }
1004 // Scale div by lambda (for compressible flows)
1005 Vmath::Smul(nq, lambda, div, 1, div, 1);
1006
1007 // Get Coordinates
1008 for (int j = 0; j < 3; ++j)
1009 {
1010 coords[j] = Array<OneD, NekDouble>(nq, 0.0);
1011 }
1012 elmt->GetCoords(coords[0], coords[1], coords[2]);
1013
1014 // identify boundary of element
1015 boundary = m_BCtoTraceID[cnt];
1016
1017 // Dimension specific part for obtaining values
1018 // at boundary and normal vector
1019 Array<OneD, Array<OneD, NekDouble>> normals =
1020 elmt->GetTraceNormal(boundary);
1021
1022 // Get expansion on boundary
1024 BndExp[n]->GetExp(i);
1025
1026 // Get number of points on the boundary
1027 int nbc = bc->GetTotPoints();
1028
1029 // Extract values at boundary
1030 Pb = Array<OneD, NekDouble>(nbc, 0.0);
1031 elmt->GetTracePhysVals(boundary, bc, pElmt, Pb);
1032
1033 for (int j = 0; j < expdim * expdim; ++j)
1034 {
1035 gradb[j] = Array<OneD, NekDouble>(nbc, 0.0);
1036 elmt->GetTracePhysVals(boundary, bc, grad[j],
1037 gradb[j]);
1038 }
1039
1040 for (int j = 0; j < 3; ++j)
1041 {
1042 coordsb[j] = Array<OneD, NekDouble>(nbc, 0.0);
1043 elmt->GetTracePhysVals(boundary, bc, coords[j],
1044 coordsb[j]);
1045
1046 // subtract m_pivotPoint
1047 Vmath::Sadd(nbc, -1.0 * m_pivotPoint[j], coordsb[j],
1048 1, coordsb[j], 1);
1049 }
1050
1051 // Calculate forces per unit length
1052
1053 // Pressure component: fp[j] = rho* p*n[j]
1054 for (int j = 0; j < expdim; j++)
1055 {
1056 fp[j] = Array<OneD, NekDouble>(nbc, 0.0);
1057 Vmath::Vmul(nbc, Pb, 1, normals[j], 1, fp[j], 1);
1058 Vmath::Smul(nbc, rho, fp[j], 1, fp[j], 1);
1059 }
1060
1061 // Viscous component:
1062 // fv[j] = -mu*{(grad[k,j]+grad[j,k]) *n[k]}
1063 for (int j = 0; j < expdim; j++)
1064 {
1065 fv[j] = Array<OneD, NekDouble>(nbc, 0.0);
1066 for (int k = 0; k < expdim; k++)
1067 {
1068 Vmath::Vvtvp(nbc, gradb[k * expdim + j], 1,
1069 normals[k], 1, fv[j], 1, fv[j], 1);
1070 Vmath::Vvtvp(nbc, gradb[j * expdim + k], 1,
1071 normals[k], 1, fv[j], 1, fv[j], 1);
1072 }
1073 if (!fluidEqu->HasConstantDensity())
1074 {
1075 // Add gradient term
1076 Vmath::Vvtvp(nbc, div, 1, normals[j], 1, fv[j],
1077 1, fv[j], 1);
1078 }
1079 Vmath::Smul(nbc, -mu, fv[j], 1, fv[j], 1);
1080 }
1081
1082 // calculate moments per unit length
1083 if (momdim == 1)
1084 {
1085
1086 mp[0] = Array<OneD, NekDouble>(nbc, 0.0);
1087 mv[0] = Array<OneD, NekDouble>(nbc, 0.0);
1088
1089 Array<OneD, NekDouble> fptmp(nbc, 0.0);
1090 Array<OneD, NekDouble> fvtmp(nbc, 0.0);
1091 Vmath::Smul(nbc, -1.0, fp[0], 1, fptmp, 1);
1092 Vmath::Smul(nbc, -1.0, fv[0], 1, fvtmp, 1);
1093
1094 // Mz = Fy * x - Fx * y
1095 Vmath::Vvtvvtp(nbc, fp[1], 1, coordsb[0], 1, fptmp,
1096 1, coordsb[1], 1, mp[0], 1);
1097
1098 Vmath::Vvtvvtp(nbc, fv[1], 1, coordsb[0], 1, fvtmp,
1099 1, coordsb[1], 1, mv[0], 1);
1100 }
1101 else
1102 {
1103 Array<OneD, NekDouble> fptmp(nbc, 0.0);
1104 Array<OneD, NekDouble> fvtmp(nbc, 0.0);
1105
1106 // Mx = Fz * y - Fy * z
1107 mp[0] = Array<OneD, NekDouble>(nbc, 0.0);
1108 mv[0] = Array<OneD, NekDouble>(nbc, 0.0);
1109
1110 Vmath::Smul(nbc, -1.0, fp[1], 1, fptmp, 1);
1111 Vmath::Smul(nbc, -1.0, fv[1], 1, fvtmp, 1);
1112 Vmath::Vvtvvtp(nbc, fp[2], 1, coordsb[1], 1, fptmp,
1113 1, coordsb[2], 1, mp[0], 1);
1114 Vmath::Vvtvvtp(nbc, fv[2], 1, coordsb[1], 1, fvtmp,
1115 1, coordsb[2], 1, mv[0], 1);
1116 // My = Fx * z - Fz * x
1117 mp[1] = Array<OneD, NekDouble>(nbc, 0.0);
1118 mv[1] = Array<OneD, NekDouble>(nbc, 0.0);
1119
1120 Vmath::Smul(nbc, -1.0, fp[2], 1, fptmp, 1);
1121 Vmath::Smul(nbc, -1.0, fv[2], 1, fvtmp, 1);
1122 Vmath::Vvtvvtp(nbc, fp[0], 1, coordsb[2], 1, fptmp,
1123 1, coordsb[0], 1, mp[1], 1);
1124 Vmath::Vvtvvtp(nbc, fv[0], 1, coordsb[2], 1, fvtmp,
1125 1, coordsb[0], 1, mv[1], 1);
1126 // Mz = Fy * x - Fx * y
1127 mp[2] = Array<OneD, NekDouble>(nbc, 0.0);
1128 mv[2] = Array<OneD, NekDouble>(nbc, 0.0);
1129
1130 Vmath::Smul(nbc, -1.0, fp[0], 1, fptmp, 1);
1131 Vmath::Smul(nbc, -1.0, fv[0], 1, fvtmp, 1);
1132 Vmath::Vvtvvtp(nbc, fp[1], 1, coordsb[0], 1, fptmp,
1133 1, coordsb[1], 1, mp[2], 1);
1134 Vmath::Vvtvvtp(nbc, fv[1], 1, coordsb[0], 1, fvtmp,
1135 1, coordsb[1], 1, mv[2], 1);
1136 }
1137
1138 // Integrate to obtain force
1139 for (int j = 0; j < expdim; j++)
1140 {
1141 m_Fpplane[j][plane] +=
1142 BndExp[n]->GetExp(i)->Integral(fp[j]);
1143 m_Fvplane[j][plane] +=
1144 BndExp[n]->GetExp(i)->Integral(fv[j]);
1145 }
1146 for (int j = 0; j < momdim; ++j)
1147 {
1148 m_Mpplane[j][plane] +=
1149 BndExp[n]->GetExp(i)->Integral(mp[j]);
1150 m_Mvplane[j][plane] +=
1151 BndExp[n]->GetExp(i)->Integral(mv[j]);
1152 }
1153 }
1154 }
1155 else
1156 {
1157 cnt += BndExp[n]->GetExpSize();
1158 }
1159 }
1160 }
1161 }
1162
1163 // Combine contributions from different processes
1164 // this is split between row and col comm because of
1165 // homostrips case, which only keeps its own strip
1166 for (int i = 0; i < expdim; i++)
1167 {
1168 rowComm->AllReduce(m_Fpplane[i], LibUtilities::ReduceSum);
1169 colComm->AllReduce(m_Fpplane[i], LibUtilities::ReduceSum);
1170
1171 rowComm->AllReduce(m_Fvplane[i], LibUtilities::ReduceSum);
1172 colComm->AllReduce(m_Fvplane[i], LibUtilities::ReduceSum);
1173 }
1174 for (int i = 0; i < momdim; ++i)
1175 {
1176 rowComm->AllReduce(m_Mpplane[i], LibUtilities::ReduceSum);
1177 colComm->AllReduce(m_Mpplane[i], LibUtilities::ReduceSum);
1178
1179 rowComm->AllReduce(m_Mvplane[i], LibUtilities::ReduceSum);
1180 colComm->AllReduce(m_Mvplane[i], LibUtilities::ReduceSum);
1181 }
1182
1183 // Pass force (computatonal frame) to FluidInterface (required for
1184 // MovingReferenceFrame)
1185 Array<OneD, NekDouble> aeroforces(6, 0.);
1186 for (size_t i = 0; i < m_Ft.size(); ++i)
1187 {
1188 aeroforces[i] = (Vmath::Vsum(m_nPlanes, m_Fpplane[i], 1) +
1190 m_nPlanes;
1191 }
1192 for (size_t i = 0; i < m_Mt.size(); ++i)
1193 {
1194 int j = m_Mt.size() - 1 - i;
1195 aeroforces[5 - i] = (Vmath::Vsum(m_nPlanes, m_Mpplane[j], 1) +
1197 m_nPlanes;
1198 }
1199 fluidEqu->SetAeroForce(aeroforces);
1200
1201 // Project results to new directions
1202 for (int plane = 0; plane < m_nPlanes; plane++)
1203 {
1204 Array<OneD, NekDouble> tmpP(expdim, 0.0);
1205 Array<OneD, NekDouble> tmpV(expdim, 0.0);
1206 for (int i = 0; i < expdim; i++)
1207 {
1208 for (int j = 0; j < expdim; j++)
1209 {
1210 tmpP[i] += m_Fpplane[j][plane] * m_directions[i][j];
1211 tmpV[i] += m_Fvplane[j][plane] * m_directions[i][j];
1212 }
1213 }
1214 // Copy result
1215 for (int i = 0; i < expdim; i++)
1216 {
1217 m_Fpplane[i][plane] = tmpP[i];
1218 m_Fvplane[i][plane] = tmpV[i];
1219 }
1220
1221 // Project moments only in 3D, since 2D moment is always in z direction
1222 if (momdim == 3)
1223 {
1224 for (int i = 0; i < 3; ++i)
1225 {
1226 tmpP[i] = 0.0;
1227 tmpV[i] = 0.0;
1228 for (int j = 0; j < 3; ++j)
1229 {
1230 tmpP[i] += m_Mpplane[j][plane] * m_directions[i][j];
1231 tmpV[i] += m_Mvplane[j][plane] * m_directions[i][j];
1232 }
1233 }
1234 // Copy result
1235 for (int i = 0; i < 3; ++i)
1236 {
1237 m_Mpplane[i][plane] = tmpP[i];
1238 m_Mvplane[i][plane] = tmpV[i];
1239 }
1240 }
1241 }
1242
1243 // Sum viscous and pressure components
1244 for (int plane = 0; plane < m_nPlanes; plane++)
1245 {
1246 for (int i = 0; i < expdim; i++)
1247 {
1248 m_Ftplane[i][plane] = m_Fpplane[i][plane] + m_Fvplane[i][plane];
1249 }
1250
1251 if (momdim == 3)
1252 {
1253 for (int i = 0; i < 3; ++i)
1254 {
1255 m_Mtplane[i][plane] = m_Mpplane[i][plane] + m_Mvplane[i][plane];
1256 }
1257 }
1258 else
1259 {
1260 m_Mtplane[0][plane] = m_Mpplane[0][plane] + m_Mvplane[0][plane];
1261 }
1262 }
1263
1264 // combine planes
1265 for (int i = 0; i < expdim; i++)
1266 {
1269 m_Ft[i] = m_Fp[i] + m_Fv[i];
1270 }
1271 for (int i = 0; i < momdim; i++)
1272 {
1275 m_Mt[i] = m_Mp[i] + m_Mv[i];
1276 }
1277
1278 // Put results back to wavespace, if necessary
1280 {
1281 for (int i = 0; i < pFields.size(); ++i)
1282 {
1283 pFields[i]->SetWaveSpace(true);
1284 pFields[i]->HomogeneousFwdTrans(pFields[i]->GetTotPoints(),
1285 pFields[i]->GetPhys(),
1286 pFields[i]->UpdatePhys());
1287 }
1288 }
1289}
Array< OneD, Array< OneD, NekDouble > > m_Fvplane
int m_nPlanes
number of planes for homogeneous1D expansion
void CalculateForcesMapping(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
std::vector< bool > m_boundaryRegionIsInList
Determines if a given Boundary Region is in m_boundaryRegionsIdList.
Array< OneD, Array< OneD, NekDouble > > m_Mpplane
GlobalMapping::MappingSharedPtr m_mapping
Array< OneD, Array< OneD, NekDouble > > m_Ftplane
Array< OneD, Array< OneD, NekDouble > > m_Mtplane
Array< OneD, Array< OneD, NekDouble > > m_Fpplane
Array< OneD, Array< OneD, NekDouble > > m_Mvplane
const std::weak_ptr< EquationSystem > m_equ
Definition: Filter.h:84
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:55
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:66
const std::vector< NekDouble > velocity
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.hpp:72
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.hpp:366
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.hpp:608
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.hpp:180
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.hpp:100
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
Definition: Vmath.hpp:194
void Vvtvvtp(int n, const T *v, int incv, const T *w, int incw, const T *x, int incx, const T *y, int incy, T *z, int incz)
vvtvvtp (vector times vector plus vector times vector):
Definition: Vmath.hpp:439

References ASSERTL0, CalculateForcesMapping(), m_BCtoElmtID, m_BCtoTraceID, m_boundaryRegionIsInList, m_directions, m_directions0, Nektar::SolverUtils::Filter::m_equ, m_Fp, m_Fpplane, m_Ft, m_Ftplane, m_Fv, m_Fvplane, m_isHomogeneous1D, m_lastTime, m_mapping, m_Mp, m_Mpplane, m_Mt, m_Mtplane, m_Mv, m_Mvplane, m_nPlanes, m_outputAllPlanes, m_pivotPoint, m_planesID, Nektar::SolverUtils::Filter::m_session, CG_Iterations::pressure, Nektar::LibUtilities::ReduceSum, Vmath::Sadd(), Vmath::Smul(), Vmath::Vadd(), Nektar::MovementTests::velocity, Vmath::Vmul(), Vmath::Vsum(), Vmath::Vvtvp(), and Vmath::Vvtvvtp().

Referenced by GetForces(), GetMoments(), and v_Update().

◆ CalculateForcesMapping()

void Nektar::SolverUtils::FilterAeroForces::CalculateForcesMapping ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
const NekDouble time 
)
private

This function calculates the forces when we have a mapping defining a coordinate system transformation

Definition at line 1295 of file FilterAeroForces.cpp.

1298{
1299 int cnt, elmtid, offset, boundary;
1300 // Get number of quadrature points and dimensions
1301 int physTot = pFields[0]->GetNpoints();
1302 int expdim = pFields[0]->GetGraph()->GetMeshDimension();
1303 int momdim = (expdim == 2) ? 1 : 3;
1304 int nVel = expdim;
1306 {
1307 nVel = nVel + 1;
1308 }
1309
1311
1312 // Pressure stress tensor
1313 // (global, in a plane, in element and boundary)
1314 Array<OneD, MultiRegions::ExpListSharedPtr> P(nVel * nVel);
1315 Array<OneD, MultiRegions::ExpListSharedPtr> PPlane(nVel * nVel);
1316 Array<OneD, Array<OneD, NekDouble>> PElmt(nVel * nVel);
1317 Array<OneD, Array<OneD, NekDouble>> PBnd(nVel * nVel);
1318 // Velocity gradient
1319 Array<OneD, MultiRegions::ExpListSharedPtr> grad(nVel * nVel);
1320 Array<OneD, MultiRegions::ExpListSharedPtr> gradPlane(nVel * nVel);
1321 Array<OneD, Array<OneD, NekDouble>> gradElmt(nVel * nVel);
1322 Array<OneD, Array<OneD, NekDouble>> gradBnd(nVel * nVel);
1323
1324 // Coordinates
1325 Array<OneD, MultiRegions::ExpListSharedPtr> coords(3);
1326 Array<OneD, MultiRegions::ExpListSharedPtr> coordsPlane(3);
1327 Array<OneD, Array<OneD, NekDouble>> coordsElmt(3);
1328 Array<OneD, Array<OneD, NekDouble>> coordsBnd(3);
1329
1330 // Transformation to cartesian system
1331 Array<OneD, MultiRegions::ExpListSharedPtr> C(nVel * nVel);
1332 Array<OneD, MultiRegions::ExpListSharedPtr> CPlane(nVel * nVel);
1333 Array<OneD, Array<OneD, NekDouble>> CElmt(nVel * nVel);
1334 Array<OneD, Array<OneD, NekDouble>> CBnd(nVel * nVel);
1335
1336 // Jacobian
1339 Array<OneD, NekDouble> JacElmt;
1340 Array<OneD, NekDouble> JacBnd;
1341
1342 // Communicators to exchange results
1343 LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
1344 LibUtilities::CommSharedPtr rowComm = vComm->GetRowComm();
1346 m_session->DefinesSolverInfo("HomoStrip")
1347 ? vComm->GetColumnComm()->GetColumnComm()
1348 : vComm->GetColumnComm();
1349
1350 // Arrays to store the plane average forces in each direction
1351 m_Fp = Array<OneD, NekDouble>(expdim, 0.0);
1352 m_Fv = Array<OneD, NekDouble>(expdim, 0.0);
1353 m_Ft = Array<OneD, NekDouble>(expdim, 0.0);
1354 m_Mp = Array<OneD, NekDouble>(momdim, 0.0);
1355 m_Mv = Array<OneD, NekDouble>(momdim, 0.0);
1356 m_Mt = Array<OneD, NekDouble>(momdim, 0.0);
1357
1358 // Arrays with forces in each plane
1359 m_Fpplane = Array<OneD, Array<OneD, NekDouble>>(expdim);
1360 m_Fvplane = Array<OneD, Array<OneD, NekDouble>>(expdim);
1361 m_Ftplane = Array<OneD, Array<OneD, NekDouble>>(expdim);
1362 for (int i = 0; i < expdim; i++)
1363 {
1364 m_Fpplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
1365 m_Fvplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
1366 m_Ftplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
1367 }
1368
1369 // Arrays with moments in each plane
1370 m_Mpplane = Array<OneD, Array<OneD, NekDouble>>(momdim);
1371 m_Mvplane = Array<OneD, Array<OneD, NekDouble>>(momdim);
1372 m_Mtplane = Array<OneD, Array<OneD, NekDouble>>(momdim);
1373 for (int i = 0; i < momdim; ++i)
1374 {
1375 m_Mpplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
1376 m_Mvplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
1377 m_Mtplane[i] = Array<OneD, NekDouble>(m_nPlanes, 0.0);
1378 }
1379
1380 // Forces per element length in a boundary
1381 Array<OneD, Array<OneD, NekDouble>> fp(nVel);
1382 Array<OneD, Array<OneD, NekDouble>> fv(nVel);
1383
1384 // moments per element length in a boundary
1385 Array<OneD, Array<OneD, NekDouble>> mp(nVel);
1386 Array<OneD, Array<OneD, NekDouble>> mv(nVel);
1387
1388 // Get viscosity
1389 NekDouble mu{1}, rho{1.};
1390 if (m_session->DefinesParameter("Kinvis"))
1391 {
1392 rho = (m_session->DefinesParameter("rho"))
1393 ? (m_session->GetParameter("rho"))
1394 : 1;
1395 mu = rho * m_session->GetParameter("Kinvis");
1396 }
1397 else
1398 {
1399 mu = m_session->GetParameter("mu");
1400 }
1401 // NekDouble lambda = -2.0/3.0;
1402
1403 // Perform BwdTrans: for case with mapping, we can never work
1404 // in wavespace
1405 for (int i = 0; i < pFields.size(); ++i)
1406 {
1408 {
1409 pFields[i]->SetWaveSpace(false);
1410 }
1411 pFields[i]->BwdTrans(pFields[i]->GetCoeffs(), pFields[i]->UpdatePhys());
1412 pFields[i]->SetPhysState(true);
1413 }
1414
1415 // Define boundary expansions
1416 Array<OneD, const SpatialDomains::BoundaryConditionShPtr> BndConds;
1417 Array<OneD, MultiRegions::ExpListSharedPtr> BndExp;
1419 {
1420 BndConds = pFields[0]->GetPlane(0)->GetBndConditions();
1421 BndExp = pFields[0]->GetPlane(0)->GetBndCondExpansions();
1422 }
1423 else
1424 {
1425 BndConds = pFields[0]->GetBndConditions();
1426 BndExp = pFields[0]->GetBndCondExpansions();
1427 }
1428
1429 //
1430 // Calculate pressure stress tensor, velocity gradient
1431 // and get informations about the mapping
1432
1433 // Initialise variables
1434 switch (expdim)
1435 {
1436 case 2:
1437 {
1439 {
1441 Exp3DH1 = std::dynamic_pointer_cast<
1442 MultiRegions::ExpList3DHomogeneous1D>(pFields[0]);
1443 for (int i = 0; i < nVel * nVel; i++)
1444 {
1445 grad[i] =
1447 AllocateSharedPtr(*Exp3DH1);
1448
1450 AllocateSharedPtr(*Exp3DH1);
1451
1453 AllocateSharedPtr(*Exp3DH1);
1454 }
1455
1456 for (int i = 0; i < 3; ++i)
1457 {
1458 coords[i] =
1460 AllocateSharedPtr(*Exp3DH1);
1461 }
1463 AllocateSharedPtr(*Exp3DH1);
1464 }
1465 else
1466 {
1468 Exp2D = std::dynamic_pointer_cast<MultiRegions::ExpList>(
1469 pFields[0]);
1470 for (int i = 0; i < nVel * nVel; i++)
1471 {
1472 grad[i] =
1474 *Exp2D);
1475
1476 P[i] =
1478 *Exp2D);
1479
1480 C[i] =
1482 *Exp2D);
1483 }
1484 for (int i = 0; i < 3; ++i)
1485 {
1486 coords[i] =
1488 *Exp2D);
1489 }
1491 *Exp2D);
1492 }
1493 break;
1494 }
1495 case 3:
1496 {
1498 Exp3D =
1499 std::dynamic_pointer_cast<MultiRegions::ExpList>(pFields[0]);
1500 for (int i = 0; i < nVel * nVel; i++)
1501 {
1502 grad[i] =
1504 *Exp3D);
1505
1507 *Exp3D);
1508
1510 *Exp3D);
1511 }
1512 for (int i = 0; i < 3; ++i)
1513 {
1514 coords[i] =
1516 *Exp3D);
1517 }
1518 Jac =
1520
1521 break;
1522 }
1523 default:
1524 ASSERTL0(false,
1525 "Expansion dimension not supported by FilterAeroForces");
1526 break;
1527 }
1528
1529 // Get g^ij
1530 Array<OneD, Array<OneD, NekDouble>> tmp(nVel * nVel);
1531 m_mapping->GetInvMetricTensor(tmp);
1532
1533 // Get Cartesian coordinates
1534 m_mapping->GetCartesianCoordinates(coords[0]->UpdatePhys(),
1535 coords[1]->UpdatePhys(),
1536 coords[2]->UpdatePhys());
1537
1538 // Calculate P^ij = g^ij*p
1539 for (int i = 0; i < nVel * nVel; ++i)
1540 {
1541 Vmath::Vmul(physTot, tmp[i], 1, pFields[nVel]->GetPhys(), 1,
1542 P[i]->UpdatePhys(), 1);
1543 }
1544
1545 // Calculate covariant derivatives of U = u^i_,k
1546 Array<OneD, Array<OneD, NekDouble>> wk(nVel);
1547 for (int i = 0; i < nVel; ++i)
1548 {
1549 wk[i] = Array<OneD, NekDouble>(physTot, 0.0);
1550 Vmath::Vcopy(physTot, pFields[i]->GetPhys(), 1, wk[i], 1);
1551 }
1552 m_mapping->ApplyChristoffelContravar(wk, tmp);
1553 for (int i = 0; i < nVel; ++i)
1554 {
1555 for (int k = 0; k < nVel; ++k)
1556 {
1557 pFields[0]->PhysDeriv(MultiRegions::DirCartesianMap[k], wk[i],
1558 grad[i * nVel + k]->UpdatePhys());
1559
1560 Vmath::Vadd(physTot, tmp[i * nVel + k], 1,
1561 grad[i * nVel + k]->UpdatePhys(), 1,
1562 grad[i * nVel + k]->UpdatePhys(), 1);
1563 }
1564 }
1565 // Raise index to obtain Grad^ij = g^jk u^i_,k
1566 for (int i = 0; i < nVel; ++i)
1567 {
1568 for (int k = 0; k < nVel; ++k)
1569 {
1570 Vmath::Vcopy(physTot, grad[i * nVel + k]->GetPhys(), 1, wk[k], 1);
1571 }
1572 m_mapping->RaiseIndex(wk, wk);
1573 for (int j = 0; j < nVel; ++j)
1574 {
1575 Vmath::Vcopy(physTot, wk[j], 1, grad[i * nVel + j]->UpdatePhys(),
1576 1);
1577 }
1578 }
1579
1580 // Get Jacobian
1581 m_mapping->GetJacobian(Jac->UpdatePhys());
1582
1583 // Get transformation to Cartesian system
1584 for (int i = 0; i < nVel; ++i)
1585 {
1586 // Zero wk storage
1587 for (int k = 0; k < nVel; ++k)
1588 {
1589 wk[k] = Array<OneD, NekDouble>(physTot, 0.0);
1590 }
1591 // Make wk[i] = 1
1592 wk[i] = Array<OneD, NekDouble>(physTot, 1.0);
1593 // Transform wk to Cartesian
1594 m_mapping->ContravarToCartesian(wk, wk);
1595 // Copy result to a column in C
1596 for (int k = 0; k < nVel; k++)
1597 {
1598 Vmath::Vcopy(physTot, wk[k], 1, C[k * nVel + i]->UpdatePhys(), 1);
1599 }
1600 }
1601
1602 //
1603 // Calculate forces
1604 //
1605
1606 // For Homogeneous, calculate force on each 2D plane
1607 // Otherwise, m_nPlanes = 1, and loop only runs once
1608 for (int plane = 0; plane < m_nPlanes; ++plane)
1609 {
1610 // Check if plane is in this proc
1611 if (m_planesID[plane] != -1)
1612 {
1613 // For Homogeneous, consider the 2D expansion
1614 // on the current plane
1616 {
1617 for (int n = 0; n < nVel * nVel; ++n)
1618 {
1619 PPlane[n] = P[n]->GetPlane(m_planesID[plane]);
1620 gradPlane[n] = grad[n]->GetPlane(m_planesID[plane]);
1621 CPlane[n] = C[n]->GetPlane(m_planesID[plane]);
1622 }
1623 for (int n = 0; n < 3; ++n)
1624 {
1625 coordsPlane[n] = coords[n]->GetPlane(m_planesID[plane]);
1626 }
1627 JacPlane = Jac->GetPlane(m_planesID[plane]);
1628 }
1629 else
1630 {
1631 for (int n = 0; n < nVel * nVel; ++n)
1632 {
1633 PPlane[n] = P[n];
1634 gradPlane[n] = grad[n];
1635 CPlane[n] = C[n];
1636 }
1637 for (int n = 0; n < 3; ++n)
1638 {
1639 coordsPlane[n] = coords[n];
1640 }
1641 JacPlane = Jac;
1642 }
1643
1644 // Loop all the Boundary Regions
1645 for (int n = cnt = 0; n < BndConds.size(); n++)
1646 {
1647 if (m_boundaryRegionIsInList[n] == 1)
1648 {
1649 for (int i = 0; i < BndExp[n]->GetExpSize(); ++i, cnt++)
1650 {
1651 elmtid = m_BCtoElmtID[cnt];
1652 elmt = PPlane[0]->GetExp(elmtid);
1653 offset = PPlane[0]->GetPhys_Offset(elmtid);
1654
1655 // Extract fields on this element
1656 for (int j = 0; j < nVel * nVel; j++)
1657 {
1658 PElmt[j] = PPlane[j]->GetPhys() + offset;
1659 gradElmt[j] = gradPlane[j]->GetPhys() + offset;
1660 CElmt[j] = CPlane[j]->GetPhys() + offset;
1661 }
1662 for (int j = 0; j < 3; ++j)
1663 {
1664 coordsElmt[j] = coordsPlane[j]->GetPhys() + offset;
1665 }
1666 JacElmt = JacPlane->GetPhys() + offset;
1667
1668 // identify boundary of element
1669 boundary = m_BCtoTraceID[cnt];
1670
1671 // Dimension specific part for obtaining values
1672 // at boundary and normal vector
1673 Array<OneD, Array<OneD, NekDouble>> normals;
1674 // Get normals
1675 normals = elmt->GetTraceNormal(boundary);
1676
1677 // Get expansion on boundary
1679 BndExp[n]->GetExp(i);
1680
1681 // Get number of points on the boundary
1682 int nbc = bc->GetTotPoints();
1683
1684 // Extract values at boundary
1685 for (int j = 0; j < nVel * nVel; ++j)
1686 {
1687 gradBnd[j] = Array<OneD, NekDouble>(nbc, 0.0);
1688 elmt->GetTracePhysVals(boundary, bc, gradElmt[j],
1689 gradBnd[j]);
1690
1691 PBnd[j] = Array<OneD, NekDouble>(nbc, 0.0);
1692 elmt->GetTracePhysVals(boundary, bc, PElmt[j],
1693 PBnd[j]);
1694
1695 CBnd[j] = Array<OneD, NekDouble>(nbc, 0.0);
1696 elmt->GetTracePhysVals(boundary, bc, CElmt[j],
1697 CBnd[j]);
1698 }
1699 for (int j = 0; j < 3; ++j)
1700 {
1701 coordsBnd[j] = Array<OneD, NekDouble>(nbc, 0.0);
1702 elmt->GetTracePhysVals(boundary, bc, coordsElmt[j],
1703 coordsBnd[j]);
1704
1705 // substract the m_pivotPoint
1706 Vmath::Sadd(nbc, -1.0 * m_pivotPoint[j],
1707 coordsBnd[j], 1, coordsBnd[j], 1);
1708 }
1709 JacBnd = Array<OneD, NekDouble>(nbc, 0.0);
1710 elmt->GetTracePhysVals(boundary, bc, JacElmt, JacBnd);
1711
1712 // Calculate forces per unit length
1713
1714 // Pressure component: fp[j] = rho*P[j,k]*n[k]
1715 for (int j = 0; j < nVel; j++)
1716 {
1717 fp[j] = Array<OneD, NekDouble>(nbc, 0.0);
1718 // Normals only has expdim elements
1719 for (int k = 0; k < expdim; k++)
1720 {
1721 Vmath::Vvtvp(nbc, PBnd[j * nVel + k], 1,
1722 normals[k], 1, fp[j], 1, fp[j], 1);
1723 }
1724 Vmath::Smul(nbc, rho, fp[j], 1, fp[j], 1);
1725 }
1726
1727 // Viscous component:
1728 // fv[j] = -mu*{(grad[k,j]+grad[j,k]) *n[k]}
1729 for (int j = 0; j < nVel; j++)
1730 {
1731 fv[j] = Array<OneD, NekDouble>(nbc, 0.0);
1732 for (int k = 0; k < expdim; k++)
1733 {
1734 Vmath::Vvtvp(nbc, gradBnd[k * nVel + j], 1,
1735 normals[k], 1, fv[j], 1, fv[j], 1);
1736 Vmath::Vvtvp(nbc, gradBnd[j * nVel + k], 1,
1737 normals[k], 1, fv[j], 1, fv[j], 1);
1738 }
1739 Vmath::Smul(nbc, -mu, fv[j], 1, fv[j], 1);
1740 }
1741
1742 // Multiply by Jacobian
1743 for (int k = 0; k < nVel; k++)
1744 {
1745 Vmath::Vmul(nbc, JacBnd, 1, fp[k], 1, fp[k], 1);
1746 Vmath::Vmul(nbc, JacBnd, 1, fv[k], 1, fv[k], 1);
1747 }
1748
1749 // Convert to cartesian system
1750 for (int k = 0; k < nVel; k++)
1751 {
1752 wk[k] = Array<OneD, NekDouble>(physTot, 0.0);
1753 for (int j = 0; j < nVel; j++)
1754 {
1755 Vmath::Vvtvp(nbc, CBnd[k * nVel + j], 1, fp[j],
1756 1, wk[k], 1, wk[k], 1);
1757 }
1758 }
1759 for (int k = 0; k < nVel; k++)
1760 {
1761 Vmath::Vcopy(nbc, wk[k], 1, fp[k], 1);
1762 }
1763
1764 for (int k = 0; k < nVel; k++)
1765 {
1766 wk[k] = Array<OneD, NekDouble>(physTot, 0.0);
1767 for (int j = 0; j < nVel; j++)
1768 {
1769 Vmath::Vvtvp(nbc, CBnd[k * nVel + j], 1, fv[j],
1770 1, wk[k], 1, wk[k], 1);
1771 }
1772 }
1773 for (int k = 0; k < nVel; k++)
1774 {
1775 Vmath::Vcopy(nbc, wk[k], 1, fv[k], 1);
1776 }
1777
1778 // Calculate moments per unit length
1779 if (momdim == 1)
1780 {
1781 Array<OneD, NekDouble> fptmp(nbc, 0.0);
1782 Array<OneD, NekDouble> fvtmp(nbc, 0.0);
1783
1784 mp[0] = Array<OneD, NekDouble>(nbc, 0.0);
1785 mv[0] = Array<OneD, NekDouble>(nbc, 0.0);
1786
1787 Vmath::Smul(nbc, -1.0, fp[0], 1, fptmp, 1);
1788 Vmath::Smul(nbc, -1.0, fv[0], 1, fvtmp, 1);
1789 // Mz = Fy * x - Fx * y
1790 Vmath::Vvtvvtp(nbc, fp[1], 1, coordsBnd[0], 1,
1791 fptmp, 1, coordsBnd[1], 1, mp[0], 1);
1792 Vmath::Vvtvvtp(nbc, fv[1], 1, coordsBnd[0], 1,
1793 fvtmp, 1, coordsBnd[1], 1, mv[0], 1);
1794 }
1795 else
1796 {
1797 Array<OneD, NekDouble> fptmp(nbc, 0.0);
1798 Array<OneD, NekDouble> fvtmp(nbc, 0.0);
1799
1800 // Mx = Fz * y - Fy * z
1801 mp[0] = Array<OneD, NekDouble>(nbc, 0.0);
1802 mv[0] = Array<OneD, NekDouble>(nbc, 0.0);
1803
1804 Vmath::Smul(nbc, -1.0, fp[1], 1, fptmp, 1);
1805 Vmath::Smul(nbc, -1.0, fv[1], 1, fvtmp, 1);
1806 Vmath::Vvtvvtp(nbc, fp[2], 1, coordsBnd[1], 1,
1807 fptmp, 1, coordsBnd[2], 1, mp[0], 1);
1808 Vmath::Vvtvvtp(nbc, fv[2], 1, coordsBnd[1], 1,
1809 fvtmp, 1, coordsBnd[2], 1, mv[0], 1);
1810 // My = Fx * z - Fz * x
1811 mp[1] = Array<OneD, NekDouble>(nbc, 0.0);
1812 mv[1] = Array<OneD, NekDouble>(nbc, 0.0);
1813
1814 Vmath::Smul(nbc, -1.0, fp[2], 1, fptmp, 1);
1815 Vmath::Smul(nbc, -1.0, fv[2], 1, fvtmp, 1);
1816 Vmath::Vvtvvtp(nbc, fp[0], 1, coordsBnd[2], 1,
1817 fptmp, 1, coordsBnd[0], 1, mp[1], 1);
1818 Vmath::Vvtvvtp(nbc, fv[0], 1, coordsBnd[2], 1,
1819 fvtmp, 1, coordsBnd[0], 1, mv[1], 1);
1820 // Mz = Fy * x - Fx * y
1821 mp[2] = Array<OneD, NekDouble>(nbc, 0.0);
1822 mv[2] = Array<OneD, NekDouble>(nbc, 0.0);
1823
1824 Vmath::Smul(nbc, -1.0, fp[0], 1, fptmp, 1);
1825 Vmath::Smul(nbc, -1.0, fv[0], 1, fvtmp, 1);
1826 Vmath::Vvtvvtp(nbc, fp[1], 1, coordsBnd[0], 1,
1827 fptmp, 1, coordsBnd[1], 1, mp[2], 1);
1828 Vmath::Vvtvvtp(nbc, fv[1], 1, coordsBnd[0], 1,
1829 fvtmp, 1, coordsBnd[1], 1, mv[2], 1);
1830 }
1831
1832 // Integrate to obtain force
1833 for (int j = 0; j < expdim; j++)
1834 {
1835 m_Fpplane[j][plane] +=
1836 BndExp[n]->GetExp(i)->Integral(fp[j]);
1837 m_Fvplane[j][plane] +=
1838 BndExp[n]->GetExp(i)->Integral(fv[j]);
1839 }
1840
1841 // Integrate to obtain moments
1842 for (int j = 0; j < momdim; ++j)
1843 {
1844 m_Mpplane[j][plane] +=
1845 BndExp[n]->GetExp(i)->Integral(mp[j]);
1846 m_Mvplane[j][plane] +=
1847 BndExp[n]->GetExp(i)->Integral(mv[j]);
1848 }
1849 }
1850 }
1851 else
1852 {
1853 cnt += BndExp[n]->GetExpSize();
1854 }
1855 }
1856 }
1857 }
1858
1859 // Combine contributions from different processes
1860 // this is split between row and col comm because of
1861 // homostrips case, which only keeps its own strip
1862 for (int i = 0; i < expdim; ++i)
1863 {
1864 rowComm->AllReduce(m_Fpplane[i], LibUtilities::ReduceSum);
1865 colComm->AllReduce(m_Fpplane[i], LibUtilities::ReduceSum);
1866
1867 rowComm->AllReduce(m_Fvplane[i], LibUtilities::ReduceSum);
1868 colComm->AllReduce(m_Fvplane[i], LibUtilities::ReduceSum);
1869 }
1870 for (int i = 0; i < momdim; ++i)
1871 {
1872 rowComm->AllReduce(m_Mpplane[i], LibUtilities::ReduceSum);
1873 colComm->AllReduce(m_Mpplane[i], LibUtilities::ReduceSum);
1874
1875 rowComm->AllReduce(m_Mvplane[i], LibUtilities::ReduceSum);
1876 colComm->AllReduce(m_Mvplane[i], LibUtilities::ReduceSum);
1877 }
1878
1879 // Project results to new directions
1880 for (int plane = 0; plane < m_nPlanes; plane++)
1881 {
1882 Array<OneD, NekDouble> tmpP(expdim, 0.0);
1883 Array<OneD, NekDouble> tmpV(expdim, 0.0);
1884 for (int i = 0; i < expdim; i++)
1885 {
1886 for (int j = 0; j < expdim; j++)
1887 {
1888 tmpP[i] += m_Fpplane[j][plane] * m_directions[i][j];
1889 tmpV[i] += m_Fvplane[j][plane] * m_directions[i][j];
1890 }
1891 }
1892 // Copy result
1893 for (int i = 0; i < expdim; i++)
1894 {
1895 m_Fpplane[i][plane] = tmpP[i];
1896 m_Fvplane[i][plane] = tmpV[i];
1897 }
1898 //
1899 // For 3D moment, project the results, note in 2D case the moment is
1900 // always in z direction
1901 if (momdim == 3)
1902 {
1903 for (int i = 0; i < 3; ++i)
1904 {
1905 tmpP[i] = 0.0;
1906 tmpV[i] = 0.0;
1907 for (int j = 0; j < 3; ++j)
1908 {
1909 tmpP[i] += m_Mpplane[j][plane] * m_directions[i][j];
1910 tmpV[i] += m_Mvplane[j][plane] * m_directions[i][j];
1911 }
1912 }
1913
1914 // copy the result
1915 for (int i = 0; i < 3; ++i)
1916 {
1917 m_Mpplane[i][plane] = tmpP[i];
1918 m_Mvplane[i][plane] = tmpV[i];
1919 }
1920 }
1921 }
1922
1923 // Sum viscous and pressure components
1924 for (int plane = 0; plane < m_nPlanes; plane++)
1925 {
1926 for (int i = 0; i < expdim; i++)
1927 {
1928 m_Ftplane[i][plane] = m_Fpplane[i][plane] + m_Fvplane[i][plane];
1929 }
1930
1931 if (momdim == 3)
1932 {
1933 for (int i = 0; i < 3; ++i)
1934 {
1935 m_Mtplane[i][plane] = m_Mpplane[i][plane] + m_Mvplane[i][plane];
1936 }
1937 }
1938 else
1939 {
1940 m_Mtplane[0][plane] = m_Mpplane[0][plane] + m_Mvplane[0][plane];
1941 }
1942 }
1943
1944 // combine planes
1945 for (int i = 0; i < expdim; i++)
1946 {
1949 m_Ft[i] = m_Fp[i] + m_Fv[i];
1950 }
1951 for (int i = 0; i < momdim; i++)
1952 {
1955 m_Mt[i] = m_Mp[i] + m_Mv[i];
1956 }
1957
1958 // Put results back to wavespace, if necessary
1960 {
1961 for (int i = 0; i < pFields.size(); ++i)
1962 {
1963 pFields[i]->SetWaveSpace(true);
1964 pFields[i]->HomogeneousFwdTrans(pFields[i]->GetTotPoints(),
1965 pFields[i]->GetPhys(),
1966 pFields[i]->UpdatePhys());
1967 }
1968 }
1969}
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
@ P
Monomial polynomials .
Definition: BasisType.h:62
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:86
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
std::shared_ptr< ExpList3DHomogeneous1D > ExpList3DHomogeneous1DSharedPtr
Shared pointer to an ExpList3DHomogeneous1D object.
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::MultiRegions::DirCartesianMap, m_BCtoElmtID, m_BCtoTraceID, m_boundaryRegionIsInList, m_directions, m_Fp, m_Fpplane, m_Ft, m_Ftplane, m_Fv, m_Fvplane, m_isHomogeneous1D, m_mapping, m_Mp, m_Mpplane, m_Mt, m_Mtplane, m_Mv, m_Mvplane, m_nPlanes, m_pivotPoint, m_planesID, Nektar::SolverUtils::Filter::m_session, Nektar::LibUtilities::P, Nektar::LibUtilities::ReduceSum, Vmath::Sadd(), Vmath::Smul(), Vmath::Vadd(), Vmath::Vcopy(), Vmath::Vmul(), Vmath::Vsum(), Vmath::Vvtvp(), and Vmath::Vvtvvtp().

Referenced by CalculateForces().

◆ create()

static FilterSharedPtr Nektar::SolverUtils::FilterAeroForces::create ( const LibUtilities::SessionReaderSharedPtr pSession,
const std::weak_ptr< EquationSystem > &  pEquation,
const std::map< std::string, std::string > &  pParams 
)
inlinestatic

Creates an instance of this class.

Definition at line 57 of file FilterAeroForces.h.

61 {
63 pSession, pEquation, pParams);
64 return p;
65 }
std::shared_ptr< Filter > FilterSharedPtr
A shared pointer to a Driver object.
Definition: Filter.h:51

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), and CellMLToNektar.cellml_metadata::p.

◆ GetForces()

void Nektar::SolverUtils::FilterAeroForces::GetForces ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
Array< OneD, NekDouble > &  Aeroforces,
const NekDouble time 
)

This function outputs the force on all planes of the current process, in the format required by ForcingMovingBody

Definition at line 665 of file FilterAeroForces.cpp.

668{
669 // Calculate forces if the result we have is not up-to-date
670 if (time > m_lastTime)
671 {
672 CalculateForces(pFields, time);
673 }
674 if (Aeroforces == NullNekDouble1DArray || Aeroforces.size() == 0)
675 {
676 return;
677 }
678 // Get information to write result
679 Array<OneD, unsigned int> ZIDs = pFields[0]->GetZIDs();
680 int local_planes = ZIDs.size();
681 int expdim = pFields[0]->GetGraph()->GetMeshDimension();
682
683 // Copy results to Aeroforces
685 {
686 for (int plane = 0; plane < local_planes; plane++)
687 {
688 for (int dir = 0; dir < expdim; dir++)
689 {
690 Aeroforces[plane + dir * local_planes] =
691 m_Ftplane[dir][ZIDs[plane]];
692 }
693 }
694 }
695 else
696 {
697 for (int plane = 0; plane < local_planes; plane++)
698 {
699 for (int dir = 0; dir < expdim; dir++)
700 {
701 Aeroforces[plane + dir * local_planes] = m_Ft[dir];
702 // m_Ftplane[dir][0];
703 }
704 }
705 }
706}
void CalculateForces(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
static Array< OneD, NekDouble > NullNekDouble1DArray

References CalculateForces(), m_Ft, m_Ftplane, m_lastTime, m_outputAllPlanes, and Nektar::NullNekDouble1DArray.

◆ GetMoments()

void Nektar::SolverUtils::FilterAeroForces::GetMoments ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
Array< OneD, NekDouble > &  moments,
const NekDouble time 
)

This function outputs the moments of force on all planes of the current process

Definition at line 712 of file FilterAeroForces.cpp.

715{
716 // Calculate forces if the result we have is not up-to-date
717 if (time > m_lastTime)
718 {
719 CalculateForces(pFields, time);
720 }
721
722 // Get information to write result
723 Array<OneD, unsigned int> ZIDs = pFields[0]->GetZIDs();
724 int local_planes = ZIDs.size();
725 int expdim = pFields[0]->GetGraph()->GetMeshDimension();
726 int momdim = (expdim == 2) ? 1 : 3;
727
728 // Copy results to moments
730 {
731 for (int plane = 0; plane < local_planes; plane++)
732 {
733 for (int dir = 0; dir < momdim; ++dir)
734 {
735 moments[plane + dir * local_planes] =
736 m_Mtplane[dir][ZIDs[plane]];
737 }
738 }
739 }
740 else
741 {
742 for (int plane = 0; plane < local_planes; ++plane)
743 {
744 for (int dir = 0; dir < momdim; dir++)
745 {
746 moments[plane + dir * local_planes] = m_Mt[dir];
747 }
748 }
749 }
750}

References CalculateForces(), m_lastTime, m_Mt, m_Mtplane, and m_outputAllPlanes.

◆ v_Finalise()

void Nektar::SolverUtils::FilterAeroForces::v_Finalise ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
const NekDouble time 
)
overrideprotectedvirtual

Implements Nektar::SolverUtils::Filter.

Definition at line 643 of file FilterAeroForces.cpp.

646{
647 if (pFields[0]->GetComm()->GetRank() == 0)
648 {
649 m_outputStream.close();
650 }
651}

References m_outputStream.

◆ v_Initialise()

void Nektar::SolverUtils::FilterAeroForces::v_Initialise ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
const NekDouble time 
)
overrideprotectedvirtual

Implements Nektar::SolverUtils::Filter.

Definition at line 235 of file FilterAeroForces.cpp.

238{
239 // Load mapping
241
242 // Parse the boundary regions into a list.
243 std::string::size_type FirstInd = m_BoundaryString.find_first_of('[') + 1;
244 std::string::size_type LastInd = m_BoundaryString.find_last_of(']') - 1;
245
246 ASSERTL0(FirstInd <= LastInd,
247 (std::string("Error reading boundary region definition:") +
249 .c_str());
250
251 std::string IndString =
252 m_BoundaryString.substr(FirstInd, LastInd - FirstInd + 1);
253 bool parseGood =
255 ASSERTL0(parseGood && !m_boundaryRegionsIdList.empty(),
256 (std::string("Unable to read boundary regions index "
257 "range for FilterAeroForces: ") +
258 IndString)
259 .c_str());
260
261 // determine what boundary regions need to be considered
262 int cnt;
263 unsigned int numBoundaryRegions = pFields[0]->GetBndConditions().size();
265 numBoundaryRegions, 0);
266
267 SpatialDomains::BoundaryConditions bcs(m_session, pFields[0]->GetGraph());
269 bcs.GetBoundaryRegions();
270
271 cnt = 0;
272 for (auto &it : bregions)
273 {
276 it.first) != m_boundaryRegionsIdList.end())
277 {
279 }
280 cnt++;
281 }
282
283 // Create map for element and edge/face of each boundary expansion
285 {
286 pFields[0]->GetPlane(0)->GetBoundaryToElmtMap(m_BCtoElmtID,
288 }
289 else
290 {
291 pFields[0]->GetBoundaryToElmtMap(m_BCtoElmtID, m_BCtoTraceID);
292 }
293
294 // Define number of planes to calculate the forces
295 // in the Homogeneous direction ( if m_outputAllPlanes is false,
296 // consider only first plane in wave space)
297 // If flow has no Homogeneous direction, use 1 to make code general
298 if (m_isHomogeneous1D && (m_outputAllPlanes || m_mapping->IsDefined()))
299 {
300 m_nPlanes = pFields[0]->GetHomogeneousBasis()->GetZ().size();
301 }
302 else
303 {
304 m_nPlanes = 1;
305 }
306
307 // Create map for Planes ID for Homogeneous direction
308 // If flow has no Homogeneous direction, create trivial map
309 int j;
310 m_planesID = Array<OneD, int>(m_nPlanes, -1);
312 {
313 Array<OneD, const unsigned int> IDs = pFields[0]->GetZIDs();
314 // Loop through all planes
315 for (cnt = 0; cnt < m_nPlanes; cnt++)
316 {
317 for (j = 0; j < IDs.size(); ++j)
318 {
319 // Look for current plane ID in this process
320 if (IDs[j] == cnt)
321 {
322 break;
323 }
324 }
325 // Assign ID to planesID
326 // If plane is not found in this process, leave it with -1
327 if (j != IDs.size())
328 {
329 m_planesID[cnt] = j;
330 }
331 }
332 }
333 else
334 {
335 m_planesID[0] = 0;
336 }
337
338 LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
339
340 // Write header
341 int expdim = pFields[0]->GetGraph()->GetMeshDimension();
342 int momdim = (expdim == 2) ? 1 : 3;
343 if (vComm->GetRank() == 0)
344 {
345 // Open output stream
346 bool adaptive;
347 m_session->MatchSolverInfo("Driver", "Adaptive", adaptive, false);
348 if (adaptive)
349 {
350 m_outputStream.open(m_outputFile.c_str(), ofstream::app);
351 }
352 else
353 {
354 m_outputStream.open(m_outputFile.c_str());
355 }
356 m_outputStream << "# Forces and moments acting on bodies" << endl;
357 for (int i = 0; i < expdim; i++)
358 {
359 m_outputStream << "#"
360 << " Direction" << i + 1 << " = (";
361 m_outputStream.width(8);
362 m_outputStream << setprecision(4) << m_directions[i][0];
363 m_outputStream.width(8);
364 m_outputStream << setprecision(4) << m_directions[i][1];
365 m_outputStream.width(8);
366 m_outputStream << setprecision(4) << m_directions[i][2];
367 m_outputStream << ")" << endl;
368 }
369
370 m_outputStream << "#"
371 << " Moments around"
372 << " (";
373 m_outputStream.width(8);
374 m_outputStream << setprecision(4) << m_pivotPoint[0];
375 m_outputStream.width(8);
376 m_outputStream << setprecision(4) << m_pivotPoint[1];
377 m_outputStream.width(8);
378 m_outputStream << setprecision(4) << m_pivotPoint[2];
379 m_outputStream << ")" << endl;
380
381 m_outputStream << "# Boundary regions: " << IndString.c_str() << endl;
382 m_outputStream << "#";
383 m_outputStream.width(7);
384 m_outputStream << "Time";
385 for (int i = 1; i <= expdim; i++)
386 {
387 m_outputStream.width(8);
388 m_outputStream << "F" << i << "-press";
389 m_outputStream.width(9);
390 m_outputStream << "F" << i << "-visc";
391 m_outputStream.width(8);
392 m_outputStream << "F" << i << "-total";
393 }
394 if (momdim == 1)
395 {
396 // 2D case: we only have M3 (z-moment)
397 m_outputStream.width(8);
398 m_outputStream << "M" << 3 << "-press";
399 m_outputStream.width(9);
400 m_outputStream << "M" << 3 << "-visc";
401 m_outputStream.width(8);
402 m_outputStream << "M" << 3 << "-total";
403 }
404 else
405 {
406 for (int i = 1; i <= momdim; i++)
407 {
408 m_outputStream.width(8);
409 m_outputStream << "M" << i << "-press";
410 m_outputStream.width(9);
411 m_outputStream << "M" << i << "-visc";
412 m_outputStream.width(8);
413 m_outputStream << "M" << i << "-total";
414 }
415 }
417 {
418 m_outputStream.width(10);
419 m_outputStream << "Plane";
420 }
421 if (m_session->DefinesSolverInfo("HomoStrip"))
422 {
423 ASSERTL0(
424 m_outputAllPlanes == false,
425 "Output forces on all planes not compatible with HomoStrips");
426 m_outputStream.width(10);
427 m_outputStream << "Strip";
428 }
429
430 m_outputStream << endl;
431 }
432
433 m_lastTime = -1;
434 m_index = 0;
435 v_Update(pFields, time);
436}
static GLOBAL_MAPPING_EXPORT MappingSharedPtr Load(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Return a pointer to the mapping, creating it on first call.
Definition: Mapping.cpp:266
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector.
Definition: ParseUtils.cpp:104
void v_Update(const Array< OneD, const MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time) override
std::vector< unsigned int > m_boundaryRegionsIdList
ID's of boundary regions where we want the forces.
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
Definition: Conditions.h:210
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:447

References ASSERTL0, Nektar::StdRegions::find(), Nektar::ParseUtils::GenerateSeqVector(), Nektar::SpatialDomains::BoundaryConditions::GetBoundaryRegions(), Nektar::GlobalMapping::Mapping::Load(), m_BCtoElmtID, m_BCtoTraceID, m_boundaryRegionIsInList, m_boundaryRegionsIdList, m_BoundaryString, m_directions, m_index, m_isHomogeneous1D, m_lastTime, m_mapping, m_nPlanes, m_outputAllPlanes, m_outputFile, m_outputStream, m_pivotPoint, m_planesID, Nektar::SolverUtils::Filter::m_session, and v_Update().

◆ v_IsTimeDependent()

bool Nektar::SolverUtils::FilterAeroForces::v_IsTimeDependent ( )
overrideprotectedvirtual

Implements Nektar::SolverUtils::Filter.

Definition at line 656 of file FilterAeroForces.cpp.

657{
658 return true;
659}

◆ v_Update()

void Nektar::SolverUtils::FilterAeroForces::v_Update ( const Array< OneD, const MultiRegions::ExpListSharedPtr > &  pFields,
const NekDouble time 
)
overrideprotectedvirtual

Implements Nektar::SolverUtils::Filter.

Definition at line 441 of file FilterAeroForces.cpp.

444{
445 // Only output every m_outputFrequency.
446 if (m_outputFrequency == 0)
447 {
448 return;
449 }
450 if ((m_index++) % m_outputFrequency || (time < m_startTime))
451 {
452 return;
453 }
454
455 // Calculate the forces
456 CalculateForces(pFields, time);
457
458 // Calculate forces including all planes
459 int expdim = pFields[0]->GetGraph()->GetMeshDimension();
460 int momdim = (expdim == 2) ? 1 : 3;
461 Array<OneD, NekDouble> Fp(expdim, 0.0);
462 Array<OneD, NekDouble> Fv(expdim, 0.0);
463 Array<OneD, NekDouble> Ft(expdim, 0.0);
464 for (int i = 0; i < expdim; i++)
465 {
466 Fp[i] = Vmath::Vsum(m_nPlanes, m_Fpplane[i], 1) / m_nPlanes;
467 Fv[i] = Vmath::Vsum(m_nPlanes, m_Fvplane[i], 1) / m_nPlanes;
468 Ft[i] = Fp[i] + Fv[i];
469 }
470
471 Array<OneD, NekDouble> Mp(momdim, 0.0);
472 Array<OneD, NekDouble> Mv(momdim, 0.0);
473 Array<OneD, NekDouble> Mt(momdim, 0.0);
474 for (int i = 0; i < momdim; i++)
475 {
476 Mp[i] = Vmath::Vsum(m_nPlanes, m_Mpplane[i], 1) / m_nPlanes;
477 Mv[i] = Vmath::Vsum(m_nPlanes, m_Mvplane[i], 1) / m_nPlanes;
478 Mt[i] = Mp[i] + Mv[i];
479 }
480
481 // Communicators to exchange results
482 LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
483
484 // get the total number of planes per strip for the case of homoStrip method
485 int nZ{1};
486 int nstrips{1};
487 int colSize;
488 int idOffset{0};
489
490 if (m_session->DefinesSolverInfo("HomoStrip"))
491 {
492 m_session->LoadParameter("Strip_Z", nstrips);
493 colSize = vComm->GetColumnComm()->GetSize();
494 idOffset = colSize / nstrips;
495 }
496
497 if (m_isHomogeneous1D && m_session->DefinesSolverInfo("HomoStrip"))
498 {
499 m_session->LoadParameter("HomModesZ", nZ);
500 }
501
502 // Write Results
503 if (vComm->GetRank() == 0)
504 {
505 // Write result in each plane
507 {
508 for (int plane = 0; plane < m_nPlanes; plane++)
509 {
510 // Write time
511 m_outputStream.width(8);
512 m_outputStream << setprecision(6) << time;
513 // Write forces
514 for (int i = 0; i < expdim; i++)
515 {
516 m_outputStream.width(15);
517 m_outputStream << setprecision(8) << m_Fpplane[i][plane];
518 m_outputStream.width(15);
519 m_outputStream << setprecision(8) << m_Fvplane[i][plane];
520 m_outputStream.width(15);
521 m_outputStream << setprecision(8) << m_Ftplane[i][plane];
522 }
523 // Write moments
524 for (int i = 0; i < momdim; i++)
525 {
526 m_outputStream.width(15);
527 m_outputStream << setprecision(8) << m_Mpplane[i][plane];
528 m_outputStream.width(15);
529 m_outputStream << setprecision(8) << m_Mvplane[i][plane];
530 m_outputStream.width(15);
531 m_outputStream << setprecision(8) << m_Mtplane[i][plane];
532 }
533 m_outputStream.width(10);
534 m_outputStream << plane;
535 m_outputStream << endl;
536 }
537 }
538 // Output average (or total) force
539 m_outputStream.width(8);
540 m_outputStream << setprecision(6) << time;
541 for (int i = 0; i < expdim; i++)
542 {
543 m_outputStream.width(15);
544 m_outputStream << setprecision(8) << Fp[i];
545 m_outputStream.width(15);
546 m_outputStream << setprecision(8) << Fv[i];
547 m_outputStream.width(15);
548 m_outputStream << setprecision(8) << Ft[i];
549 }
550 for (int i = 0; i < momdim; i++)
551 {
552 m_outputStream.width(15);
553 m_outputStream << setprecision(8) << Mp[i];
554 m_outputStream.width(15);
555 m_outputStream << setprecision(8) << Mv[i];
556 m_outputStream.width(15);
557 m_outputStream << setprecision(8) << Mt[i];
558 }
560 {
561 m_outputStream.width(10);
562 m_outputStream << "average";
563 }
564
565 if (m_session->DefinesSolverInfo("HomoStrip"))
566 {
567 // The result we already wrote is for strip 0
568 m_outputStream.width(10);
569 m_outputStream << 0;
570 m_outputStream << endl;
571
572 // Now get result from other strips
573
574 for (int i = 1; i < nstrips; i++)
575 {
576 int id = i * idOffset;
577 vComm->GetColumnComm()->Recv(id, Fp);
578 vComm->GetColumnComm()->Recv(id, Fv);
579 vComm->GetColumnComm()->Recv(id, Ft);
580 vComm->GetColumnComm()->Recv(id, Mp);
581 vComm->GetColumnComm()->Recv(id, Mv);
582 vComm->GetColumnComm()->Recv(id, Mt);
583
584 m_outputStream.width(8);
585 m_outputStream << setprecision(6) << time;
586 for (int j = 0; j < expdim; j++)
587 {
588 m_outputStream.width(15);
589 m_outputStream << setprecision(8) << Fp[j];
590 m_outputStream.width(15);
591 m_outputStream << setprecision(8) << Fv[j];
592 m_outputStream.width(15);
593 m_outputStream << setprecision(8) << Ft[j];
594 }
595 for (int j = 0; j < momdim; j++)
596 {
597 m_outputStream.width(15);
598 m_outputStream << setprecision(8) << Mp[j];
599 m_outputStream.width(15);
600 m_outputStream << setprecision(8) << Mv[j];
601 m_outputStream.width(15);
602 m_outputStream << setprecision(8) << Mt[j];
603 }
604 m_outputStream.width(10);
605 m_outputStream << i;
606 m_outputStream << endl;
607 }
608 }
609 else
610 {
611 m_outputStream << endl;
612 }
613 }
614 else
615 {
616 // In the homostrips case, we need to send result to root
617 if (m_session->DefinesSolverInfo("HomoStrip") &&
618 (vComm->GetRowComm()->GetRank() == 0))
619 {
620 // we start from strip 1 not 0, since we already have the data of
621 // strip 0
622 for (int i = 1; i < nstrips; ++i)
623 {
624 int rid = i * idOffset;
625 int sid = vComm->GetColumnComm()->GetRank();
626 if (rid == sid)
627 {
628 vComm->GetColumnComm()->Send(0, Fp);
629 vComm->GetColumnComm()->Send(0, Fv);
630 vComm->GetColumnComm()->Send(0, Ft);
631 vComm->GetColumnComm()->Send(0, Mp);
632 vComm->GetColumnComm()->Send(0, Mv);
633 vComm->GetColumnComm()->Send(0, Mt);
634 }
635 }
636 }
637 }
638}

References CalculateForces(), m_Fpplane, m_Ftplane, m_Fvplane, m_index, m_isHomogeneous1D, m_Mpplane, m_Mtplane, m_Mvplane, m_nPlanes, m_outputAllPlanes, m_outputFrequency, m_outputStream, Nektar::SolverUtils::Filter::m_session, m_startTime, and Vmath::Vsum().

Referenced by v_Initialise().

Friends And Related Function Documentation

◆ MemoryManager< FilterAeroForces >

friend class MemoryManager< FilterAeroForces >
friend

Definition at line 153 of file FilterAeroForces.h.

Member Data Documentation

◆ className

std::string Nektar::SolverUtils::FilterAeroForces::className
static
Initial value:
=
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:197
static FilterSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const std::map< std::string, std::string > &pParams)
Creates an instance of this class.
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:39

Name of the class.

Definition at line 68 of file FilterAeroForces.h.

◆ m_BCtoElmtID

Array<OneD, int> Nektar::SolverUtils::FilterAeroForces::m_BCtoElmtID
private

Definition at line 113 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Initialise().

◆ m_BCtoTraceID

Array<OneD, int> Nektar::SolverUtils::FilterAeroForces::m_BCtoTraceID
private

Definition at line 114 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Initialise().

◆ m_boundaryRegionIsInList

std::vector<bool> Nektar::SolverUtils::FilterAeroForces::m_boundaryRegionIsInList
private

Determines if a given Boundary Region is in m_boundaryRegionsIdList.

Definition at line 102 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Initialise().

◆ m_boundaryRegionsIdList

std::vector<unsigned int> Nektar::SolverUtils::FilterAeroForces::m_boundaryRegionsIdList
private

ID's of boundary regions where we want the forces.

Definition at line 99 of file FilterAeroForces.h.

Referenced by v_Initialise().

◆ m_BoundaryString

std::string Nektar::SolverUtils::FilterAeroForces::m_BoundaryString
private

Definition at line 112 of file FilterAeroForces.h.

Referenced by FilterAeroForces(), and v_Initialise().

◆ m_directions

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_directions
private

◆ m_directions0

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_directions0
private

Definition at line 121 of file FilterAeroForces.h.

Referenced by CalculateForces(), and FilterAeroForces().

◆ m_Fp

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_Fp
private

Definition at line 130 of file FilterAeroForces.h.

Referenced by CalculateForces(), and CalculateForcesMapping().

◆ m_Fpplane

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_Fpplane
private

Definition at line 127 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Update().

◆ m_Ft

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_Ft
private

Definition at line 132 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and GetForces().

◆ m_Ftplane

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_Ftplane
private

Definition at line 129 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), GetForces(), and v_Update().

◆ m_Fv

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_Fv
private

Definition at line 131 of file FilterAeroForces.h.

Referenced by CalculateForces(), and CalculateForcesMapping().

◆ m_Fvplane

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_Fvplane
private

Definition at line 128 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Update().

◆ m_homogeneousBasis

LibUtilities::BasisSharedPtr Nektar::SolverUtils::FilterAeroForces::m_homogeneousBasis
private

Definition at line 111 of file FilterAeroForces.h.

◆ m_index

unsigned int Nektar::SolverUtils::FilterAeroForces::m_index
private

Definition at line 103 of file FilterAeroForces.h.

Referenced by v_Initialise(), and v_Update().

◆ m_isHomogeneous1D

bool Nektar::SolverUtils::FilterAeroForces::m_isHomogeneous1D
private

◆ m_lastTime

NekDouble Nektar::SolverUtils::FilterAeroForces::m_lastTime
private

Definition at line 141 of file FilterAeroForces.h.

Referenced by CalculateForces(), GetForces(), GetMoments(), and v_Initialise().

◆ m_mapping

GlobalMapping::MappingSharedPtr Nektar::SolverUtils::FilterAeroForces::m_mapping
private

Definition at line 142 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Initialise().

◆ m_Mp

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_Mp
private

Definition at line 134 of file FilterAeroForces.h.

Referenced by CalculateForces(), and CalculateForcesMapping().

◆ m_Mpplane

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_Mpplane
private

Definition at line 137 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Update().

◆ m_Mt

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_Mt
private

Definition at line 136 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and GetMoments().

◆ m_Mtplane

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_Mtplane
private

Definition at line 139 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), GetMoments(), and v_Update().

◆ m_Mv

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_Mv
private

Definition at line 135 of file FilterAeroForces.h.

Referenced by CalculateForces(), and CalculateForcesMapping().

◆ m_Mvplane

Array<OneD, Array<OneD, NekDouble> > Nektar::SolverUtils::FilterAeroForces::m_Mvplane
private

Definition at line 138 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Update().

◆ m_nPlanes

int Nektar::SolverUtils::FilterAeroForces::m_nPlanes
private

number of planes for homogeneous1D expansion

Definition at line 116 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), v_Initialise(), and v_Update().

◆ m_outputAllPlanes

bool Nektar::SolverUtils::FilterAeroForces::m_outputAllPlanes
private

if using a homogeneous1D expansion, determine if should output all planes or just the average

Definition at line 107 of file FilterAeroForces.h.

Referenced by CalculateForces(), FilterAeroForces(), GetForces(), GetMoments(), v_Initialise(), and v_Update().

◆ m_outputFile

std::string Nektar::SolverUtils::FilterAeroForces::m_outputFile
private

Definition at line 109 of file FilterAeroForces.h.

Referenced by FilterAeroForces(), and v_Initialise().

◆ m_outputFrequency

unsigned int Nektar::SolverUtils::FilterAeroForces::m_outputFrequency
private

Definition at line 104 of file FilterAeroForces.h.

Referenced by FilterAeroForces(), and v_Update().

◆ m_outputStream

std::ofstream Nektar::SolverUtils::FilterAeroForces::m_outputStream
private

Definition at line 110 of file FilterAeroForces.h.

Referenced by v_Finalise(), v_Initialise(), and v_Update().

◆ m_pivotPoint

Array<OneD, NekDouble> Nektar::SolverUtils::FilterAeroForces::m_pivotPoint
private

◆ m_planesID

Array<OneD, int> Nektar::SolverUtils::FilterAeroForces::m_planesID
private

Definition at line 117 of file FilterAeroForces.h.

Referenced by CalculateForces(), CalculateForcesMapping(), and v_Initialise().

◆ m_startTime

NekDouble Nektar::SolverUtils::FilterAeroForces::m_startTime
private

Definition at line 119 of file FilterAeroForces.h.

Referenced by FilterAeroForces(), and v_Update().