Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fe_jac_fill_funcs.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Sacado Package
4 //
5 // Copyright 2006 NTESS and the Sacado contributors.
6 // SPDX-License-Identifier: LGPL-2.1-or-later
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef FE_JAC_FILL_FUNCS_HPP
11 #define FE_JAC_FILL_FUNCS_HPP
12 
13 #include "Sacado_No_Kokkos.hpp"
14 #include "Sacado_Fad_SimpleFad.hpp"
15 
16 #include "Teuchos_Time.hpp"
18 
19 // ADOL-C includes
20 #ifdef HAVE_ADOLC
21 #ifdef PACKAGE
22 #undef PACKAGE
23 #endif
24 #ifdef PACKAGE_NAME
25 #undef PACKAGE_NAME
26 #endif
27 #ifdef PACKAGE_BUGREPORT
28 #undef PACKAGE_BUGREPORT
29 #endif
30 #ifdef PACKAGE_STRING
31 #undef PACKAGE_STRING
32 #endif
33 #ifdef PACKAGE_TARNAME
34 #undef PACKAGE_TARNAME
35 #endif
36 #ifdef PACKAGE_VERSION
37 #undef PACKAGE_VERSION
38 #endif
39 #ifdef VERSION
40 #undef VERSION
41 #endif
42 //#define ADOLC_TAPELESS
43 #define NUMBER_DIRECTIONS 100
44 #include "adolc/adouble.h"
45 #include "adolc/drivers/drivers.h"
46 #include "adolc/interfaces.h"
47 #include "adolc/taping.h"
48 #endif
49 
50 #ifdef HAVE_ADIC
51 // We have included an ADIC differentiated version of the element fill
52 // routine to compare the speed of operator overloading to source
53 // transformation. To run this code, all that is necessary is to turn
54 // on the ADIC TPL. However to modify the code, it is necessary to
55 // re-run the ADIC source transformation tool. To do so, first update
56 // the changes to adic_element_fill.c. Then set the following environment
57 // variables:
58 // export ADIC_ARCH=linux
59 // export ADIC=/home/etphipp/AD_libs/adic
60 // Next run ADIC via in the tests/performance source directory:
61 // ${ADIC}/bin/linux/adiC -vd gradient -i adic_element_fill.init
62 // Finally, copy the resulting differentiated function in adic_element_fill.ad.c
63 // back into this file. The function will need to be edited by changing
64 // the allocation of s to a std::vector<DERIV_TYPE> (the compiler
65 // doesn't seem to like malloc), and commenting out the g_filenum lines.
66 #define ad_GRAD_MAX 130
67 #include "ad_deriv.h"
68 #endif
69 
70 
71 // A performance test that computes a finite-element-like Jacobian using
72 // several Fad variants
73 
74 struct ElemData {
75  static const unsigned int nqp = 2;
76  static const unsigned int nnode = 2;
77  double w[nqp], jac[nqp], phi[nqp][nnode], dphi[nqp][nnode];
78  unsigned int gid[nnode];
79 
80  ElemData(double mesh_spacing) {
81  // Quadrature points
82  double xi[nqp];
83  xi[0] = -1.0 / std::sqrt(3.0);
84  xi[1] = 1.0 / std::sqrt(3.0);
85 
86  for (unsigned int i=0; i<nqp; i++) {
87  // Weights
88  w[i] = 1.0;
89 
90  // Element transformation Jacobian
91  jac[i] = 0.5*mesh_spacing;
92 
93  // Shape functions & derivatives
94  phi[i][0] = 0.5*(1.0 - xi[i]);
95  phi[i][1] = 0.5*(1.0 + xi[i]);
96  dphi[i][0] = -0.5;
97  dphi[i][1] = 0.5;
98  }
99  }
100 };
101 
102 template <class FadType>
103 void fad_init_fill(const ElemData& e,
104  unsigned int neqn,
105  const std::vector<double>& x,
106  std::vector<FadType>& x_fad) {
107  for (unsigned int node=0; node<e.nnode; node++)
108  for (unsigned int eqn=0; eqn<neqn; eqn++)
109  x_fad[node*neqn+eqn] = FadType(e.nnode*neqn, node*neqn+eqn,
110  x[e.gid[node]*neqn+eqn]);
111 }
112 
113 template <class T>
115  unsigned int neqn,
116  const std::vector<T>& x,
117  std::vector<T>& u,
118  std::vector<T>& du,
119  std::vector<T>& f) {
120  // Construct element solution, derivative
121  for (unsigned int qp=0; qp<e.nqp; qp++) {
122  for (unsigned int eqn=0; eqn<neqn; eqn++) {
123  u[qp*neqn+eqn] = 0.0;
124  du[qp*neqn+eqn] = 0.0;
125  for (unsigned int node=0; node<e.nnode; node++) {
126  u[qp*neqn+eqn] += x[node*neqn+eqn] * e.phi[qp][node];
127  du[qp*neqn+eqn] += x[node*neqn+eqn] * e.dphi[qp][node];
128  }
129  }
130  }
131 
132  // Compute sum of equations for coupling
133  std::vector<T> s(e.nqp);
134  for (unsigned int qp=0; qp<e.nqp; qp++) {
135  s[qp] = 0.0;
136  for (unsigned int eqn=0; eqn<neqn; eqn++)
137  s[qp] += u[qp*neqn+eqn]*u[qp*neqn+eqn];
138  }
139 
140  // Evaluate element residual
141  for (unsigned int node=0; node<e.nnode; node++) {
142  for (unsigned int eqn=0; eqn<neqn; eqn++) {
143  unsigned int row = node*neqn+eqn;
144  f[row] = 0.0;
145  for (unsigned int qp=0; qp<e.nqp; qp++) {
146  double c1 = e.w[qp]*e.jac[qp];
147  double c2 = -e.dphi[qp][node]/(e.jac[qp]*e.jac[qp]);
148  f[row] +=
149  c1*(c2*du[qp*neqn+eqn] + e.phi[qp][node]*s[qp]*exp(u[qp*neqn+eqn]));
150  }
151  }
152  }
153 }
154 
155 template <class FadType>
157  unsigned int neqn,
158  const std::vector<FadType>& f_fad,
159  std::vector<double>& f,
160  std::vector< std::vector<double> >& jac) {
161  for (unsigned int eqn_row=0; eqn_row<neqn; eqn_row++) {
162  f[e.gid[0]*neqn+eqn_row] += f_fad[0*neqn+eqn_row].val();
163  f[e.gid[1]*neqn+eqn_row] += f_fad[1*neqn+eqn_row].val();
164  for (unsigned int node_col=0; node_col<e.nnode; node_col++) {
165  for (unsigned int eqn_col=0; eqn_col<neqn; eqn_col++) {
166  unsigned int col = node_col*neqn+eqn_col;
167  unsigned int next_col = (node_col+1)*neqn+eqn_col;
168  jac[e.gid[0]*neqn+eqn_row][next_col] +=
169  f_fad[0*neqn+eqn_row].fastAccessDx(col);
170  jac[e.gid[1]*neqn+eqn_row][col] +=
171  f_fad[1*neqn+eqn_row].fastAccessDx(col);
172  }
173  }
174  }
175 }
176 
177 template <class FadType>
178 double fad_jac_fill(unsigned int num_nodes, unsigned int num_eqns,
179  double mesh_spacing) {
180  ElemData e(mesh_spacing);
181 
182  // Solution vector, residual, jacobian
183  std::vector<double> x(num_nodes*num_eqns), f(num_nodes*num_eqns);
184  std::vector< std::vector<double> > jac(num_nodes*num_eqns);
185  for (unsigned int node_row=0; node_row<num_nodes; node_row++) {
186  for (unsigned int eqn_row=0; eqn_row<num_eqns; eqn_row++) {
187  unsigned int row = node_row*num_eqns + eqn_row;
188  x[row] = (mesh_spacing*node_row - 0.5)*(mesh_spacing*node_row - 0.5);
189  f[row] = 0.0;
190  jac[row] = std::vector<double>((e.nnode+1)*num_eqns);
191  for (unsigned int node_col=0; node_col<e.nnode+1; node_col++) {
192  for (unsigned int eqn_col=0; eqn_col<num_eqns; eqn_col++) {
193  unsigned int col = node_col*num_eqns + eqn_col;
194  jac[row][col] = 0.0;
195  }
196  }
197  }
198  }
199 
200  Teuchos::Time timer("FE Fad Jacobian Fill", false);
201  timer.start(true);
202  std::vector<FadType> x_fad(e.nnode*num_eqns), f_fad(e.nnode*num_eqns);
203  std::vector<FadType> u(e.nqp*num_eqns), du(e.nqp*num_eqns);
204  for (unsigned int i=0; i<num_nodes-1; i++) {
205  e.gid[0] = i;
206  e.gid[1] = i+1;
207 
208  fad_init_fill(e, num_eqns, x, x_fad);
209  template_element_fill(e, num_eqns, x_fad, u, du, f_fad);
210  fad_process_fill(e, num_eqns, f_fad, f, jac);
211  }
212  timer.stop();
213 
214  // std::cout << "Fad Residual = " << std::endl;
215  // for (unsigned int i=0; i<num_nodes*num_eqns; i++)
216  // std::cout << "\t" << f[i] << std::endl;
217 
218  // std::cout.precision(8);
219  // std::cout << "Fad Jacobian = " << std::endl;
220  // for (unsigned int i=0; i<num_nodes*num_eqns; i++) {
221  // std::cout << "\t";
222  // for (unsigned int j=0; j<(e.nnode+1)*num_eqns; j++)
223  // std::cout << jac[i][j] << "\t";
224  // std::cout << std::endl;
225  // }
226 
227  return timer.totalElapsedTime();
228 }
229 
230 double analytic_jac_fill(unsigned int num_nodes, unsigned int num_eqns,
231  double mesh_spacing);
232 double residual_fill(unsigned int num_nodes, unsigned int num_eqns,
233  double mesh_spacing);
234 
235 #ifdef HAVE_ADOLC
236 #ifndef ADOLC_TAPELESS
237 void adolc_init_fill(bool retape,
238  int tag,
239  const ElemData& e,
240  unsigned int neqn,
241  const std::vector<double>& x,
242  std::vector<double>& x_local,
243  std::vector<adouble>& x_ad);
244 
245 void adolc_process_fill(bool retape,
246  int tag,
247  const ElemData& e,
248  unsigned int neqn,
249  std::vector<double>& x_local,
250  std::vector<adouble>& f_ad,
251  std::vector<double>& f,
252  std::vector<double>& f_local,
253  std::vector< std::vector<double> >& jac,
254  double **seed,
255  double **jac_local);
256 
257 double adolc_jac_fill(unsigned int num_nodes, unsigned int num_eqns,
258  double mesh_spacing);
259 
260 double adolc_retape_jac_fill(unsigned int num_nodes, unsigned int num_eqns,
261  double mesh_spacing);
262 
263 #else
264 
265 void adolc_tapeless_init_fill(const ElemData& e,
266  unsigned int neqn,
267  const std::vector<double>& x,
268  std::vector<adtl::adouble>& x_ad);
269 
270 void adolc_tapeless_process_fill(const ElemData& e,
271  unsigned int neqn,
272  const std::vector<adtl::adouble>& f_ad,
273  std::vector<double>& f,
274  std::vector< std::vector<double> >& jac);
275 
276 double adolc_tapeless_jac_fill(unsigned int num_nodes, unsigned int num_eqns,
277  double mesh_spacing);
278 
279 #endif
280 #endif
281 
282 #ifdef HAVE_ADIC
283 void adic_init_fill(const ElemData& e,
284  unsigned int neqn,
285  const std::vector<double>& x,
286  std::vector<DERIV_TYPE>& x_fad);
287 void adic_element_fill(ElemData *e,unsigned int neqn,DERIV_TYPE *x,DERIV_TYPE *u,DERIV_TYPE *du,DERIV_TYPE *f);
288 void adic_process_fill(const ElemData& e,
289  unsigned int neqn,
290  const std::vector<DERIV_TYPE>& f_fad,
291  std::vector<double>& f,
292  std::vector< std::vector<double> >& jac);
293 double adic_jac_fill(unsigned int num_nodes, unsigned int num_eqns,
294  double mesh_spacing);
295 inline void AD_Init(int arg0) {
296  ad_AD_GradInit(arg0);
297 }
298 inline void AD_Final() {
299  ad_AD_GradFinal();
300 }
301 #endif
302 
303 #endif
void f()
void AD_Init(int)
double residual_fill(unsigned int num_nodes, unsigned int num_eqns, double mesh_spacing)
void template_element_fill(const ElemData &e, unsigned int neqn, const std::vector< T > &x, std::vector< T > &u, std::vector< T > &du, std::vector< T > &f)
InactiveDouble * jac
InactiveDouble * w
void AD_Final()
void adic_element_fill(ElemData *e, unsigned int neqn, const DERIV_TYPE *x, DERIV_TYPE *u, DERIV_TYPE *du, DERIV_TYPE *f)
double analytic_jac_fill(unsigned int num_nodes, unsigned int num_eqns, double mesh_spacing)
Sacado::Fad::DFad< double > FadType
ElemData(double mesh_spacing)
void fad_init_fill(const ElemData &e, unsigned int neqn, const std::vector< double > &x, std::vector< FadType > &x_fad)
void start(bool reset=false)
double stop()
sqrt(expr.val())
InactiveDouble ** phi
InactiveDouble ** dphi
void fad_process_fill(const ElemData &e, unsigned int neqn, const std::vector< FadType > &f_fad, std::vector< double > &f, std::vector< std::vector< double > > &jac)
double totalElapsedTime(bool readCurrentTime=false) const
double fad_jac_fill(unsigned int num_nodes, unsigned int num_eqns, double mesh_spacing)
exp(expr.val())