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 // Authors: Alessandro Tasora, Radu Serban, Rainer Gericke
13 // =============================================================================
14
15 #include "chrono/physics/ChShaft.h"
16 #include "chrono/physics/ChShaftsTorqueConverter.h"
17 #include "chrono/physics/ChSystem.h"
18
19 namespace chrono {
20
21 // Register into the object factory, to enable run-time dynamic creation and persistence
CH_FACTORY_REGISTER(ChShaftsTorqueConverter)22 CH_FACTORY_REGISTER(ChShaftsTorqueConverter)
23
24 ChShaftsTorqueConverter::ChShaftsTorqueConverter()
25 : shaft1(NULL),
26 shaft2(NULL),
27 shaft_stator(NULL),
28 torque_in(0),
29 torque_out(0),
30 state_warning_reverseflow(false),
31 state_warning_wrongimpellerdirection(false) {
32 K = chrono_types::make_shared<ChFunction_Const>(0.9);
33 T = chrono_types::make_shared<ChFunction_Const>(0.9);
34 }
35
ChShaftsTorqueConverter(const ChShaftsTorqueConverter & other)36 ChShaftsTorqueConverter::ChShaftsTorqueConverter(const ChShaftsTorqueConverter& other) : ChPhysicsItem(other) {
37 shaft1 = NULL;
38 shaft2 = NULL;
39 shaft_stator = NULL;
40
41 torque_in = other.torque_in;
42 torque_out = other.torque_out;
43
44 state_warning_reverseflow = other.state_warning_reverseflow;
45 state_warning_wrongimpellerdirection = other.state_warning_wrongimpellerdirection;
46
47 K = std::shared_ptr<ChFunction>(other.K->Clone()); // deep copy
48 T = std::shared_ptr<ChFunction>(other.T->Clone()); // deep copy
49 }
50
Initialize(std::shared_ptr<ChShaft> mshaft1,std::shared_ptr<ChShaft> mshaft2,std::shared_ptr<ChShaft> mshaft_stator)51 bool ChShaftsTorqueConverter::Initialize(std::shared_ptr<ChShaft> mshaft1, // input shaft
52 std::shared_ptr<ChShaft> mshaft2, // output shaft
53 std::shared_ptr<ChShaft> mshaft_stator // stator shaft (often fixed)
54 ) {
55 ChShaft* mm1 = mshaft1.get();
56 ChShaft* mm2 = mshaft2.get();
57 ChShaft* mm_stator = mshaft_stator.get();
58 assert(mm1 && mm2 && mm_stator);
59 assert((mm1 != mm2) && (mm1 != mm_stator));
60 assert((mm1->GetSystem() == mm2->GetSystem()) && (mm1->GetSystem() == mm_stator->GetSystem()));
61
62 shaft1 = mm1;
63 shaft2 = mm2;
64 shaft_stator = mm_stator;
65
66 SetSystem(shaft1->GetSystem());
67
68 return true;
69 }
70
GetSpeedRatio() const71 double ChShaftsTorqueConverter::GetSpeedRatio() const {
72 double wrel1 = shaft1->GetPos_dt() - shaft_stator->GetPos_dt();
73 double wrel2 = shaft2->GetPos_dt() - shaft_stator->GetPos_dt();
74
75 if ((fabs(wrel1) < 10e-9) || (fabs(wrel2) < 10e-9))
76 return 0;
77
78 return wrel2 / wrel1;
79 }
80
Update(double mytime,bool update_assets)81 void ChShaftsTorqueConverter::Update(double mytime, bool update_assets) {
82 // Inherit time changes of parent class
83 ChPhysicsItem::Update(mytime, update_assets);
84
85 // update class data
86
87 state_warning_wrongimpellerdirection = false;
88 state_warning_reverseflow = false;
89
90 // Compute actual speed ratio
91 double mR = GetSpeedRatio();
92
93 // The speed ratio must always be in the [0...1] range,
94 // anyway let's correct singular cases:
95
96 // - it should be unusual that speed ratio >1, say if the impeller
97 // outruns turbine (if there's a clutch lock-in, this should happen).
98 // If so, assume a reflection of T curve and a polar reflection of K curve, after 1.
99 if (mR > 1) {
100 mR = 1 - (mR - 1);
101 state_warning_reverseflow = true;
102 }
103
104 // - if the output shaft is spinning a bit backward, when
105 // close to stall, maybe win/wout < 0. If so, set as stall anyway:
106 if (mR < 0)
107 mR = 0;
108
109 // - if input impeller shaft is spinning in negative direction,
110 // this is assumed as an error: set all torques to zero and bail out:
111 if (shaft1->GetPos_dt() - shaft_stator->GetPos_dt() < 0) {
112 state_warning_wrongimpellerdirection = true;
113 torque_in = 0;
114 torque_out = 0;
115 return;
116 }
117
118 // Compute actual capacity factor
119 double mK = K->Get_y(mR);
120
121 // Compute actual torque factor
122 double mT = T->Get_y(mR);
123
124 // compute input torque (with minus sign because applied TO input thaft)
125 torque_in = -pow((shaft1->GetPos_dt() / mK), 2);
126
127 if (state_warning_reverseflow)
128 torque_in = -torque_in;
129
130 // compute output torque (with opposite sign because
131 // applied to output shaft, with same direction of input shaft)
132 if (state_warning_reverseflow) {
133 // in reverse flow situation the converter is always in clutch mode (TR=1)
134 // so the torque cannot be increased
135 torque_out = -torque_in;
136
137 } else {
138 torque_out = -mT * torque_in;
139 }
140 }
141
142 //// STATE BOOKKEEPING FUNCTIONS
143
IntLoadResidual_F(const unsigned int off,ChVectorDynamic<> & R,const double c)144 void ChShaftsTorqueConverter::IntLoadResidual_F(const unsigned int off, // offset in R residual
145 ChVectorDynamic<>& R, // result: the R residual, R += c*F
146 const double c // a scaling factor
147 ) {
148 if (shaft1->IsActive())
149 R(shaft1->GetOffset_w()) += torque_in * c;
150 if (shaft2->IsActive())
151 R(shaft2->GetOffset_w()) += torque_out * c;
152 if (shaft_stator->IsActive())
153 R(shaft_stator->GetOffset_w()) += GetTorqueReactionOnStator() * c;
154 }
155
156 // SOLVER INTERFACES
157
VariablesFbLoadForces(double factor)158 void ChShaftsTorqueConverter::VariablesFbLoadForces(double factor) {
159 // Apply torques to the three connected 1D variables:
160 shaft1->Variables().Get_fb()(0) += torque_in * factor;
161 shaft2->Variables().Get_fb()(0) += torque_out * factor;
162 shaft_stator->Variables().Get_fb()(0) += GetTorqueReactionOnStator() * factor;
163 }
164
165 // FILE I/O
166
ArchiveOUT(ChArchiveOut & marchive)167 void ChShaftsTorqueConverter::ArchiveOUT(ChArchiveOut& marchive) {
168 // version number
169 marchive.VersionWrite<ChShaftsTorqueConverter>();
170
171 // serialize parent class
172 ChPhysicsItem::ArchiveOUT(marchive);
173
174 // serialize all member data:
175 marchive << CHNVP(K);
176 marchive << CHNVP(T);
177 // marchive << CHNVP(shaft1); //***TODO*** serialize with shared ptr
178 // marchive << CHNVP(shaft2); //***TODO*** serialize with shared ptr
179 // marchive << CHNVP(shaft_stator); //***TODO*** serialize with shared ptr
180 }
181
182 /// Method to allow de serialization of transient data from archives.
ArchiveIN(ChArchiveIn & marchive)183 void ChShaftsTorqueConverter::ArchiveIN(ChArchiveIn& marchive) {
184 // version number
185 /*int version =*/ marchive.VersionRead<ChShaftsTorqueConverter>();
186
187 // deserialize parent class:
188 ChPhysicsItem::ArchiveIN(marchive);
189
190 // deserialize all member data:
191 marchive >> CHNVP(K);
192 marchive >> CHNVP(T);
193 // marchive >> CHNVP(shaft1); //***TODO*** serialize with shared ptr
194 // marchive >> CHNVP(shaft2); //***TODO*** serialize with shared ptr
195 // marchive >> CHNVP(shaft_stator); //***TODO*** serialize with shared ptr
196 }
197
198 } // end namespace chrono