@@ -34,6 +34,13 @@ Gather2DField(const Teuchos::ParameterList& p,
34
34
{
35
35
this ->addEvaluatedField (field2D);
36
36
37
+ const std::string transientFieldName = " Time Dependent 2D Field Name" ;
38
+ enableTransient = p.isParameter (transientFieldName);
39
+ if (enableTransient) {
40
+ field2D_dot = PHX::MDField<ScalarT,Cell,Node>(p.get <std::string>(transientFieldName), dl->node_scalar );
41
+ this ->addEvaluatedField (field2D_dot);
42
+ }
43
+
37
44
fieldLevel = p.get <int >(" Field Level" );
38
45
TEUCHOS_TEST_FOR_EXCEPTION (fieldLevel<0 , Teuchos::Exceptions::InvalidParameter,
39
46
" [Gather2DField] Error! Field level must be non-negative.\n " );
@@ -66,6 +73,8 @@ postRegistrationSetup(typename Traits::SetupData /* d */,
66
73
PHX::FieldManager<Traits>& fm)
67
74
{
68
75
this ->utils .setFieldData (field2D,fm);
76
+ if (enableTransient)
77
+ this ->utils .setFieldData (field2D_dot,fm);
69
78
}
70
79
71
80
template <typename EvalT, typename Traits>
@@ -91,6 +100,13 @@ evaluateFields (typename PHALTraits::EvalData workset)
91
100
const auto & elem_lids = workset.disc ->getElementLIDs_host (workset.wsIndex );
92
101
93
102
const auto x_data = Albany::getLocalData (workset.x );
103
+
104
+ Teuchos::ArrayRCP<const RealType> xdot_data;
105
+ const bool gather_xdot = workset.transientTerms && enableTransient;
106
+ if (gather_xdot)
107
+ xdot_data = Albany::getLocalData (workset.xdot );
108
+
109
+
94
110
const auto & dof_mgr = workset.disc ->getDOFManager ();
95
111
const auto & elem_dof_lids = dof_mgr->elem_dof_lids ().host ();
96
112
const auto & node_dof_mgr = workset.disc ->getNodeDOFManager ();
@@ -115,6 +131,8 @@ evaluateFields (typename PHALTraits::EvalData workset)
115
131
for (int inode=0 ; inode<num_nodes; ++inode) {
116
132
const LO ldof = elem_dof_lids (field_elem_LID,field_nodes[inode]);
117
133
field2D (cell,nodes[inode]) = x_data[ldof];
134
+ if (gather_xdot)
135
+ field2D_dot (cell,nodes[inode]) = xdot_data[ldof];
118
136
}
119
137
};
120
138
@@ -143,6 +161,8 @@ evaluateFields (typename PHALTraits::EvalData workset)
143
161
for (int i=0 ; i<numSideNodes; ++i){
144
162
const LO ldof = elem_dof_lids (elem_LID,offsets[i]);
145
163
field2D (cell,nodes[i]) = x_data[ldof];
164
+ if (gather_xdot)
165
+ field2D_dot (cell,nodes[i]) = xdot_data[ldof];
146
166
}
147
167
}
148
168
}
@@ -165,6 +185,11 @@ evaluateFields (typename PHALTraits::EvalData workset)
165
185
" - num layers : " + std::to_string (layers_data->numLayers ) + " \n " );
166
186
167
187
const auto x_data = Albany::getLocalData (workset.x );
188
+ Teuchos::ArrayRCP<const RealType> xdot_data;
189
+ const bool gather_xdot = workset.transientTerms && enableTransient;
190
+ if (gather_xdot)
191
+ xdot_data = Albany::getLocalData (workset.xdot );
192
+
168
193
const auto & dof_mgr = workset.disc ->getDOFManager ();
169
194
const auto & elem_dof_lids = dof_mgr->elem_dof_lids ().host ();
170
195
const auto & node_dof_mgr = workset.disc ->getNodeDOFManager ();
@@ -193,6 +218,11 @@ evaluateFields (typename PHALTraits::EvalData workset)
193
218
val = ScalarT (val.size (),x_data[ldof]);
194
219
val.setUpdateValue (!workset.ignore_residual );
195
220
val.fastAccessDx (firstunk) = workset.j_coeff ;
221
+ if (gather_xdot) {
222
+ ref_t valdot = field2D_dot (cell,nodes[inode]);
223
+ valdot = ScalarT (valdot.size (),xdot_data[ldof]);
224
+ valdot.fastAccessDx (firstunk) = workset.m_coeff ;
225
+ }
196
226
}
197
227
};
198
228
@@ -225,6 +255,137 @@ evaluateFields (typename PHALTraits::EvalData workset)
225
255
ref_t val = field2D (cell,nodes[i]);
226
256
val = ScalarT (val.size (), x_data[ldof]);
227
257
val.fastAccessDx (nodes[i]*neq + offset) = workset.j_coeff ;
258
+ if (gather_xdot) {
259
+ ref_t valdot = field2D_dot (cell,nodes[i]);
260
+ valdot = ScalarT (valdot.size (),xdot_data[ldof]);
261
+ valdot.fastAccessDx (nodes[i]*neq + offset) = workset.m_coeff ;
262
+ }
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+
269
+ // **********************************************************************
270
+ template <>
271
+ void Gather2DField<PHALTraits::Tangent, PHALTraits>::
272
+ evaluateFields (typename PHALTraits::EvalData workset)
273
+ {
274
+ // Mesh data
275
+ const auto & layers_data = workset.disc ->getLayeredMeshNumberingLO ();
276
+ const auto & elem_lids = workset.disc ->getElementLIDs_host (workset.wsIndex );
277
+ const int bot = layers_data->bot_side_pos ;
278
+ const int top = layers_data->top_side_pos ;
279
+
280
+ ALBANY_EXPECT (fieldLevel==0 || fieldLevel==layers_data->numLayers ,
281
+ " Field level must be 0 or match the number of layers in the mesh.\n "
282
+ " - field level: " + std::to_string (fieldLevel) + " \n "
283
+ " - num layers : " + std::to_string (layers_data->numLayers ) + " \n " );
284
+
285
+ const auto x_data = Albany::getLocalData (workset.x );
286
+ Teuchos::ArrayRCP<const RealType> xdot_data;
287
+ Teuchos::ArrayRCP<Teuchos::ArrayRCP<const ST>> Vx_data, Vxdot_data;
288
+ const bool gather_Vx = Teuchos::nonnull (workset.Vx );
289
+ if (gather_Vx)
290
+ Vx_data = Albany::getLocalData (workset.Vx );
291
+ const bool gather_xdot = Teuchos::nonnull (workset.xdot ) && enableTransient;
292
+ const bool gather_Vxdot = Teuchos::nonnull (workset.Vxdot ) && enableTransient;
293
+ if (gather_xdot)
294
+ xdot_data = Albany::getLocalData (workset.xdot );
295
+ if (gather_Vxdot)
296
+ Vxdot_data = Albany::getLocalData (workset.Vxdot );
297
+
298
+ const auto & dof_mgr = workset.disc ->getDOFManager ();
299
+ const auto & elem_dof_lids = dof_mgr->elem_dof_lids ().host ();
300
+ const auto & node_dof_mgr = workset.disc ->getNodeDOFManager ();
301
+
302
+ const int neq = dof_mgr->getNumFields ();
303
+
304
+ if (extruded) {
305
+ #ifdef ALBANY_DEBUG
306
+ check_topology (dof_mgr->get_topology ());
307
+ #endif
308
+ const int field_layer = fieldLevel==0 ? 0 : fieldLevel-1 ;
309
+ const int field_side_pos = field_layer==0 ? bot : top;
310
+ const auto & field_nodes = dof_mgr->getGIDFieldOffsetsSide (offset,field_side_pos);
311
+ for (std::size_t cell=0 ; cell<workset.numCells ; ++cell ) {
312
+ const int elem_LID = elem_lids (cell);
313
+ const int basal_elem_LID = layers_data->getColumnId (elem_LID);
314
+ const int field_elem_LID = layers_data->getId (basal_elem_LID,field_layer);
315
+
316
+ const auto f = [&] (const std::vector<int >& nodes) {
317
+ const int num_nodes = nodes.size ();
318
+ for (int inode=0 ; inode<num_nodes; ++inode) {
319
+ LO ldof = elem_dof_lids (field_elem_LID,field_nodes[inode]);
320
+
321
+ ref_t val = field2D (cell,nodes[inode]);
322
+ if (gather_Vx) {
323
+ val = TanFadType (val.size (),x_data[ldof]);
324
+ for (int k=0 ; k<workset.num_cols_x ; ++k)
325
+ val.fastAccessDx (k) = workset.j_coeff *Vx_data[ldof][k];
326
+ } else {
327
+ val = TanFadType (x_data[ldof]);
328
+ }
329
+
330
+ if (gather_xdot) {
331
+ ref_t valdot = field2D_dot (cell,nodes[inode]);
332
+ if (gather_Vxdot) {
333
+ valdot = TanFadType (valdot.size (),xdot_data[ldof]);
334
+ for (int k=0 ; k<workset.num_cols_x ; ++k)
335
+ valdot.fastAccessDx (k) = workset.m_coeff *Vxdot_data[ldof][k];
336
+ } else {
337
+ valdot = TanFadType (xdot_data[ldof]);
338
+ }
339
+ }
340
+ }
341
+ };
342
+
343
+ // Run lambda on both top and bottom nodes in the cell, but make sure
344
+ // we order them in whatever way the nodes on $field_side_pos would be ordered
345
+ f (node_dof_mgr->getGIDFieldOffsetsSide (0 ,bot,field_side_pos));
346
+ f (node_dof_mgr->getGIDFieldOffsetsSide (0 ,top,field_side_pos));
347
+ }
348
+ } else {
349
+ TEUCHOS_TEST_FOR_EXCEPTION (workset.sideSets .is_null (), std::logic_error,
350
+ " Side sets defined in input file but not properly specified on the mesh.\n " );
351
+
352
+ // Check for early return
353
+ if (workset.sideSets ->count (meshPart)==0 ) {
354
+ return ;
355
+ }
356
+
357
+ for (const auto & side : workset.sideSets ->at (meshPart)) {
358
+ // Get the data that corresponds to the side
359
+ const int cell = side.ws_elem_idx ;
360
+ const int elem_LID = elem_lids (cell);
361
+ const int side_pos = side.side_pos ;
362
+
363
+ // Note: explicitly as for the offsets to be ordered as the dofs on this side pos
364
+ const auto & offsets = dof_mgr->getGIDFieldOffsetsSide (offset,side_pos);
365
+ const auto & nodes = node_dof_mgr->getGIDFieldOffsetsSide (0 , side_pos);
366
+ const int numSideNodes = nodes.size ();
367
+ for (int i=0 ; i<numSideNodes; ++i){
368
+ const LO ldof = elem_dof_lids (elem_LID,offsets[i]);
369
+ ref_t val = field2D (cell,nodes[i]);
370
+
371
+ if (gather_Vx) {
372
+ val = TanFadType (val.size (),x_data[ldof]);
373
+ for (int k=0 ; k<workset.num_cols_x ; ++k)
374
+ val.fastAccessDx (k) = workset.j_coeff *Vx_data[ldof][k];
375
+ } else {
376
+ val = TanFadType (x_data[ldof]);
377
+ }
378
+
379
+ if (gather_xdot) {
380
+ ref_t valdot = field2D_dot (cell,nodes[i]);
381
+ if (gather_Vxdot) {
382
+ valdot = TanFadType (valdot.size (),xdot_data[ldof]);
383
+ for (int k=0 ; k<workset.num_cols_x ; ++k)
384
+ valdot.fastAccessDx (k) = workset.m_coeff *Vxdot_data[ldof][k];
385
+ } else {
386
+ valdot = TanFadType (xdot_data[ldof]);
387
+ }
388
+ }
228
389
}
229
390
}
230
391
}
@@ -279,6 +440,11 @@ evaluateFields (typename PHALTraits::EvalData workset)
279
440
const auto & elem_lids = workset.disc ->getElementLIDs_host (workset.wsIndex );
280
441
281
442
const auto x_data = Albany::getLocalData (workset.x );
443
+ Teuchos::ArrayRCP<const RealType> xdot_data;
444
+ const bool gather_xdot = workset.transientTerms && enableTransient;
445
+ if (gather_xdot)
446
+ xdot_data = Albany::getLocalData (workset.xdot );
447
+
282
448
const auto & dof_mgr = workset.disc ->getDOFManager ();
283
449
const auto & elem_dof_lids = dof_mgr->elem_dof_lids ().host ();
284
450
const auto & node_dof_mgr = workset.disc ->getNodeDOFManager ();
@@ -306,6 +472,10 @@ evaluateFields (typename PHALTraits::EvalData workset)
306
472
const LO ldof = elem_dof_lids (field_elem_LID,field_nodes[inode]);
307
473
ref_t val = field2D (cell,nodes[inode]);
308
474
val = HessianVecFad (val.size (), x_data[ldof]);
475
+
476
+ if (gather_xdot)
477
+ field2D_dot (cell,nodes[inode]) = xdot_data[ldof];
478
+
309
479
if (is_x_active) {
310
480
int firstunk = neq*nodes[inode] + offset;
311
481
val.fastAccessDx (firstunk).val () = workset.j_coeff ;
@@ -348,7 +518,10 @@ evaluateFields (typename PHALTraits::EvalData workset)
348
518
const LO ldof = elem_dof_lids (elem_LID,offsets[i]);
349
519
ref_t val = field2D (cell,nodes[i]);
350
520
val = HessianVecFad (val.size (), x_data[ldof]);
351
-
521
+
522
+ if (gather_xdot)
523
+ field2D_dot (cell,nodes[i]) = xdot_data[ldof];
524
+
352
525
// If we differentiate w.r.t. the solution, we have to set the first
353
526
// derivative to workset.j_coeff
354
527
if (is_x_active)
0 commit comments