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