MAST
kinematic_coupling_constraint.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 // MAST includes
23 #include "base/nonlinear_system.h"
24 
25 
28  const libMesh::Node& slave_node,
29  const std::set<const libMesh::Node*>& master_nodes,
30  bool constrain_rotations):
31 _sys_init (sys_init),
32 _slave (&slave_node),
33 _masters (master_nodes),
34 _constrain_rotations (constrain_rotations) {
35 
36 }
37 
38 
40 
41 }
42 
43 
44 void
46 get_dof_constraint_row(std::vector<std::tuple
47  <libMesh::dof_id_type, libMesh::DofConstraintRow,Real>>& constraints) const {
48 
49 
50  constraints.clear();
51 
52  libMesh::DofMap& dof_map = _sys_init.system().get_dof_map();
53 
54  std::vector<libMesh::dof_id_type>
55  slave_dofs;
56 
57  // master nodes, their dofs and weights
58  std::map<const libMesh::Node*, std::pair<std::vector<libMesh::dof_id_type>, Real>>
59  master_node_data; // master dofs of all nodes
60 
61 
62  // get dofs for all the nodes
63  dof_map.dof_indices(_slave, slave_dofs);
64 
65  std::set<const libMesh::Node*>::const_iterator
66  n_it = _masters.begin(),
67  n_end = _masters.end();
68 
69  libMesh::Point dx;
70 
71  std::map<const libMesh::Node*, Real> weights;
72 
73  Real
74  sum = 0.,
75  val = 0.;
76 
77  // compute the position vectors for nodal weight
78  for ( ; n_it != n_end; n_it++ ) {
79 
80  const libMesh::Node* nd = *n_it;
81 
82  dx = *_slave - *nd;
83 
84  // exponential function, so that closer nodes are more influential
85  // than distant nodes.
86  val = exp(-dx.norm());
87  sum += val;
88 
89  weights[nd] = val;
90  }
91 
92  // now compute the constraint data
93  n_it = _masters.begin();
94 
95  for ( ; n_it != n_end; n_it++ ) {
96 
97  const libMesh::Node* nd = *n_it;
98 
99  std::pair<std::vector<libMesh::dof_id_type>, Real> dofs_wt_pair;
100  dof_map.dof_indices(nd, dofs_wt_pair.first);
101  // divide by sum so that all weights sum to a value of 1.
102  dofs_wt_pair.second = weights[nd]/sum;
103 
104  master_node_data[nd] = dofs_wt_pair;
105  }
106 
107  // now initialize the vector with constraint data. This assumes that dof_ids
108  // for all nodes have the same sequence: ux, uy, uz, tx, ty, tz
109  unsigned int
110  dofs_to_constrain = _constrain_rotations?6:3,
111  idx = 0;
112 
113  constraints.resize(dofs_to_constrain);
114 
115  // the translation and rotation dofs both share a common code, except
116  // translation constraints require a contribution from the rotational dofs
117  for (unsigned int i=0; i<dofs_to_constrain; i++) {
118 
119  // dof id of ith variable for slave node
120  std::get<0>(constraints[i]) = slave_dofs[i];
121 
122  // rhs of the constraint is zero
123  std::get<2>(constraints[i]) = 0.;
124 
125  libMesh::DofConstraintRow&
126  c_row = std::get<1>(constraints[i]);
127 
128  std::map<const libMesh::Node*,
129  std::pair<std::vector<libMesh::dof_id_type>, Real>>::const_iterator
130  master_nd_it = master_node_data.begin(),
131  master_nd_end = master_node_data.end();
132 
133  for ( ; master_nd_it != master_nd_end; master_nd_it++) {
134 
135  dx = *_slave - *master_nd_it->first;
136 
137  const std::vector<libMesh::dof_id_type>
138  &master_dofs = master_nd_it->second.first;
139 
140  // dof id of the i^th var on the master node
141  idx = master_dofs[i];
142  val = master_nd_it->second.second; // weight for this node
143 
144  // add constraints with rotational dofs of all nodes
145  // -1 is used since the constraint reads
146  // slave dof = avg of master dofs
147  // or, slave dof - avg of master dofs = 0
148  c_row[idx] = -val * -1.;
149 
150  // for translation dofs a contribution is needed from the
151  // rotation of the master nodes
152  if (i<3) {
153 
154  switch (i) {
155  case 0: {
156  // index of the rotational dof of the master node
157  c_row[master_dofs[4]] = -dx(2) * val; // theta_y * dz
158  c_row[master_dofs[5]] = dx(1) * val; // -theta_z * dy
159  }
160  break;
161 
162  case 1: {
163  // index of the rotational dof of the master node
164  c_row[master_dofs[3]] = -dx(2) * val; // theta_x * dz
165  c_row[master_dofs[5]] = dx(0) * val; // -theta_z * dx
166  }
167  break;
168 
169  case 2: {
170  // index of the rotational dof of the master node
171  c_row[master_dofs[3]] = -dx(1) * val; // theta_x * dy
172  c_row[master_dofs[4]] = dx(0) * val; // -theta_y * dx
173  }
174  break;
175  }
176  }
177  }
178  }
179 }
180 
MAST::NonlinearSystem & system()
libMesh::Real Real
KinematicCouplingConstraint(MAST::SystemInitialization &sys_init, const libMesh::Node &slave_node, const std::set< const libMesh::Node * > &master_nodes, bool constrain_rotations)
void get_dof_constraint_row(std::vector< std::tuple< libMesh::dof_id_type, libMesh::DofConstraintRow, Real >> &constraints) const
initializes the vector of libMesh::DofConstraintRow objects and rhs values for this node ...
std::set< const libMesh::Node * > _masters