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