1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/aero/gust.cc,v 1.18 2017/01/12 14:45:58 masarati Exp $ */
2 /*
3 * MBDyn (C) is a multibody analysis code.
4 * http://www.mbdyn.org
5 *
6 * Copyright (C) 1996-2017
7 *
8 * Pierangelo Masarati <masarati@aero.polimi.it>
9 * Paolo Mantegazza <mantegazza@aero.polimi.it>
10 *
11 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12 * via La Masa, 34 - 20156 Milano, Italy
13 * http://www.aero.polimi.it
14 *
15 * Changing this copyright notice is forbidden.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation (version 2 of the License).
20 *
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31
32 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
33
34 #include "gust.h"
35 #include "dataman.h"
36 #include "drive_.h"
37
38 #include "windprof.h"
39
40 /* Gust - begin */
41
~Gust(void)42 Gust::~Gust(void)
43 {
44 NO_OP;
45 }
46
47 void
SetAirProperties(const AirProperties * pap)48 Gust::SetAirProperties(const AirProperties *pap)
49 {
50 ASSERT(pap != 0);
51 pAP = pap;
52 }
53
54 Vec3
GetVelocity(const Vec3 & X) const55 Gust::GetVelocity(const Vec3& X) const
56 {
57 Vec3 V(Zero3);
58 GetVelocity(X, V);
59 return V;
60 }
61
~GustRead(void)62 GustRead::~GustRead(void)
63 {
64 NO_OP;
65 }
66
67 /* Gust - end */
68
69 /* Gust1D - begin */
70
71 class Gust1D : public Gust {
72 private:
73 Vec3 FrontDir;
74 Vec3 GustDir;
75 doublereal dVRef;
76 DriveOwner Time;
77 DriveOwner GustProfile;
78
79 public:
80 Gust1D(const Vec3& f, const Vec3& g, const doublereal& v,
81 DriveCaller *pT, DriveCaller *pG);
82 ~Gust1D(void);
83
84 virtual std::ostream& Restart(std::ostream& out) const;
85 bool GetVelocity(const Vec3& X, Vec3& V) const;
86 };
87
Gust1D(const Vec3 & f,const Vec3 & g,const doublereal & v,DriveCaller * pT,DriveCaller * pG)88 Gust1D::Gust1D(const Vec3& f, const Vec3& g, const doublereal& v,
89 DriveCaller *pT, DriveCaller *pG)
90 : FrontDir(f),
91 GustDir(g),
92 dVRef(v),
93 Time(pT),
94 GustProfile(pG)
95 {
96 ASSERT(pT != NULL);
97 ASSERT(pG != NULL);
98 }
99
~Gust1D(void)100 Gust1D::~Gust1D(void)
101 {
102 NO_OP;
103 }
104
105 std::ostream&
Restart(std::ostream & out) const106 Gust1D::Restart(std::ostream& out) const
107 {
108 out << "front 1D, ",
109 FrontDir.Write(out, ", ")
110 << ", ", GustDir.Write(out, ", ")
111 << ", " << dVRef
112 << ", ", GustProfile.pGetDriveCaller()->Restart(out);
113 return out;
114 }
115
116 bool
GetVelocity(const Vec3 & X,Vec3 & V) const117 Gust1D::GetVelocity(const Vec3& X, Vec3& V) const
118 {
119 doublereal x = FrontDir*X + dVRef*Time.dGet();
120 doublereal v = GustProfile.dGet(x);
121 V = GustDir*v;
122 return true;
123 }
124
125 /* reads a front 1D gust */
126 struct Gust1DGR : public GustRead {
127 public:
128 virtual ~Gust1DGR(void);
129 virtual Gust *
130 Read(const DataManager* pDM, MBDynParser& HP);
131 };
132
~Gust1DGR(void)133 Gust1DGR::~Gust1DGR(void)
134 {
135 NO_OP;
136 }
137
138 Gust *
Read(const DataManager * pDM,MBDynParser & HP)139 Gust1DGR::Read(const DataManager* pDM, MBDynParser& HP)
140 {
141 /* front direction */
142 Vec3 f = HP.GetVecAbs(::AbsRefFrame);
143
144 /* gust velocity direction */
145 Vec3 g = HP.GetVecAbs(::AbsRefFrame);
146
147 /* reference velocity */
148 doublereal v = HP.GetReal();
149
150 /* time drive caller
151 * FIXME: not needed if v = 0 */
152 DriveCaller *pT = NULL;
153 SAFENEWWITHCONSTRUCTOR(pT, TimeDriveCaller,
154 TimeDriveCaller(pDM->pGetDrvHdl()));
155
156 /* gust profile drive caller */
157 DriveCaller *pP = HP.GetDriveCaller();
158
159 /* gust */
160 Gust *pG = 0;
161 SAFENEWWITHCONSTRUCTOR(pG, Gust1D, Gust1D(f, g, v, pT, pP));
162
163 return pG;
164 }
165
166 /* Gust1D - end */
167
168 /* bag that contains functions to parse gusts */
169
170 typedef std::map<std::string, GustRead *, ltstrcase> GustFuncMapType;
171 static GustFuncMapType GustFuncMap;
172
173 struct GustWordSetType : public HighParser::WordSet {
IsWordGustWordSetType174 bool IsWord(const std::string& s) const {
175 return GustFuncMap.find(s) != GustFuncMap.end();
176 };
177 };
178
179 static GustWordSetType GustWordSet;
180
181 bool
SetGustData(const char * name,GustRead * rf)182 SetGustData(const char *name, GustRead *rf)
183 {
184 pedantic_cout("registering gust \"" << name << "\"" << std::endl);
185 return GustFuncMap.insert(GustFuncMapType::value_type(name, rf)).second;
186 }
187
188 // read gust data
189 Gust *
ReadGustData(const DataManager * pDM,MBDynParser & HP)190 ReadGustData(const DataManager* pDM, MBDynParser& HP)
191 {
192 DEBUGCOUTFNAME("ReadGustData()");
193
194 const char *s = HP.IsWord(GustWordSet);
195 if (s == 0) {
196 return 0;
197 }
198
199 GustFuncMapType::iterator func = GustFuncMap.find(std::string(s));
200 if (func == GustFuncMap.end()) {
201 silent_cerr("unknown gust type \"" << s << "\" "
202 "at line " << HP.GetLineData() << std::endl);
203 throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
204 }
205
206 return func->second->Read(pDM, HP);
207 }
208
209 static unsigned done;
210
211 void
InitGustData(void)212 InitGustData(void)
213 {
214 if (::done++ > 0) {
215 return;
216 }
217
218 SetGustData("front" "1D", new Gust1DGR);
219 SetGustData("scalar" "function", new ScalarFuncGR);
220 SetGustData("power" "law", new PowerLawGR);
221 SetGustData("logarithmic", new LogarithmicGR);
222
223 /* NOTE: add here initialization of new built-in drive callers;
224 * alternative ways to register new custom gust models are:
225 * - call SetGustData() from anywhere in the code
226 * - write a module that calls SetGustData() from inside a function
227 * called module_init(), and run-time load it using "module load"
228 * in the input file.
229 */
230 }
231
232 void
DestroyGustData(void)233 DestroyGustData(void)
234 {
235 if (::done == 0) {
236 silent_cerr("DestroyGustData() called once too many" << std::endl);
237 throw DataManager::ErrGeneric(MBDYN_EXCEPT_ARGS);
238 }
239
240 if (--::done > 0) {
241 return;
242 }
243
244 /* free stuff */
245 for (GustFuncMapType::iterator i = GustFuncMap.begin(); i != GustFuncMap.end(); ++i) {
246 delete i->second;
247 }
248 GustFuncMap.clear();
249 }
250
251