| ceed-basis.c (d1ca5d5ed7eef5ba04c025231ef3837c27c70d10) | ceed-basis.c (c8c3fa7d27bffffddcff68a8a1d51314e0358a98) |
|---|---|
| 1// Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2// All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3// 4// SPDX-License-Identifier: BSD-2-Clause 5// 6// This file is part of CEED: http://github.com/ceed 7 8#include <ceed-impl.h> --- 244 unchanged lines hidden (view full) --- 253 @param[in] basis CeedBasis 254 @param[out] collo_grad_1d Row-major (Q_1d * Q_1d) matrix expressing derivatives of basis functions at quadrature points 255 256 @return An error code: 0 - success, otherwise - failure 257 258 @ref Backend 259**/ 260int CeedBasisGetCollocatedGrad(CeedBasis basis, CeedScalar *collo_grad_1d) { | 1// Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2// All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3// 4// SPDX-License-Identifier: BSD-2-Clause 5// 6// This file is part of CEED: http://github.com/ceed 7 8#include <ceed-impl.h> --- 244 unchanged lines hidden (view full) --- 253 @param[in] basis CeedBasis 254 @param[out] collo_grad_1d Row-major (Q_1d * Q_1d) matrix expressing derivatives of basis functions at quadrature points 255 256 @return An error code: 0 - success, otherwise - failure 257 258 @ref Backend 259**/ 260int CeedBasisGetCollocatedGrad(CeedBasis basis, CeedScalar *collo_grad_1d) { |
| 261 int i, j, k; | |
| 262 Ceed ceed; 263 CeedInt P_1d = (basis)->P_1d, Q_1d = (basis)->Q_1d; 264 CeedScalar *interp_1d, *grad_1d, *tau; 265 266 CeedCall(CeedMalloc(Q_1d * P_1d, &interp_1d)); 267 CeedCall(CeedMalloc(Q_1d * P_1d, &grad_1d)); 268 CeedCall(CeedMalloc(Q_1d, &tau)); 269 memcpy(interp_1d, (basis)->interp_1d, Q_1d * P_1d * sizeof(basis)->interp_1d[0]); 270 memcpy(grad_1d, (basis)->grad_1d, Q_1d * P_1d * sizeof(basis)->interp_1d[0]); 271 272 // QR Factorization, interp_1d = Q R 273 CeedCall(CeedBasisGetCeed(basis, &ceed)); 274 CeedCall(CeedQRFactorization(ceed, interp_1d, tau, Q_1d, P_1d)); 275 // Note: This function is for backend use, so all errors are terminal and we do not need to clean up memory on failure. 276 | 261 Ceed ceed; 262 CeedInt P_1d = (basis)->P_1d, Q_1d = (basis)->Q_1d; 263 CeedScalar *interp_1d, *grad_1d, *tau; 264 265 CeedCall(CeedMalloc(Q_1d * P_1d, &interp_1d)); 266 CeedCall(CeedMalloc(Q_1d * P_1d, &grad_1d)); 267 CeedCall(CeedMalloc(Q_1d, &tau)); 268 memcpy(interp_1d, (basis)->interp_1d, Q_1d * P_1d * sizeof(basis)->interp_1d[0]); 269 memcpy(grad_1d, (basis)->grad_1d, Q_1d * P_1d * sizeof(basis)->interp_1d[0]); 270 271 // QR Factorization, interp_1d = Q R 272 CeedCall(CeedBasisGetCeed(basis, &ceed)); 273 CeedCall(CeedQRFactorization(ceed, interp_1d, tau, Q_1d, P_1d)); 274 // Note: This function is for backend use, so all errors are terminal and we do not need to clean up memory on failure. 275 |
| 277 // Apply Rinv, collo_grad_1d = grad_1d Rinv 278 for (i = 0; i < Q_1d; i++) { // Row i | 276 // Apply R_inv, collo_grad_1d = grad_1d R_inv 277 for (CeedInt i = 0; i < Q_1d; i++) { // Row i |
| 279 collo_grad_1d[Q_1d * i] = grad_1d[P_1d * i] / interp_1d[0]; | 278 collo_grad_1d[Q_1d * i] = grad_1d[P_1d * i] / interp_1d[0]; |
| 280 for (j = 1; j < P_1d; j++) { // Column j | 279 for (CeedInt j = 1; j < P_1d; j++) { // Column j |
| 281 collo_grad_1d[j + Q_1d * i] = grad_1d[j + P_1d * i]; | 280 collo_grad_1d[j + Q_1d * i] = grad_1d[j + P_1d * i]; |
| 282 for (k = 0; k < j; k++) collo_grad_1d[j + Q_1d * i] -= interp_1d[j + P_1d * k] * collo_grad_1d[k + Q_1d * i]; | 281 for (CeedInt k = 0; k < j; k++) collo_grad_1d[j + Q_1d * i] -= interp_1d[j + P_1d * k] * collo_grad_1d[k + Q_1d * i]; |
| 283 collo_grad_1d[j + Q_1d * i] /= interp_1d[j + P_1d * j]; 284 } | 282 collo_grad_1d[j + Q_1d * i] /= interp_1d[j + P_1d * j]; 283 } |
| 285 for (j = P_1d; j < Q_1d; j++) collo_grad_1d[j + Q_1d * i] = 0; | 284 for (CeedInt j = P_1d; j < Q_1d; j++) collo_grad_1d[j + Q_1d * i] = 0; |
| 286 } 287 288 // Apply Q^T, collo_grad_1d = collo_grad_1d Q^T 289 CeedCall(CeedHouseholderApplyQ(collo_grad_1d, interp_1d, tau, CEED_NOTRANSPOSE, Q_1d, Q_1d, P_1d, 1, Q_1d)); 290 291 CeedCall(CeedFree(&interp_1d)); 292 CeedCall(CeedFree(&grad_1d)); 293 CeedCall(CeedFree(&tau)); --- 651 unchanged lines hidden (view full) --- 945 @param[out] basis Address of the variable where the newly created CeedBasis will be stored. 946 947 @return An error code: 0 - success, otherwise - failure 948 949 @ref User 950**/ 951int CeedBasisCreateTensorH1Lagrange(Ceed ceed, CeedInt dim, CeedInt num_comp, CeedInt P, CeedInt Q, CeedQuadMode quad_mode, CeedBasis *basis) { 952 // Allocate | 285 } 286 287 // Apply Q^T, collo_grad_1d = collo_grad_1d Q^T 288 CeedCall(CeedHouseholderApplyQ(collo_grad_1d, interp_1d, tau, CEED_NOTRANSPOSE, Q_1d, Q_1d, P_1d, 1, Q_1d)); 289 290 CeedCall(CeedFree(&interp_1d)); 291 CeedCall(CeedFree(&grad_1d)); 292 CeedCall(CeedFree(&tau)); --- 651 unchanged lines hidden (view full) --- 944 @param[out] basis Address of the variable where the newly created CeedBasis will be stored. 945 946 @return An error code: 0 - success, otherwise - failure 947 948 @ref User 949**/ 950int CeedBasisCreateTensorH1Lagrange(Ceed ceed, CeedInt dim, CeedInt num_comp, CeedInt P, CeedInt Q, CeedQuadMode quad_mode, CeedBasis *basis) { 951 // Allocate |
| 953 int ierr = CEED_ERROR_SUCCESS, i, j, k; | 952 int ierr = CEED_ERROR_SUCCESS; |
| 954 CeedScalar c1, c2, c3, c4, dx, *nodes, *interp_1d, *grad_1d, *q_ref_1d, *q_weight_1d; 955 956 CeedCheck(dim > 0, ceed, CEED_ERROR_DIMENSION, "Basis dimension must be a positive value"); 957 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "Basis must have at least 1 component"); 958 CeedCheck(P > 0, ceed, CEED_ERROR_DIMENSION, "Basis must have at least 1 node"); 959 CeedCheck(Q > 0, ceed, CEED_ERROR_DIMENSION, "Basis must have at least 1 quadrature point"); 960 961 // Get Nodes and Weights --- 10 unchanged lines hidden (view full) --- 972 case CEED_GAUSS_LOBATTO: 973 ierr = CeedLobattoQuadrature(Q, q_ref_1d, q_weight_1d); 974 break; 975 } 976 if (ierr != CEED_ERROR_SUCCESS) goto cleanup; 977 978 // Build B, D matrix 979 // Fornberg, 1998 | 953 CeedScalar c1, c2, c3, c4, dx, *nodes, *interp_1d, *grad_1d, *q_ref_1d, *q_weight_1d; 954 955 CeedCheck(dim > 0, ceed, CEED_ERROR_DIMENSION, "Basis dimension must be a positive value"); 956 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "Basis must have at least 1 component"); 957 CeedCheck(P > 0, ceed, CEED_ERROR_DIMENSION, "Basis must have at least 1 node"); 958 CeedCheck(Q > 0, ceed, CEED_ERROR_DIMENSION, "Basis must have at least 1 quadrature point"); 959 960 // Get Nodes and Weights --- 10 unchanged lines hidden (view full) --- 971 case CEED_GAUSS_LOBATTO: 972 ierr = CeedLobattoQuadrature(Q, q_ref_1d, q_weight_1d); 973 break; 974 } 975 if (ierr != CEED_ERROR_SUCCESS) goto cleanup; 976 977 // Build B, D matrix 978 // Fornberg, 1998 |
| 980 for (i = 0; i < Q; i++) { | 979 for (CeedInt i = 0; i < Q; i++) { |
| 981 c1 = 1.0; 982 c3 = nodes[0] - q_ref_1d[i]; 983 interp_1d[i * P + 0] = 1.0; | 980 c1 = 1.0; 981 c3 = nodes[0] - q_ref_1d[i]; 982 interp_1d[i * P + 0] = 1.0; |
| 984 for (j = 1; j < P; j++) { | 983 for (CeedInt j = 1; j < P; j++) { |
| 985 c2 = 1.0; 986 c4 = c3; 987 c3 = nodes[j] - q_ref_1d[i]; | 984 c2 = 1.0; 985 c4 = c3; 986 c3 = nodes[j] - q_ref_1d[i]; |
| 988 for (k = 0; k < j; k++) { | 987 for (CeedInt k = 0; k < j; k++) { |
| 989 dx = nodes[j] - nodes[k]; 990 c2 *= dx; 991 if (k == j - 1) { 992 grad_1d[i * P + j] = c1 * (interp_1d[i * P + k] - c4 * grad_1d[i * P + k]) / c2; 993 interp_1d[i * P + j] = -c1 * c4 * interp_1d[i * P + k] / c2; 994 } 995 grad_1d[i * P + k] = (c3 * grad_1d[i * P + k] - interp_1d[i * P + k]) / dx; 996 interp_1d[i * P + k] = c3 * interp_1d[i * P + k] / dx; --- 351 unchanged lines hidden (view full) --- 1348 CeedSize u_length = 0, v_length; 1349 CeedInt dim, num_comp, q_comp, num_nodes, num_qpts; 1350 CeedCall(CeedBasisGetDimension(basis, &dim)); 1351 CeedCall(CeedBasisGetNumComponents(basis, &num_comp)); 1352 CeedCall(CeedBasisGetNumQuadratureComponents(basis, eval_mode, &q_comp)); 1353 CeedCall(CeedBasisGetNumNodes(basis, &num_nodes)); 1354 CeedCall(CeedBasisGetNumQuadraturePoints(basis, &num_qpts)); 1355 CeedCall(CeedVectorGetLength(v, &v_length)); | 988 dx = nodes[j] - nodes[k]; 989 c2 *= dx; 990 if (k == j - 1) { 991 grad_1d[i * P + j] = c1 * (interp_1d[i * P + k] - c4 * grad_1d[i * P + k]) / c2; 992 interp_1d[i * P + j] = -c1 * c4 * interp_1d[i * P + k] / c2; 993 } 994 grad_1d[i * P + k] = (c3 * grad_1d[i * P + k] - interp_1d[i * P + k]) / dx; 995 interp_1d[i * P + k] = c3 * interp_1d[i * P + k] / dx; --- 351 unchanged lines hidden (view full) --- 1347 CeedSize u_length = 0, v_length; 1348 CeedInt dim, num_comp, q_comp, num_nodes, num_qpts; 1349 CeedCall(CeedBasisGetDimension(basis, &dim)); 1350 CeedCall(CeedBasisGetNumComponents(basis, &num_comp)); 1351 CeedCall(CeedBasisGetNumQuadratureComponents(basis, eval_mode, &q_comp)); 1352 CeedCall(CeedBasisGetNumNodes(basis, &num_nodes)); 1353 CeedCall(CeedBasisGetNumQuadraturePoints(basis, &num_qpts)); 1354 CeedCall(CeedVectorGetLength(v, &v_length)); |
| 1356 if (u) { 1357 CeedCall(CeedVectorGetLength(u, &u_length)); 1358 } | 1355 if (u) CeedCall(CeedVectorGetLength(u, &u_length)); |
| 1359 1360 CeedCheck(basis->Apply, basis->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support BasisApply"); 1361 1362 // Check compatibility of topological and geometrical dimensions 1363 CeedCheck((t_mode == CEED_TRANSPOSE && v_length % num_nodes == 0 && u_length % num_qpts == 0) || 1364 (t_mode == CEED_NOTRANSPOSE && u_length % num_nodes == 0 && v_length % num_qpts == 0), 1365 basis->ceed, CEED_ERROR_DIMENSION, "Length of input/output vectors incompatible with basis dimensions"); 1366 --- 15 unchanged lines hidden (view full) --- 1382 } 1383 CeedCheck(good_dims, basis->ceed, CEED_ERROR_DIMENSION, "Input/output vectors too short for basis and evaluation mode"); 1384 1385 CeedCall(basis->Apply(basis, num_elem, t_mode, eval_mode, u, v)); 1386 return CEED_ERROR_SUCCESS; 1387} 1388 1389/** | 1356 1357 CeedCheck(basis->Apply, basis->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support BasisApply"); 1358 1359 // Check compatibility of topological and geometrical dimensions 1360 CeedCheck((t_mode == CEED_TRANSPOSE && v_length % num_nodes == 0 && u_length % num_qpts == 0) || 1361 (t_mode == CEED_NOTRANSPOSE && u_length % num_nodes == 0 && v_length % num_qpts == 0), 1362 basis->ceed, CEED_ERROR_DIMENSION, "Length of input/output vectors incompatible with basis dimensions"); 1363 --- 15 unchanged lines hidden (view full) --- 1379 } 1380 CeedCheck(good_dims, basis->ceed, CEED_ERROR_DIMENSION, "Input/output vectors too short for basis and evaluation mode"); 1381 1382 CeedCall(basis->Apply(basis, num_elem, t_mode, eval_mode, u, v)); 1383 return CEED_ERROR_SUCCESS; 1384} 1385 1386/** |
| 1387 @brief Apply basis evaluation from nodes to arbitrary points 1388 1389 @param[in] basis CeedBasis to evaluate 1390 @param[in] num_points The number of points to apply the basis evaluation to 1391 @param[in] t_mode \ref CEED_NOTRANSPOSE to evaluate from nodes to points; 1392 \ref CEED_TRANSPOSE to apply the transpose, mapping from points to nodes 1393 @param[in] eval_mode \ref CEED_EVAL_INTERP to use interpolated values, 1394 \ref CEED_EVAL_GRAD to use gradients 1395 @param[in] x_ref CeedVector holding reference coordinates of each point 1396 @param[in] u Input CeedVector, of length `num_nodes * num_comp` for `CEED_NOTRANSPOSE` 1397 @param[out] v Output CeedVector, of length `num_points * num_q_comp` for `CEED_NOTRANSPOSE` with `CEED_EVAL_INTERP` 1398 1399 @return An error code: 0 - success, otherwise - failure 1400 1401 @ref User 1402**/ 1403int CeedBasisApplyAtPoints(CeedBasis basis, CeedInt num_points, CeedTransposeMode t_mode, CeedEvalMode eval_mode, CeedVector x_ref, CeedVector u, 1404 CeedVector v) { 1405 CeedSize x_length = 0, u_length = 0, v_length; 1406 CeedInt dim, num_comp, num_q_comp, num_nodes, P_1d = 1, Q_1d = 1; 1407 1408 CeedCall(CeedBasisGetDimension(basis, &dim)); 1409 CeedCall(CeedBasisGetNumNodes1D(basis, &P_1d)); 1410 CeedCall(CeedBasisGetNumQuadraturePoints1D(basis, &Q_1d)); 1411 CeedCall(CeedBasisGetNumComponents(basis, &num_comp)); 1412 CeedCall(CeedBasisGetNumQuadratureComponents(basis, eval_mode, &num_q_comp)); 1413 CeedCall(CeedBasisGetNumNodes(basis, &num_nodes)); 1414 CeedCall(CeedVectorGetLength(x_ref, &x_length)); 1415 CeedCall(CeedVectorGetLength(v, &v_length)); 1416 CeedCall(CeedVectorGetLength(u, &u_length)); 1417 1418 // Check compatibility of topological and geometrical dimensions 1419 CeedCheck((t_mode == CEED_TRANSPOSE && v_length % num_nodes == 0) || (t_mode == CEED_NOTRANSPOSE && u_length % num_nodes == 0), basis->ceed, 1420 CEED_ERROR_DIMENSION, "Length of input/output vectors incompatible with basis dimensions and number of points"); 1421 1422 // Check compatibility coordinates vector 1423 CeedCheck(x_length >= num_points * dim, basis->ceed, CEED_ERROR_DIMENSION, 1424 "Length of reference coordinate vector incompatible with basis dimension and number of points"); 1425 1426 // Check vector lengths to prevent out of bounds issues 1427 bool good_dims = false; 1428 switch (eval_mode) { 1429 case CEED_EVAL_INTERP: 1430 good_dims = ((t_mode == CEED_TRANSPOSE && (u_length >= num_points * num_q_comp || v_length >= num_nodes * num_comp)) || 1431 (t_mode == CEED_NOTRANSPOSE && (v_length >= num_points * num_q_comp || u_length >= num_nodes * num_comp))); 1432 break; 1433 case CEED_EVAL_GRAD: 1434 case CEED_EVAL_NONE: 1435 case CEED_EVAL_WEIGHT: 1436 case CEED_EVAL_DIV: 1437 case CEED_EVAL_CURL: 1438 // LCOV_EXCL_START 1439 return CeedError(basis->ceed, CEED_ERROR_UNSUPPORTED, "Evaluation at arbitrary points not supported for %s", CeedEvalModes[eval_mode]); 1440 // LCOV_EXCL_STOP 1441 } 1442 CeedCheck(good_dims, basis->ceed, CEED_ERROR_DIMENSION, "Input/output vectors too short for basis and evaluation mode"); 1443 1444 // Backend method 1445 if (basis->ApplyAtPoints) { 1446 CeedCall(basis->ApplyAtPoints(basis, num_points, t_mode, eval_mode, x_ref, u, v)); 1447 return CEED_ERROR_SUCCESS; 1448 } 1449 1450 // Default implementation 1451 CeedCheck(basis->is_tensor_basis, basis->ceed, CEED_ERROR_UNSUPPORTED, "Evaluation at arbitrary points only supported for tensor product bases"); 1452 if (!basis->basis_chebyshev) { 1453 // Build matrix mapping from quadrature point values to Chebyshev coefficients 1454 CeedScalar *tau, *C, *I, *chebyshev_coeffs_1d; 1455 const CeedScalar *q_ref_1d; 1456 1457 // Build coefficient matrix 1458 // -- Note: Clang-tidy needs this check because it does not understand the is_tensor_basis check above 1459 CeedCheck(P_1d > 0 && Q_1d > 0, basis->ceed, CEED_ERROR_INCOMPATIBLE, "Basis dimensions are malformed"); 1460 CeedCall(CeedCalloc(Q_1d * Q_1d, &C)); 1461 CeedCall(CeedBasisGetQRef(basis, &q_ref_1d)); 1462 for (CeedInt i = 0; i < Q_1d; i++) { 1463 const CeedScalar x = q_ref_1d[i]; 1464 1465 C[i * Q_1d + 0] = 1.0; 1466 C[i * Q_1d + 1] = 2 * x; 1467 for (CeedInt j = 2; j < Q_1d; j++) C[i * Q_1d + j] = 2 * x * C[i * Q_1d + j - 1] - C[i * Q_1d + j - 2]; 1468 } 1469 1470 // Inverse of coefficient matrix 1471 CeedCall(CeedCalloc(Q_1d * Q_1d, &chebyshev_coeffs_1d)); 1472 CeedCall(CeedCalloc(Q_1d * Q_1d, &I)); 1473 CeedCall(CeedCalloc(Q_1d, &tau)); 1474 // -- QR Factorization, C = Q R 1475 CeedCall(CeedQRFactorization(basis->ceed, C, tau, Q_1d, Q_1d)); 1476 // -- chebyshev_coeffs_1d = R_inv Q^T 1477 for (CeedInt i = 0; i < Q_1d; i++) I[i * Q_1d + i] = 1.0; 1478 // ---- Apply R_inv, chebyshev_coeffs_1d = I R_inv 1479 for (CeedInt i = 0; i < Q_1d; i++) { // Row i 1480 chebyshev_coeffs_1d[Q_1d * i] = I[Q_1d * i] / C[0]; 1481 for (CeedInt j = 1; j < Q_1d; j++) { // Column j 1482 chebyshev_coeffs_1d[j + Q_1d * i] = I[j + Q_1d * i]; 1483 for (CeedInt k = 0; k < j; k++) chebyshev_coeffs_1d[j + Q_1d * i] -= C[j + Q_1d * k] * chebyshev_coeffs_1d[k + Q_1d * i]; 1484 chebyshev_coeffs_1d[j + Q_1d * i] /= C[j + Q_1d * j]; 1485 } 1486 } 1487 // ---- Apply Q^T, chebyshev_coeffs_1d = R_inv Q^T 1488 CeedCall(CeedHouseholderApplyQ(chebyshev_coeffs_1d, C, tau, CEED_NOTRANSPOSE, Q_1d, Q_1d, Q_1d, 1, Q_1d)); 1489 1490 // Build basis mapping from nodes to Chebyshev coefficients 1491 CeedScalar *chebyshev_interp_1d, *chebyshev_grad_1d, *chebyshev_q_weight_1d; 1492 const CeedScalar *interp_1d; 1493 1494 CeedCall(CeedCalloc(Q_1d * Q_1d, &chebyshev_interp_1d)); 1495 CeedCall(CeedCalloc(Q_1d * Q_1d, &chebyshev_grad_1d)); 1496 CeedCall(CeedCalloc(Q_1d, &chebyshev_q_weight_1d)); 1497 CeedCall(CeedBasisGetInterp1D(basis, &interp_1d)); 1498 CeedCall(CeedMatrixMatrixMultiply(basis->ceed, chebyshev_coeffs_1d, interp_1d, chebyshev_interp_1d, Q_1d, P_1d, Q_1d)); 1499 1500 CeedCall(CeedVectorCreate(basis->ceed, num_comp * CeedIntPow(Q_1d, dim), &basis->vec_chebyshev)); 1501 CeedCall(CeedBasisCreateTensorH1(basis->ceed, dim, num_comp, Q_1d, Q_1d, chebyshev_interp_1d, chebyshev_grad_1d, q_ref_1d, chebyshev_q_weight_1d, 1502 &basis->basis_chebyshev)); 1503 1504 // Cleanup 1505 CeedCall(CeedFree(&C)); 1506 CeedCall(CeedFree(&chebyshev_coeffs_1d)); 1507 CeedCall(CeedFree(&I)); 1508 CeedCall(CeedFree(&tau)); 1509 CeedCall(CeedFree(&chebyshev_interp_1d)); 1510 CeedCall(CeedFree(&chebyshev_grad_1d)); 1511 CeedCall(CeedFree(&chebyshev_q_weight_1d)); 1512 } 1513 1514 // Create TensorContract object if needed, such as a basis from the GPU backends 1515 if (!basis->contract) { 1516 Ceed ceed_ref; 1517 CeedBasis basis_ref; 1518 1519 CeedCall(CeedInit("/cpu/self", &ceed_ref)); 1520 // Only need matching tensor contraction dimensions, any type of basis will work 1521 CeedCall(CeedBasisCreateTensorH1Lagrange(ceed_ref, dim, num_comp, Q_1d, Q_1d, CEED_GAUSS, &basis_ref)); 1522 CeedCall(CeedTensorContractReference(basis_ref->contract)); 1523 basis->contract = basis_ref->contract; 1524 CeedCall(CeedBasisDestroy(&basis_ref)); 1525 CeedCall(CeedDestroy(&ceed_ref)); 1526 } 1527 1528 // Basis evaluation 1529 switch (t_mode) { 1530 case CEED_NOTRANSPOSE: { 1531 // Nodes to arbitrary points 1532 CeedScalar *v_array; 1533 const CeedScalar *chebyshev_coeffs, *x_array_read; 1534 1535 // -- Interpolate to Chebyshev coefficients 1536 CeedCall(CeedBasisApply(basis->basis_chebyshev, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, u, basis->vec_chebyshev)); 1537 1538 // -- Evaluate Chebyshev polynomials at arbitrary points 1539 CeedCall(CeedVectorGetArrayRead(basis->vec_chebyshev, CEED_MEM_HOST, &chebyshev_coeffs)); 1540 CeedCall(CeedVectorGetArrayRead(x_ref, CEED_MEM_HOST, &x_array_read)); 1541 CeedCall(CeedVectorGetArrayWrite(v, CEED_MEM_HOST, &v_array)); 1542 { 1543 CeedScalar tmp[2][num_comp * CeedIntPow(Q_1d, dim)], chebyshev_x[Q_1d]; 1544 1545 // ---- Values at point 1546 for (CeedInt p = 0; p < num_points; p++) { 1547 CeedInt pre = num_comp * CeedIntPow(Q_1d, dim - 1), post = 1; 1548 1549 for (CeedInt d = dim - 1; d >= 0; d--) { 1550 // ------ Compute Chebyshev polynomial values 1551 { 1552 const CeedScalar x = x_array_read[p * dim + d]; 1553 1554 chebyshev_x[0] = 1.0; 1555 chebyshev_x[1] = 2 * x; 1556 for (CeedInt j = 2; j < Q_1d; j++) chebyshev_x[j] = 2 * x * chebyshev_x[j - 1] - chebyshev_x[j - 2]; 1557 } 1558 // ------ Tensor contract 1559 CeedCall(CeedTensorContractApply(basis->contract, pre, Q_1d, post, 1, chebyshev_x, t_mode, false, 1560 d == (dim - 1) ? chebyshev_coeffs : tmp[d % 2], d == 0 ? &v_array[p * num_comp] : tmp[(d + 1) % 2])); 1561 pre /= Q_1d; 1562 post *= 1; 1563 } 1564 } 1565 } 1566 CeedCall(CeedVectorRestoreArrayRead(basis->vec_chebyshev, &chebyshev_coeffs)); 1567 CeedCall(CeedVectorRestoreArrayRead(x_ref, &x_array_read)); 1568 CeedCall(CeedVectorRestoreArray(v, &v_array)); 1569 break; 1570 } 1571 case CEED_TRANSPOSE: 1572 return CeedError(basis->ceed, CEED_ERROR_UNSUPPORTED, "CEED_TRANSPOSE unsupported for arbitrary basis point evaluation"); 1573 } 1574 1575 return CEED_ERROR_SUCCESS; 1576} 1577 1578/** |
|
| 1390 @brief Get Ceed associated with a CeedBasis 1391 1392 @param[in] basis CeedBasis 1393 @param[out] ceed Variable to store Ceed 1394 1395 @return An error code: 0 - success, otherwise - failure 1396 1397 @ref Advanced --- 292 unchanged lines hidden (view full) --- 1690 CeedCall(CeedFree(&(*basis)->q_ref_1d)); 1691 CeedCall(CeedFree(&(*basis)->q_weight_1d)); 1692 CeedCall(CeedFree(&(*basis)->interp)); 1693 CeedCall(CeedFree(&(*basis)->interp_1d)); 1694 CeedCall(CeedFree(&(*basis)->grad)); 1695 CeedCall(CeedFree(&(*basis)->grad_1d)); 1696 CeedCall(CeedFree(&(*basis)->div)); 1697 CeedCall(CeedFree(&(*basis)->curl)); | 1579 @brief Get Ceed associated with a CeedBasis 1580 1581 @param[in] basis CeedBasis 1582 @param[out] ceed Variable to store Ceed 1583 1584 @return An error code: 0 - success, otherwise - failure 1585 1586 @ref Advanced --- 292 unchanged lines hidden (view full) --- 1879 CeedCall(CeedFree(&(*basis)->q_ref_1d)); 1880 CeedCall(CeedFree(&(*basis)->q_weight_1d)); 1881 CeedCall(CeedFree(&(*basis)->interp)); 1882 CeedCall(CeedFree(&(*basis)->interp_1d)); 1883 CeedCall(CeedFree(&(*basis)->grad)); 1884 CeedCall(CeedFree(&(*basis)->grad_1d)); 1885 CeedCall(CeedFree(&(*basis)->div)); 1886 CeedCall(CeedFree(&(*basis)->curl)); |
| 1887 CeedCall(CeedVectorDestroy(&(*basis)->vec_chebyshev)); 1888 CeedCall(CeedBasisDestroy(&(*basis)->basis_chebyshev)); |
|
| 1698 CeedCall(CeedDestroy(&(*basis)->ceed)); 1699 CeedCall(CeedFree(basis)); 1700 return CEED_ERROR_SUCCESS; 1701} 1702 1703/** 1704 @brief Construct a Gauss-Legendre quadrature 1705 --- 116 unchanged lines hidden --- | 1889 CeedCall(CeedDestroy(&(*basis)->ceed)); 1890 CeedCall(CeedFree(basis)); 1891 return CEED_ERROR_SUCCESS; 1892} 1893 1894/** 1895 @brief Construct a Gauss-Legendre quadrature 1896 --- 116 unchanged lines hidden --- |