PeriDEM 0.2.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
particleULoading.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2024 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE)
9 */
10
11#include "particleULoading.h"
12#include "fe/mesh.h"
15#include "util/function.h"
16#include "util/geom.h"
17#include "util/transformation.h"
18#include <taskflow/taskflow/taskflow.hpp>
19#include <taskflow/taskflow/algorithm/for_each.hpp>
20
21namespace {
22
23bool isInList(const size_t &i, const std::vector<size_t> &list) {
24 for (const auto &l : list)
25 if (l == i)
26 return true;
27
28 return false;
29}
30
31} // namespace
32
34 std::vector<inp::PBCData> &bc_data) {
35
36 d_bcData = bc_data;
37
38 d_pZeroDisplacementApplied = std::vector<bool>(d_bcData.size(), false);
39}
40
42
43 // if there is a list, and if particle is not in the list, skip
44 bool skip_condition1 = (bc.d_selectionType == "particle"
45 || bc.d_selectionType == "region_with_include_list")
46 && !isInList(id, bc.d_pList);
47 // if there is an exclusion list, and if particle is in the list, skip
48 bool skip_condition2 = (bc.d_selectionType == "region_with_exclude_list")
49 && isInList(id, bc.d_pNotList);
50 // if there is a inclusion and an exclusion list,
51 // and if particle is either in the exclusion list or not in the inclusion list, skip
52 bool skip_condition3 = (bc.d_selectionType == "region_with_include_list_with_exclude_list")
53 && (isInList(id, bc.d_pNotList) ||
54 !isInList(id, bc.d_pList));
55
56 bool skip = skip_condition1 or skip_condition2 or skip_condition3;
57 return !skip;
58}
59
61 size_t id,
62 const inp::PBCData &bc) {
63
64 if (!bc.d_isRegionActive) {
65 if (bc.d_selectionType == "particle" &&
66 isInList(id, bc.d_pList))
67 return true;
68 }
69 else {
70 if (bc.d_selectionType == "region" && bc.d_regionGeomData.d_geom_p->isInside(x))
71 return true;
72 else if (bc.d_selectionType == "region_with_include_list" &&
73 bc.d_regionGeomData.d_geom_p->isInside(x) &&
74 isInList(id, bc.d_pList))
75 return true;
76 else if (bc.d_selectionType == "region_with_exclude_list" &&
77 bc.d_regionGeomData.d_geom_p->isInside(x) &&
78 !isInList(id, bc.d_pNotList))
79 return true;
80 else if (bc.d_selectionType == "region_with_include_list_with_exclude_list" &&
81 bc.d_regionGeomData.d_geom_p->isInside(x) &&
82 isInList(id, bc.d_pList) &&
83 !isInList(id, bc.d_pNotList))
84 return true;
85 }
86
87 return false;
88}
89
91
92 for (size_t s = 0; s < d_bcData.size(); s++) {
93
94 // get alias for bc data
95 const auto &bc = d_bcData[s];
96
97 // check if we need to process this particle
98 if (!needToProcessParticle(particle->getId(), bc))
99 continue;
100
101 for (size_t i = 0; i < particle->getNumNodes(); i++) {
102
103 const auto x = particle->getXRefLocal(i);
104
105 if (!needToComputeDof(x, particle->getId(), bc))
106 continue;
107
108 // set fixity to true
109 for (auto d : bc.d_direction)
110 particle->setFixLocal(i, d - 1, true);
111 } // loop over nodes
112 } // loop over bc sets
113}
114
115void loading::ParticleULoading::apply(const double &time,
117
118 for (size_t s = 0; s < d_bcData.size(); s++) {
119
120 // get alias for bc data
121 const auto &bc = d_bcData[s];
122
123 // if this is zero displacement condition, and if we have already applied
124 // displacement then do not need to reapply this
125 if (bc.d_isDisplacementZero && d_pZeroDisplacementApplied[s])
126 continue;
127
128 // set to true so that next time this is not called
129 if (bc.d_isDisplacementZero)
130 d_pZeroDisplacementApplied[s] = true;
131
132 // check if we need to process this particle
133 if (!needToProcessParticle(particle->getId(), bc))
134 continue;
135
136 // get bounding box (quite possibly be generic)
137 auto reg_box = bc.d_regionGeomData.d_geom_p->box();
138
139 // for (size_t i = 0; i < particle->getNumNodes(); i++) {
140 tf::Executor executor(util::parallel::getNThreads());
141 tf::Taskflow taskflow;
142
143 taskflow.for_each_index(
144 (std::size_t) 0, particle->getNumNodes(), (std::size_t) 1,
145 [time, &particle, bc, reg_box, this] (std::size_t i) {
146
147 const auto x = particle->getXRefLocal(i);
148
149 double umax = bc.d_timeFnParams[0];
150 double du = 0.;
151 double dv = 0.;
152
153 auto box = reg_box;
154 if (!bc.d_isRegionActive) {
155 // get box from particle
156 box = particle->d_geom_p->box();
157 }
158
159 if (needToComputeDof(x, particle->getId(), bc)) {
160
161 // apply spatial function
162 if (bc.d_spatialFnType == "hat_x") {
163 umax = bc.d_spatialFnParams[0] *
164 util::hatFunction(x.d_x, box.first.d_x,
165 box.second.d_x);
166 } else if (bc.d_spatialFnType == "hat_y") {
167 umax = bc.d_spatialFnParams[0] *
168 util::hatFunction(x.d_y, box.first.d_y,
169 box.second.d_y);
170 } else if (bc.d_spatialFnType == "sin_x") {
171 double a = M_PI * bc.d_spatialFnParams[0];
172 umax = umax * std::sin(a * x.d_x);
173 } else if (bc.d_spatialFnType == "sin_y") {
174 double a = M_PI * bc.d_spatialFnParams[0];
175 umax = umax * std::sin(a * x.d_y);
176 } else if (bc.d_spatialFnType == "linear_x") {
177 double a = bc.d_spatialFnParams[0];
178 umax = umax * a * x.d_x;
179 } else if (bc.d_spatialFnType == "linear_y") {
180 double a = bc.d_spatialFnParams[0];
181 umax = umax * a * x.d_y;
182 }
183
184 // apply time function
185 if (bc.d_timeFnType == "constant")
186 du = umax;
187 else if (bc.d_timeFnType == "linear") {
188 du = umax * time;
189 dv = umax;
190 } else if (bc.d_timeFnType == "quadratic") {
191 du = umax * time + bc.d_timeFnParams[1] * time * time;
192 dv = umax + bc.d_timeFnParams[1] * time;
193 } else if (bc.d_timeFnType == "sin") {
194 double a = M_PI * bc.d_timeFnParams[1];
195 du = umax * std::sin(a * time);
196 dv = umax * a * std::cos(a * time);
197 }
198
199 auto u_i = util::Point();
200 auto v_i = util::Point();
201 for (auto d : bc.d_direction) {
202 u_i[d-1] = du;
203 v_i[d-1] = dv;
204 }
205
206 if (bc.d_timeFnType == "rotation") {
207 auto x0 = util::Point(bc.d_timeFnParams[1], bc.d_timeFnParams[2],
208 bc.d_timeFnParams[3]);
209 auto dx = x - x0;
210 auto r_x = util::rotate2D(
211 dx, bc.d_timeFnParams[0] * time);
212 auto dr_x = util::derRotate2D(
213 dx, bc.d_timeFnParams[0] * time);
214
215 u_i += r_x - dx;
216 v_i += bc.d_timeFnParams[0] * dr_x;
217 }
218
219 for (auto d : bc.d_direction) {
220 particle->setULocal(i, d-1, u_i[d-1]);
221 particle->setVLocal(i, d-1, v_i[d-1]);
222 auto xref = particle->getXRefLocal(i)[d-1];
223 particle->setXLocal(i, d-1, u_i[d-1] + xref);
224 }
225 } // if compute displacement
226 }
227 ); // for_each
228
229 executor.run(taskflow).get();
230 } // loop over bc sets
231}
std::vector< inp::PBCData > d_bcData
List of displacement bcs.
bool needToProcessParticle(size_t id, const inp::PBCData &bc)
Function that checks if given particle with id = id needs to be processed within boundary condition d...
ParticleULoading(std::vector< inp::PBCData > &bc_data)
Constructor.
bool needToComputeDof(const util::Point &x, size_t id, const inp::PBCData &bc)
Function that checks if we need to do computation at a given point x within a particle with id = id.
void apply(const double &time, particle::BaseParticle *particle)
Applies displacement boundary condition.
void setFixity(particle::BaseParticle *particle)
Sets fixity mask.
std::vector< bool > d_pZeroDisplacementApplied
Flag to indicate whether particles are fixed.
A class to store particle geometry, nodal discretization, and methods.
bool isInList(const size_t &i, const std::vector< size_t > &list)
Collection of methods and data related to particle object.
unsigned int getNThreads()
Get number of threads to be used by taskflow.
std::vector< double > rotate2D(const std::vector< double > &x, const double &theta)
Rotates a vector in xy-plane assuming ACW convention.
util::Point derRotate2D(const util::Point &x, const double &theta)
Computes derivative of rotation wrt to time.
User-input data for particle neighbor search.
Definition pBCData.h:24
std::vector< size_t > d_pList
List of particles (if any)
Definition pBCData.h:48
std::string d_selectionType
Method for applying force e.g.
Definition pBCData.h:35
util::geometry::GeomData d_regionGeomData
Region geometry (if any)
Definition pBCData.h:45
std::vector< size_t > d_pNotList
List of particles to not include (if any)
Definition pBCData.h:51
bool d_isRegionActive
Flag that indicates if region-based application of boundary condition is active. So cases of 'region'...
Definition pBCData.h:42
A structure to represent 3d vectors.
Definition point.h:30
std::shared_ptr< util::geometry::GeomObject > d_geom_p
Zone geometry.