8 #define fem_amg_setup FORTRAN_UNPREFIXED(fem_amg_setup, FEM_AMG_SETUP)
9 #define fem_amg_solve FORTRAN_UNPREFIXED(fem_amg_solve, FEM_AMG_SOLVE)
14 #include "_hypre_utilities.h"
15 #include "HYPRE_parcsr_ls.h"
16 #include "_hypre_parcsr_ls.h"
24 int n_x, n_y, n_z, n_elem, n_dim;
26 double *x_m, *y_m, *z_m;
36 HYPRE_ParCSRMatrix A_fem;
38 HYPRE_ParCSRMatrix B_fem;
40 HYPRE_ParVector Bd_fem;
42 HYPRE_ParVector f_fem;
44 HYPRE_ParVector u_fem;
46 HYPRE_ParVector Bf_fem;
47 HYPRE_IJVector Binv_sem_bc;
48 HYPRE_ParVector Binv_sem;
49 HYPRE_Solver amg_preconditioner;
55 double HYPREsettings[NPARAM];
58 void fem_amg_setup(
const sint *n_x_,
const sint *n_y_,
const sint *n_z_,
59 const sint *n_elem_,
const sint *n_dim_,
60 double *x_m_,
double *y_m_,
double *z_m_,
61 double *pmask_,
double *binv_,
const sint *nullspace,
62 const sint *gshf,
double *param)
77 n_xyz = n_x * n_y * n_z;
78 n_xyze = n_x * n_y * n_z * n_elem;
83 if (
comm.id == 0) printf(
"fem_amg_setup ...\n");
85 if (
sizeof(HYPRE_Int) !=
sizeof(
long long)) {
87 fail(1,__FILE__,__LINE__,
"incompatible long long size");
91 double time0 = comm_time();
96 long long row_start = hypre_ParCSRMatrixFirstRowIndex(A_fem);
97 long long row_end = hypre_ParCSRMatrixLastRowIndex(A_fem);
99 HYPRE_IJVectorCreate(
comm.c, row_start, row_end, &u_bc);
100 HYPRE_IJVectorSetObjectType(u_bc, HYPRE_PARCSR);
101 HYPRE_IJVectorInitialize(u_bc);
102 HYPRE_IJVectorAssemble(u_bc);
103 HYPRE_IJVectorGetObject(u_bc, (
void**) &u_fem);
105 HYPRE_IJVectorCreate(
comm.c, row_start, row_end, &f_bc);
106 HYPRE_IJVectorSetObjectType(f_bc, HYPRE_PARCSR);
107 HYPRE_IJVectorInitialize(f_bc);
108 HYPRE_IJVectorAssemble(f_bc);
109 HYPRE_IJVectorGetObject(f_bc, (
void**) &f_fem);
111 HYPRE_IJVectorCreate(
comm.c, row_start, row_end, &Bf_bc);
112 HYPRE_IJVectorSetObjectType(Bf_bc, HYPRE_PARCSR);
113 HYPRE_IJVectorInitialize(Bf_bc);
114 HYPRE_IJVectorAssemble(Bf_bc);
115 HYPRE_IJVectorGetObject(Bf_bc, (
void**) &Bf_fem);
117 HYPRE_IJVectorCreate(
comm.c, row_start, row_end, &Binv_sem_bc);
118 HYPRE_IJVectorSetObjectType(Binv_sem_bc, HYPRE_PARCSR);
119 HYPRE_IJVectorInitialize(Binv_sem_bc);
121 for (row = row_start; row <= row_end; row++)
122 HYPRE_IJVectorSetValues(Binv_sem_bc, 1, &row, &(binv[dof_map[row - row_start]]));
124 HYPRE_IJVectorAssemble(Binv_sem_bc);
125 HYPRE_IJVectorGetObject(Binv_sem_bc, (
void**) &Binv_sem);
127 HYPRE_BoomerAMGCreate(&amg_preconditioner);
129 int uparam = (int) param[0];
133 for (i=1; i < NPARAM; i++) {
134 HYPREsettings[i-1] = param[i];
136 printf(
"Custom HYPREsettings[%d]: %.2f\n", i, HYPREsettings[i-1]);
139 HYPREsettings[0] = 10;
140 HYPREsettings[1] = 6;
141 HYPREsettings[2] = 3;
142 HYPREsettings[3] = 3;
143 HYPREsettings[4] = 1;
144 HYPREsettings[5] = 0.25;
145 HYPREsettings[6] = 0.1;
148 HYPRE_BoomerAMGSetCoarsenType(amg_preconditioner, HYPREsettings[0]);
149 HYPRE_BoomerAMGSetInterpType(amg_preconditioner, HYPREsettings[1]);
150 if (*nullspace == 1 || (
int) param[0] != 0) {
151 HYPRE_BoomerAMGSetRelaxType(amg_preconditioner, HYPREsettings[2]);
152 HYPRE_BoomerAMGSetCycleRelaxType(amg_preconditioner, HYPREsettings[3], 3);
153 HYPRE_BoomerAMGSetCycleNumSweeps(amg_preconditioner, HYPREsettings[4], 3);
155 HYPRE_BoomerAMGSetStrongThreshold(amg_preconditioner, HYPREsettings[5]);
156 HYPRE_BoomerAMGSetNonGalerkinTol(amg_preconditioner, HYPREsettings[6]);
158 HYPRE_BoomerAMGSetLevelNonGalerkinTol(amg_preconditioner, HYPREsettings[7], 0);
159 HYPRE_BoomerAMGSetLevelNonGalerkinTol(amg_preconditioner, HYPREsettings[8], 1);
161 fflush(stdout);HYPRE_BoomerAMGSetLevelNonGalerkinTol(amg_preconditioner, HYPREsettings[9], 2);
164 HYPRE_BoomerAMGSetMaxRowSum(amg_preconditioner, 1);
165 HYPRE_BoomerAMGSetPMaxElmts(amg_preconditioner, 4);
166 HYPRE_BoomerAMGSetMaxCoarseSize(amg_preconditioner, 50);
167 HYPRE_BoomerAMGSetMaxIter(amg_preconditioner,1);
168 HYPRE_BoomerAMGSetTol(amg_preconditioner, 0);
169 HYPRE_BoomerAMGSetPrintLevel(amg_preconditioner, 1);
171 HYPRE_BoomerAMGSetup(amg_preconditioner, A_fem, NULL, NULL);
173 double time1 = comm_time();
174 if (
comm.id == 0) printf(
"fem_amg_setup: done %fs\n",time1-time0);
187 fail(1,__FILE__,__LINE__,
"AMG hasn't been setup");
192 HYPRE_IJVectorInitialize(f_bc);
194 switch (precond_type)
198 for (row = row_start; row <= row_end; row++)
199 HYPRE_IJVectorSetValues(f_bc, 1, &row, &(
w[dof_map[row - row_start]]));
205 for (row = row_start; row <= row_end; row++)
208 double Binv_sem_value;
210 HYPRE_IJVectorGetValues(Bd_bc, 1, &row, &Bd_fem_value);
211 HYPRE_IJVectorGetValues(Binv_sem_bc, 1, &row, &Binv_sem_value);
213 double value = Bd_fem_value * Binv_sem_value *
w[dof_map[row - row_start]];
215 HYPRE_IJVectorSetValues(f_bc, 1, &row, &value);
222 for (row = row_start; row <= row_end; row++)
224 double Binv_sem_value;
226 HYPRE_IJVectorGetValues(Binv_sem_bc, 1, &row, &Binv_sem_value);
228 double value = Binv_sem_value *
w[dof_map[row - row_start]];
230 HYPRE_IJVectorSetValues(Bf_bc, 1, &row, &value);
233 HYPRE_ParCSRMatrixMatvec(1.0, B_fem, Bf_fem, 0.0, f_fem);
238 HYPRE_IJVectorAssemble(f_bc);
241 HYPRE_BoomerAMGSolve(amg_preconditioner, A_fem, f_fem, u_fem);
244 for (idx = 0; idx < n_xyze; idx++)
247 for (row = row_start; row <= row_end; row++)
248 HYPRE_IJVectorGetValues(u_bc, 1, &row, &(z[dof_map[row - row_start]]));
250 gs(z, gs_double, gs_add, 0, gsh, 0);
264 long long idx_start = n_xyze;
265 long long scan_out[2], scan_buf[2];
266 comm_scan(scan_out, &
comm, gs_long_long, gs_add, &idx_start, 1, scan_buf);
267 idx_start = scan_out[0];
271 for (idx = 0; idx < n_xyze; idx++)
273 if (pmask[idx] > 0.0)
274 glo_num[idx] = idx_start + (
long long)idx;
279 gs(glo_num, gs_long_long, gs_min, 0, gsh, 0);
282 long long maximum_value_local = 0;
283 long long maximum_value = 0;
285 for (idx = 0; idx < n_xyze; idx++)
287 maximum_value_local = (glo_num[idx] > maximum_value_local) ? glo_num[idx] : maximum_value_local;
290 comm_allreduce(&
comm, gs_long_long, gs_max, &maximum_value_local, 1, &maximum_value);
291 const long long nstar = maximum_value/
comm.np + 1;
300 struct array ranking_transfer;
301 array_init(
struct ranking_tuple, &ranking_transfer, n_xyze);
302 ranking_transfer.n = n_xyze;
303 struct ranking_tuple *ranking_tuple_array = ranking_transfer.ptr;
305 for (idx = 0; idx < ranking_transfer.n; idx++)
307 ranking_tuple_array[idx].rank = glo_num[idx];
308 ranking_tuple_array[idx].proc = glo_num[idx] / nstar;
309 ranking_tuple_array[idx].idx = idx;
312 struct crystal crystal_router_handle;
313 crystal_init(&crystal_router_handle, &comm);
314 sarray_transfer(
struct ranking_tuple, &ranking_transfer, proc, 1, &crystal_router_handle);
315 ranking_tuple_array = ranking_transfer.ptr;
317 buffer_init(&my_buffer, 1);
318 sarray_sort(
struct ranking_tuple, ranking_transfer.ptr, ranking_transfer.n, rank, 1, &my_buffer);
320 long long current_rank = ranking_tuple_array[0].rank;
321 long long current_count = 0;
322 ranking_tuple_array[0].rank = current_count;
324 for (idx = 1; idx < ranking_transfer.n; idx++) {
326 if (ranking_tuple_array[idx].rank > current_rank) {
328 current_rank = ranking_tuple_array[idx].rank;
329 ranking_tuple_array[idx].rank = current_count;
330 }
else if (ranking_tuple_array[idx].rank == current_rank) {
331 ranking_tuple_array[idx].rank = current_count;
339 long long rank_start;
340 comm_scan(scan_out, &comm, gs_long_long, gs_add, ¤t_count, 1, scan_buf);
341 rank_start = scan_out[0];
343 for (idx = 0; idx < ranking_transfer.n; idx++)
345 ranking_tuple_array[idx].rank += rank_start;
348 sarray_transfer(
struct ranking_tuple, &ranking_transfer, proc, 1, &crystal_router_handle);
349 ranking_tuple_array = ranking_transfer.ptr;
351 buffer_init(&my_buffer, 1);
352 sarray_sort(
struct ranking_tuple, ranking_transfer.ptr, ranking_transfer.n, idx, 0, &my_buffer);
354 for (idx = 0; idx < n_xyze; idx++)
356 glo_num[idx] = ranking_tuple_array[idx].rank;
359 array_free(&ranking_transfer);
360 crystal_free(&crystal_router_handle);
372 int i, j, k, e, d, t, q;
383 for (idx = 0; idx < n_xyze; idx++)
384 ranking[idx] = glo_num[idx];
389 for (idx = 0; idx < n_xyze; idx++)
390 if (ranking[idx] >= 0) row_end =
maximum(row_end, ranking[idx]);
392 long long scan_out[2], scan_buf[2];
393 comm_scan(scan_out, &comm, gs_long_long, gs_max, &row_end, 1, scan_buf);
394 if (comm.id > 0) row_start = scan_out[0] + 1;
396 num_loc_dofs = row_end - row_start + 1;
400 for (idx = 0; idx < n_xyze; idx++)
402 if ((row_start <= ranking[idx]) && (ranking[idx] <= row_end))
404 dof_map[ranking[idx] - row_start] = idx;
409 HYPRE_IJMatrixCreate(comm.c, row_start, row_end, row_start, row_end, &A_bc);
410 HYPRE_IJMatrixSetObjectType(A_bc, HYPRE_PARCSR);
411 HYPRE_IJMatrixInitialize(A_bc);
413 HYPRE_IJMatrixCreate(comm.c, row_start, row_end, row_start, row_end, &B_bc);
414 HYPRE_IJMatrixSetObjectType(B_bc, HYPRE_PARCSR);
415 HYPRE_IJMatrixInitialize(B_bc);
417 HYPRE_IJVectorCreate(comm.c, row_start, row_end, &Bd_bc);
418 HYPRE_IJVectorSetObjectType(Bd_bc, HYPRE_PARCSR);
419 HYPRE_IJVectorInitialize(Bd_bc);
422 for (i = 0; i < n_xyze; i++) Bd_sum[i] = 0.0;
425 int n_quad = (n_dim == 2) ? 3 : 4;
437 num_fem = (meshing_type == 0) ? 4 : 2;
439 num_fem = (meshing_type == 0) ? 8 : 6;
452 Basis phi[n_dim + 1];
469 int E_z = (n_dim == 2) ? 1 : n_z - 1;
471 for (e = 0; e < n_elem; e++)
474 for (s_z = 0; s_z < E_z; s_z++)
476 for (s_y = 0; s_y < E_y; s_y++)
478 for (s_x = 0; s_x < E_x; s_x++)
485 s[0] = s_x; s[1] = s_y;
489 s[0] = s_x; s[1] = s_y; s[2] = s_z;
492 int idx[(int)(pow(2, n_dim))];
494 for (i = 0; i < pow(2, n_dim); i++)
498 for (d = 0; d < n_dim; d++)
500 idx[i] += (s[d] + v_coord[i][d]) * pow(n_x, d);
505 for (t = 0; t < num_fem; t++)
508 for (i = 0; i < n_dim + 1; i++)
512 x_t[0][i] = x_m[idx[t_map[t][i]] + e * n_xyz];
513 x_t[1][i] = y_m[idx[t_map[t][i]] + e * n_xyz];
517 x_t[0][i] = x_m[idx[t_map[t][i]] + e * n_xyz];
518 x_t[1][i] = y_m[idx[t_map[t][i]] + e * n_xyz];
519 x_t[2][i] = z_m[idx[t_map[t][i]] + e * n_xyz];
525 for (i = 0; i < n_dim + 1; i++)
527 for (j = 0; j < n_dim + 1; j++)
535 for (q = 0; q < n_quad; q++)
538 x_map(&q_x, q_r[q], x_t, n_dim, phi);
539 J_xr_map(&J_xr, q_r[q], x_t, n_dim, dphi);
544 for (i = 0; i < n_dim + 1; i++)
546 for (j = 0; j < n_dim + 1; j++)
551 for (alpha = 0; alpha < n_dim; alpha++)
553 double a = 0.0, b = 0.0;
555 for (beta = 0; beta < n_dim; beta++)
557 dphi[i](&dp, q_r[q]);
558 a += dp[beta] * J_rx[beta][alpha];
560 dphi[j](&dp, q_r[q]);
561 b += dp[beta] * J_rx[beta][alpha];
567 A_loc[i][j] += func * det_J_xr * q_w[q];
568 B_loc[i][j] += phi[i](q_r[q]) * phi[j](q_r[q]) * det_J_xr * q_w[q];
574 for (i = 0; i < n_dim + 1; i++)
576 for (j = 0; j < n_dim + 1; j++)
578 if ((pmask[idx[t_map[t][i]] + e * n_xyz] > 0.0) && (pmask[idx[t_map[t][j]] + e * n_xyz] > 0.0))
580 long long row = ranking[idx[t_map[t][i]] + e * n_xyz];
581 long long col = ranking[idx[t_map[t][j]] + e * n_xyz];
583 double A_val = A_loc[i][j];
584 double B_val = B_loc[i][j];
589 if (fabs(A_val) > 1.0e-14)
591 insert_error = HYPRE_IJMatrixAddToValues(A_bc, 1, &ncols, &row, &col, &A_val);
594 if (fabs(B_val) > 1.0e-14)
596 insert_error = HYPRE_IJMatrixAddToValues(B_bc, 1, &ncols, &row, &col, &B_val);
599 if (insert_error != 0)
602 printf(
"There was an error with entry A(%lld, %lld) = %f or B(%lld, %lld) = %f\n", row, col, A_val, row, col, B_val);
608 int row = idx[t_map[t][i]] + e * n_xyz;
609 int col = idx[t_map[t][j]] + e * n_xyz;
610 Bd_sum[row] += B_loc[i][j];
611 Bd_sum[col] += B_loc[i][j];
620 for (idx = 0; idx < n_xyze; idx++)
623 gs(Bd_sum, gs_double, gs_add, 0, gsh, 0);
625 for (row = row_start; row <= row_end; row++)
626 HYPRE_IJVectorSetValues(Bd_bc, 1, &row, &(Bd_sum[dof_map[row - row_start]]));
628 HYPRE_IJMatrixAssemble(A_bc);
629 HYPRE_IJMatrixGetObject(A_bc, (
void**) &A_fem);
631 HYPRE_IJMatrixAssemble(B_bc);
632 HYPRE_IJMatrixGetObject(B_bc, (
void**) &B_fem);
634 HYPRE_IJVectorAssemble(Bd_bc);
635 HYPRE_IJVectorGetObject(Bd_bc, (
void**) &Bd_fem);
654 void quadrature_rule(
double ***q_r,
double **q_w,
int n_quad,
int n_dim)
663 (*q_r)[0][0] = 1.0 / 6.0; (*q_r)[0][1] = 1.0 / 6.0;
664 (*q_r)[1][0] = 2.0 / 3.0; (*q_r)[1][1] = 1.0 / 6.0;
665 (*q_r)[2][0] = 1.0 / 6.0; (*q_r)[2][1] = 2.0 / 3.0;
667 (*q_w)[0] = 1.0 / 6.0;
668 (*q_w)[1] = 1.0 / 6.0;
669 (*q_w)[2] = 1.0 / 6.0;
671 else if (n_quad == 4)
673 (*q_r)[0][0] = 1.0 / 3.0; (*q_r)[0][1] = 1.0 / 3.0;
674 (*q_r)[1][0] = 1.0 / 5.0; (*q_r)[1][1] = 3.0 / 5.0;
675 (*q_r)[2][0] = 1.0 / 5.0; (*q_r)[2][1] = 1.0 / 5.0;
676 (*q_r)[3][0] = 3.0 / 5.0; (*q_r)[3][1] = 1.0 / 5.0;
678 (*q_w)[0] = - 27.0 / 96.0;
679 (*q_w)[1] = 25.0 / 96.0;
680 (*q_w)[2] = 25.0 / 96.0;
681 (*q_w)[3] = 25.0 / 96.0;
685 printf(
"No quadrature rule for %d points available\n", n_quad);
693 double a = (5.0 + 3.0 * sqrt(5.0)) / 20.0;
694 double b = (5.0 - sqrt(5.0)) / 20.0;
696 (*q_r)[0][0] = a; (*q_r)[0][1] = b; (*q_r)[0][2] = b;
697 (*q_r)[1][0] = b; (*q_r)[1][1] = a; (*q_r)[1][2] = b;
698 (*q_r)[2][0] = b; (*q_r)[2][1] = b; (*q_r)[2][2] = a;
699 (*q_r)[3][0] = b; (*q_r)[3][1] = b; (*q_r)[3][2] = b;
701 (*q_w)[0] = 1.0 / 24.0;
702 (*q_w)[1] = 1.0 / 24.0;
703 (*q_w)[2] = 1.0 / 24.0;
704 (*q_w)[3] = 1.0 / 24.0;
706 else if (n_quad == 5)
708 (*q_r)[0][0] = 1.0 / 2.0; (*q_r)[0][1] = 1.0 / 6.0; (*q_r)[0][2] = 1.0 / 6.0;
709 (*q_r)[1][0] = 1.0 / 6.0; (*q_r)[1][1] = 1.0 / 2.0; (*q_r)[1][2] = 1.0 / 6.0;
710 (*q_r)[2][0] = 1.0 / 6.0; (*q_r)[2][1] = 1.0 / 6.0; (*q_r)[2][2] = 1.0 / 2.0;
711 (*q_r)[3][0] = 1.0 / 6.0; (*q_r)[3][1] = 1.0 / 6.0; (*q_r)[3][2] = 1.0 / 6.0;
712 (*q_r)[4][0] = 1.0 / 4.0; (*q_r)[4][1] = 1.0 / 4.0; (*q_r)[4][2] = 1.0 / 4.0;
714 (*q_w)[0] = 9.0 / 20.0;
715 (*q_w)[1] = 9.0 / 20.0;
716 (*q_w)[2] = 9.0 / 20.0;
717 (*q_w)[3] = 9.0 / 20.0;
718 (*q_w)[4] = - 4.0 / 5.0;
722 printf(
"No quadrature rule for %d points available\n", n_quad);
735 (*v_coord)[0][0] = 0; (*v_coord)[0][1] = 0;
736 (*v_coord)[1][0] = 1; (*v_coord)[1][1] = 0;
737 (*v_coord)[2][0] = 0; (*v_coord)[2][1] = 1;
738 (*v_coord)[3][0] = 1; (*v_coord)[3][1] = 1;
742 (*t_map)[0][0] = 0; (*t_map)[0][1] = 1; (*t_map)[0][2] = 3;
743 (*t_map)[1][0] = 0; (*t_map)[1][1] = 3; (*t_map)[1][2] = 2;
745 else if (num_fem == 4)
747 (*t_map)[0][0] = 1; (*t_map)[0][1] = 2; (*t_map)[0][2] = 0;
748 (*t_map)[1][0] = 3; (*t_map)[1][1] = 0; (*t_map)[1][2] = 1;
749 (*t_map)[2][0] = 0; (*t_map)[2][1] = 3; (*t_map)[2][2] = 2;
750 (*t_map)[3][0] = 2; (*t_map)[3][1] = 1; (*t_map)[3][2] = 3;
754 printf(
"Wrong number of triangles\n");
760 (*v_coord)[0][0] = 0; (*v_coord)[0][1] = 0; (*v_coord)[0][2] = 0;
761 (*v_coord)[1][0] = 1; (*v_coord)[1][1] = 0; (*v_coord)[1][2] = 0;
762 (*v_coord)[2][0] = 0; (*v_coord)[2][1] = 1; (*v_coord)[2][2] = 0;
763 (*v_coord)[3][0] = 1; (*v_coord)[3][1] = 1; (*v_coord)[3][2] = 0;
764 (*v_coord)[4][0] = 0; (*v_coord)[4][1] = 0; (*v_coord)[4][2] = 1;
765 (*v_coord)[5][0] = 1; (*v_coord)[5][1] = 0; (*v_coord)[5][2] = 1;
766 (*v_coord)[6][0] = 0; (*v_coord)[6][1] = 1; (*v_coord)[6][2] = 1;
767 (*v_coord)[7][0] = 1; (*v_coord)[7][1] = 1; (*v_coord)[7][2] = 1;
771 (*t_map)[0][0] = 0; (*t_map)[0][1] = 2; (*t_map)[0][2] = 1; (*t_map)[0][3] = 5;
772 (*t_map)[1][0] = 1; (*t_map)[1][1] = 2; (*t_map)[1][2] = 3; (*t_map)[1][3] = 5;
773 (*t_map)[2][0] = 0; (*t_map)[2][1] = 4; (*t_map)[2][2] = 2; (*t_map)[2][3] = 5;
774 (*t_map)[3][0] = 5; (*t_map)[3][1] = 3; (*t_map)[3][2] = 7; (*t_map)[3][3] = 2;
775 (*t_map)[4][0] = 4; (*t_map)[4][1] = 5; (*t_map)[4][2] = 6; (*t_map)[4][3] = 2;
776 (*t_map)[5][0] = 5; (*t_map)[5][1] = 7; (*t_map)[5][2] = 6; (*t_map)[5][3] = 2;
778 else if (num_fem == 8)
780 (*t_map)[0][0] = 0; (*t_map)[0][1] = 2; (*t_map)[0][2] = 1; (*t_map)[0][3] = 4;
781 (*t_map)[1][0] = 1; (*t_map)[1][1] = 0; (*t_map)[1][2] = 3; (*t_map)[1][3] = 5;
782 (*t_map)[2][0] = 2; (*t_map)[2][1] = 6; (*t_map)[2][2] = 3; (*t_map)[2][3] = 0;
783 (*t_map)[3][0] = 3; (*t_map)[3][1] = 2; (*t_map)[3][2] = 7; (*t_map)[3][3] = 1;
784 (*t_map)[4][0] = 4; (*t_map)[4][1] = 5; (*t_map)[4][2] = 6; (*t_map)[4][3] = 0;
785 (*t_map)[5][0] = 5; (*t_map)[5][1] = 7; (*t_map)[5][2] = 4; (*t_map)[5][3] = 1;
786 (*t_map)[6][0] = 6; (*t_map)[6][1] = 7; (*t_map)[6][2] = 2; (*t_map)[6][3] = 4;
787 (*t_map)[7][0] = 7; (*t_map)[7][1] = 3; (*t_map)[7][2] = 6; (*t_map)[7][3] = 5;
791 printf(
"Wrong number of tetrahedrals\n");
797 void x_map(
double **x,
double *r,
double **x_t,
int n_dim,
Basis *phi)
801 for (d = 0; d < n_dim; d++)
805 for (i = 0; i < n_dim + 1; i++)
807 (*x)[d] += x_t[d][i] * phi[i](r);
812 void J_xr_map(
double ***J_xr,
double *r,
double **x_t,
int n_dim,
DBasis *dphi)
817 for (i = 0; i < n_dim; i++)
819 for (j = 0; j < n_dim; j++)
823 for (k = 0; k < n_dim + 1; k++)
827 (*J_xr)[i][j] += x_t[i][k] * deriv[j];
836 double phi_2D_1(
double *r) {
return r[0]; }
837 double phi_2D_2(
double *r) {
return r[1]; }
838 double phi_2D_3(
double *r) {
return 1.0 - r[0] - r[1]; }
839 void dphi_2D_1(
double **dp,
double *r) { (*dp)[0] = 1.0; (*dp)[1] = 0.0; }
840 void dphi_2D_2(
double **dp,
double *r) { (*dp)[0] = 0.0; (*dp)[1] = 1.0; }
841 void dphi_2D_3(
double **dp,
double *r) { (*dp)[0] = -1.0; (*dp)[1] = -1.0; }
844 double phi_3D_1(
double *r) {
return r[0]; }
845 double phi_3D_2(
double *r) {
return r[1]; }
846 double phi_3D_3(
double *r) {
return r[2]; }
847 double phi_3D_4(
double *r) {
return 1.0 - r[0] - r[1] - r[2]; }
848 void dphi_3D_1(
double **dp,
double *r) { (*dp)[0] = 1.0; (*dp)[1] = 0.0; (*dp)[2] = 0.0; }
849 void dphi_3D_2(
double **dp,
double *r) { (*dp)[0] = 0.0; (*dp)[1] = 1.0; (*dp)[2] = 0.0; }
850 void dphi_3D_3(
double **dp,
double *r) { (*dp)[0] = 0.0; (*dp)[1] = 0.0; (*dp)[2] = 1.0; }
851 void dphi_3D_4(
double **dp,
double *r) { (*dp)[0] = -1.0; (*dp)[1] = -1.0; (*dp)[2] = -1.0; }
854 long long maximum(
long long a,
long long b)
856 return a > b ? a : b;
866 double d_1 = A[0][0] * A[1][1] - A[1][0] * A[0][1];
872 double d_1 = A[0][0] * (A[1][1] * A[2][2] - A[2][1] * A[1][2]);
873 double d_2 = A[0][1] * (A[1][0] * A[2][2] - A[2][0] * A[1][2]);
874 double d_3 = A[0][2] * (A[1][0] * A[2][1] - A[2][0] * A[1][1]);
876 return d_1 - d_2 + d_3;
880 double d_1 = A[0][0];
881 double d_11 = A[1][1] * (A[2][2] * A[3][3] - A[3][2] * A[2][3]);
882 double d_12 = A[1][2] * (A[2][1] * A[3][3] - A[3][1] * A[2][3]);
883 double d_13 = A[1][3] * (A[2][1] * A[3][2] - A[3][1] * A[2][2]);
885 double d_2 = A[0][1];
886 double d_21 = A[1][0] * (A[2][2] * A[3][3] - A[3][2] * A[2][3]);
887 double d_22 = A[1][2] * (A[2][0] * A[3][3] - A[3][0] * A[2][3]);
888 double d_23 = A[1][3] * (A[2][0] * A[3][2] - A[3][0] * A[2][2]);
890 double d_3 = A[0][2];
891 double d_31 = A[1][0] * (A[2][1] * A[3][3] - A[3][1] * A[2][3]);
892 double d_32 = A[1][1] * (A[2][0] * A[3][3] - A[3][0] * A[2][3]);
893 double d_33 = A[1][3] * (A[2][0] * A[3][1] - A[3][0] * A[2][1]);
895 double d_4 = A[0][3];
896 double d_41 = A[1][0] * (A[2][1] * A[3][2] - A[3][1] * A[2][2]);
897 double d_42 = A[1][1] * (A[2][0] * A[3][2] - A[3][0] * A[2][2]);
898 double d_43 = A[1][2] * (A[2][0] * A[3][1] - A[3][0] * A[2][1]);
900 return d_1 * (d_11 - d_12 + d_13) - d_2 * (d_21 - d_22 + d_23) + d_3 * (d_31 - d_32 + d_33) - d_4 * (d_41 - d_42 + d_43);
904 printf(
"ERROR: No determinant implementation for matrices of size > 4\n");
909 void inverse(
double*** inv_A,
double** A,
int n)
918 (*inv_A)[0][0] = (1.0 / det_A) * A[1][1];
919 (*inv_A)[0][1] = -(1.0 / det_A) * A[0][1];
920 (*inv_A)[1][0] = -(1.0 / det_A) * A[1][0];
921 (*inv_A)[1][1] = (1.0 / det_A) * A[0][0];
925 (*inv_A)[0][0] = (1.0 / det_A) * (A[1][1] * A[2][2] - A[2][1] * A[1][2]);
926 (*inv_A)[0][1] = (1.0 / det_A) * (A[0][2] * A[2][1] - A[2][2] * A[0][1]);
927 (*inv_A)[0][2] = (1.0 / det_A) * (A[0][1] * A[1][2] - A[1][1] * A[0][2]);
928 (*inv_A)[1][0] = (1.0 / det_A) * (A[1][2] * A[2][0] - A[2][2] * A[1][0]);
929 (*inv_A)[1][1] = (1.0 / det_A) * (A[0][0] * A[2][2] - A[2][0] * A[0][2]);
930 (*inv_A)[1][2] = (1.0 / det_A) * (A[0][2] * A[1][0] - A[1][2] * A[0][0]);
931 (*inv_A)[2][0] = (1.0 / det_A) * (A[1][0] * A[2][1] - A[2][0] * A[1][1]);
932 (*inv_A)[2][1] = (1.0 / det_A) * (A[0][1] * A[2][0] - A[2][1] * A[0][0]);
933 (*inv_A)[2][2] = (1.0 / det_A) * (A[0][0] * A[1][1] - A[1][0] * A[0][1]);
937 printf(
"ERROR: No inverse implementation for matrices of size > 3\n");
945 int *array = (
int*) malloc(n *
sizeof(
int));
952 long long *array = (
long long*) malloc(n *
sizeof(
long long));
959 double *array = (
double*) malloc(n *
sizeof(
double));
967 int **array = (
int**) malloc(n *
sizeof(
int*));
969 for (i = 0; i < n; i++)
970 array[i] = (
int*) malloc(m *
sizeof(
int));
978 double **array = (
double**) malloc(n *
sizeof(
double*));
980 for (i = 0; i < n; i++)
981 array[i] = (
double*) malloc(m *
sizeof(
double));
1005 for (i = 0; i < n; i++)
1015 for (i = 0; i < n; i++)
1022 const sint *n_elem_,
const sint *n_dim_,
1023 double *x_m_,
double *y_m_,
double *z_m_,
1024 double *pmask_,
double *binv_,
const sint *nullspace,
1027 fail(1,__FILE__,__LINE__,
"please recompile with HYPRE support");
1031 fail(1,__FILE__,__LINE__,
"please recompile with HYPRE support");
void dphi_3D_4(double **, double *)
void dphi_3D_3(double **, double *)
void mem_free_2D_double(double ***, int, int)
void mem_free_1D_double(double **, int)
long long * mem_alloc_1D_long(int)
void mem_free_2D_int(int ***, int, int)
void dphi_2D_2(double **, double *)
void matrix_distribution()
long long maximum(long long, long long)
void J_xr_map(double ***, double *, double **, int, DBasis *)
double phi_3D_2(double *)
double phi_2D_2(double *)
double phi_3D_3(double *)
int * mem_alloc_1D_int(int)
void mesh_connectivity(int ***, int ***, int, int)
void quadrature_rule(double ***, double **, int, int)
double(* Basis)(double *)
double phi_3D_1(double *)
void inverse(double ***, double **, int)
int ** mem_alloc_2D_int(int, int)
double * mem_alloc_1D_double(int)
double determinant(double **, int)
void dphi_3D_1(double **, double *)
void mem_free_1D_long(long long **, int)
double phi_3D_4(double *)
double ** mem_alloc_2D_double(int, int)
void dphi_2D_1(double **, double *)
double phi_2D_3(double *)
void dphi_3D_2(double **, double *)
void dphi_2D_3(double **, double *)
void(* DBasis)(double **, double *)
void mem_free_1D_int(int **, int)
double phi_2D_1(double *)
void x_map(double **, double *, double **, int, Basis *)
The nomenclature of the interpolating fields saved by Nek into the binary file int_fld is here explained w