1 // ============================================================================= 2 // PROJECT CHRONO - http://projectchrono.org 3 // 4 // Copyright (c) 2014 projectchrono.org 5 // All rights reserved. 6 // 7 // Use of this source code is governed by a BSD-style license that can be found 8 // in the LICENSE file at the top level of the distribution and at 9 // http://projectchrono.org/license-chrono.txt. 10 // 11 // ============================================================================= 12 13 #ifndef CHLOADERUV_H 14 #define CHLOADERUV_H 15 16 #include "chrono/physics/ChLoader.h" 17 18 namespace chrono { 19 20 /// Class of loaders for ChLoadableUV objects (which support surface loads). 21 22 class ChLoaderUV : public ChLoader { 23 public: 24 typedef ChLoadableUV type_loadable; 25 26 std::shared_ptr<ChLoadableUV> loadable; 27 ChLoaderUV(std::shared_ptr<ChLoadableUV> mloadable)28 ChLoaderUV(std::shared_ptr<ChLoadableUV> mloadable) : loadable(mloadable) {} ~ChLoaderUV()29 virtual ~ChLoaderUV() {} 30 31 /// Children classes must provide this function that evaluates F = F(u,v) 32 /// This will be evaluated during ComputeQ() to perform integration over the domain. 33 virtual void ComputeF(const double U, ///< parametric coordinate in surface 34 const double V, ///< parametric coordinate in surface 35 ChVectorDynamic<>& F, ///< Result F vector here, size must be = n.field coords.of loadable 36 ChVectorDynamic<>* state_x, ///< if != 0, update state (pos. part) to this, then evaluate F 37 ChVectorDynamic<>* state_w ///< if != 0, update state (speed part) to this, then evaluate F 38 ) = 0; 39 SetLoadable(std::shared_ptr<ChLoadableUV> mloadable)40 void SetLoadable(std::shared_ptr<ChLoadableUV> mloadable) { loadable = mloadable; } GetLoadable()41 virtual std::shared_ptr<ChLoadable> GetLoadable() override { return loadable; } GetLoadableUV()42 std::shared_ptr<ChLoadableUV> GetLoadableUV() { return loadable; } 43 }; 44 45 /// Class of loaders for ChLoadableUV objects (which support surface loads), for loads of distributed type, 46 /// so these loads will undergo Gauss quadrature to integrate them in the surface. 47 48 class ChLoaderUVdistributed : public ChLoaderUV { 49 public: ChLoaderUVdistributed(std::shared_ptr<ChLoadableUV> mloadable)50 ChLoaderUVdistributed(std::shared_ptr<ChLoadableUV> mloadable) : ChLoaderUV(mloadable){}; ~ChLoaderUVdistributed()51 virtual ~ChLoaderUVdistributed() {} 52 53 virtual int GetIntegrationPointsU() = 0; 54 virtual int GetIntegrationPointsV() = 0; 55 56 /// Computes Q = integral (N'*F*detJ dudvdz) ComputeQ(ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)57 virtual void ComputeQ(ChVectorDynamic<>* state_x, ///< if != 0, update state (pos. part) to this, then evaluate Q 58 ChVectorDynamic<>* state_w ///< if != 0, update state (speed part) to this, then evaluate Q 59 ) override { 60 Q.setZero(loadable->LoadableGet_ndof_w()); 61 ChVectorDynamic<> mF(loadable->Get_field_ncoords()); 62 mF.setZero(); 63 64 if (!loadable->IsTriangleIntegrationNeeded()) { 65 // Case of normal quadrilateral isoparametric coords 66 assert(GetIntegrationPointsU() <= ChQuadrature::GetStaticTables()->Weight.size()); 67 assert(GetIntegrationPointsV() <= ChQuadrature::GetStaticTables()->Weight.size()); 68 const std::vector<double>& Ulroots = ChQuadrature::GetStaticTables()->Lroots[GetIntegrationPointsU() - 1]; 69 const std::vector<double>& Uweight = ChQuadrature::GetStaticTables()->Weight[GetIntegrationPointsU() - 1]; 70 const std::vector<double>& Vlroots = ChQuadrature::GetStaticTables()->Lroots[GetIntegrationPointsV() - 1]; 71 const std::vector<double>& Vweight = ChQuadrature::GetStaticTables()->Weight[GetIntegrationPointsV() - 1]; 72 73 ChVectorDynamic<> mNF(Q.size()); // temporary value for loop 74 75 // Gauss quadrature : Q = sum (N'*F*detJ * wi*wj) 76 for (unsigned int iu = 0; iu < Ulroots.size(); iu++) { 77 for (unsigned int iv = 0; iv < Vlroots.size(); iv++) { 78 double detJ; 79 // Compute F= F(u,v) 80 this->ComputeF(Ulroots[iu], Vlroots[iv], mF, state_x, state_w); 81 // Compute mNF= N(u,v)'*F 82 loadable->ComputeNF(Ulroots[iu], Vlroots[iv], mNF, detJ, mF, state_x, state_w); 83 // Compute Q+= mNF detJ * wi*wj 84 mNF *= (detJ * Uweight[iu] * Vweight[iv]); 85 Q += mNF; 86 } 87 } 88 } else { 89 // case of triangle: use special 3d quadrature tables (given U,V,W orders, use the U only) 90 assert(GetIntegrationPointsU() <= ChQuadrature::GetStaticTablesTriangle()->Weight.size()); 91 const std::vector<double>& Ulroots = ChQuadrature::GetStaticTablesTriangle()->LrootsU[GetIntegrationPointsU() - 1]; 92 const std::vector<double>& Vlroots = ChQuadrature::GetStaticTablesTriangle()->LrootsV[GetIntegrationPointsU() - 1]; 93 const std::vector<double>& weight = ChQuadrature::GetStaticTablesTriangle()->Weight[GetIntegrationPointsU() - 1]; 94 95 ChVectorDynamic<> mNF(Q.size()); // temporary value for loop 96 97 // Gauss quadrature : Q = sum (N'*F*detJ * wi *1/2) often detJ= 2 * triangle area 98 for (unsigned int i = 0; i < Ulroots.size(); i++) { 99 double detJ; 100 // Compute F= F(u,v) 101 this->ComputeF(Ulroots[i], Vlroots[i], mF, state_x, state_w); 102 // Compute mNF= N(u,v)'*F 103 loadable->ComputeNF(Ulroots[i], Vlroots[i], mNF, detJ, mF, state_x, state_w); 104 // Compute Q+= mNF detJ * wi *1/2 105 mNF *= (detJ * weight[i] * (1. / 2.)); // (the 1/2 coefficient is not in the table); 106 Q += mNF; 107 } 108 } 109 } 110 }; 111 112 /// Class of loaders for ChLoadableUV objects (which support surface loads) of atomic type, 113 /// that is, with a concentrated load in a point Pu,Pv. 114 115 class ChLoaderUVatomic : public ChLoaderUV { 116 public: 117 double Pu; 118 double Pv; 119 ChLoaderUVatomic(std::shared_ptr<ChLoadableUV> mloadable)120 ChLoaderUVatomic(std::shared_ptr<ChLoadableUV> mloadable) : ChLoaderUV(mloadable), Pu(0), Pv(0) {} ~ChLoaderUVatomic()121 virtual ~ChLoaderUVatomic() {} 122 123 /// Computes Q = N'*F ComputeQ(ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)124 virtual void ComputeQ(ChVectorDynamic<>* state_x, ///< if != 0, update state (pos. part) to this, then evaluate Q 125 ChVectorDynamic<>* state_w ///< if != 0, update state (speed part) to this, then evaluate Q 126 ) override { 127 Q.setZero(loadable->LoadableGet_ndof_w()); 128 ChVectorDynamic<> mF(loadable->Get_field_ncoords()); 129 mF.setZero(); 130 131 // Compute F=F(u,v) 132 this->ComputeF(Pu, Pv, mF, state_x, state_w); 133 134 // Compute N(u,v)'*F 135 double detJ; 136 loadable->ComputeNF(Pu, Pv, Q, detJ, mF, state_x, state_w); 137 } 138 139 /// Set the position, on the surface where the atomic load is applied SetApplication(double mu,double mv)140 void SetApplication(double mu, double mv) { 141 Pu = mu; 142 Pv = mv; 143 } 144 }; 145 146 //-------------------------------------------------------------------------------- 147 // BASIC UV LOADERS 148 // 149 // Some ready-to use basic loaders 150 151 /// A very simple surface loader: a constant force vector, applied to a point on a u,v surface 152 153 class ChLoaderForceOnSurface : public ChLoaderUVatomic { 154 private: 155 ChVector<> force; 156 157 public: ChLoaderForceOnSurface(std::shared_ptr<ChLoadableUV> mloadable)158 ChLoaderForceOnSurface(std::shared_ptr<ChLoadableUV> mloadable) : ChLoaderUVatomic(mloadable) {} 159 ComputeF(const double U,const double V,ChVectorDynamic<> & F,ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)160 virtual void ComputeF(const double U, ///< parametric coordinate in surface 161 const double V, ///< parametric coordinate in surface 162 ChVectorDynamic<>& F, ///< Result F vector here, size must be = n.field coords.of loadable 163 ChVectorDynamic<>* state_x, ///< if != 0, update state (pos. part) to this, then evaluate F 164 ChVectorDynamic<>* state_w ///< if != 0, update state (speed part) to this, then evaluate F 165 ) override { 166 F.segment(0, 3) = force.eigen(); 167 } 168 // Set constant force (assumed in absolute coordinates) SetForce(ChVector<> mforce)169 void SetForce(ChVector<> mforce) { force = mforce; } 170 // Get constant force (assumed in absolute coordinates) GetForce()171 ChVector<> GetForce() { return force; } 172 IsStiff()173 virtual bool IsStiff() override { return false; } 174 }; 175 176 /// A very usual type of surface loader: the constant pressure load, a 3D per-area force that is aligned to the surface normal. 177 178 class ChLoaderPressure : public ChLoaderUVdistributed { 179 private: 180 double pressure; 181 bool is_stiff; 182 int num_integration_points; 183 184 public: ChLoaderPressure(std::shared_ptr<ChLoadableUV> mloadable)185 ChLoaderPressure(std::shared_ptr<ChLoadableUV> mloadable) 186 : ChLoaderUVdistributed(mloadable), is_stiff(false), num_integration_points(1) {} 187 ComputeF(const double U,const double V,ChVectorDynamic<> & F,ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)188 virtual void ComputeF(const double U, ///< parametric coordinate in surface 189 const double V, ///< parametric coordinate in surface 190 ChVectorDynamic<>& F, ///< Result F vector here, size must be = n.field coords.of loadable 191 ChVectorDynamic<>* state_x, ///< if != 0, update state (pos. part) to this, then evaluate F 192 ChVectorDynamic<>* state_w ///< if != 0, update state (speed part) to this, then evaluate F 193 ) override { 194 ChVector<> mnorm = this->loadable->ComputeNormal(U, V); 195 F.segment(0, 3) = -pressure * mnorm.eigen(); 196 } 197 SetPressure(double mpressure)198 void SetPressure(double mpressure) { pressure = mpressure; } GetPressure()199 double GetPressure() { return pressure; } 200 SetIntegrationPoints(int val)201 void SetIntegrationPoints(int val) { num_integration_points = val; } GetIntegrationPointsU()202 virtual int GetIntegrationPointsU() override { return num_integration_points; } GetIntegrationPointsV()203 virtual int GetIntegrationPointsV() override { return num_integration_points; } 204 SetStiff(bool val)205 void SetStiff(bool val) { is_stiff = val; } IsStiff()206 virtual bool IsStiff() override { return is_stiff; } 207 }; 208 209 } // end namespace chrono 210 211 #endif 212