1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3ed264d09SValeria Barra // 4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 5ed264d09SValeria Barra // 6*3d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 7ed264d09SValeria Barra 8ed264d09SValeria Barra /// @file 9ed264d09SValeria Barra /// libCEED QFunctions for mass operator example for a vector field on the sphere using PETSc 10ed264d09SValeria Barra 11f6b55d2cSvaleriabarra #ifndef bp4sphere_h 12f6b55d2cSvaleriabarra #define bp4sphere_h 13f6b55d2cSvaleriabarra 14ed264d09SValeria Barra #include <math.h> 15ed264d09SValeria Barra 16e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 17ed264d09SValeria Barra // This QFunction sets up the rhs and true solution for the problem 18ed264d09SValeria Barra // ----------------------------------------------------------------------------- 19ed264d09SValeria Barra CEED_QFUNCTION(SetupDiffRhs3)(void *ctx, const CeedInt Q, 20ed264d09SValeria Barra const CeedScalar *const *in, 21ed264d09SValeria Barra CeedScalar *const *out) { 22ed264d09SValeria Barra // Inputs 239b072555Sjeremylt const CeedScalar *X = in[0], *q_data = in[1]; 24ed264d09SValeria Barra // Outputs 25ed264d09SValeria Barra CeedScalar *true_soln = out[0], *rhs = out[1]; 26ed264d09SValeria Barra 27ed264d09SValeria Barra // Context 28ed264d09SValeria Barra const CeedScalar *context = (const CeedScalar*)ctx; 29ed264d09SValeria Barra const CeedScalar R = context[0]; 30ed264d09SValeria Barra 31ed264d09SValeria Barra // Quadrature Point Loop 32ed264d09SValeria Barra CeedPragmaSIMD 33ed264d09SValeria Barra for (CeedInt i=0; i<Q; i++) { 34ed264d09SValeria Barra // Read global Cartesian coordinates 35ed264d09SValeria Barra CeedScalar x = X[i+Q*0], y = X[i+Q*1], z = X[i+Q*2]; 36ed264d09SValeria Barra // Normalize quadrature point coordinates to sphere 37ed264d09SValeria Barra CeedScalar rad = sqrt(x*x + y*y + z*z); 38ed264d09SValeria Barra x *= R / rad; 39ed264d09SValeria Barra y *= R / rad; 40ed264d09SValeria Barra z *= R / rad; 41ed264d09SValeria Barra // Compute latitude and longitude 42ed264d09SValeria Barra const CeedScalar theta = asin(z / R); // latitude 43ed264d09SValeria Barra const CeedScalar lambda = atan2(y, x); // longitude 44ed264d09SValeria Barra 459b072555Sjeremylt // Use absolute value of latitude for true solution 46ed264d09SValeria Barra // Component 1 47ed264d09SValeria Barra true_soln[i+0*Q] = sin(lambda) * cos(theta); 48ed264d09SValeria Barra // Component 2 49ed264d09SValeria Barra true_soln[i+1*Q] = 2 * true_soln[i+0*Q]; 50ed264d09SValeria Barra // Component 3 51ed264d09SValeria Barra true_soln[i+2*Q] = 3 * true_soln[i+0*Q]; 52ed264d09SValeria Barra 53ed264d09SValeria Barra // Component 1 549b072555Sjeremylt rhs[i+0*Q] = q_data[i+Q*0] * 2 * sin(lambda)*cos(theta) / (R*R); 55ed264d09SValeria Barra // Component 2 56ed264d09SValeria Barra rhs[i+1*Q] = 2 * rhs[i+0*Q]; 57ed264d09SValeria Barra // Component 3 58ed264d09SValeria Barra rhs[i+2*Q] = 3 * rhs[i+0*Q]; 59ed264d09SValeria Barra } // End of Quadrature Point Loop 60ed264d09SValeria Barra 61ed264d09SValeria Barra return 0; 62ed264d09SValeria Barra } 63ed264d09SValeria Barra 64e83e87a5Sjeremylt // ----------------------------------------------------------------------------- 65ed264d09SValeria Barra // This QFunction applies the diffusion operator for a vector field of 3 components. 66ed264d09SValeria Barra // 67ed264d09SValeria Barra // Inputs: 68ed264d09SValeria Barra // ug - Input vector Jacobian at quadrature points 699b072555Sjeremylt // q_data - Geometric factors 70ed264d09SValeria Barra // 71ed264d09SValeria Barra // Output: 72ed264d09SValeria Barra // vJ - Output vector (test functions) Jacobian at quadrature points 73ed264d09SValeria Barra // 74ed264d09SValeria Barra // ----------------------------------------------------------------------------- 75ed264d09SValeria Barra CEED_QFUNCTION(Diff3)(void *ctx, const CeedInt Q, 76ed264d09SValeria Barra const CeedScalar *const *in, CeedScalar *const *out) { 779b072555Sjeremylt const CeedScalar *ug = in[0], *q_data = in[1]; 78ed264d09SValeria Barra CeedScalar *vJ = out[0]; 79ed264d09SValeria Barra 80ed264d09SValeria Barra // Quadrature Point Loop 81ed264d09SValeria Barra CeedPragmaSIMD 82ed264d09SValeria Barra for (CeedInt i=0; i<Q; i++) { 83ed264d09SValeria Barra // Read spatial derivatives of u 84ed264d09SValeria Barra const CeedScalar uJ[3][2] = {{ug[i+(0+0*3)*Q], 85ed264d09SValeria Barra ug[i+(0+1*3)*Q]}, 86ed264d09SValeria Barra {ug[i+(1+0*3)*Q], 87ed264d09SValeria Barra ug[i+(1+1*3)*Q]}, 88ed264d09SValeria Barra {ug[i+(2+0*3)*Q], 89ed264d09SValeria Barra ug[i+(2+1*3)*Q]} 90ed264d09SValeria Barra }; 919b072555Sjeremylt // Read q_data 929b072555Sjeremylt const CeedScalar w_det_J = q_data[i+Q*0]; 939b072555Sjeremylt // -- Grad-to-Grad q_data 94ed264d09SValeria Barra // ---- dXdx_j,k * dXdx_k,j 959b072555Sjeremylt const CeedScalar dXdxdXdx_T[2][2] = {{q_data[i+Q*1], 969b072555Sjeremylt q_data[i+Q*3]}, 979b072555Sjeremylt {q_data[i+Q*3], 989b072555Sjeremylt q_data[i+Q*2]} 99ed264d09SValeria Barra }; 100ed264d09SValeria Barra 101ed264d09SValeria Barra for (int k=0; k<3; k++) // k = component 102ed264d09SValeria Barra for (int j=0; j<2; j++) // j = direction of vg 1039b072555Sjeremylt vJ[i+(k+j*3)*Q] = w_det_J * (uJ[k][0] * dXdxdXdx_T[0][j] + 1049b072555Sjeremylt uJ[k][1] * dXdxdXdx_T[1][j]); 105ed264d09SValeria Barra 106ed264d09SValeria Barra } // End of Quadrature Point Loop 107ed264d09SValeria Barra 108ed264d09SValeria Barra return 0; 109ed264d09SValeria Barra } 110ed264d09SValeria Barra // ----------------------------------------------------------------------------- 111f6b55d2cSvaleriabarra 112f6b55d2cSvaleriabarra #endif // bp4sphere_h 113