MFEM  v4.6.0
Finite element discretization library
material_metrics.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details
11 
12 #include "material_metrics.hpp"
13 
14 namespace mfem
15 {
16 
18 {
19  std::vector<double> dist_vector;
20  dist_vector.resize(particle_positions_.size());
21  // 1. Compute the distance to each particle.
22  for (size_t i = 0; i < particle_positions_.size(); i++)
23  {
24  Vector y(3);
25  particle_orientations_[i].Mult(x, y);
26  dist_vector[i] = particle_positions_[i].DistanceTo(y);
27  }
28  // 2. Choose smallest number in the vector dist_vector.
29  double min_dist = *std::min_element(dist_vector.begin(), dist_vector.end());
30  return min_dist;
31 }
32 
33 void ParticleTopology::Initialize(std::vector<double> &random_positions,
34  std::vector<double> &random_rotations)
35 {
36  // 1. Initialize the particle positions.
37  particle_positions_.resize(number_of_particles_);
38  particle_orientations_.resize(number_of_particles_);
39  for (size_t i = 0; i < number_of_particles_; i++)
40  {
41  // 2.1 Read the positions.
42  size_t idx_pos = i * 3;
43  Vector particle_position({random_positions[idx_pos],
44  random_positions[idx_pos + 1],
45  random_positions[idx_pos + 2]});
46 
47  // 2.2 Read the random rotations.
48  size_t idx_rot = i * 9;
49  DenseMatrix R(3, 3);
50  R(0, 0) = random_rotations[idx_rot + 0];
51  R(0, 1) = random_rotations[idx_rot + 1];
52  R(0, 2) = random_rotations[idx_rot + 2];
53  R(1, 0) = random_rotations[idx_rot + 3];
54  R(1, 1) = random_rotations[idx_rot + 4];
55  R(1, 2) = random_rotations[idx_rot + 5];
56  R(2, 0) = random_rotations[idx_rot + 6];
57  R(2, 1) = random_rotations[idx_rot + 7];
58  R(2, 2) = random_rotations[idx_rot + 8];
59 
60  // 2.3 Fill the orientation vector.
61  DenseMatrix res(3, 3);
62  MultADBt(R, particle_shape_, R, res);
63  particle_orientations_[i] = res;
64 
65  // 2.4 Scale position for distance metric
66  Vector scaled_position(3);
67  res.Mult(particle_position, scaled_position);
68  particle_positions_[i] = scaled_position;
69  }
70 }
71 
72 double Edge::GetDistanceTo(const Vector &x) const
73 {
74  // Implements formula used in [2, Example 5].
75  const double a = start_.DistanceTo(x);
76  const double b = end_.DistanceTo(x);
77  const double c = start_.DistanceTo(end_);
78  const double s1 = (pow(a, 2) + pow(b, 2)) / 2;
79  const double s2 = pow(c, 2) / 4;
80  const double s3 = pow((pow(a, 2) - pow(b, 2)) / (2 * c), 2);
81  return sqrt(abs(s1 - s2 - s3));
82 }
83 
85 {
86  // Define the point in the vector which differentiates between the periodic
87  // points and the inner points.
88  constexpr size_t periodic_edges = 6;
89 
90  // 1. Fill a vector with x and it's ghost points mimicking the periodicity
91  // of the topology.
92  std::vector<Vector> periodic_points;
93  CreatePeriodicPoints(x, periodic_points);
94  std::vector<double> dist_vector;
95 
96  // 2. Compute the distance to each periodic points to the outer edges.
97  for (const auto &point : periodic_points)
98  {
99  for (size_t i = 0; i < periodic_edges; i++)
100  {
101  dist_vector.push_back(edges_[i].GetDistanceTo(point));
102  }
103  }
104 
105  // 3. Add distance between x and the remaining inner edges
106  for (size_t i = periodic_edges; i < edges_.size(); i++)
107  {
108  dist_vector.push_back(edges_[i].GetDistanceTo(x));
109  }
110 
111  // 3. Choose the smallest number in the vector dist_vector.
112  double min_dist = *std::min_element(dist_vector.begin(), dist_vector.end());
113  return min_dist;
114 }
115 
116 void OctetTrussTopology::Initialize()
117 {
118  // 1. Create the points defining the topology (begin and end points of the
119  // edges). Outer structure
120  double p1_data[3] = {0, 0, 0};
121  double p2_data[3] = {0, 1, 1};
122  double p3_data[3] = {1, 0, 1};
123  double p4_data[3] = {1, 1, 0};
124 
125  Vector p1(p1_data, 3);
126  Vector p2(p2_data, 3);
127  Vector p3(p3_data, 3);
128  Vector p4(p4_data, 3);
129 
130  points_.push_back(p1);
131  points_.push_back(p2);
132  points_.push_back(p3);
133  points_.push_back(p4);
134 
135  // 2. Create the inner structure
136  double p5_data[3] = {0, 0.5, 0.5}; // left
137  double p6_data[3] = {1, 0.5, 0.5}; // right
138  double p7_data[3] = {0.5, 0, 0.5}; // bottom
139  double p8_data[3] = {0.5, 1, 0.5}; // top
140  double p9_data[3] = {0.5, 0.5, 0}; // front
141  double p10_data[3] = {0.5, 0.5, 1}; // back
142 
143  Vector p5(p5_data, 3);
144  Vector p6(p6_data, 3);
145  Vector p7(p7_data, 3);
146  Vector p8(p8_data, 3);
147  Vector p9(p9_data, 3);
148  Vector p10(p10_data, 3);
149 
150  points_.push_back(p5);
151  points_.push_back(p6);
152  points_.push_back(p7);
153  points_.push_back(p8);
154  points_.push_back(p9);
155  points_.push_back(p10);
156 
157  // 3. Create the outer edges.
158  for (size_t i = 0; i < 4; i++)
159  {
160  for (size_t j = i + 1; j < 4; j++)
161  {
162  Edge edge(points_[i], points_[j]);
163  edges_.push_back(edge);
164  }
165  }
166 
167  // 4. Create the inner edges from p5 and p6 to p7, p8, p9, p10; plus the
168  // latter four connected in a cycle.
169  Edge edge5(points_[4], points_[6]);
170  Edge edge6(points_[4], points_[7]);
171  Edge edge7(points_[4], points_[8]);
172  Edge edge8(points_[4], points_[9]);
173  Edge edge9(points_[5], points_[6]);
174  Edge edge10(points_[5], points_[7]);
175  Edge edge11(points_[5], points_[8]);
176  Edge edge12(points_[5], points_[9]);
177  Edge edge13(points_[6], points_[8]);
178  Edge edge14(points_[6], points_[9]);
179  Edge edge15(points_[7], points_[8]);
180  Edge edge16(points_[7], points_[9]);
181 
182  // Push into edges vector
183  edges_.push_back(edge5);
184  edges_.push_back(edge6);
185  edges_.push_back(edge7);
186  edges_.push_back(edge8);
187  edges_.push_back(edge9);
188  edges_.push_back(edge10);
189  edges_.push_back(edge11);
190  edges_.push_back(edge12);
191  edges_.push_back(edge13);
192  edges_.push_back(edge14);
193  edges_.push_back(edge15);
194  edges_.push_back(edge16);
195 }
196 
197 void OctetTrussTopology::CreatePeriodicPoints(
198  const Vector &x, std::vector<Vector> &periodic_points) const
199 {
200  Vector xx(x);
201  // Compute the displaced ghost points. Computation assumes domain [0,1]^3.
202  double d_x[3] = {1, 0, 0};
203  double d_y[3] = {0, 1, 0};
204  double d_z[3] = {0, 0, 1};
205 
206  Vector dispcement_x(d_x, 3);
207  Vector dispcement_y(d_y, 3);
208  Vector dispcement_z(d_z, 3);
209 
210  Vector x_shifted_x_pos = x;
211  x_shifted_x_pos += dispcement_x;
212  Vector x_shifted_x_neg = x;
213  x_shifted_x_neg -= dispcement_x;
214  Vector x_shifted_y_pos = x;
215  x_shifted_y_pos += dispcement_y;
216  Vector x_shifted_y_neg = x;
217  x_shifted_y_neg -= dispcement_y;
218  Vector x_shifted_z_pos = x;
219  x_shifted_z_pos += dispcement_z;
220  Vector x_shifted_z_neg = x;
221  x_shifted_z_neg -= dispcement_z;
222  // Fill the vector with all relevant points
223  periodic_points.push_back(xx);
224  periodic_points.push_back(x_shifted_x_pos);
225  periodic_points.push_back(x_shifted_x_neg);
226  periodic_points.push_back(x_shifted_y_pos);
227  periodic_points.push_back(x_shifted_y_neg);
228  periodic_points.push_back(x_shifted_z_pos);
229  periodic_points.push_back(x_shifted_z_neg);
230 }
231 
232 } // namespace mfem
double GetDistanceTo(const Vector &x) const
Compute the distance between a point and the edge.
double DistanceTo(const double *p) const
Compute the Euclidean distance to another vector.
Definition: vector.hpp:669
double b
Definition: lissajous.cpp:42
void MultADBt(const DenseMatrix &A, const Vector &D, const DenseMatrix &B, DenseMatrix &ADBt)
ADBt = A D B^t, where D is diagonal.
Definition: densemat.cpp:2826
double a
Definition: lissajous.cpp:41
double ComputeMetric(const Vector &x) final
Compute the metric rho describing the material topology.
Vector data type.
Definition: vector.hpp:58
double ComputeMetric(const Vector &x) final