File: ForceEngine.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 (123 lines) | stat: -rw-r--r-- 3,505 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
// 2004 © Janek Kozicki <cosurgi@berlios.de>
// 2009 © Václav Šmilauer <eudoxos@arcig.cz>

#include "ForceEngine.hpp"
#include <lib/high-precision/Constants.hpp>
#include <lib/smoothing/LinearInterpolate.hpp>
#include <core/Scene.hpp>
#include <pkg/common/Sphere.hpp>
#include <preprocessing/dem/Shop.hpp>

#include <core/IGeom.hpp>
#include <core/IPhys.hpp>

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

YADE_PLUGIN((ForceEngine)(InterpolatingDirectedForceEngine)(RadialForceEngine)(DragEngine)(LinearDragEngine)(HarmonicForceEngine));

void ForceEngine::action()
{
	FOREACH(Body::id_t id, ids)
	{
		if (!(scene->bodies->exists(id))) continue;
		scene->forces.addForce(id, force);
	}
}

void InterpolatingDirectedForceEngine::action()
{
	Real virtTime = wrap ? Shop::periodicWrap(scene->time, *times.begin(), *times.rbegin()) : scene->time;
	direction.normalize();
	force = linearInterpolate<Real, Real>(virtTime, times, magnitudes, _pos) * direction;
	ForceEngine::action();
}

void RadialForceEngine::postLoad(RadialForceEngine&) { axisDir.normalize(); }

void RadialForceEngine::action()
{
	FOREACH(Body::id_t id, ids)
	{
		if (!(scene->bodies->exists(id))) continue;
		const Vector3r& pos    = Body::byId(id, scene)->state->pos;
		Vector3r        radial = (pos - (axisPt + axisDir * /* t */ ((pos - axisPt).dot(axisDir)))).normalized();
		if (radial.squaredNorm() == 0) continue;
		scene->forces.addForce(id, fNorm * radial);
	}
}

void DragEngine::action()
{
	FOREACH(Body::id_t id, ids)
	{
		Body* b = Body::byId(id, scene).get();
		if (!b) continue;
		if (!(scene->bodies->exists(id))) continue;
		const Sphere* sphere = dynamic_cast<Sphere*>(b->shape.get());
		if (sphere) {
			Real     A          = sphere->radius * sphere->radius * Mathr::PI; //Crossection of the sphere
			Vector3r velSphTemp = Vector3r::Zero();
			Vector3r dragForce  = Vector3r::Zero();

			if (scene->isPeriodic) {
				velSphTemp = scene->cell->bodyFluctuationVel(b->state->pos, b->state->vel, scene->cell->prevVelGrad);
			} else {
				velSphTemp = b->state->vel;
			}

			if (velSphTemp != Vector3r::Zero()) { dragForce = -0.5 * Rho * A * Cd * velSphTemp.squaredNorm() * velSphTemp.normalized(); }
			scene->forces.addForce(id, dragForce);
		}
	}
}

void LinearDragEngine::action()
{
	FOREACH(Body::id_t id, ids)
	{
		Body* b = Body::byId(id, scene).get();
		if (!b) continue;
		if (!(scene->bodies->exists(id))) continue;
		const Sphere* sphere = dynamic_cast<Sphere*>(b->shape.get());
		if (sphere) {
			Vector3r velSphTemp = Vector3r::Zero();

			if (scene->isPeriodic) {
				velSphTemp = scene->cell->bodyFluctuationVel(b->state->pos, b->state->vel, scene->cell->prevVelGrad);
			} else {
				velSphTemp = b->state->vel;
			}

			Vector3r dragForce = Vector3r::Zero();

			Real b2 = 6. * Mathr::PI * nu * sphere->radius;

			if (velSphTemp != Vector3r::Zero()) { dragForce = -b2 * velSphTemp; }
			scene->forces.addForce(id, dragForce);
		}
	}
}

void HarmonicForceEngine::action()
{
	if (ids.size() > 0) {
		Vector3r w = f * 2.0 * Mathr::PI; //Angular frequency

		Vector3r force = (((w * scene->time + fi).array().sin()));

		force = force.cwiseProduct(A);

		FOREACH(Body::id_t id, ids)
		{
			assert(id < (Body::id_t)scene->bodies->size());
			Body* b = Body::byId(id, scene).get();
			if (!b) continue;
			if (!(scene->bodies->exists(id))) continue;
			scene->forces.addForce(id, force);
		}
	} else {
		LOG_WARN("The list of ids is empty! Can't apply any forces.");
	}
}

} // namespace yade