KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
GeometryFunctions.h
Go to the documentation of this file.
1 /*
2  * File: GeometryFunctions.h
3  * Author: msantasusana, Chun Feng
4  *
5  * Created on 21 de mayo de 2012, 19:40
6  */
7 
8 #ifndef _GEOMETRYFUNCTIONS_H
9 #define _GEOMETRYFUNCTIONS_H
10 
11 #include <cmath>
12 #include "utilities/openmp_utils.h"
13 #include "utilities/quaternion.h"
14 #include "includes/model_part.h"
16 
17 namespace Kratos {
18 
19  namespace GeometryFunctions {
20 
22 
24  const double ang, array_1d<double, 3>& new_vec) {
25  double cang = std::cos(ang);
26  double sang = std::sin(ang);
27 
28  new_vec[0] = axis[0] * (axis[0] * old_vec[0] + axis[1] * old_vec[1] + axis[2] * old_vec[2]) * (1 - cang) + old_vec[0] * cang + (-axis[2] * old_vec[1] + axis[1] * old_vec[2]) * sang;
29  new_vec[1] = axis[1] * (axis[0] * old_vec[0] + axis[1] * old_vec[1] + axis[2] * old_vec[2]) * (1 - cang) + old_vec[1] * cang + ( axis[2] * old_vec[0] - axis[0] * old_vec[2]) * sang;
30  new_vec[2] = axis[2] * (axis[0] * old_vec[0] + axis[1] * old_vec[1] + axis[2] * old_vec[2]) * (1 - cang) + old_vec[2] * cang + (-axis[1] * old_vec[0] + axis[0] * old_vec[1]) * sang;
31  }
32 
33  static inline void TranslateGridOfNodes(const double time, const double velocity_start_time, const double velocity_stop_time, array_1d<double, 3>& center_position,
34  const array_1d<double, 3>& initial_center, array_1d<double, 3>& previous_displ, array_1d<double, 3>& linear_velocity_changed,
35  const double linear_period, const double dt, const array_1d<double, 3>& linear_velocity) {
36 
37  if (time < velocity_start_time || time > velocity_stop_time) {
38  center_position[0] = initial_center[0] + previous_displ[0];
39  center_position[1] = initial_center[1] + previous_displ[1];
40  center_position[2] = initial_center[2] + previous_displ[2];
41  linear_velocity_changed = ZeroVector(3);
42  } else {
43  if (linear_period > 0.0) {
44  double linear_omega = 2.0 * Globals::Pi / linear_period;
45  double inv_linear_omega = 1.0 / linear_omega;
46  noalias(center_position) = initial_center + linear_velocity * std::sin(linear_omega * (time - velocity_start_time)) * inv_linear_omega;
47  noalias(linear_velocity_changed) = linear_velocity * std::cos(linear_omega * (time - velocity_start_time));
48  noalias(previous_displ) = center_position - initial_center;
49  } else {
50  center_position[0] = initial_center[0] + previous_displ[0] + dt * linear_velocity[0];
51  center_position[1] = initial_center[1] + previous_displ[1] + dt * linear_velocity[1];
52  center_position[2] = initial_center[2] + previous_displ[2] + dt * linear_velocity[2];
53  previous_displ[0] += dt * linear_velocity[0];
54  previous_displ[1] += dt * linear_velocity[1];
55  previous_displ[2] += dt * linear_velocity[2];
56  linear_velocity_changed = linear_velocity;
57  }
58  }
59  }
60 
61  static inline int sign(const double a)
62  {
63  return (0.0 < a) - (a < 0.0);
64  /*int output;
65  if (a < 0.0) output = -1;
66  else if (a > 0.0) output = 1;
67  else output = 0;
68  return output;*/
69  }
70 
71  static inline double min(double a, double b)
72  {
73  double output;
74  if (a<=b) output = a;
75  else output = b;
76  return output;
77  }
78 
79  static inline double max(double a, double b)
80  {
81  double output;
82  if (a>=b) output = a;
83  else output = b;
84  return output;
85  }
86 
87  static inline void normalize(double Vector[3])
88  {
89  double distance = DEM_INNER_PRODUCT_3(Vector, Vector);
90  double inv_distance = (distance > 0.0) ? 1.0 / sqrt(distance) : 0.00;
91 
92  Vector[0] = Vector[0] * inv_distance;
93  Vector[1] = Vector[1] * inv_distance;
94  Vector[2] = Vector[2] * inv_distance;
95  }
96 
97  static inline void normalize(array_1d<double,3>& Vector, double& distance)
98  {
99  distance = DEM_MODULUS_3(Vector);
100  double inv_distance = (distance != 0.0) ? 1.0 / distance : 0.00;
101 
102  Vector[0] = Vector[0] * inv_distance;
103  Vector[1] = Vector[1] * inv_distance;
104  Vector[2] = Vector[2] * inv_distance;
105  }
106 
107  static inline void normalize(double Vector[3], double& distance)
108  {
109  distance = DEM_MODULUS_3(Vector);
110  double inv_distance = (distance != 0.0) ? 1.0 / distance : 0.00;
111 
112  Vector[0] = Vector[0] * inv_distance;
113  Vector[1] = Vector[1] * inv_distance;
114  Vector[2] = Vector[2] * inv_distance;
115  }
116 
117  static inline void normalize(array_1d<double,3>& Vector)
118  {
119  double distance = DEM_MODULUS_3(Vector);
120  double inv_distance = (distance != 0.0) ? 1.0 / distance : 0.00;
121 
122  Vector[0] = Vector[0] * inv_distance;
123  Vector[1] = Vector[1] * inv_distance;
124  Vector[2] = Vector[2] * inv_distance;
125  }
126 
127  static inline void module(const array_1d<double,3>& Vector, double& distance)
128  {
129  distance = DEM_MODULUS_3(Vector);
130  }
131 
132  static inline double module(const double Vector[3])
133  {
134  return DEM_MODULUS_3(Vector);
135  }
136 
137  static inline void module(const double Vector[3], double& distance)
138  {
139  distance = DEM_MODULUS_3(Vector);
140  }
141 
142  static inline double module(const array_1d<double,3>& Vector)
143  {
144  double distance = DEM_MODULUS_3(Vector);
145  return distance;
146  }
147 
148  static inline void VectorGlobal2Local(const double LocalCoordSystem[3][3], const double GlobalVector[3], double LocalVector[3])
149  {
150  for (int i=0; i<3; i++) {
151  LocalVector[i] = 0.0;
152  for (int j=0; j<3; j++) {
153  LocalVector[i]+=LocalCoordSystem[i][j]*GlobalVector[j];
154  }
155  }
156  }
157 
158  static inline void VectorGlobal2Local(const double LocalCoordSystem[3][3], const array_1d<double, 3>& GlobalVector, array_1d<double, 3>& LocalVector)
159  {
160  for (int i=0; i<3; i++) {
161  LocalVector[i] = 0.0;
162  for (int j=0; j<3; j++) {
163  LocalVector[i]+=LocalCoordSystem[i][j]*GlobalVector[j];
164  }
165  }
166  }
167 
168  static inline void VectorGlobal2Local(const double LocalCoordSystem[3][3], const array_1d<double, 3>& GlobalVector, double LocalVector[3])
169  {
170  for (int i=0; i<3; i++) {
171  LocalVector[i] = 0.0;
172  for (int j=0; j<3; j++) {
173  LocalVector[i]+=LocalCoordSystem[i][j]*GlobalVector[j];
174  }
175  }
176  }
177 
178  static inline void VectorLocal2Global(const double LocalCoordSystem[3][3], const double LocalVector[3], double GlobalVector[3])
179  {
180  for (int i=0; i<3; i++) {
181  GlobalVector[i] = 0.0;
182  for (int j=0; j<3; j++) {
183  GlobalVector[i]+=LocalCoordSystem[j][i]*LocalVector[j];
184  }
185  }
186  }
187 
188  static inline void VectorLocal2Global(const double LocalCoordSystem[3][3], const array_1d<double, 3>& LocalVector, array_1d<double, 3>& GlobalVector)
189  {
190  for (int i=0; i<3; i++) {
191  GlobalVector[i] = 0.0;
192  for (int j=0; j<3; j++) {
193  GlobalVector[i]+=LocalCoordSystem[j][i]*LocalVector[j];
194  }
195  }
196  }
197 
198  static inline void VectorLocal2Global(const double LocalCoordSystem[3][3], const array_1d<double, 3>& LocalVector, double GlobalVector[3])
199  {
200  for (int i=0; i<3; i++) {
201  GlobalVector[i] = 0.0;
202  for (int j=0; j<3; j++) {
203  GlobalVector[i]+=LocalCoordSystem[j][i]*LocalVector[j];
204  }
205  }
206  }
207 
208  static inline void VectorLocal2Global(const double LocalCoordSystem[3][3], const double LocalVector[3], array_1d<double, 3>& GlobalVector)
209  {
210  for (int i=0; i<3; i++) {
211  GlobalVector[i] = 0.0;
212  for (int j=0; j<3; j++) {
213  GlobalVector[i]+=LocalCoordSystem[j][i]*LocalVector[j];
214  }
215  }
216  }
217 
218  static inline void ProductMatrices3X3(const double Matrix1[3][3], const double Matrix2[3][3], double Matrix3[3][3])
219  {
220  for (int i = 0; i < 3; i++) {
221  for (int j = 0; j < 3; j++) {
222  Matrix3[i][j] = 0.0;
223  for (int k = 0; k < 3; k++) {
224  Matrix3[i][j] += Matrix1[i][k] * Matrix2[k][j];
225  }
226  }
227  }
228  }
229 
230  static inline void ProductMatrix3X3Vector3X1(const double Matrix[3][3], const array_1d<double,3>& Vector1, array_1d<double,3>& Vector2)
231  {
232  for (int i=0; i<3; i++) {
233  Vector2[i] = 0.0;
234  for (int j=0; j<3; j++) {
235  Vector2[i]+=Matrix[j][i]*Vector1[j];
236  }
237  }
238  }
239 
240  static inline void TensorGlobal2Local(const double LocalCoordSystem[3][3], const double GlobalTensor[3][3], double LocalTensor[3][3])
241  {
242  // We will compute LocalTensor = LocalCoordSystem * GlobalTensor * transposed(LocalCoordSystem)
243  // starting on the left, so we will first compute the product TemporalResult = LocalCoordSystem * GlobalTensor
244  // and afterwards TemporalResult * transposed(LocalCoordSystem), which will give the value of the tensor LocalTensor
245 
246  double TransposedLocalCoordSystem[3][3];
247  double TemporalResult[3][3];
248 
249  TransposedLocalCoordSystem[0][0] = LocalCoordSystem[0][0]; TransposedLocalCoordSystem[0][1] = LocalCoordSystem[1][0]; TransposedLocalCoordSystem[0][2] = LocalCoordSystem[2][0];
250  TransposedLocalCoordSystem[1][0] = LocalCoordSystem[0][1]; TransposedLocalCoordSystem[1][1] = LocalCoordSystem[1][1]; TransposedLocalCoordSystem[1][2] = LocalCoordSystem[2][1];
251  TransposedLocalCoordSystem[2][0] = LocalCoordSystem[0][2]; TransposedLocalCoordSystem[2][1] = LocalCoordSystem[1][2]; TransposedLocalCoordSystem[2][2] = LocalCoordSystem[2][2];
252 
253  ProductMatrices3X3(LocalCoordSystem, GlobalTensor, TemporalResult);
254  ProductMatrices3X3(TemporalResult, TransposedLocalCoordSystem, LocalTensor);
255  }
256 
257  static inline void TensorLocal2Global(const double LocalCoordSystem[3][3], const double LocalTensor[3][3], double GlobalTensor[3][3])
258  {
259  // We will compute GlobalTensor = transposed(LocalCoordSystem) * LocalTensor * LocalCoordSystem
260  // starting on the left, so we will first compute the product TemporalResult = transposed(LocalCoordSystem) * LocalTensor
261  // and afterwards TemporalResult * LocalCoordSystem, which will give the value of the tensor LocalTensor
262 
263  double TransposedLocalCoordSystem[3][3];
264  double TemporalResult[3][3];
265 
266  TransposedLocalCoordSystem[0][0] = LocalCoordSystem[0][0]; TransposedLocalCoordSystem[0][1] = LocalCoordSystem[1][0]; TransposedLocalCoordSystem[0][2] = LocalCoordSystem[2][0];
267  TransposedLocalCoordSystem[1][0] = LocalCoordSystem[0][1]; TransposedLocalCoordSystem[1][1] = LocalCoordSystem[1][1]; TransposedLocalCoordSystem[1][2] = LocalCoordSystem[2][1];
268  TransposedLocalCoordSystem[2][0] = LocalCoordSystem[0][2]; TransposedLocalCoordSystem[2][1] = LocalCoordSystem[1][2]; TransposedLocalCoordSystem[2][2] = LocalCoordSystem[2][2];
269 
270  ProductMatrices3X3(TransposedLocalCoordSystem, LocalTensor, TemporalResult);
271  ProductMatrices3X3(TemporalResult, LocalCoordSystem, GlobalTensor);
272  }
273 
274  static inline void RotaMatrixTensorLocal2Global(const double R[3][3], const double LocalTensor[3][3], double GlobalTensor[3][3])
275  {
276  double RT[3][3]; double Temp[3][3];
277 
278  RT[0][0] = R[0][0]; RT[0][1] = R[1][0]; RT[0][2] = R[2][0];
279  RT[1][0] = R[0][1]; RT[1][1] = R[1][1]; RT[1][2] = R[2][1];
280  RT[2][0] = R[0][2]; RT[2][1] = R[1][2]; RT[2][2] = R[2][2];
281 
282  ProductMatrices3X3(R, LocalTensor, Temp);
283  ProductMatrices3X3(Temp, RT, GlobalTensor);
284  }
285 
286  static inline void ConstructLocalTensor(const double moment_of_inertia, double LocalTensor[3][3])
287  {
288  LocalTensor[0][0] = moment_of_inertia; LocalTensor[0][1] = 0.0; LocalTensor[0][2] = 0.0;
289  LocalTensor[1][0] = 0.0; LocalTensor[1][1] = moment_of_inertia; LocalTensor[1][2] = 0.0;
290  LocalTensor[2][0] = 0.0; LocalTensor[2][1] = 0.0; LocalTensor[2][2] = moment_of_inertia;
291  }
292 
293  static inline void ConstructInvLocalTensor(const double moment_of_inertia, double LocalTensorInv[3][3])
294  {
295  double moment_of_inertia_inv = 1/moment_of_inertia;
296  LocalTensorInv[0][0] = moment_of_inertia_inv; LocalTensorInv[0][1] = 0.0; LocalTensorInv[0][2] = 0.0;
297  LocalTensorInv[1][0] = 0.0; LocalTensorInv[1][1] = moment_of_inertia_inv; LocalTensorInv[1][2] = 0.0;
298  LocalTensorInv[2][0] = 0.0; LocalTensorInv[2][1] = 0.0; LocalTensorInv[2][2] = moment_of_inertia_inv;
299  }
300 
301  static inline void ConstructLocalTensor(const array_1d<double, 3 >& moments_of_inertia, double LocalTensor[3][3])
302  {
303  LocalTensor[0][0] = moments_of_inertia[0]; LocalTensor[0][1] = 0.0; LocalTensor[0][2] = 0.0;
304  LocalTensor[1][0] = 0.0; LocalTensor[1][1] = moments_of_inertia[1]; LocalTensor[1][2] = 0.0;
305  LocalTensor[2][0] = 0.0; LocalTensor[2][1] = 0.0; LocalTensor[2][2] = moments_of_inertia[2];
306  }
307 
308  static inline void ConstructInvLocalTensor(const array_1d<double, 3 >& moments_of_inertia, double LocalTensorInv[3][3])
309  {
310  LocalTensorInv[0][0] = 1/moments_of_inertia[0]; LocalTensorInv[0][1] = 0.0; LocalTensorInv[0][2] = 0.0;
311  LocalTensorInv[1][0] = 0.0; LocalTensorInv[1][1] = 1/moments_of_inertia[1]; LocalTensorInv[1][2] = 0.0;
312  LocalTensorInv[2][0] = 0.0; LocalTensorInv[2][1] = 0.0; LocalTensorInv[2][2] = 1/moments_of_inertia[2];
313  }
314 
315  static inline double DotProduct(double Vector1[3], double Vector2[3])
316  {
317  return Vector1[0] * Vector2[0] + Vector1[1] * Vector2[1] + Vector1[2] * Vector2[2];
318  }
319 
320  static inline double DotProduct(const array_1d<double,3>& Vector1, const array_1d<double,3>& Vector2)
321  {
322  return Vector1[0] * Vector2[0] + Vector1[1] * Vector2[1] + Vector1[2] * Vector2[2];
323  }
324 
325  static inline void CrossProduct(const double u[3], const double v[3], double ReturnVector[3])
326  {
327  ReturnVector[0] = u[1]*v[2] - u[2]*v[1];
328  ReturnVector[1] = v[0]*u[2] - u[0]*v[2];
329  ReturnVector[2] = u[0]*v[1] - u[1]*v[0];
330  }
331 
332  static inline void CrossProduct(const array_1d<double,3>& u, const array_1d<double,3>& v, array_1d<double,3>& ReturnVector)
333  {
334  ReturnVector[0] = u[1]*v[2] - u[2]*v[1];
335  ReturnVector[1] = v[0]*u[2] - u[0]*v[2];
336  ReturnVector[2] = u[0]*v[1] - u[1]*v[0];
337  }
338 
339  static inline void CrossProduct(const double u[3], const array_1d<double,3>& v, double ReturnVector[3])
340  {
341  ReturnVector[0] = u[1]*v[2] - u[2]*v[1];
342  ReturnVector[1] = v[0]*u[2] - u[0]*v[2];
343  ReturnVector[2] = u[0]*v[1] - u[1]*v[0];
344  }
345 
346  static inline void CrossProduct(const array_1d<double,3>& u, const double v[3], double ReturnVector[3])
347  {
348  ReturnVector[0] = u[1]*v[2] - u[2]*v[1];
349  ReturnVector[1] = v[0]*u[2] - u[0]*v[2];
350  ReturnVector[2] = u[0]*v[1] - u[1]*v[0];
351  }
352 
353  static inline void CrossProduct(const array_1d<double,3>& u, const double v[3], array_1d<double,3>& ReturnVector)
354  {
355  ReturnVector[0] = u[1]*v[2] - u[2]*v[1];
356  ReturnVector[1] = v[0]*u[2] - u[0]*v[2];
357  ReturnVector[2] = u[0]*v[1] - u[1]*v[0];
358  }
359 
360  static inline void CrossProduct(const array_1d<double,3>& u, const array_1d<double,3>& v, double ReturnVector[3])
361  {
362  ReturnVector[0] = u[1]*v[2] - u[2]*v[1];
363  ReturnVector[1] = v[0]*u[2] - u[0]*v[2];
364  ReturnVector[2] = u[0]*v[1] - u[1]*v[0];
365  }
366 
368  const double ang, array_1d<double, 3>& new_axes1, array_1d<double, 3>& new_axes2,
369  array_1d<double, 3>& new_axes3) {
370 
372 
374 
375  CrossProduct(new_axes1, new_axes2, new_axes3);
376  }
377 
378  static inline void RotateGridOfNodes(const double time, const double angular_velocity_start_time, const double angular_velocity_stop_time,
379  array_1d<double, 3>& angular_velocity_changed, const double angular_period, const double mod_angular_velocity,
380  const array_1d<double, 3>& angular_velocity, array_1d<double, 3>& new_axes1, array_1d<double, 3>& new_axes2,
381  array_1d<double, 3>& new_axes3) {
382 
383  array_1d<double, 3> angle;
384  noalias(angle) = ZeroVector(3);
385  double sign_angle = 1.0;
386  array_1d<double, 3> final_angle = ZeroVector(3);
387 
388  if (time < angular_velocity_start_time) angular_velocity_changed = ZeroVector(3);
389 
390  else if (((time - angular_velocity_start_time) > 0.0) && ((time - angular_velocity_stop_time) < 0.0)) {
391 
392  if (angular_period > 0.0) {
393  double angular_omega = 2.0 * Globals::Pi / angular_period;
394  double inv_angular_omega = 1.0 / angular_omega;
395  noalias(angle) = angular_velocity * std::sin(angular_omega * (time - angular_velocity_start_time)) * inv_angular_omega;
396  sign_angle = std::sin(angular_omega * (time - angular_velocity_start_time)) / fabs(sin(angular_omega * (time - angular_velocity_start_time)));
397  noalias(angular_velocity_changed) = angular_velocity * std::cos(angular_omega * (time - angular_velocity_start_time));
398  noalias(final_angle) = angle;
399  } else {
400  noalias(angle) = angular_velocity * (time - angular_velocity_start_time);
401  noalias(angular_velocity_changed) = angular_velocity;
402  }
403  } else { //if ((time - angular_velocity_stop_time) > 0.0) {
404  noalias(angular_velocity_changed) = ZeroVector(3);
405 
406  if (angular_period > 0.0) {
407  double angular_omega = 2.0 * Globals::Pi / angular_period;
408  double inv_angular_omega = 1.0 / angular_omega;
409  noalias(angle) = angular_velocity * std::sin(angular_omega * (angular_velocity_stop_time - angular_velocity_start_time)) * inv_angular_omega;
410  } else {
411  noalias(angle) = angular_velocity * (angular_velocity_stop_time - angular_velocity_start_time);
412  }
413  }
414 
415  //mod_angular_velocity = MathUtils<double>::Norm3(angular_velocity);
416 
417  new_axes1[0] = 1.0;
418  new_axes1[1] = 0.0;
419  new_axes1[2] = 0.0;
420 
421  new_axes2[0] = 0.0;
422  new_axes2[1] = 1.0;
423  new_axes2[2] = 0.0;
424 
425  new_axes3[0] = 0.0;
426  new_axes3[1] = 0.0;
427  new_axes3[2] = 1.0;
428 
429  if (mod_angular_velocity > 0.0) {
430 
431  double ang = sign_angle * MathUtils<double>::Norm3(angle);
432  array_1d<double, 3> rotation_axis;
433  noalias(rotation_axis) = angular_velocity / mod_angular_velocity;
435  e1[0] = 1.0;
436  e1[1] = 0.0;
437  e1[2] = 0.0;
438 
440  e2[0] = 0.0;
441  e2[1] = 1.0;
442  e2[2] = 0.0;
443 
444  RotateRightHandedBasisAroundAxis(e1, e2, rotation_axis, ang, new_axes1, new_axes2, new_axes3);
445  }
446  }
447 
448  static inline void UpdateKinematicVariablesOfAGridOfNodes(double mod_angular_velocity, const array_1d<double, 3>& linear_velocity,
449  const array_1d<double, 3>& initial_center, array_1d<double, 3>& new_axes1, array_1d<double, 3>& new_axes2,
450  array_1d<double, 3>& new_axes3, array_1d<double, 3>& angular_velocity_changed,
451  array_1d<double, 3>& linear_velocity_changed, array_1d<double, 3>& center_position,
452  const bool fixed_mesh, const double dt, ModelPart::NodesContainerType& pNodes)
453  {
454  if (mod_angular_velocity > std::numeric_limits<double>::epsilon() || MathUtils<double>::Norm3(linear_velocity) > std::numeric_limits<double>::epsilon()) {
455 
456  #pragma omp parallel for
457  for (int k = 0; k < (int)pNodes.size(); k++) {
458 
459  array_1d<double, 3> local_coordinates = ZeroVector(3);
460  array_1d<double, 3> relative_position = ZeroVector(3);
461 
462  ModelPart::NodeIterator node = pNodes.begin() + k;
463 
464  noalias(local_coordinates) = node->GetInitialPosition().Coordinates() - initial_center;
465  noalias(relative_position) = new_axes1 * local_coordinates[0] + new_axes2 * local_coordinates[1] + new_axes3 * local_coordinates[2];
466  array_1d<double, 3> old_coordinates;
467  noalias(old_coordinates) = node->Coordinates();
468  array_1d<double, 3> velocity_due_to_rotation;
469  array_1d<double, 3>& velocity = node->FastGetSolutionStepValue(VELOCITY);
470 
471  CrossProduct(angular_velocity_changed, relative_position, velocity_due_to_rotation);
472  noalias(velocity) = linear_velocity_changed + velocity_due_to_rotation;
473 
474  if (!fixed_mesh) {
475  // NEW POSITION
476  noalias(node->Coordinates()) = center_position + relative_position;
477  // DISPLACEMENT
478  noalias(node->FastGetSolutionStepValue(DISPLACEMENT)) = node->Coordinates() - node->GetInitialPosition().Coordinates();
479  noalias(node->FastGetSolutionStepValue(DELTA_DISPLACEMENT)) = node->Coordinates() - old_coordinates;
480  } else {
481  (node->FastGetSolutionStepValue(DISPLACEMENT)).clear(); //Set values to zero
482  noalias(node->FastGetSolutionStepValue(DELTA_DISPLACEMENT)) = velocity * dt; //But still there must be some delta_displacement (or motion won't be detected by the spheres!)
483  }
484  }
485  }
486  }
487 
488  //NOTE:: Modified by M. Santasusana Feb 2013 - simplification (the one proposed by F. Chun was for a more generalized case)
489 
490  static inline void ComputeContactLocalCoordSystem(array_1d<double, 3> NormalDirection, const double& distance, double LocalCoordSystem[3][3]) //inline: modifies the LocalCoordSystem as it were a reference
491  {
492  double inv_distance = (distance != 0.0) ? 1.0 / distance : 0.0;
493  NormalDirection[0] *= inv_distance;
494  NormalDirection[1] *= inv_distance;
495  NormalDirection[2] *= inv_distance;
496  double N_fast[3];
497  N_fast[0] = NormalDirection[0];
498  N_fast[1] = NormalDirection[1];
499  N_fast[2] = NormalDirection[2];
500 
501  if (fabs(N_fast[0]) >= 0.577) //0.57735026919
502  {
503  LocalCoordSystem[0][0] = - N_fast[1];
504  LocalCoordSystem[0][1] = N_fast[0];
505  LocalCoordSystem[0][2] = 0.0;
506  }
507  else if (fabs(N_fast[1]) >= 0.577)
508  {
509  LocalCoordSystem[0][0] = 0.0;
510  LocalCoordSystem[0][1] = - N_fast[2];
511  LocalCoordSystem[0][2] = N_fast[1];
512  }
513  else
514  {
515  LocalCoordSystem[0][0] = N_fast[2];
516  LocalCoordSystem[0][1] = 0.0;
517  LocalCoordSystem[0][2] = - N_fast[0];
518  }
519 
520  //normalize(Vector0);
521  double distance0 = DEM_MODULUS_3(LocalCoordSystem[0]);
522  double inv_distance0 = (distance0 != 0.0) ? 1.0 / distance0 : 0.0;
523  LocalCoordSystem[0][0] = LocalCoordSystem[0][0] * inv_distance0;
524  LocalCoordSystem[0][1] = LocalCoordSystem[0][1] * inv_distance0;
525  LocalCoordSystem[0][2] = LocalCoordSystem[0][2] * inv_distance0;
526 
527  //CrossProduct(NormalDirection, Vector0, Vector1);
528  LocalCoordSystem[1][0] = N_fast[1] * LocalCoordSystem[0][2] - N_fast[2] * LocalCoordSystem[0][1];
529  LocalCoordSystem[1][1] = N_fast[2] * LocalCoordSystem[0][0] - N_fast[0] * LocalCoordSystem[0][2];
530  LocalCoordSystem[1][2] = N_fast[0] * LocalCoordSystem[0][1] - N_fast[1] * LocalCoordSystem[0][0];
531 
532  //normalize(Vector1);
533 
534  LocalCoordSystem[2][0] = N_fast[0];
535  LocalCoordSystem[2][1] = N_fast[1];
536  LocalCoordSystem[2][2] = N_fast[2];
537  }
538 
539  static inline double DistanceOfTwoPoint(const double coord1[3], const double coord2[3])
540  {
541  double dx = coord1[0] - coord2[0];
542  double dy = coord1[1] - coord2[1];
543  double dz = coord1[2] - coord2[2];
544 
545  return sqrt(dx * dx + dy * dy + dz * dz);
546  }
547 
548  static inline double DistanceOfTwoPoint(const array_1d<double,3>& coord1, const double coord2[3])
549  {
550  double dx = coord1[0] - coord2[0];
551  double dy = coord1[1] - coord2[1];
552  double dz = coord1[2] - coord2[2];
553 
554  return sqrt(dx * dx + dy * dy + dz * dz);
555  }
556 
557  static inline double DistanceOfTwoPointSquared(const array_1d<double,3>& coord1, const array_1d<double,3>& coord2)
558  {
559  double dx = coord1[0] - coord2[0];
560  double dy = coord1[1] - coord2[1];
561  double dz = coord1[2] - coord2[2];
562 
563  return (dx * dx + dy * dy + dz * dz);
564  }
565 
566  static inline double DistanceOfTwoPointSquared(double coord1[3], double coord2[3])
567  {
568  double dx = coord1[0] - coord2[0];
569  double dy = coord1[1] - coord2[1];
570  double dz = coord1[2] - coord2[2];
571 
572  return (dx * dx + dy * dy + dz * dz);
573  }
574  static inline double DistancePointToPlane(const array_1d<double,3>& CoordInPlane, double PlaneUnitNormalVector[3], double TestCoord[3])
575  {
576  double Vector1[3] = {0.0};
577 
578  for (unsigned int i = 0; i<3; i++)
579  {
580  Vector1[i] = TestCoord[i]- CoordInPlane[i];
581  }
582 
583  double dist = fabs (DotProduct(Vector1, PlaneUnitNormalVector));
584 
585  return dist;
586  }
587 
588  static inline void CoordProjectionOnPlane(double CoordOut[3], double CoordIn[3], double LocalCoordSystem[3][3], double IntersectionCoord[3])
589  {
590  double out_coord_local[3] = {0.0};
591  double in_coord_local[3] = {0.0};
592 
593  VectorGlobal2Local(LocalCoordSystem, CoordOut, out_coord_local);
594  VectorGlobal2Local(LocalCoordSystem, CoordIn, in_coord_local);
595 
596  double vector1[3] = {0.0};
597  vector1[0] = out_coord_local[0];
598  vector1[1] = out_coord_local[1];
599  vector1[2] = in_coord_local [2];
600 
601  VectorLocal2Global(LocalCoordSystem, vector1, IntersectionCoord);
602 
603  }
604 
605  static inline void CoordProjectionOnPlaneNew(double CoordOut[3], const array_1d<double, 3>& CoordIn, double LocalCoordSystem[3][3], double IntersectionCoord[3])
606  {
607  double out_coord_local[3] = {0.0};
608  double in_coord_local[3] = {0.0};
609 
610  VectorGlobal2Local(LocalCoordSystem, CoordOut, out_coord_local);
611  VectorGlobal2Local(LocalCoordSystem, CoordIn, in_coord_local);
612 
613  double vector1[3] = {0.0};
614  vector1[0] = out_coord_local[0];
615  vector1[1] = out_coord_local[1];
616  vector1[2] = in_coord_local [2];
617 
618  VectorLocal2Global(LocalCoordSystem, vector1, IntersectionCoord);
619 
620  }
621 
622  static inline void Compute3DimElementFaceLocalSystem(const array_1d <double,3>& FaceCoord1, const array_1d <double,3>& FaceCoord2, const array_1d <double,3>& FaceCoord3, double ParticleCoord[3],
623  double LocalCoordSystem[3][3], double& normal_flag)
624  {
625  //NOTE: this function is designed in a way that the normal always points the side where the center of particle is found. Therefore should only be used in this way if the indentation is less than the radius value.
626  //the function returns a flag with the same value as the dot product of the normal of the triangle and the normal pointing to the particle.
627 
628  double Vector1[3] = {0.0};
629  double Vector2[3] = {0.0};
630  double Vector3[3] = {0.0};
631  double Normal[3] = {0.0};
632 
633  Vector1[0] = FaceCoord2[0] - FaceCoord1[0];
634  Vector1[1] = FaceCoord2[1] - FaceCoord1[1];
635  Vector1[2] = FaceCoord2[2] - FaceCoord1[2];
636 
637  Vector2[0] = FaceCoord3[0] - FaceCoord2[0];
638  Vector2[1] = FaceCoord3[1] - FaceCoord2[1];
639  Vector2[2] = FaceCoord3[2] - FaceCoord2[2];
640 
641  normalize(Vector1);
642  CrossProduct(Vector1, Vector2, Normal);
643  normalize(Normal);
644 
645  CrossProduct(Normal, Vector1, Vector2);
646  normalize(Vector2);
647 
648  Vector3[0] = ParticleCoord[0] - FaceCoord1[0];
649  Vector3[1] = ParticleCoord[1] - FaceCoord1[1];
650  Vector3[2] = ParticleCoord[2] - FaceCoord1[2];
651 
653 
654  if (DotProduct(Vector3, Normal) > 0.0)
655  {
656  for (int ia = 0; ia < 3; ia++)
657  {
658  normal_flag = 1.0;
659  LocalCoordSystem[0][ia] = Vector1[ia];
660  LocalCoordSystem[1][ia] = Vector2[ia];
661  LocalCoordSystem[2][ia] = Normal [ia];
662  }
663  }
664  else
665  {
666  for (int ia = 0; ia < 3; ia++)
667  {
668  normal_flag = -1.0;
669  LocalCoordSystem[0][ia] = -Vector1[ia];
670  LocalCoordSystem[1][ia] = -Vector2[ia];
671  LocalCoordSystem[2][ia] = -Normal [ia];
672  }
673  }
674  }
675 
676  //MSIMSI this one is being used only for distributed... adapt it
677  static inline void Compute3DimElementFaceLocalSystem(double FaceCoord1[3], double FaceCoord2[3], double FaceCoord3[3], double ParticleCoord[3],
678  double LocalCoordSystem[3][3], double& normal_flag){
679 
680  //NOTE: this function is designed in a way that the normal always points the side where the center of particle is found. Therefore should only be used in this way if the indentation is less than the radius value.
681  //the function returns a flag with the same value as the dot product of the normal of the triangle and the normal pointing to the particle.
682 
683  double Vector1[3] = {0.0};
684  double Vector2[3] = {0.0};
685  double Vector3[3] = {0.0};
686  double Normal[3] = {0.0};
687 
688  Vector1[0] = FaceCoord2[0] - FaceCoord1[0];
689  Vector1[1] = FaceCoord2[1] - FaceCoord1[1];
690  Vector1[2] = FaceCoord2[2] - FaceCoord1[2];
691 
692  Vector2[0] = FaceCoord3[0] - FaceCoord2[0];
693  Vector2[1] = FaceCoord3[1] - FaceCoord2[1];
694  Vector2[2] = FaceCoord3[2] - FaceCoord2[2];
695 
696  normalize(Vector1);
697  CrossProduct(Vector1, Vector2, Normal);
698  normalize(Normal);
699 
700  CrossProduct(Normal, Vector1, Vector2);
701  normalize(Vector2);
702 
703  Vector3[0] = ParticleCoord[0] - FaceCoord1[0];
704  Vector3[1] = ParticleCoord[1] - FaceCoord1[1];
705  Vector3[2] = ParticleCoord[2] - FaceCoord1[2];
707 
708  if (DotProduct(Vector3, Normal) > 0.0)
709  {
710  for (int ia = 0; ia < 3; ia++)
711  {
712  normal_flag = 1.0;
713  LocalCoordSystem[0][ia] = Vector1[ia];
714  LocalCoordSystem[1][ia] = Vector2[ia];
715  LocalCoordSystem[2][ia] = Normal [ia];
716  }
717  }
718  else
719  {
720  for (int ia = 0; ia < 3; ia++)
721  {
722  normal_flag = -1.0;
723  LocalCoordSystem[0][ia] = -Vector1[ia];
724  LocalCoordSystem[1][ia] = -Vector2[ia];
725  LocalCoordSystem[2][ia] = -Normal [ia];
726  }
727  }
728  }//Compute3DimElementFaceLocalSystem
729 
730 
734 
735  static inline void RotatePointAboutArbitraryLine(array_1d<double,3>& TargetPoint, const array_1d<double,3>& CentrePoint, const array_1d<double,3>& LineVector, const double RotationAngle)
736  {
737  const double O = RotationAngle;
738  double x = TargetPoint[0], a = CentrePoint[0], u = LineVector[0];
739  double y = TargetPoint[1], b = CentrePoint[1], v = LineVector[1];
740  double z = TargetPoint[2], c = CentrePoint[2], w = LineVector[2];
741  double L = u*u+v*v+w*w;
742 
743  if (L==0)
744  {
745  }
746  else
747  {
748  const double inv_L = 1.0 / L;
749  TargetPoint[0] = ((a*(v*v+w*w)-u*(b*v+c*w-u*x-v*y-w*z))*(1-cos(O))+L*x*cos(O)+sqrt(L)*(-c*w+b*w-w*y+v*z)*sin(O))* inv_L;
750  TargetPoint[1] = ((b*(u*u+w*w)-v*(a*u+c*w-u*x-v*y-w*z))*(1-cos(O))+L*y*cos(O)+sqrt(L)*(c*u-a*w+w*x-u*z)*sin(O))* inv_L;
751  TargetPoint[2] = ((c*(u*u+v*v)-w*(a*u+b*v-u*x-v*y-w*z))*(1-cos(O))+L*z*cos(O)+sqrt(L)*(-b*u+a*v-v*x+u*y)*sin(O))* inv_L;
752  }
753  }
754 
758 
759  static inline void QuaternionVectorLocal2Global(const Quaternion<double>& Q, const array_1d<double, 3>& LocalVector, array_1d<double, 3>& GlobalVector)
760  {
761  Q.RotateVector3(LocalVector, GlobalVector);
762  }
763 
764  static inline void QuaternionVectorGlobal2Local(const Quaternion<double>& Q, const array_1d<double, 3>& GlobalVector, array_1d<double, 3>& LocalVector)
765  {
766  Quaternion<double> Q_conj = Q.conjugate();
767  Q_conj.RotateVector3(GlobalVector, LocalVector);
768  }
769 
770  static inline void QuaternionTensorLocal2Global(const Quaternion<double>& Q, const double LocalTensor[3][3], double GlobalTensor[3][3])
771  {
772  array_1d<double, 3> LocalTensorC1; array_1d<double, 3> LocalTensorC2; array_1d<double, 3> LocalTensorC3;
773 
774  LocalTensorC1[0] = LocalTensor[0][0]; LocalTensorC2[0] = LocalTensor[0][1]; LocalTensorC3[0] = LocalTensor[0][2];
775  LocalTensorC1[1] = LocalTensor[1][0]; LocalTensorC2[1] = LocalTensor[1][1]; LocalTensorC3[1] = LocalTensor[1][2];
776  LocalTensorC1[2] = LocalTensor[2][0]; LocalTensorC2[2] = LocalTensor[2][1]; LocalTensorC3[2] = LocalTensor[2][2];
777 
778  array_1d<double, 3> TempTensorC1; array_1d<double, 3> TempTensorC2; array_1d<double, 3> TempTensorC3;
779  array_1d<double, 3> TempTensorTraspC1; array_1d<double, 3> TempTensorTraspC2; array_1d<double, 3> TempTensorTraspC3;
780 
781  Q.RotateVector3(LocalTensorC1, TempTensorC1);
782  Q.RotateVector3(LocalTensorC2, TempTensorC2);
783  Q.RotateVector3(LocalTensorC3, TempTensorC3);
784 
785  TempTensorTraspC1[0] = TempTensorC1[0]; TempTensorTraspC2[0] = TempTensorC1[1]; TempTensorTraspC3[0] = TempTensorC1[2];
786  TempTensorTraspC1[1] = TempTensorC2[0]; TempTensorTraspC2[1] = TempTensorC2[1]; TempTensorTraspC3[1] = TempTensorC2[2];
787  TempTensorTraspC1[2] = TempTensorC3[0]; TempTensorTraspC2[2] = TempTensorC3[1]; TempTensorTraspC3[2] = TempTensorC3[2];
788 
789  array_1d<double, 3> GlobalTensorTraspC1; array_1d<double, 3> GlobalTensorTraspC2; array_1d<double, 3> GlobalTensorTraspC3;
790 
791  Q.RotateVector3(TempTensorTraspC1, GlobalTensorTraspC1);
792  Q.RotateVector3(TempTensorTraspC2, GlobalTensorTraspC2);
793  Q.RotateVector3(TempTensorTraspC3, GlobalTensorTraspC3);
794 
795  GlobalTensor[0][0] = GlobalTensorTraspC1[0]; GlobalTensor[0][1] = GlobalTensorTraspC1[1]; GlobalTensor[0][2] = GlobalTensorTraspC1[2];
796  GlobalTensor[1][0] = GlobalTensorTraspC2[0]; GlobalTensor[1][1] = GlobalTensorTraspC2[1]; GlobalTensor[1][2] = GlobalTensorTraspC2[2];
797  GlobalTensor[2][0] = GlobalTensorTraspC3[0]; GlobalTensor[2][1] = GlobalTensorTraspC3[1]; GlobalTensor[2][2] = GlobalTensorTraspC3[2];
798  }
799 
800  static inline void UpdateOrientation(array_1d<double, 3>& EulerAngles, Quaternion<double>& Orientation, const array_1d<double, 3>& DeltaRotation)
801  {
803 
804  array_1d<double, 3 > theta = DeltaRotation;
805  DEM_MULTIPLY_BY_SCALAR_3(theta, 0.5);
806 
807  double thetaMag = DEM_MODULUS_3(theta);
808  const double epsilon = std::numeric_limits<double>::epsilon();
809 
810  if (thetaMag * thetaMag * thetaMag * thetaMag / 24.0 < epsilon) { //Taylor: low angle
811  double aux = (1 - thetaMag * thetaMag / 6);
812  DeltaOrientation = Quaternion<double>((1 + thetaMag * thetaMag / 2), theta[0]*aux, theta[1]*aux, theta[2]*aux);
813  DeltaOrientation.normalize();
814  }
815  else {
816  double aux = std::sin(thetaMag)/thetaMag;
817  DeltaOrientation = Quaternion<double>(cos(thetaMag), theta[0]*aux, theta[1]*aux, theta[2]*aux);
818  DeltaOrientation.normalize();
819  }
820  Orientation = DeltaOrientation * Orientation;
821  Orientation.ToEulerAngles(EulerAngles);
822  }
823 
824  static inline void UpdateOrientation(Quaternion<double>& Orientation, const array_1d<double, 3>& DeltaRotation)
825  {
827 
828  array_1d<double, 3 > theta = DeltaRotation;
829  DEM_MULTIPLY_BY_SCALAR_3(theta, 0.5);
830 
831  double thetaMag = DEM_MODULUS_3(theta);
832  const double epsilon = std::numeric_limits<double>::epsilon();
833 
834  if (thetaMag * thetaMag * thetaMag * thetaMag / 24.0 < epsilon) { //Taylor: low angle
835  double aux = (1 - thetaMag * thetaMag / 6);
836  DeltaOrientation = Quaternion<double>((1 + thetaMag * thetaMag * 0.5), theta[0]*aux, theta[1]*aux, theta[2]*aux);
837  DeltaOrientation.normalize();
838  }
839  else {
840  double aux = std::sin(thetaMag)/thetaMag;
841  DeltaOrientation = Quaternion<double>(cos(thetaMag), theta[0]*aux, theta[1]*aux, theta[2]*aux);
842  DeltaOrientation.normalize();
843  }
844  Orientation = DeltaOrientation * Orientation;
845  }
846 
847  static inline void UpdateOrientation(const Quaternion<double>& Orientation, Quaternion<double>& NewOrientation, const array_1d<double, 3>& DeltaRotation)
848  {
850 
851  array_1d<double, 3 > theta = DeltaRotation;
852  DEM_MULTIPLY_BY_SCALAR_3(theta, 0.5);
853 
854  double thetaMag = DEM_MODULUS_3(theta);
855  const double epsilon = std::numeric_limits<double>::epsilon();
856 
857  if (thetaMag * thetaMag * thetaMag * thetaMag / 24.0 < epsilon) { //Taylor: low angle
858  double aux = (1 - thetaMag * thetaMag / 6);
859  DeltaOrientation = Quaternion<double>((1 + thetaMag * thetaMag * 0.5), theta[0]*aux, theta[1]*aux, theta[2]*aux);
860  DeltaOrientation.normalize();
861  }
862  else {
863  double aux = std::sin(thetaMag)/thetaMag;
864  DeltaOrientation = Quaternion<double>(cos(thetaMag), theta[0]*aux, theta[1]*aux, theta[2]*aux);
865  DeltaOrientation.normalize();
866  }
867  NewOrientation = DeltaOrientation * Orientation;
868  }
869 
870  static inline void EulerAnglesFromRotationAngle(array_1d<double, 3>& EulerAngles, const array_1d<double, 3>& RotatedAngle)
871  {
873 
874  array_1d<double, 3 > theta = RotatedAngle;
875  DEM_MULTIPLY_BY_SCALAR_3(theta, 0.5);
876 
877  double thetaMag = DEM_MODULUS_3(theta);
878 
879  const double epsilon = std::numeric_limits<double>::epsilon();
880 
881  if (thetaMag * thetaMag * thetaMag * thetaMag / 24.0 < epsilon) { //Taylor: low angle
882  double aux = (1 - thetaMag * thetaMag / 6);
883  Orientation = Quaternion<double>((1 + thetaMag * thetaMag / 2), theta[0]*aux, theta[1]*aux, theta[2]*aux);
884  Orientation.normalize();
885  }
886  else {
887  double aux = std::sin(thetaMag)/thetaMag;
888  Orientation = Quaternion<double>(cos(thetaMag), theta[0]*aux, theta[1]*aux, theta[2]*aux);
889  Orientation.normalize();
890  }
891  Orientation.ToEulerAngles(EulerAngles);
892  }
893 
894  static inline void OrientationFromRotationAngle(Quaternion<double>& DeltaOrientation, const array_1d<double, 3>& DeltaRotation)
895  {
896  array_1d<double, 3 > theta = DeltaRotation;
897  DEM_MULTIPLY_BY_SCALAR_3(theta, 0.5);
898 
899  double thetaMag = DEM_MODULUS_3(theta);
900  const double epsilon = std::numeric_limits<double>::epsilon();
901 
902  if (thetaMag * thetaMag * thetaMag * thetaMag / 24.0 < epsilon) { //Taylor: low angle
903  double aux = (1 - thetaMag * thetaMag / 6);
904  DeltaOrientation = Quaternion<double>((1 + thetaMag * thetaMag / 2), theta[0]*aux, theta[1]*aux, theta[2]*aux);
905  DeltaOrientation.normalize();
906  }
907  else {
908  double aux = std::sin(thetaMag)/thetaMag;
909  DeltaOrientation = Quaternion<double>(cos(thetaMag), theta[0]*aux, theta[1]*aux, theta[2]*aux);
910  DeltaOrientation.normalize();
911  }
912  }
913 
917 
918 
919  /*static inline void CalculateEulerAngles(const array_1d<double,3>& OriginalVector_X, const array_1d<double,3>& OriginalVector_Z,
920  const array_1d<double,3>& RotatedVector_X, const array_1d<double,3>& RotatedVector_Z, array_1d<double,3>& EulerAngles)
921  {
922 
923  array_1d< double,3 > N = ZeroVector(3);
924 
925 
926 
927  CrossProduct( OriginalVector_Z, RotatedVector_Z, N);
928 
929  double return1 = DotProduct(N,OriginalVector_X); //cos(Alpha)
930  double return2 = DotProduct(OriginalVector_Z, RotatedVector_Z); //cos(Beta)
931  double return3 = DotProduct(N,RotatedVector_X); //cos(Gamma)
932 
933  EulerAngles[0] = acos(return1);
934  EulerAngles[1] = acos(return2);
935  EulerAngles[2] = acos(return3);
936 
937  }*/
938 
939  static inline void RotateCoordToDirection(const double OLdCoordSystem[3][3], double Vector[3], double NewCoordSystem[3][3])
940  {
941  double x_axis[3] = {0.0};
942  double y_axis[3] = {0.0};
943  double z_axis[3] = {0.0};
944 
945  x_axis[0] = OLdCoordSystem[0][0];
946  x_axis[1] = OLdCoordSystem[0][1];
947  x_axis[2] = OLdCoordSystem[0][2];
948  y_axis[0] = OLdCoordSystem[1][0];
949  y_axis[1] = OLdCoordSystem[1][1];
950  y_axis[2] = OLdCoordSystem[1][2];
951  z_axis[0] = OLdCoordSystem[2][0];
952  z_axis[1] = OLdCoordSystem[2][1];
953  z_axis[2] = OLdCoordSystem[2][2];
954 
955  normalize(Vector);
956 
957  double rotation_matrix[3][3];
958  rotation_matrix[2][0] = Vector[0];
959  rotation_matrix[2][1] = Vector[1];
960  rotation_matrix[2][2] = Vector[2];
961  CrossProduct(rotation_matrix[2], y_axis, rotation_matrix[0]);
962  normalize(rotation_matrix[0]);
963  CrossProduct(rotation_matrix[2], rotation_matrix[0], rotation_matrix[1]);
964 
965  NewCoordSystem[0][0] = rotation_matrix[0][0] * x_axis[0] + rotation_matrix[0][1] * y_axis[0] + rotation_matrix[0][2] * z_axis[0];
966  NewCoordSystem[0][1] = rotation_matrix[0][0] * x_axis[1] + rotation_matrix[0][1] * y_axis[1] + rotation_matrix[0][2] * z_axis[1];
967  NewCoordSystem[0][2] = rotation_matrix[0][0] * x_axis[2] + rotation_matrix[0][1] * y_axis[2] + rotation_matrix[0][2] * z_axis[2];
968  NewCoordSystem[1][0] = rotation_matrix[2][0];
969  NewCoordSystem[1][1] = rotation_matrix[2][1];
970  NewCoordSystem[1][2] = rotation_matrix[2][2];
971  NewCoordSystem[2][0] = rotation_matrix[1][0] * x_axis[0] + rotation_matrix[1][1] * y_axis[0] + rotation_matrix[1][2] * z_axis[0];
972  NewCoordSystem[2][1] = rotation_matrix[1][0] * x_axis[1] + rotation_matrix[1][1] * y_axis[1] + rotation_matrix[1][2] * z_axis[1];
973  NewCoordSystem[2][2] = rotation_matrix[1][0] * x_axis[2] + rotation_matrix[1][1] * y_axis[2] + rotation_matrix[1][2] * z_axis[2];
974  }
975 
976  static inline bool InsideOutside(const array_1d<double, 3>& Coord1,
977  const array_1d<double, 3>& Coord2,
978  const array_1d<double, 3>& JudgeCoord,
979  const array_1d<double, 3>& normal_element,
980  double& area){
981 
982  //NOTE:: Normal_out here has to be the normal of the element orientation (not pointing particle)
983  double b[3];
984  double p1[3];
985  double coor[3];
986  DEM_COPY_SECOND_TO_FIRST_3(coor, Coord1)
987  b[0] = Coord2[0] - coor[0];
988  b[1] = Coord2[1] - coor[1];
989  b[2] = Coord2[2] - coor[2];
990  p1[0] = JudgeCoord[0] - coor[0];
991  p1[1] = JudgeCoord[1] - coor[1];
992  p1[2] = JudgeCoord[2] - coor[2];
994 
995  if (DEM_INNER_PRODUCT_3(coor, normal_element) >= 0){
996  area = 0.5 * DEM_MODULUS_3(coor);
997  return true;
998  }
999  else return false;
1000 
1001  }//InsideOutside
1002 
1003  static inline bool InsideOutside(const array_1d<double, 3> &Coord1,
1004  const array_1d<double, 3>& Coord2,
1005  const array_1d<double, 3>& JudgeCoord,
1006  const array_1d<double, 3>& normal_element) {
1007 
1008  //NOTE:: Normal_out here has to be the normal of the element orientation (not pointing particle)
1009  array_1d<double, 3> cp1;
1010  array_1d<double, 3> b_a;
1011  array_1d<double, 3> p1_a;
1012 
1013  noalias(b_a) = Coord2 - Coord1;
1014  noalias(p1_a) = JudgeCoord - Coord1;
1015 
1016  GeometryFunctions::CrossProduct(b_a, p1_a, cp1);
1017 
1018  if (GeometryFunctions::DotProduct(cp1, normal_element) >= 0)
1019  {
1020  //area = sqrt(cp1[0] * cp1[0] + cp1[1] * cp1[1] + cp1[2] * cp1[2]) * 0.5;
1021  return true;
1022  }
1023  else return false;
1024 
1025  }//InsideOutside
1026 
1027  static inline void WeightsCalculation(std::vector<double> Area, std::vector<double>& Weight)
1028  {
1029  unsigned int facet_size = Area.size();
1030  if (facet_size == 3)
1031  {
1032  const double total_area = Area[0]+Area[1]+Area[2];
1033  const double inv_total_area = 1.0 / total_area;
1034  for (unsigned int i = 0; i< 3; i++)
1035  {
1036  Weight[i] = Area[(i+1)%facet_size] * inv_total_area;
1037  }
1038  }
1039  else if (facet_size == 4)
1040  {
1041  const double total_discriminant = Area[0]*Area[1]+Area[1]*Area[2]+Area[2]*Area[3]+Area[3]*Area[0]; //(Zhong et al 1993)
1042  const double inv_total_discriminant = 1.0 / total_discriminant;
1043  for (unsigned int i = 0; i< 4; i++)
1044  {
1045  Weight[i] = (Area[(i+1)%facet_size]*Area[(i+2)%facet_size]) * inv_total_discriminant;
1046  }
1047  }
1048  else {
1049  KRATOS_WATCH("WEIGHTS FOR N-SIZE POLYGONAL FE TO BE IMPLEMENTED")
1050  }
1051  }//WeightsCalculation
1052 
1053  static inline bool FastFacetCheck(const std::vector< array_1d <double,3> >& Coord, const array_1d <double,3>& Particle_Coord, double rad, double &DistPToB, unsigned int &current_edge_index)
1054  {
1055  double A[3];
1056  double B[3];
1057  double PC[3];
1058 
1059  for (unsigned int i = 0; i < 3; i++){
1060  B[i] = Coord[0][i];
1061  PC[i] = Coord[1][i];
1062  A[i] = Coord[2][i];
1063  }
1064 
1065  for (unsigned int i = 0; i < 3; i++){
1066  A[i] = A[i] - PC[i];
1067  B[i] = B[i] - PC[i];
1068  PC[i] = Particle_Coord[i] - PC[i];
1069  }
1070 
1071  //Calculate Normal
1072 
1073  double N_fast[3];
1075  //normalize
1076 
1077  double normal_flag = 1.0;
1078 
1079  if (DEM_INNER_PRODUCT_3(PC, N_fast) < 0){ //it is assumed that Indentation wont be greater than radius so we can detect contacts on both sides of the FE.
1080  normal_flag = -1.0;
1081  }
1082 
1083  normalize(N_fast);
1084 
1085  //Calculate distance:
1086 
1087  DistPToB = 0.0;
1088 
1089  for (unsigned int i = 0; i < 3; i++){
1090  DistPToB += normal_flag * N_fast[i] * PC[i];
1091  }
1092 
1093  if (DistPToB < rad){
1094  array_1d <double, 3> IntersectionCoord;
1096 
1097  for (unsigned int i = 0; i < 3; i++){
1098  IntersectionCoord[i] = Particle_Coord[i] - DistPToB * normal_flag * N_fast[i];
1099  N[i] = N_fast[i];
1100  }
1101 
1102  int facet_size = Coord.size();
1103 
1104  for (int i = 0; i < facet_size; i++) {
1105  double this_area = 0.0;
1106 
1107  if (InsideOutside(Coord[i], Coord[(i+1)%facet_size], IntersectionCoord, N, this_area) == false){
1108  current_edge_index = i;
1109  return false;
1110  }
1111  }
1112  return true;
1113  }//if DistPToB < rad
1114 
1115  return false;
1116  }//FastFacetCheck
1117 
1118  static inline bool FacetCheck(const GeometryType& Coord, const array_1d <double,3>& Particle_Coord, double rad,
1119  double LocalCoordSystem[3][3], double& DistPToB, std::vector<double>& Weight, unsigned int& current_edge_index, bool& inside)
1120  {
1121  int facet_size = Coord.size();
1122  //Calculate Normal
1123 
1128 
1129  for (unsigned int i = 0; i<3; i++)
1130  {
1131  A[i] = Coord[2].Coordinates()[i]-Coord[1].Coordinates()[i];
1132  B[i] = Coord[0].Coordinates()[i]-Coord[1].Coordinates()[i];
1133  PC[i] = Particle_Coord[i]-Coord[1].Coordinates()[i];
1134  }
1135 
1136  N[0] = A[1]*B[2] - A[2]*B[1];
1137  N[1] = A[2]*B[0] - A[0]*B[2];
1138  N[2] = A[0]*B[1] - A[1]*B[0];
1139  //normalize
1140 
1141  double normal_flag = 1.0;
1142 
1143  if (DotProduct(PC,N) < 0) //it is assumed that Indentation wont be greater than radius so we can detect contacts on both sides of the FE.
1144  {
1145  normal_flag = - 1.0;
1146  N[0]=-N[0];
1147  N[1]=-N[1];
1148  N[2]=-N[2];
1149  }
1150  normalize(N);
1151 
1152  //Calculate distance:
1153 
1154  DistPToB = 0.0;
1155 
1156  for (unsigned int i = 0; i<3; i++)
1157  {
1158  DistPToB += N[i]*PC[i];
1159  }
1160 
1161  // Check if particle is inside Finite Element (even if contact is not possible, i.e. DistPToB >= rad)
1162  array_1d <double,3> IntersectionCoord;
1163 
1164  for (unsigned int i = 0; i<3; i++)
1165  {
1166  IntersectionCoord[i] = Particle_Coord[i] - DistPToB*N[i];
1167  }
1168 
1169  std::vector<double> Area;
1170  Area.resize(facet_size);
1171 
1172  for (int i = 0; i<facet_size; i++)
1173  {
1174  double this_area = 0.0;
1175  if (InsideOutside(Coord[i],
1176  Coord[(i+1)%facet_size],
1177  IntersectionCoord,
1178  normal_flag*N,
1179  this_area) == false)
1180  {
1181  current_edge_index = i;
1182  inside = false;
1183  return false;
1184  }
1185  else
1186  {
1187  inside = true;
1188  Area[i] = this_area; //the area adjacent to vertex[ID] is assigned as Area[ID] so further treatment shall be done for the Weight calculation
1189  }
1190 
1191  }//for every vertex
1192 
1193  if (DistPToB < rad)
1194  {
1195  double auxiliar_unit_vector[3];
1196  CrossProduct( N,A,auxiliar_unit_vector );
1197  normalize( auxiliar_unit_vector );
1198  normalize( A );
1199  for (unsigned int j = 0; j<3; j++)
1200  {
1201  LocalCoordSystem[0][j] = A[j];
1202  LocalCoordSystem[1][j] = auxiliar_unit_vector[j];
1203  LocalCoordSystem[2][j] = N[j];
1204  }
1205 
1206  WeightsCalculation(Area,Weight);
1207  return true;
1208 
1209  }//if DistPToB < rad
1210 
1211  return false;
1212 
1213  } //FacetCheck
1214 
1215  static inline bool FastEdgeVertexCheck(const array_1d<double,3>& Coord1, const array_1d<double,3>& Coord2, const array_1d<double,3>& Particle_Coord, double Radius)
1216  {
1217  double IntersectionCoordEdge[3];
1218  double normal_unit_vector[3];
1219  double edge_unit_vector[3];
1220  double module_edge_vector = 0.0;
1221  double particle_vector1[3];
1222  double particle_vector2[3];
1223 
1224  for (unsigned int j = 0; j<3; j++)
1225  {
1226  edge_unit_vector[j] = Coord2[j] - Coord1[j];
1227  particle_vector1[j] = Particle_Coord[j] - Coord1[j];
1228  particle_vector2[j] = Particle_Coord[j] - Coord2[j];
1229  }
1230 
1231  normalize( edge_unit_vector, module_edge_vector);
1232  double projection_on_edge = DotProduct(particle_vector1,edge_unit_vector);
1233 
1234  double eta = projection_on_edge/module_edge_vector;
1235 
1236  if ((eta>=0.0) && (eta<=1.0)) //can only be edge, no vertex
1237  {
1238  for (unsigned int j = 0; j<3; j++)
1239  {
1240  IntersectionCoordEdge[j] = Coord1[j] + projection_on_edge*edge_unit_vector[j];
1241  normal_unit_vector[j] = Particle_Coord[j] - IntersectionCoordEdge[j];
1242  }
1243 
1244  double DistParticleToEdge;
1245  normalize( normal_unit_vector, DistParticleToEdge);
1246 
1247  if (DistParticleToEdge < Radius)
1248  {
1249  return true;
1250  }
1251  }
1252 
1253  if (eta < 0.0) //1rst Vertex
1254  {
1255  double dist_to_vertex_sq = 0.0;
1256  double Rad_sq = Radius*Radius;
1257 
1258  for (unsigned int j = 0; j<3; j++)
1259  {
1260  dist_to_vertex_sq +=particle_vector1[j]*particle_vector1[j];
1261  }
1262 
1263  if (dist_to_vertex_sq < Rad_sq)
1264  {
1265  return true;
1266  }
1267  }
1268 
1269  if (eta > 1.0) //2n vertex
1270  {
1271  double dist_to_vertex_sq = 0.0;
1272  double Rad_sq = Radius*Radius;
1273  for (unsigned int j = 0; j<3; j++)
1274  {
1275  dist_to_vertex_sq +=particle_vector2[j]*particle_vector2[j];
1276  }
1277 
1278  if (dist_to_vertex_sq < Rad_sq)
1279  {
1280  return true;
1281  }
1282  }
1283 
1284  return false;
1285 
1286  }//FastEdgeVertexCheck;
1287 
1288  static inline bool EdgeCheck(const array_1d<double,3>& Coord1, const array_1d<double,3>& Coord2, const array_1d<double,3>& Particle_Coord, double Radius,
1289  double LocalCoordSystem[3][3], double& DistParticleToEdge, double& eta)
1290  {
1291  double IntersectionCoordEdge[3];
1292  double normal_unit_vector[3];
1293  double edge_unit_vector[3];
1294  double module_edge_vector = 0.0;
1295  double particle_vector[3];
1296 
1297  for (unsigned int j = 0; j<3; j++)
1298  {
1299  edge_unit_vector[j] = Coord2[j] - Coord1[j];
1300  particle_vector[j] = Particle_Coord[j] - Coord1[j];
1301  }
1302 
1303  normalize(edge_unit_vector, module_edge_vector);
1304  double projection_on_edge = DotProduct(particle_vector,edge_unit_vector);
1305 
1306  for (unsigned int j = 0; j<3; j++)
1307  {
1308  IntersectionCoordEdge[j] = Coord1[j] + projection_on_edge*edge_unit_vector[j];
1309  normal_unit_vector[j] = Particle_Coord[j] - IntersectionCoordEdge[j];
1310  }
1311 
1312  normalize( normal_unit_vector, DistParticleToEdge);
1313 
1314  eta = projection_on_edge / module_edge_vector;
1315 
1316  if (DistParticleToEdge < Radius)
1317  {
1318  if ((eta>=0.0) && (eta<=1.0))
1319  {
1320  double dummy_length = 0.0;
1321  double auxiliar_unit_vector[3];
1322  CrossProduct(normal_unit_vector,edge_unit_vector,auxiliar_unit_vector);
1323  normalize(auxiliar_unit_vector, dummy_length);
1324 
1325  for (unsigned int j = 0; j<3; j++)
1326  {
1327  LocalCoordSystem[0][j] = edge_unit_vector[j];
1328  LocalCoordSystem[1][j] = auxiliar_unit_vector[j];
1329  LocalCoordSystem[2][j] = normal_unit_vector[j];
1330  }
1331 
1332  return true;
1333  }
1334  } //if distance to edge < radius
1335 
1336  return false;
1337 
1338  }//EdgeCheck
1339 
1340  static inline bool VertexCheck(const array_1d<double,3>& Coord, const array_1d<double,3>& Particle_Coord, double Radius, double LocalCoordSystem[3][3], double& DistParticleToVertex)
1341  {
1342  double dist_sq = 0.0;
1343  array_1d<double, 3> normal_v;
1344  for (unsigned int j = 0; j < 3; j++)
1345  {
1346  normal_v[j] = Particle_Coord[j] - Coord[j];
1347  dist_sq += normal_v[j] * normal_v[j];
1348  }
1349  if (dist_sq <= Radius * Radius)
1350  {
1351  DistParticleToVertex = sqrt(dist_sq);
1352  ComputeContactLocalCoordSystem(normal_v, DistParticleToVertex, LocalCoordSystem);
1353  return true;
1354  }
1355  return false;
1356  }//VertexCheck
1357 
1358 
1359  static inline bool FastVertexCheck(const array_1d<double,3>& Coord, const array_1d<double,3>& Particle_Coord, double Radius)
1360  {
1361  double dist_sq = 0.0;
1362  array_1d<double, 3> normal_v;
1363  for (unsigned int j = 0; j < 3; j++)
1364  {
1365  normal_v[j] = Particle_Coord[j] - Coord[j];
1366  dist_sq += normal_v[j] * normal_v[j];
1367  }
1368  if (dist_sq <= Radius * Radius) return true;
1369  return false;
1370  }//FastVertexCheck
1371 
1375  /*static inline void Coord_transform(double origin[3], double coordsystem[3][3], double Coord[3], double TransCoord[3])
1376  {
1377  TransCoord[0]=0.0;
1378  TransCoord[1]=0.0;
1379  TransCoord[2]=0.0;
1380  double vector[3];
1381  vector[0]=Coord[0] - origin[0];
1382  vector[1]=Coord[1] - origin[1];
1383  vector[2]=Coord[2] - origin[2];
1384  TransCoord[0]=DotProduct(coordsystem[0],vector);
1385  TransCoord[1]=DotProduct(coordsystem[1],vector);
1386  TransCoord[2]=DotProduct(coordsystem[2],vector);
1387  }*/
1388 
1389  /*static inline void N44(double xp,double yp,double xy[4][2],double& N1,double& N2,double& N3,double& N4)
1390  {
1391  double xc=(xy[0][0]+xy[1][0]+xy[2][0]+xy[3][0])/4.0;
1392  double yc=(xy[0][1]+xy[1][1]+xy[2][1]+xy[3][1])/4.0;
1393 
1394  double elelength_x=2.0*fabs(xy[0][0]-xc);
1395  double elelength_y=2.0*fabs(xy[0][1]-yc);
1396 
1397  double Eps,Ita;
1398  Eps=2.0*(xp-xc)/elelength_x;
1399  Ita=2.0*(yp-yc)/elelength_y;
1400  N1=0.25*(1+Eps*2*(xy[0][0]-xc)/elelength_x)*(1+Ita*2*(xy[0][1]-yc)/elelength_y);
1401  N2=0.25*(1+Eps*2*(xy[1][0]-xc)/elelength_x)*(1+Ita*2*(xy[1][1]-yc)/elelength_y);
1402  N3=0.25*(1+Eps*2*(xy[2][0]-xc)/elelength_x)*(1+Ita*2*(xy[2][1]-yc)/elelength_y);
1403  N4=0.25*(1+Eps*2*(xy[3][0]-xc)/elelength_x)*(1+Ita*2*(xy[3][1]-yc)/elelength_y);
1404  }*/
1405 
1406  //Cfeng: irregular quadrilateral transfer to regular quadrilateral
1407  /*static inline void gl_to_iso(double x0, double y0, double xy[4][2], double& x_exisp, double& y_etasp)
1408  {
1409  double exisp=0.0;
1410  double etasp=0.0;
1411  double tolerance=1.0e-8;
1412  double x,y,x1,x2,x3,x4,y1,y2,y3,y4,a1,a2,a3,a4,b1,b2,b3,b4,s1,t1,d1,g1,g2,g0;
1413  x1 = xy[0][0];
1414  x2 = xy[1][0];
1415  x3 = xy[2][0];
1416  x4 = xy[3][0];
1417  y1 = xy[0][1];
1418  y2 = xy[1][1];
1419  y3 = xy[2][1];
1420  y4 = xy[3][1];
1421  a1=0.25*(-x1+x2+x3-x4);
1422  a2=0.25*(x1-x2+x3-x4);
1423  a3=0.25*(-x1-x2+x3+x4);
1424  a4=0.25*(x1+x2+x3+x4);
1425  b1=0.25*(-y1+y2+y3-y4);
1426  b2=0.25*(y1-y2+y3-y4);
1427  b3=0.25*(-y1-y2+y3+y4);
1428  b4=0.25*(y1+y2+y3+y4);
1429 
1430  x = x0 - a4;
1431  y = y0 - b4;
1432  s1 = a2*b3 - a3*b2;
1433  t1 = b2*x - a2*y + a1*b3 - a3*b1;
1434  d1 = b1*x - a1*y;
1435 
1436  if (fabs(s1) < tolerance)
1437  {
1438  etasp = -d1/t1;
1439  exisp = (x-a3*etasp) / (a1+a2*etasp);
1440  }
1441  else
1442  {
1443  const double sqrt_aux = sqrt(t1*t1-4*s1*d1);
1444  g1 = (-t1 + sqrt_aux) / (2*s1);
1445  g2 = (-t1 - sqrt_aux) / (2*s1);
1446  if (fabs(g1) < 1.0+tolerance)
1447  {
1448  g0 = (x-a3*g1) / (a1+a2*g1);
1449  if (fabs(g0) < 1.0+tolerance)
1450  {
1451  etasp = g1;
1452  exisp = g0;
1453  }
1454  }
1455  if(fabs(g2) < 1.0+tolerance)
1456  {
1457  g0 = (x-a3*g2) / (a1+a2*g2);
1458  if(fabs(g0) < 1.0+tolerance)
1459  {
1460  etasp = g2;
1461  exisp = g0;
1462  }
1463  }
1464  }
1465  x_exisp=exisp;
1466  y_etasp=etasp;
1467  }*/
1468 
1469  /*static void CalQuadWeightCoefficient(double Coord[4][3], double LocalCoordSystem[3][3], double IntersectionCoord[3], double Weight[4])
1470  {
1471 
1472 
1473  int j;
1474 
1475  double FaceCenter[3] = {0.0};
1476  for(j = 0; j < 4; j++)
1477  {
1478  FaceCenter[0] += Coord[j][0] * 0.25;
1479  FaceCenter[1] += Coord[j][1] * 0.25;
1480  FaceCenter[2] += Coord[j][2] * 0.25;
1481  }
1482 
1483  double TransCoord0[3],TransCoord1[3],TransCoord2[3],TransCoord3[3];
1484  double xy[4][2];
1485  double xy1[4][2]={{-1.0,-1.0},{1.0,-1.0},{1.0,1.0},{-1.0,1.0}};
1486 
1487 
1488  double TempLocalCoordSystem[3][3]={{0.0}, {0.0}, {0.0}};
1489  double vx[3]={1.0,0,0},vy[3]={0,1.0,0},vz[3]={0, 0, 1.0};
1490 
1491  if( DotProduct(LocalCoordSystem[2],vx)<0 || DotProduct(LocalCoordSystem[2],vy)<0 || DotProduct(LocalCoordSystem[2],vz)<0 )
1492  {
1493  for(j=0;j<3;j++)
1494  {
1495  TempLocalCoordSystem[0][j] = LocalCoordSystem[0][j];
1496  TempLocalCoordSystem[1][j] = LocalCoordSystem[1][j];
1497  TempLocalCoordSystem[2][j] = -LocalCoordSystem[2][j];
1498  }
1499  }
1500 
1501 
1502 
1503  else
1504  {
1505  for(j=0;j<3;j++)
1506  {
1507  TempLocalCoordSystem[0][j] = LocalCoordSystem[0][j];
1508  TempLocalCoordSystem[1][j] = LocalCoordSystem[1][j];
1509  TempLocalCoordSystem[2][j] = LocalCoordSystem[2][j];
1510  }
1511  }
1512 
1513 
1514  Coord_transform(FaceCenter, TempLocalCoordSystem, Coord[0], TransCoord0);
1515  Coord_transform(FaceCenter, TempLocalCoordSystem, Coord[1], TransCoord1);
1516  Coord_transform(FaceCenter, TempLocalCoordSystem, Coord[2], TransCoord2);
1517  Coord_transform(FaceCenter, TempLocalCoordSystem, Coord[3], TransCoord3);
1518 
1519 
1520  xy[0][0] = TransCoord0[0]; xy[0][1] = TransCoord0[1];
1521  xy[1][0] = TransCoord1[0]; xy[1][1] = TransCoord1[1];
1522  xy[2][0] = TransCoord2[0]; xy[2][1] = TransCoord2[1];
1523  xy[3][0] = TransCoord3[0]; xy[3][1] = TransCoord3[1];
1524 
1525  double in0=0.0, in1=0.0, in2=0.0, in3=0.0;
1526  double TransCoordp[3];
1527  double Coordp_iso[2];
1528 
1529 
1530  Coord_transform(FaceCenter, TempLocalCoordSystem, IntersectionCoord, TransCoordp);
1531 
1532  gl_to_iso(TransCoordp[0],TransCoordp[1],xy,Coordp_iso[0],Coordp_iso[1]);
1533 
1534  N44(Coordp_iso[0],Coordp_iso[1], xy1, in0, in1, in2, in3);
1535 
1536  Weight[0]=in0;
1537  Weight[1]=in1;
1538  Weight[2]=in2;
1539  Weight[3]=in3;
1540 
1541 
1542 
1543  }*/
1544 
1548 
1549  static inline void GetRotationMatrix(const array_1d<double, 3>& EulerAngles, double rotation_matrix[3][3]) {
1550 
1551  double cosA=cos(EulerAngles[0]);
1552  double sinA=sin(EulerAngles[0]);
1553  double cosB=cos(EulerAngles[1]);
1554  double sinB=sin(EulerAngles[1]);
1555  double cosC=cos(EulerAngles[2]);
1556  double sinC=sin(EulerAngles[2]);
1557 
1558  rotation_matrix[0][0] = cosC*cosA - cosB*sinA*sinC;
1559  rotation_matrix[0][1] = -sinC*cosA - cosB*sinA*cosC;
1560  rotation_matrix[0][2] = sinB*sinA;
1561  rotation_matrix[1][0] = cosC*sinA + cosB*cosA*sinC;
1562  rotation_matrix[1][1] = -sinC*sinA + cosB*cosA*cosC;
1563  rotation_matrix[1][2] = -sinB*cosA;
1564  rotation_matrix[2][0] = sinC*sinB;
1565  rotation_matrix[2][1] = cosC*sinB;
1566  rotation_matrix[2][2] = cosB;
1567 
1568  return;
1569  }
1570 
1571  static inline void GetEulerAngles(const double rotation_matrix[3][3], array_1d<double, 3 > & EulerAngles)
1572  {
1573  if (rotation_matrix[2][2] < 1.0)
1574  {
1575  if (rotation_matrix[2][2] > -1.0) {
1576  EulerAngles[0] = atan2(rotation_matrix[0][2], -rotation_matrix[1][2]);
1577  EulerAngles[1] = acos(rotation_matrix[2][2]);
1578  EulerAngles[2] = atan2(rotation_matrix[2][0], rotation_matrix[2][1]);
1579  }
1580  else // r22 = -1
1581  {
1582  // Not a unique solution: thetaZ1 - thetaZ0 = atan2(-r01,r00)
1583  EulerAngles[0] = -atan2(-rotation_matrix[0][1], rotation_matrix[0][0]);
1584  EulerAngles[1] = Globals::Pi;
1585  EulerAngles[2] = 0;
1586  }
1587  }
1588  else // r22 = +1
1589  {
1590  // Not a unique solution: thetaZ1 + thetaZ0 = atan2(-r01,r00)
1591  EulerAngles[0] = atan2(-rotation_matrix[0][1], rotation_matrix[0][0]);
1592  EulerAngles[1] = 0;
1593  EulerAngles[2] = 0;
1594  }
1595 
1596  return;
1597  }
1598 
1599  static inline void GetGiDEulerAngles(const BoundedMatrix<double, 3, 3>& rotation_matrix, array_1d<double, 3>& EulerAngles) {
1600  const double numerical_limit = std::numeric_limits<double>::epsilon();
1601  const double two_pi = 3.1415926535897932384626433 * 2.0;
1602  if(rotation_matrix(2, 2)<1.0-numerical_limit && rotation_matrix(2, 2)>-1.0+numerical_limit){
1603  const double senb=sqrt(1.0-rotation_matrix(2, 2)*rotation_matrix(2, 2));
1604  EulerAngles[1]=acos(rotation_matrix(2, 2));
1605  EulerAngles[2]=acos(rotation_matrix(1, 2)/senb);
1606  if(rotation_matrix(0, 2)/senb<0.0) EulerAngles[2]=two_pi - EulerAngles[2];
1607  EulerAngles[0]=acos(-rotation_matrix(2, 1)/senb);
1608  if(rotation_matrix(2, 0)/senb<0.0) EulerAngles[0]=two_pi - EulerAngles[0];
1609  } else {
1610  // fixed a=0.0 (arbitrary)
1611  EulerAngles[1]=acos(rotation_matrix(2, 2));
1612  EulerAngles[0]=0.0;
1613  EulerAngles[2]=acos(rotation_matrix(0, 0));
1614  if(-rotation_matrix(1, 0)<0.0) EulerAngles[2]=two_pi - EulerAngles[2];
1615  }
1616  }
1617 
1618  inline void QuaternionToGiDEulerAngles(const Quaternion<double>& quaternion, array_1d<double, 3>& EulerAngles) {
1619  BoundedMatrix<double, 3, 3> rotation_matrix = ZeroMatrix(3,3);
1620  quaternion.ToRotationMatrix(rotation_matrix);
1621  GetGiDEulerAngles(rotation_matrix, EulerAngles);
1622  }
1623 
1627 
1628  static inline void TriAngleArea(double Coord1[3], double Coord2[3], double Coord3[3], double& area)
1629  {
1630  int k;
1631  double Vector1[3],Vector2[3],Vector0[3];
1632  for (k = 0;k < 3; k++)
1633  {
1634  Vector1[k] = Coord3[k] - Coord1[k];
1635  Vector2[k] = Coord2[k] - Coord1[k];
1636  }
1637 
1638  CrossProduct(Vector1, Vector2, Vector0);
1639  area = 0.5 * DEM_MODULUS_3(Vector0);
1640  }
1641 
1642  //TriAngle Weight, coord1,coord2,coord3,testcoord,weight
1643  static inline void TriAngleWeight(double Coord1[3], double Coord2[3], double Coord3[3], double JudgeCoord[3], double Weight[3])
1644  {
1645  double area[3], s;
1646  TriAngleArea(Coord1, Coord2, JudgeCoord, area[0]);
1647  TriAngleArea(Coord2, Coord3, JudgeCoord, area[1]);
1648  TriAngleArea(Coord3, Coord1, JudgeCoord, area[2]);
1649 
1650  TriAngleArea(Coord1, Coord2, Coord3, s);
1652  const double s_inv = 1.0 / s;
1653  Weight[0] = area[1] * s_inv;
1654  Weight[1] = area[2] * s_inv;
1655  Weight[2] = area[0] * s_inv;
1656  }
1657 
1658  //Quadrilatera Weight, coord1,coord2,coord3,testcoord,weight (Paper Zhang)
1659  static inline void QuadAngleWeight(double Coord1[3], double Coord2[3], double Coord3[3], double Coord4[3], double JudgeCoord[3], double Weight[4])
1660  {
1661  double area[4], s1, s2, s;
1662  TriAngleArea(Coord1, Coord2, JudgeCoord, area[0]);
1663  TriAngleArea(Coord2, Coord3, JudgeCoord, area[1]);
1664  TriAngleArea(Coord3, Coord4, JudgeCoord, area[2]);
1665  TriAngleArea(Coord4, Coord1, JudgeCoord, area[3]);
1666 
1667  TriAngleArea(Coord1, Coord2, Coord3, s1);//msimsi
1668  TriAngleArea(Coord1, Coord3, Coord4, s2);//msimsi
1669 
1670  s = s1 + s2;
1671 
1672  if (fabs(area[0] + area[1] + area[2] + area[3] - s) < 1.0e-15) //msimsi
1673  {
1674  double QuadNormArea = 1 / ((area[0] + area[2]) * (area[1] + area[3]));
1675 
1676  Weight[0] = (area[1] * area[2]) * QuadNormArea;
1677  Weight[1] = (area[2] * area[3]) * QuadNormArea;
1678  Weight[2] = (area[3] * area[0]) * QuadNormArea;
1679  Weight[3] = (area[0] * area[1]) * QuadNormArea;
1680  }
1681  }
1682 
1683  static inline void AreaAndCentroidCircularSector(double C[3], double Radius, double P1[3], double P2[3], double Normal[3], double& Area, double CoMSC[3])
1684  {
1685  double a[3] = {0.0};
1686  double c[3] = {0.0};
1687  double bisection[3] = {0.0};
1688  double norm_a = 0.0;
1689 
1690  for (unsigned int index = 0;index<3;index++) {
1691 
1692  a[index] = P1[index]-C[index];
1693  c[index] = P2[index]-P1[index];
1694 
1695  }
1696 
1697  CrossProduct(Normal,c,bisection);
1699  double dot_product = DotProduct(bisection,a);
1700 
1701  if (dot_product<0.0) {
1702 
1703  for (unsigned int index = 0;index<3;index++) {
1704 
1705  bisection[index] = -bisection[index];
1706  }
1707 
1708  dot_product = -dot_product;
1709  }
1710 
1711  module(a, norm_a);
1712 
1713  double cos_alpha = dot_product/norm_a;
1714  double alpha = acos(cos_alpha);
1715  double sin_alpha = std::sin(alpha);
1716 
1717  Area = Radius*Radius*alpha;
1718  double dist = 0.66666666666666*(Radius*sin_alpha/alpha);
1719  for (unsigned int index = 0;index<3;index++) {
1720  CoMSC[index] = C[index]+dist*bisection[index];
1721  }
1722 
1723  }//AreaCircularSector
1724 
1725  static inline void AlternativeAreaCircularSegment(double Radius, double tol_Radius, double V0V1[3], double V0CC[3], double Normal[3], double& AreaSC, bool& flag)
1726  {
1727 
1728  double normal_outwards[3] = {0.0};
1729  flag = false;
1730  AreaSC = 0.0;
1731 
1732  CrossProduct(V0V1, Normal, normal_outwards);
1733  normalize(normal_outwards);
1734 
1735  double dist = DotProduct(normal_outwards,V0CC);
1736  double delta_circle = Radius + dist; //distance can be positive or negative, depending on the side where the circle is
1737 
1738  if ((delta_circle > tol_Radius) && (delta_circle - 2*Radius < -tol_Radius)) {//check for intersection
1739 
1740  flag = true;
1741  double b = sqrt(delta_circle*(2*Radius-delta_circle));
1742  AreaSC = 2.0*Radius*Radius*atan(delta_circle/b)-b*(Radius-delta_circle);
1743  }
1744  }//AreaAndCentroidCircularSector1
1745 
1746  static inline void AreaAndCentroidCircularSegment(double Centre[3], double Radius, double tol_Radius, double V0[3], double V1[3], double Normal[3], double& AreaSegC, double CoMSegC[3], bool& flag)
1747  {
1748  double V0V1[3] = {0.0};
1749  double V0CC[3] = {0.0};
1750  double a[3] = {0.0};
1751  double normal_outwards[3] = {0.0};
1752  double Radius_SQ = 0.0;
1753  double distance_V0V1 = 0.0;
1754  double dist_CoM = 0.0;
1755  AreaSegC = 0.0;
1756  flag = false;
1757 
1758  for (unsigned int index = 0; index<3; index++) {
1759 
1760  V0V1[index] = V1[index] - V0[index];
1761  V0CC[index] = Centre[index] - V0[index];
1762  }
1763 
1764  GeometryFunctions::CrossProduct(V0V1,Normal,normal_outwards);
1765  GeometryFunctions::normalize(V0V1,distance_V0V1);
1766 
1767  double distV0 = GeometryFunctions::DotProduct(V0CC,V0V1);
1768 
1769  if ((distV0 > 0.0) && (distV0 < distance_V0V1)) {
1770 
1771  GeometryFunctions::normalize(normal_outwards);
1772  double dist_normal = GeometryFunctions::DotProduct(normal_outwards,V0CC);
1773  double delta_circle = Radius + dist_normal; //distance can be positive or negative, depending on the side where the circle is
1774 
1775  if ((delta_circle > tol_Radius) && ( delta_circle - 2.0*Radius < -tol_Radius)) {//check for intersection
1776 
1777  Radius_SQ = Radius*Radius;
1778  double semi_dist = sqrt(Radius_SQ - dist_normal*dist_normal);
1779  flag = true;
1780 
1781  for (unsigned int index = 0;index<3;index++) {
1782 
1783  a[index] = V0[index] + (distV0 - semi_dist)*V0V1[index] - Centre[index]; //Vector from Center to first intersection point
1784  }
1785 
1786  double cos_alpha = GeometryFunctions::DotProduct(a,normal_outwards)/(GeometryFunctions::module(a)*GeometryFunctions::module(normal_outwards));
1787  double alpha = acos(cos_alpha);
1788  double sin_alpha = std::sin(alpha);
1789 
1790  AreaSegC = Radius_SQ*(alpha-sin_alpha*cos_alpha);
1791 
1792  if (fabs(sin_alpha) < tol_Radius) {dist_CoM=0.0;}
1793 
1794  else {dist_CoM = 0.6666666666666 * (Radius*sin_alpha*sin_alpha*sin_alpha/(alpha-sin_alpha*cos_alpha));}
1795 
1796  for (unsigned int index = 0; index<3; index++) {
1797  CoMSegC[index] = Centre[index] + dist_CoM*normal_outwards[index];
1798  }
1799  } //if normal dist is okay
1800 
1801  } // if longitudinal dist is okay
1802 
1803  }//AreaAndCentroidCircularSegment
1804 
1805  static inline void AreaAndCentroidTriangle(double Coord1[3], double Coord2[3], double Coord3[3], double& area, double CoMTri[3]) {
1806 
1807  TriAngleArea(Coord1,Coord2,Coord3,area);
1808 
1809  for (unsigned int index =0; index<3; index++) {
1810 
1811  CoMTri[index] = 0.33333333333333 * (Coord1[index]+Coord2[index]+Coord3[index]);
1812  }
1813 
1814  } //AreaAndCentroidTriangle
1815 
1816  } //namespace GeometryFunctions
1817 
1818 } //namespace Kratos
1819 
1820 #endif /* _GEOMETRYFUNCTIONS_H */
#define DEM_MODULUS_3(a)
Definition: DEM_application_variables.h:29
#define DEM_MULTIPLY_BY_SCALAR_3(a, b)
Definition: DEM_application_variables.h:28
#define DEM_INNER_PRODUCT_3(a, b)
Definition: DEM_application_variables.h:31
#define DEM_SET_TO_CROSS_OF_FIRST_TWO_3(a, b, c)
Definition: DEM_application_variables.h:32
#define DEM_COPY_SECOND_TO_FIRST_3(a, b)
Definition: DEM_application_variables.h:23
Geometry base class.
Definition: geometry.h:71
SizeType size() const
Definition: geometry.h:518
Various mathematical utilitiy functions.
Definition: math_utils.h:62
static double Norm3(const TVectorType &a)
Calculates the norm of vector "a" which is assumed to be of size 3.
Definition: math_utils.h:691
MeshType::NodeIterator NodeIterator
Definition: model_part.h:134
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
static Quaternion Identity()
Definition: quaternion.h:383
void normalize()
Definition: quaternion.h:179
void ToRotationMatrix(TMatrix3x3 &R) const
Definition: quaternion.h:213
void ToEulerAngles(array_1d< double, 3 > &EA) const
Definition: quaternion.h:236
void RotateVector3(const TVector3_A &a, TVector3_B &b) const
Definition: quaternion.h:325
#define KRATOS_WATCH(variable)
Definition: define.h:806
dt
Definition: DEM_benchmarks.py:173
z
Definition: GenerateWind.py:163
static void WeightsCalculation(std::vector< double > Area, std::vector< double > &Weight)
Definition: GeometryFunctions.h:1027
static void QuaternionVectorGlobal2Local(const Quaternion< double > &Q, const array_1d< double, 3 > &GlobalVector, array_1d< double, 3 > &LocalVector)
Definition: GeometryFunctions.h:764
static bool FastFacetCheck(const std::vector< array_1d< double, 3 > > &Coord, const array_1d< double, 3 > &Particle_Coord, double rad, double &DistPToB, unsigned int &current_edge_index)
Definition: GeometryFunctions.h:1053
static bool FastVertexCheck(const array_1d< double, 3 > &Coord, const array_1d< double, 3 > &Particle_Coord, double Radius)
Definition: GeometryFunctions.h:1359
static void RotaMatrixTensorLocal2Global(const double R[3][3], const double LocalTensor[3][3], double GlobalTensor[3][3])
Definition: GeometryFunctions.h:274
static void VectorLocal2Global(const double LocalCoordSystem[3][3], const double LocalVector[3], double GlobalVector[3])
Definition: GeometryFunctions.h:178
static void RotateRightHandedBasisAroundAxis(const array_1d< double, 3 > &e1, const array_1d< double, 3 > &e2, const array_1d< double, 3 > &axis, const double ang, array_1d< double, 3 > &new_axes1, array_1d< double, 3 > &new_axes2, array_1d< double, 3 > &new_axes3)
Definition: GeometryFunctions.h:367
static void GetGiDEulerAngles(const BoundedMatrix< double, 3, 3 > &rotation_matrix, array_1d< double, 3 > &EulerAngles)
Definition: GeometryFunctions.h:1599
static void QuaternionVectorLocal2Global(const Quaternion< double > &Q, const array_1d< double, 3 > &LocalVector, array_1d< double, 3 > &GlobalVector)
Definition: GeometryFunctions.h:759
static bool EdgeCheck(const array_1d< double, 3 > &Coord1, const array_1d< double, 3 > &Coord2, const array_1d< double, 3 > &Particle_Coord, double Radius, double LocalCoordSystem[3][3], double &DistParticleToEdge, double &eta)
Definition: GeometryFunctions.h:1288
static void ConstructInvLocalTensor(const double moment_of_inertia, double LocalTensorInv[3][3])
Definition: GeometryFunctions.h:293
static void normalize(double Vector[3])
Definition: GeometryFunctions.h:87
Geometry< Node > GeometryType
Definition: GeometryFunctions.h:21
static void RotateAVectorAGivenAngleAroundAUnitaryVector(const array_1d< double, 3 > &old_vec, const array_1d< double, 3 > &axis, const double ang, array_1d< double, 3 > &new_vec)
Definition: GeometryFunctions.h:23
static void ComputeContactLocalCoordSystem(array_1d< double, 3 > NormalDirection, const double &distance, double LocalCoordSystem[3][3])
Definition: GeometryFunctions.h:490
static void Compute3DimElementFaceLocalSystem(const array_1d< double, 3 > &FaceCoord1, const array_1d< double, 3 > &FaceCoord2, const array_1d< double, 3 > &FaceCoord3, double ParticleCoord[3], double LocalCoordSystem[3][3], double &normal_flag)
Definition: GeometryFunctions.h:622
static void module(const array_1d< double, 3 > &Vector, double &distance)
Definition: GeometryFunctions.h:127
static void EulerAnglesFromRotationAngle(array_1d< double, 3 > &EulerAngles, const array_1d< double, 3 > &RotatedAngle)
Definition: GeometryFunctions.h:870
static bool FastEdgeVertexCheck(const array_1d< double, 3 > &Coord1, const array_1d< double, 3 > &Coord2, const array_1d< double, 3 > &Particle_Coord, double Radius)
Definition: GeometryFunctions.h:1215
static void GetEulerAngles(const double rotation_matrix[3][3], array_1d< double, 3 > &EulerAngles)
Definition: GeometryFunctions.h:1571
static bool InsideOutside(const array_1d< double, 3 > &Coord1, const array_1d< double, 3 > &Coord2, const array_1d< double, 3 > &JudgeCoord, const array_1d< double, 3 > &normal_element, double &area)
Definition: GeometryFunctions.h:976
static void QuadAngleWeight(double Coord1[3], double Coord2[3], double Coord3[3], double Coord4[3], double JudgeCoord[3], double Weight[4])
Definition: GeometryFunctions.h:1659
static void TensorLocal2Global(const double LocalCoordSystem[3][3], const double LocalTensor[3][3], double GlobalTensor[3][3])
Definition: GeometryFunctions.h:257
static void AreaAndCentroidCircularSegment(double Centre[3], double Radius, double tol_Radius, double V0[3], double V1[3], double Normal[3], double &AreaSegC, double CoMSegC[3], bool &flag)
Definition: GeometryFunctions.h:1746
static void ProductMatrix3X3Vector3X1(const double Matrix[3][3], const array_1d< double, 3 > &Vector1, array_1d< double, 3 > &Vector2)
Definition: GeometryFunctions.h:230
static void TranslateGridOfNodes(const double time, const double velocity_start_time, const double velocity_stop_time, array_1d< double, 3 > &center_position, const array_1d< double, 3 > &initial_center, array_1d< double, 3 > &previous_displ, array_1d< double, 3 > &linear_velocity_changed, const double linear_period, const double dt, const array_1d< double, 3 > &linear_velocity)
Definition: GeometryFunctions.h:33
static void AreaAndCentroidTriangle(double Coord1[3], double Coord2[3], double Coord3[3], double &area, double CoMTri[3])
Definition: GeometryFunctions.h:1805
static double max(double a, double b)
Definition: GeometryFunctions.h:79
static void AlternativeAreaCircularSegment(double Radius, double tol_Radius, double V0V1[3], double V0CC[3], double Normal[3], double &AreaSC, bool &flag)
Definition: GeometryFunctions.h:1725
static void CoordProjectionOnPlane(double CoordOut[3], double CoordIn[3], double LocalCoordSystem[3][3], double IntersectionCoord[3])
Definition: GeometryFunctions.h:588
static bool VertexCheck(const array_1d< double, 3 > &Coord, const array_1d< double, 3 > &Particle_Coord, double Radius, double LocalCoordSystem[3][3], double &DistParticleToVertex)
Definition: GeometryFunctions.h:1340
static void OrientationFromRotationAngle(Quaternion< double > &DeltaOrientation, const array_1d< double, 3 > &DeltaRotation)
Definition: GeometryFunctions.h:894
static bool FacetCheck(const GeometryType &Coord, const array_1d< double, 3 > &Particle_Coord, double rad, double LocalCoordSystem[3][3], double &DistPToB, std::vector< double > &Weight, unsigned int &current_edge_index, bool &inside)
Definition: GeometryFunctions.h:1118
static void RotatePointAboutArbitraryLine(array_1d< double, 3 > &TargetPoint, const array_1d< double, 3 > &CentrePoint, const array_1d< double, 3 > &LineVector, const double RotationAngle)
Definition: GeometryFunctions.h:735
static void RotateCoordToDirection(const double OLdCoordSystem[3][3], double Vector[3], double NewCoordSystem[3][3])
Definition: GeometryFunctions.h:939
static void GetRotationMatrix(const array_1d< double, 3 > &EulerAngles, double rotation_matrix[3][3])
Definition: GeometryFunctions.h:1549
static double DistanceOfTwoPointSquared(const array_1d< double, 3 > &coord1, const array_1d< double, 3 > &coord2)
Definition: GeometryFunctions.h:557
static void UpdateKinematicVariablesOfAGridOfNodes(double mod_angular_velocity, const array_1d< double, 3 > &linear_velocity, const array_1d< double, 3 > &initial_center, array_1d< double, 3 > &new_axes1, array_1d< double, 3 > &new_axes2, array_1d< double, 3 > &new_axes3, array_1d< double, 3 > &angular_velocity_changed, array_1d< double, 3 > &linear_velocity_changed, array_1d< double, 3 > &center_position, const bool fixed_mesh, const double dt, ModelPart::NodesContainerType &pNodes)
Definition: GeometryFunctions.h:448
static void ConstructLocalTensor(const double moment_of_inertia, double LocalTensor[3][3])
Definition: GeometryFunctions.h:286
void QuaternionToGiDEulerAngles(const Quaternion< double > &quaternion, array_1d< double, 3 > &EulerAngles)
Definition: GeometryFunctions.h:1618
static double DistanceOfTwoPoint(const double coord1[3], const double coord2[3])
Definition: GeometryFunctions.h:539
static void QuaternionTensorLocal2Global(const Quaternion< double > &Q, const double LocalTensor[3][3], double GlobalTensor[3][3])
Definition: GeometryFunctions.h:770
static void CrossProduct(const double u[3], const double v[3], double ReturnVector[3])
Definition: GeometryFunctions.h:325
static double DistancePointToPlane(const array_1d< double, 3 > &CoordInPlane, double PlaneUnitNormalVector[3], double TestCoord[3])
Definition: GeometryFunctions.h:574
static int sign(const double a)
Definition: GeometryFunctions.h:61
static void TensorGlobal2Local(const double LocalCoordSystem[3][3], const double GlobalTensor[3][3], double LocalTensor[3][3])
Definition: GeometryFunctions.h:240
static void ProductMatrices3X3(const double Matrix1[3][3], const double Matrix2[3][3], double Matrix3[3][3])
Definition: GeometryFunctions.h:218
static void RotateGridOfNodes(const double time, const double angular_velocity_start_time, const double angular_velocity_stop_time, array_1d< double, 3 > &angular_velocity_changed, const double angular_period, const double mod_angular_velocity, const array_1d< double, 3 > &angular_velocity, array_1d< double, 3 > &new_axes1, array_1d< double, 3 > &new_axes2, array_1d< double, 3 > &new_axes3)
Definition: GeometryFunctions.h:378
static void AreaAndCentroidCircularSector(double C[3], double Radius, double P1[3], double P2[3], double Normal[3], double &Area, double CoMSC[3])
Definition: GeometryFunctions.h:1683
static void TriAngleWeight(double Coord1[3], double Coord2[3], double Coord3[3], double JudgeCoord[3], double Weight[3])
Definition: GeometryFunctions.h:1643
static double DotProduct(double Vector1[3], double Vector2[3])
Definition: GeometryFunctions.h:315
static void CoordProjectionOnPlaneNew(double CoordOut[3], const array_1d< double, 3 > &CoordIn, double LocalCoordSystem[3][3], double IntersectionCoord[3])
Definition: GeometryFunctions.h:605
static void UpdateOrientation(array_1d< double, 3 > &EulerAngles, Quaternion< double > &Orientation, const array_1d< double, 3 > &DeltaRotation)
Definition: GeometryFunctions.h:800
static void TriAngleArea(double Coord1[3], double Coord2[3], double Coord3[3], double &area)
Definition: GeometryFunctions.h:1628
static double min(double a, double b)
Definition: GeometryFunctions.h:71
static void VectorGlobal2Local(const double LocalCoordSystem[3][3], const double GlobalVector[3], double LocalVector[3])
Definition: GeometryFunctions.h:148
constexpr double Pi
Definition: global_variables.h:25
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
KratosZeroMatrix< double > ZeroMatrix
Definition: amatrix_interface.h:559
T & noalias(T &TheMatrix)
Definition: amatrix_interface.h:484
REACTION_CHECK_STIFFNESS_FACTOR int
Definition: contact_structural_mechanics_application_variables.h:75
Temp
Definition: PecletTest.py:105
float velocity
Definition: PecletTest.py:54
axis
Definition: all_t_win_vs_m_fixed_error.py:239
float dist
Definition: edgebased_PureConvection.py:89
time
Definition: face_heat.py:85
y
Other simbols definition.
Definition: generate_axisymmetric_navier_stokes_element.py:54
v
Definition: generate_convection_diffusion_explicit_element.py:114
w
Definition: generate_convection_diffusion_explicit_element.py:108
alpha
Definition: generate_convection_diffusion_explicit_element.py:113
output
Definition: generate_frictional_mortar_condition.py:444
int C
Definition: generate_hyper_elastic_simo_taylor_neo_hookean.py:27
a
Definition: generate_stokes_twofluid_element.py:77
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
u
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:30
c
Definition: generate_weakly_compressible_navier_stokes_element.py:108
R
Definition: isotropic_damage_automatic_differentiation.py:172
tuple Q
Definition: isotropic_damage_automatic_differentiation.py:235
def bisection(f, a, b, tol)
Definition: normed_exact_hinsberg_test.py:17
int L
Definition: ode_solve.py:390
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
A
Definition: sensitivityMatrix.py:70
N
Definition: sensitivityMatrix.py:29
x
Definition: sensitivityMatrix.py:49
B
Definition: sensitivityMatrix.py:76
integer i
Definition: TensorModule.f:17
Definition: mesh_converter.cpp:38