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