v0.14.0
Loading...
Searching...
No Matches
electrostatics.hpp
Go to the documentation of this file.
1
2#ifndef __ELECTROSTATICS_HPP__
3#define __ELECTROSTATICS_HPP__
4
5#include <MoFEM.hpp>
6using namespace MoFEM;
7constexpr auto domainField = "POTENTIAL";
8constexpr int BASE_DIM = 1;
9constexpr int FIELD_DIM = 1;
11const double bodySource = 0.0;
12
13// aliases for elements types from the pipeline
16using DomainEleOp = DomainEle::UserDataOperator;
17using IntEleOp = IntEle::UserDataOperator;
21using SideEleOp = SideEle::UserDataOperator;
24
25template <int SPACE_DIM> struct intPostProc {};
26
27template <> struct intPostProc<2> {
29};
30
31template <> struct intPostProc<3> {
33};
34
36
37// forms integrators to calculate the LHS and RHS
41
46
47// Common data structure for blocks
48struct BlockData {
49 int iD;
51 double epsPermit;
56};
57
64 blockChrgDens = 0.0;
65 PetscInt ghosts[2] = {0, 1};
66 if (!m_field.get_comm_rank())
67 petscVec = createGhostVector(m_field.get_comm(), 2, 2, 0, ghosts);
68 else
69 petscVec = createGhostVector(m_field.get_comm(), 0, 2, 2, ghosts);
70 }
71};
72
73// Operator to get the charge density on the interface
76 boost::shared_ptr<DataAtIntegrationPts> common_data_ptr,
77 boost::shared_ptr<std::map<int, BlockData>> int_block_sets_ptr,
78 const std::string &field_name)
79 : IntEleOp(field_name, field_name, OPROWCOL, false),
80 commonDataPtr(common_data_ptr), intBlockSetsPtr(int_block_sets_ptr) {
81 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
82 doEntities[MBVERTEX] = true;
83 }
84
85 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
86 EntityType col_type, EntData &row_data,
87 EntData &col_data) {
89 for (const auto &m : *intBlockSetsPtr) {
90 if (m.second.interfaceEnts.find(getFEEntityHandle()) !=
91 m.second.interfaceEnts.end()) {
92 commonDataPtr->blockChrgDens = m.second.chargeDensity;
93 }
94 }
96 }
97
98protected:
99 boost::shared_ptr<DataAtIntegrationPts> commonDataPtr;
100 boost::shared_ptr<std::map<int, BlockData>> intBlockSetsPtr;
101};
102// Operator to get the permittivity of the domain/block
104
106 boost::shared_ptr<DataAtIntegrationPts> common_data_ptr,
107 boost::shared_ptr<map<int, BlockData>> perm_block_sets_ptr,
108 const std::string &field_name)
109 : DomainEleOp(field_name, field_name, OPROWCOL, false),
110 commonDataPtr(common_data_ptr), permBlockSetsPtr(perm_block_sets_ptr) {
111 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
112 doEntities[MBVERTEX] = true;
113 }
114
115 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
116 EntityType col_type,
118 EntitiesFieldData::EntData &col_data) {
120 for (auto &m : (*permBlockSetsPtr)) {
121 if (m.second.domainEnts.find(getFEEntityHandle()) !=
122 m.second.domainEnts.end()) {
123 commonDataPtr->blockPermittivity = m.second.epsPermit;
124 }
125 }
127 }
128
129protected:
130 boost::shared_ptr<map<int, BlockData>> permBlockSetsPtr;
131 boost::shared_ptr<DataAtIntegrationPts> commonDataPtr;
132};
133
134// Operator to calculate Total Electrgy density in Post Porocessing
135struct OpTotalEnergy : public DomainEleOp {
137 const std::string &field_name,
138 boost::shared_ptr<MatrixDouble> grad_u_negative,
139 boost::shared_ptr<std::map<int, BlockData>> perm_block_sets_ptr,
140 boost::shared_ptr<std::map<int, BlockData>> int_domain_block_sets_ptr,
141 boost::shared_ptr<DataAtIntegrationPts> common_data_ptr,
142 SmartPetscObj<Vec> petsc_vec_energy)
144 gradUNegative(grad_u_negative), permBlockSetsPtr(perm_block_sets_ptr),
145 intDomainBlocksetsPtr(int_domain_block_sets_ptr),
146 commonDataPtr(common_data_ptr), petscTotalEnergy(petsc_vec_energy) {
147 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
148 doEntities[MBVERTEX] = true;
149 }
150 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
152
153 auto t_negative_grad_u = getFTensor1FromMat<SPACE_DIM>(*gradUNegative);
155 double area = getMeasure();
156 auto t_w = getFTensor0IntegrationWeight();
157 auto nb_gauss_pts = getGaussPts().size2();
158 double totalEnergy = 0.0;
159 int index = 0;
160 // Total Energy Density = 0.5 * E^2 * Perm * Area
161 for (const auto &m : *intDomainBlocksetsPtr) {
162
163 double blockPermittivity = 0.0;
164
165 if (m.second.internalDomainEnts.find(getFEEntityHandle()) !=
166 m.second.internalDomainEnts.end()) {
167 for (const auto &n : *permBlockSetsPtr) {
168 if (n.second.domainEnts.find(getFEEntityHandle()) !=
169 n.second.domainEnts.end()) {
170 blockPermittivity = n.second.epsPermit;
171 }
172 }
173
174 for (int gg = 0; gg != nb_gauss_pts; gg++) {
175 totalEnergy += 0.5 * t_negative_grad_u(I) * t_negative_grad_u(I) *
176 blockPermittivity * t_w * area;
177 ++t_negative_grad_u;
178 ++t_w;
179 }
180 }
181 }
182 CHKERR VecSetValues(petscTotalEnergy, 1, &index, &totalEnergy, ADD_VALUES);
183
185 }
186
187private:
188 boost::shared_ptr<MatrixDouble> gradUNegative;
189 boost::shared_ptr<std::map<int, BlockData>> permBlockSetsPtr;
190 boost::shared_ptr<std::map<int, BlockData>> intDomainBlocksetsPtr;
191 boost::shared_ptr<DataAtIntegrationPts> commonDataPtr;
193};
194
196
198 const std::string &field_name,
199 boost::shared_ptr<MatrixDouble> grad_u_negative,
200 boost::shared_ptr<VectorDouble> energy_densiity_ptr,
201 boost::shared_ptr<std::map<int, BlockData>> perm_block_sets_ptr,
202 boost::shared_ptr<DataAtIntegrationPts> common_data_ptr)
203 : DomainEleOp(field_name, field_name, OPROWCOL, false),
204 energyDensity(energy_densiity_ptr), gradUNegative(grad_u_negative),
205 permBlockSetsPtr(perm_block_sets_ptr), commonDataPtr(common_data_ptr) {
206 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
207 doEntities[MBVERTEX] = true;
208 }
209
210 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
211 EntityType col_type,
213 EntitiesFieldData::EntData &col_data) {
215
216 size_t nb_gauss_pts = getGaussPts().size2();
217 energyDensity->resize(nb_gauss_pts, false);
218 energyDensity->clear();
219 auto t_energy_density = getFTensor0FromVec(*energyDensity);
220 auto t_negative_grad_u = getFTensor1FromMat<SPACE_DIM>(*gradUNegative);
222 double blockPermittivity = 0.0;
223 for (const auto &n : *permBlockSetsPtr) {
224 if (n.second.domainEnts.find(getFEEntityHandle()) !=
225 n.second.domainEnts.end()) {
226 blockPermittivity = n.second.epsPermit;
227 }
228 }
229 // E = 0.5 * E^2 * Perm
230 for (int gg = 0; gg != nb_gauss_pts; gg++) {
231 t_energy_density =
232 0.5 * t_negative_grad_u(I) * t_negative_grad_u(I) * blockPermittivity;
233 ++t_negative_grad_u;
234 ++t_energy_density;
235 }
236
238 }
239
240private:
241 boost::shared_ptr<MatrixDouble> gradUNegative;
242 boost::shared_ptr<VectorDouble> energyDensity;
243 boost::shared_ptr<std::map<int, BlockData>> permBlockSetsPtr;
244 boost::shared_ptr<DataAtIntegrationPts> commonDataPtr;
245};
246
248
250 const std::string &field_name,
251 boost::shared_ptr<MatrixDouble> grad_u_negative,
252 boost::shared_ptr<MatrixDouble> grad_times_perm,
253 boost::shared_ptr<std::map<int, BlockData>> perm_block_sets_ptr,
254 boost::shared_ptr<DataAtIntegrationPts> common_data_ptr)
255 : DomainEleOp(field_name, field_name, OPROWCOL, false),
256 gradTimesPerm(grad_times_perm), gradUNegative(grad_u_negative),
257 permBlockSetsPtr(perm_block_sets_ptr), commonDataPtr(common_data_ptr) {
258 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
259 doEntities[MBVERTEX] = true;
260 }
261
262 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
263 EntityType col_type,
265 EntitiesFieldData::EntData &col_data) {
267
268 size_t nb_gauss_pts = getGaussPts().size2();
269 gradTimesPerm->resize(SPACE_DIM, nb_gauss_pts, false);
270 gradTimesPerm->clear();
271 auto t_grad_times_perm = getFTensor1FromMat<SPACE_DIM>(*gradTimesPerm);
272 auto t_negative_grad_u = getFTensor1FromMat<SPACE_DIM>(*gradUNegative);
274 double blockPermittivity = 0.0;
275 for (const auto &n : *permBlockSetsPtr) {
276 if (n.second.domainEnts.find(getFEEntityHandle()) !=
277 n.second.domainEnts.end()) {
278 blockPermittivity = n.second.epsPermit;
279 }
280 }
281 for (int gg = 0; gg != nb_gauss_pts; gg++) {
282 t_grad_times_perm(I) = t_negative_grad_u(I) * blockPermittivity;
283
284 ++t_negative_grad_u;
285 ++t_grad_times_perm;
286 }
287
289 }
290
291private:
292 boost::shared_ptr<MatrixDouble> gradUNegative;
293 boost::shared_ptr<MatrixDouble> gradTimesPerm;
294 boost::shared_ptr<std::map<int, BlockData>> permBlockSetsPtr;
295 boost::shared_ptr<DataAtIntegrationPts> commonDataPtr;
296};
297
298// operator to get the electric jump on the all side elecment of the domain:
299// d = E1 * perm1 - E2 * perm1
300template <int SPACE_DIM> struct OpElectricDispJump : public SideEleOp {
302 const std::string field_name, boost::shared_ptr<MatrixDouble> grad_ptr,
303 boost::shared_ptr<MatrixDouble> d_jump,
304 boost::shared_ptr<DataAtIntegrationPts> common_data_ptr,
305 boost::shared_ptr<std::map<int, BlockData>> perm_block_sets_ptr)
306 : SideEleOp(field_name, SideEleOp::OPROW, false), gradPtr(grad_ptr),
307 djump(d_jump), commonDataPtr(common_data_ptr),
308 permBlockSetsPtr(perm_block_sets_ptr)
309
310 {
311 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
312 doEntities[MBVERTEX] = true;
313 }
314
315 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
317
319 auto t_field_grad = getFTensor1FromMat<SPACE_DIM>(*gradPtr);
320
321 double blockPermittivity = 0.0;
322
323 for (const auto &n : *permBlockSetsPtr) {
324 if (n.second.domainEnts.find(getFEEntityHandle()) !=
325 n.second.domainEnts.end()) {
326 blockPermittivity = n.second.epsPermit;
327 }
328 }
329 auto N_InLoop = getNinTheLoop();
330 auto sensee = getSkeletonSense();
331 auto nb_gauss_pts = getGaussPts().size2();
332
333 if (N_InLoop == 0) {
334 djump->resize(SPACE_DIM, nb_gauss_pts, false);
335 djump->clear();
336 }
337 auto t_jump = getFTensor1FromMat<SPACE_DIM>(*djump);
338
339 for (int gg = 0; gg != nb_gauss_pts; gg++) {
340 t_jump(i) -= t_field_grad(i) * blockPermittivity * sensee;
341 ++t_jump;
342 ++t_field_grad;
343 }
344
346 }
347
348protected:
349 boost::shared_ptr<MatrixDouble> gradPtr;
350 boost::shared_ptr<MatrixDouble> djump;
351 boost::shared_ptr<std::map<int, BlockData>> permBlockSetsPtr;
352 boost::shared_ptr<DataAtIntegrationPts> commonDataPtr;
353};
354
355// operator to get the charge value on the inerface: Alpha = d * n
356
357template <int SPACE_DIM> struct OpElectrodeCharge : public IntEleOp {
359 const std::string field_name, boost::shared_ptr<MatrixDouble> d_jump,
360 SmartPetscObj<Vec> alpha_vec,
361 boost::shared_ptr<std::map<int, BlockData>> electrode_block_sets_ptr)
362 : IntEleOp(field_name, IntEleOp::OPROW, false), dJumpPtr(d_jump),
363 petscVec(alpha_vec), elecBlockSetsPtr(electrode_block_sets_ptr) {
364 std::fill(&doEntities[MBVERTEX], &doEntities[MBMAXTYPE], false);
365 doEntities[MBVERTEX] = true;
366 }
367 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
370 int index = 0;
371 auto fe_ent = getFEEntityHandle();
372 auto nb_gauss_pts = getGaussPts().size2();
373 double area = getMeasure();
374 dJumpPtr->resize(SPACE_DIM, nb_gauss_pts, false);
376 auto t_normal = getFTensor1NormalsAtGaussPts();
377 auto t_w = getFTensor0IntegrationWeight();
378 for (auto &m : *elecBlockSetsPtr) {
379 double alphaPart = 0.0;
380 if (m.second.electrodeEnts.find(fe_ent) != m.second.electrodeEnts.end()) {
381
382 for (int gg = 0; gg != nb_gauss_pts; gg++) {
384 t_r(i) = t_normal(i);
385 auto t_r_normalized = t_r.normalize();
386 alphaPart += (t_jump(i) * t_r(i)) * t_w * area;
387 ++t_jump;
388 ++t_normal;
389 ++t_w;
390 }
391 CHKERR ::VecSetValues(petscVec, 1, &index, &alphaPart,
392 ADD_VALUES); // add the alpha value to the vector
393 }
394 ++index;
395 }
396
398 }
399
400protected:
401 boost::shared_ptr<MatrixDouble> dJumpPtr;
402 boost::shared_ptr<std::map<int, BlockData>> elecBlockSetsPtr;
404};
405
406struct OpElectricField : public ForcesAndSourcesCore::UserDataOperator {
407 OpElectricField(boost::shared_ptr<MatrixDouble> grad_u_negative,
408 boost::shared_ptr<MatrixDouble> grad_u)
410 gradUNegative(grad_u_negative), gradU(grad_u) {}
411
412 MoFEMErrorCode doWork(int side, EntityType type,
413 DataForcesAndSourcesCore::EntData &data) {
415
416 const size_t nb_gauss_pts = getGaussPts().size2();
417 gradUNegative->resize(SPACE_DIM, nb_gauss_pts, false);
418 gradUNegative->clear();
419 auto t_grad_u = getFTensor1FromMat<SPACE_DIM>(*gradU);
420 auto t_negative_grad_u = getFTensor1FromMat<SPACE_DIM>(*gradUNegative);
422
423 for (int gg = 0; gg != nb_gauss_pts; gg++) {
424 t_negative_grad_u(I) = -t_grad_u(I);
425 ++t_grad_u;
426 ++t_negative_grad_u;
427 }
428
430 }
431
432private:
433 boost::shared_ptr<MatrixDouble> gradUNegative;
434 boost::shared_ptr<MatrixDouble> gradU;
435};
436
437#endif // __ELECTROSTATICS_HPP__
ForcesAndSourcesCore::UserDataOperator UserDataOperator
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
Tensor1< T, Tensor_Dim > normalize()
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int SPACE_DIM
constexpr int FIELD_DIM
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::BoundaryEle IntEle
constexpr auto domainField
constexpr int BASE_DIM
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpBodySourceVectorb
intPostProc< SPACE_DIM >::intEle IntElementForcesAndSourcesCore
FormsIntegrators< IntEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpInterfaceRhsVectorF
const double bodySource
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpGradGrad< BASE_DIM, FIELD_DIM, SPACE_DIM > OpDomainLhsMatrixK
FTensor::Index< 'i', SPACE_DIM > i
const double n
refractive index of diffusive medium
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
FTensor::Tensor1< FTensor::PackPtr< T *, S >, Tensor_Dim > getFTensor1FromMat(ublas::matrix< T, L, A > &data)
Get tensor rank 1 (vector) form data matrix.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
auto createGhostVector(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt nghost, const PetscInt ghosts[])
Create smart ghost vector.
MoFEMErrorCode VecSetValues(Vec V, const EntitiesFieldData::EntData &data, const double *ptr, InsertMode iora)
Assemble PETSc vector.
FormsIntegrators< DomainEleOp >::Assembly< A >::BiLinearForm< I >::OpGradGrad< 1, FIELD_DIM, SPACE_DIM > OpGradGrad
constexpr IntegrationType I
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
constexpr auto field_name
FTensor::Index< 'm', 3 > m
Range electrodeEnts
Range interfaceEnts
double chargeDensity
Range internalDomainEnts
SmartPetscObj< Vec > petscVec
DataAtIntegrationPts(MoFEM::Interface &m_field)
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
structure to get information form mofem into EntitiesFieldData
intrusive_ptr for managing petsc objects
boost::shared_ptr< std::map< int, BlockData > > intBlockSetsPtr
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
OpBlockChargeDensity(boost::shared_ptr< DataAtIntegrationPts > common_data_ptr, boost::shared_ptr< std::map< int, BlockData > > int_block_sets_ptr, const std::string &field_name)
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntData &row_data, EntData &col_data)
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
boost::shared_ptr< map< int, BlockData > > permBlockSetsPtr
OpBlockPermittivity(boost::shared_ptr< DataAtIntegrationPts > common_data_ptr, boost::shared_ptr< map< int, BlockData > > perm_block_sets_ptr, const std::string &field_name)
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
boost::shared_ptr< MatrixDouble > djump
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
boost::shared_ptr< MatrixDouble > gradPtr
OpElectricDispJump(const std::string field_name, boost::shared_ptr< MatrixDouble > grad_ptr, boost::shared_ptr< MatrixDouble > d_jump, boost::shared_ptr< DataAtIntegrationPts > common_data_ptr, boost::shared_ptr< std::map< int, BlockData > > perm_block_sets_ptr)
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
OpElectricField(boost::shared_ptr< MatrixDouble > grad_u_negative, boost::shared_ptr< MatrixDouble > grad_u)
MoFEMErrorCode doWork(int side, EntityType type, DataForcesAndSourcesCore::EntData &data)
boost::shared_ptr< MatrixDouble > gradU
boost::shared_ptr< MatrixDouble > gradUNegative
boost::shared_ptr< std::map< int, BlockData > > elecBlockSetsPtr
SmartPetscObj< Vec > petscVec
OpElectrodeCharge(const std::string field_name, boost::shared_ptr< MatrixDouble > d_jump, SmartPetscObj< Vec > alpha_vec, boost::shared_ptr< std::map< int, BlockData > > electrode_block_sets_ptr)
boost::shared_ptr< MatrixDouble > dJumpPtr
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
boost::shared_ptr< MatrixDouble > gradUNegative
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
boost::shared_ptr< VectorDouble > energyDensity
OpEnergyDensity(const std::string &field_name, boost::shared_ptr< MatrixDouble > grad_u_negative, boost::shared_ptr< VectorDouble > energy_densiity_ptr, boost::shared_ptr< std::map< int, BlockData > > perm_block_sets_ptr, boost::shared_ptr< DataAtIntegrationPts > common_data_ptr)
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
OpGradTimesPerm(const std::string &field_name, boost::shared_ptr< MatrixDouble > grad_u_negative, boost::shared_ptr< MatrixDouble > grad_times_perm, boost::shared_ptr< std::map< int, BlockData > > perm_block_sets_ptr, boost::shared_ptr< DataAtIntegrationPts > common_data_ptr)
boost::shared_ptr< MatrixDouble > gradTimesPerm
boost::shared_ptr< MatrixDouble > gradUNegative
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
boost::shared_ptr< std::map< int, BlockData > > intDomainBlocksetsPtr
boost::shared_ptr< std::map< int, BlockData > > permBlockSetsPtr
boost::shared_ptr< DataAtIntegrationPts > commonDataPtr
SmartPetscObj< Vec > petscTotalEnergy
boost::shared_ptr< MatrixDouble > gradUNegative
OpTotalEnergy(const std::string &field_name, boost::shared_ptr< MatrixDouble > grad_u_negative, boost::shared_ptr< std::map< int, BlockData > > perm_block_sets_ptr, boost::shared_ptr< std::map< int, BlockData > > int_domain_block_sets_ptr, boost::shared_ptr< DataAtIntegrationPts > common_data_ptr, SmartPetscObj< Vec > petsc_vec_energy)
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)