File: Disp2DPropLoadEngine.cpp

package info (click to toggle)
yade 2026.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 34,448 kB
  • sloc: cpp: 97,645; python: 52,173; sh: 677; makefile: 162
file content (215 lines) | stat: -rw-r--r-- 8,491 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*************************************************************************
*  Copyright (C) 2008 by Jerome Duriez                                   *
*  jerome.duriez@hmg.inpg.fr                                             *
*                                                                        *
*  This program is free software; it is licensed under the terms of the  *
*  GNU General Public License v2 or later. See file LICENSE for details. *
*************************************************************************/


#include "Disp2DPropLoadEngine.hpp"
#include <lib/base/Math.hpp>
#include <lib/high-precision/Constants.hpp>
#include <core/Scene.hpp>
#include <core/State.hpp>
#include <pkg/common/Box.hpp>

#include <boost/filesystem.hpp>

namespace yade { // Cannot have #include directive inside.

YADE_PLUGIN((Disp2DPropLoadEngine));

void Disp2DPropLoadEngine::postLoad(Disp2DPropLoadEngine&)
{
	std::string outputFile = "DirSearch" + Key + "Yade";
	ofile.open(outputFile.c_str(), std::ios::app);
	if (!boost::filesystem::exists(outputFile.c_str()))
		ofile << "theta (!angle in plane (gamma,-du) ) dtau (kPa) dsigma (kPa) dgamma (m) du (m) tau0 (kPa) sigma0 (kPa) d2W coordSs0 coordTot0 "
		         "coordSsF coordTotF (Yade)"
		      << endl;
}


void Disp2DPropLoadEngine::action()
{
	if (LOG) cerr << "debut applyCondi !!" << endl;
	leftbox  = Body::byId(id_boxleft);
	rightbox = Body::byId(id_boxright);
	frontbox = Body::byId(id_boxfront);
	backbox  = Body::byId(id_boxback);
	topbox   = Body::byId(id_topbox);
	boxbas   = Body::byId(id_boxbas);

	if (firstIt) {
		it_begin       = scene->iter;
		H0             = topbox->state->pos.y();
		X0             = topbox->state->pos.x();
		Vector3r F_sup = scene->forces.getForce(id_topbox);
		Fn0            = F_sup.y();
		Ft0            = F_sup.x();

		Real OnlySsInt = 0 // the half number of real sphere-sphere (only) interactions, at the beginning of the perturbation
		        ,
		     TotInt = 0 // the half number of all the real interactions, at the beginning of the perturbation
		        ;

		InteractionContainer::iterator ii    = scene->interactions->begin();
		InteractionContainer::iterator iiEnd = scene->interactions->end();
		for (; ii != iiEnd; ++ii) {
			if ((*ii)->isReal()) {
				TotInt += 1;
				const shared_ptr<Body>& b1 = Body::byId((*ii)->getId1());
				const shared_ptr<Body>& b2 = Body::byId((*ii)->getId2());
				if ((b1->isDynamic()) && (b2->isDynamic())) OnlySsInt += 1;
			}
		}

		coordSs0  = OnlySsInt / 8590; // 8590 is the number of spheres in the CURRENT case
		coordTot0 = TotInt / 8596;    // 8596 is the number of bodies in the CURRENT case

		firstIt = false;
	}


	if ((scene->iter - it_begin) < nbre_iter) {
		letDisturb();
	} else if ((scene->iter - it_begin) == nbre_iter) {
		stopMovement();
		string fileName = Key + "DR" + boost::lexical_cast<string>(nbre_iter) + "ItAtV_" + boost::lexical_cast<string>(v) + "done.xml";
		// 		Omega::instance().saveSimulation ( fileName );
		saveData();
	}
}

void Disp2DPropLoadEngine::letDisturb()
{
	const Real& dt = scene->dt;
	dgamma         = cos(theta * Mathr::PI / 180.0) * v * dt;
	dh             = sin(theta * Mathr::PI / 180.0) * v * dt;

	Real Ysup = topbox->state->pos.y();
	Real Ylat = leftbox->state->pos.y();

	// 	Changes in vertical and horizontal position :
	topbox->state->pos += Vector3r(dgamma, dh, 0);

	leftbox->state->pos += Vector3r(dgamma / 2.0, dh / 2.0, 0);
	rightbox->state->pos += Vector3r(dgamma / 2.0, dh / 2.0, 0);

	Real Ysup_mod = topbox->state->pos.y();
	Real Ylat_mod = leftbox->state->pos.y();

	//	with the corresponding velocities :
	topbox->state->vel = Vector3r(dgamma / dt, dh / dt, 0);

	leftbox->state->vel = Vector3r((dgamma / dt) / 2.0, dh / (2.0 * dt), 0);

	rightbox->state->vel = Vector3r((dgamma / dt) / 2.0, dh / (2.0 * dt), 0);

	//	Then computation of the angle of the rotation to be done :
	computeAlpha();
	if (alpha == Mathr::PI / 2.0) // Case of the very beginning
	{
		dalpha = -atan(dgamma / (Ysup_mod - Ylat_mod));
	} else {
		Real A = (Ysup_mod - Ylat_mod) * 2.0 * tan(alpha) / (2.0 * (Ysup - Ylat) + dgamma * tan(alpha));
		dalpha = atan((A - tan(alpha)) / (1.0 + A * tan(alpha)));
	}

	Quaternionr qcorr(AngleAxisr(dalpha, Vector3r::UnitZ()));
	if (LOG) cout << "Quaternion associe a la rotation incrementale : " << qcorr.w() << " " << qcorr.x() << " " << qcorr.y() << " " << qcorr.z() << endl;

	// On applique la rotation en changeant l'orientation des plaques, leurs vang et en affectant donc alpha
	leftbox->state->ori    = qcorr * leftbox->state->ori;
	leftbox->state->angVel = Vector3r(0, 0, 1) * dalpha / dt;

	rightbox->state->ori    = qcorr * leftbox->state->ori;
	rightbox->state->angVel = Vector3r(0, 0, 1) * dalpha / dt;
}


void Disp2DPropLoadEngine::computeAlpha()
{
	Quaternionr orientationLeftBox, orientationRightBox;
	orientationLeftBox  = leftbox->state->ori;
	orientationRightBox = rightbox->state->ori;
	if (orientationLeftBox.matrix() != orientationRightBox.matrix()) {
		cout << "WARNING !!! your lateral boxes have not the same orientation, you're not in the case of a box imagined for creating these engines"
		     << endl;
	}
	AngleAxisr aa(orientationLeftBox);
	alpha = Mathr::PI / 2.0
	        - aa.angle(); // right if the initial orientation of the body (on the beginning of the simulation) is q =(1,0,0,0) = FromAxisAngle((0,0,1),0)
}


void Disp2DPropLoadEngine::stopMovement()
{
	// annulation de la vitesse de la plaque du haut
	topbox->state->vel = Vector3r(0, 0, 0);

	// de la plaque gauche
	leftbox->state->vel    = Vector3r(0, 0, 0);
	leftbox->state->angVel = Vector3r(0, 0, 0);

	// de la plaque droite
	rightbox->state->vel    = Vector3r(0, 0, 0);
	rightbox->state->angVel = Vector3r(0, 0, 0);
}


void Disp2DPropLoadEngine::saveData()
{
	Real Xleft = leftbox->state->pos.x() + (YADE_CAST<Box*>(leftbox->shape.get()))->extents.x();

	Real Xright = rightbox->state->pos.x() - (YADE_CAST<Box*>(rightbox->shape.get()))->extents.x();

	Real Zfront = frontbox->state->pos.z() - YADE_CAST<Box*>(frontbox->shape.get())->extents.z();
	Real Zback  = backbox->state->pos.z() + (YADE_CAST<Box*>(backbox->shape.get()))->extents.z();

	Real Scontact = (Xright - Xleft) * (Zfront - Zback); // that's so the value of section at the middle of the height of the box

	InteractionContainer::iterator ii    = scene->interactions->begin();
	InteractionContainer::iterator iiEnd = scene->interactions->end();

	Real OnlySsInt = 0 // the half number of real sphere-sphere (only) interactions, at the end of the perturbation
	        ,
	     TotInt = 0 // the half number of all the real interactions, at the end of the perturbation
	        ;
	for (; ii != iiEnd; ++ii) {
		if ((*ii)->isReal()) {
			TotInt += 1;
			const shared_ptr<Body>& b1 = Body::byId((*ii)->getId1());
			const shared_ptr<Body>& b2 = Body::byId((*ii)->getId2());
			if ((b1->isDynamic()) && (b2->isDynamic())) OnlySsInt += 1;
		}
	}

	Real coordSs     = OnlySsInt / 8590, // 8590 is the number of spheres in the CURRENT case
	        coordTot = TotInt / 8596;    // 8596 is the number of bodies in the CURRENT case

	Vector3r F_sup = scene->forces.getForce(id_topbox);

	// declaration of ‘dgamma’ shadows a member of ‘yade::Disp2DPropLoadEngine’ [-Werror=shadow]
	Real dFn = F_sup.y() - Fn0 // OK pour le signe
	        ,
	     dFt = (F_sup.x() - Ft0), du = -(topbox->state->pos.y() - H0) // OK pour le signe (>0 en compression)
	        ,
	     dgamma2 = topbox->state->pos.x() - X0, SigN0 = (Fn0 / Scontact) / 1000 // en kPa, pour comparer à Fortran
	        ,
	     Tau0 = -(Ft0 / Scontact) / 1000 // en kPa, pour comparer à Fortran, Ok pour le signe, cf p. Yade29
	        ,
	     dSigN = (dFn / Scontact) / 1000 // Ok pour le signe
	        ,
	     dTau = -(dFt / Scontact) / 1000 // Ok pour le signe, idem que Tau0
	        ,
	     d2W = dSigN * du + dTau * dgamma2;

	ofile << boost::lexical_cast<string>(theta) << " " << boost::lexical_cast<string>(dTau) << " " << boost::lexical_cast<string>(dSigN) << " "
	      << boost::lexical_cast<string>(dgamma2) << " " << boost::lexical_cast<string>(du) << " " << boost::lexical_cast<string>(Tau0) << " "
	      << boost::lexical_cast<string>(SigN0) << " " << boost::lexical_cast<string>(d2W) << " " << boost::lexical_cast<string>(coordSs0) << " "
	      << boost::lexical_cast<string>(coordTot0) << " " << boost::lexical_cast<string>(coordSs) << " " << boost::lexical_cast<string>(coordTot) << endl;
}

} // namespace yade