// Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. // All Rights reserved. See files LICENSE and NOTICE for details. // // This file is part of CEED, a collection of benchmarks, miniapps, software // libraries and APIs for efficient high-order finite element and spectral // element discretizations for exascale applications. For more information and // source code availability see http://github.com/ceed. // // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, // a collaborative effort of two U.S. Department of Energy organizations (Office // of Science and the National Nuclear Security Administration) responsible for // the planning and preparation of a capable exascale ecosystem, including // software, applications, hardware, advanced system engineering and early // testbed platforms, in support of the nation's exascale computing imperative. #include "ceed-ref.h" static int CeedOperatorDestroy_Ref(CeedOperator op) { int ierr; CeedOperator_Ref *impl; ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); for (CeedInt i=0; inumein+impl->numeout; i++) { ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); } ierr = CeedFree(&impl->evecs); CeedChk(ierr); ierr = CeedFree(&impl->edata); CeedChk(ierr); ierr = CeedFree(&impl->inputstate); CeedChk(ierr); for (CeedInt i=0; inumein; i++) { ierr = CeedVectorDestroy(&impl->evecsin[i]); CeedChk(ierr); ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr); } ierr = CeedFree(&impl->evecsin); CeedChk(ierr); ierr = CeedFree(&impl->qvecsin); CeedChk(ierr); for (CeedInt i=0; inumeout; i++) { ierr = CeedVectorDestroy(&impl->evecsout[i]); CeedChk(ierr); ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); } ierr = CeedFree(&impl->evecsout); CeedChk(ierr); ierr = CeedFree(&impl->qvecsout); CeedChk(ierr); ierr = CeedFree(&impl); CeedChk(ierr); return 0; } /* Setup infields or outfields */ static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, bool inOrOut, CeedVector *fullevecs, CeedVector *evecs, CeedVector *qvecs, CeedInt starte, CeedInt numfields, CeedInt Q) { CeedInt dim, ierr, ncomp, P; Ceed ceed; ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); CeedBasis basis; CeedElemRestriction Erestrict; CeedOperatorField *opfields; CeedQFunctionField *qffields; if (inOrOut) { ierr = CeedOperatorGetFields(op, NULL, &opfields); CeedChk(ierr); ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChk(ierr); } else { ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChk(ierr); ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); } // Loop over fields for (CeedInt i=0; ievecs); CeedChk(ierr); ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); CeedChk(ierr); ierr = CeedCalloc(16, &impl->inputstate); CeedChk(ierr); ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); impl->numein = numinputfields; impl->numeout = numoutputfields; // Set up infield and outfield evecs and qvecs // Infields ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, impl->evecsin, impl->qvecsin, 0, numinputfields, Q); CeedChk(ierr); // Outfields ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, impl->evecsout, impl->qvecsout, numinputfields, numoutputfields, Q); CeedChk(ierr); ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); return 0; } static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, CeedVector outvec, CeedRequest *request) { int ierr; CeedOperator_Ref *impl; ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); CeedQFunction qf; ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); CeedChk(ierr); CeedTransposeMode lmode; CeedOperatorField *opinputfields, *opoutputfields; ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); CeedChk(ierr); CeedQFunctionField *qfinputfields, *qfoutputfields; ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); CeedChk(ierr); CeedEvalMode emode; CeedVector vec; CeedBasis basis; CeedElemRestriction Erestrict; uint64_t state; // Setup ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); // Input Evecs and Restriction for (CeedInt i=0; iinputstate[i] || vec == invec) { ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); CeedChk(ierr); ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, lmode, vec, impl->evecs[i], request); CeedChk(ierr); impl->inputstate[i] = state; } // Get evec ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, (const CeedScalar **) &impl->edata[i]); CeedChk(ierr); } } // Output Evecs for (CeedInt i=0; ievecs[i+impl->numein], CEED_MEM_HOST, &impl->edata[i + numinputfields]); CeedChk(ierr); } // Loop through elements for (CeedInt e=0; eqvecsin[i], CEED_MEM_HOST, CEED_USE_POINTER, &impl->edata[i][e*Q*ncomp]); CeedChk(ierr); break; case CEED_EVAL_INTERP: ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, CEED_USE_POINTER, &impl->edata[i][e*elemsize*ncomp]); CeedChk(ierr); ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, impl->evecsin[i], impl->qvecsin[i]); CeedChk(ierr); break; case CEED_EVAL_GRAD: ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, CEED_USE_POINTER, &impl->edata[i][e*elemsize*ncomp]); CeedChk(ierr); ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, impl->evecsin[i], impl->qvecsin[i]); CeedChk(ierr); break; case CEED_EVAL_WEIGHT: break; // No action case CEED_EVAL_DIV: break; // Not implimented case CEED_EVAL_CURL: break; // Not implimented } } // Output pointers for (CeedInt i=0; iqvecsout[i], CEED_MEM_HOST, CEED_USE_POINTER, &impl->edata[i + numinputfields][e*Q*ncomp]); CeedChk(ierr); } } // Q function ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); // Output basis apply if needed for (CeedInt i=0; ievecsout[i], CEED_MEM_HOST, CEED_USE_POINTER, &impl->edata[i + numinputfields][e*elemsize*ncomp]); CeedChk(ierr); ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, CEED_EVAL_INTERP, impl->qvecsout[i], impl->evecsout[i]); CeedChk(ierr); break; case CEED_EVAL_GRAD: ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); CeedChk(ierr); ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, CEED_USE_POINTER, &impl->edata[i + numinputfields][e*elemsize*ncomp]); CeedChk(ierr); ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, CEED_EVAL_GRAD, impl->qvecsout[i], impl->evecsout[i]); CeedChk(ierr); break; case CEED_EVAL_WEIGHT: { Ceed ceed; ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); return CeedError(ceed, 1, "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); break; // Should not occur } case CEED_EVAL_DIV: break; // Not implimented case CEED_EVAL_CURL: break; // Not implimented } } } // Zero lvecs for (CeedInt i=0; iadd) { vec = outvec; ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); } } else { ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); } } impl->add = false; // Output restriction for (CeedInt i=0; ievecs[i+impl->numein], &impl->edata[i + numinputfields]); CeedChk(ierr); // Get output vector ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); // Active if (vec == CEED_VECTOR_ACTIVE) vec = outvec; // Restrict ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); CeedChk(ierr); ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, lmode, impl->evecs[i+impl->numein], vec, request); CeedChk(ierr); } // Restore input arrays for (CeedInt i=0; ievecs[i], (const CeedScalar **) &impl->edata[i]); CeedChk(ierr); } } return 0; } static int CeedCompositeOperatorApply_Ref(CeedOperator op, CeedVector invec, CeedVector outvec, CeedRequest *request) { int ierr; CeedInt numsub; CeedOperator_Ref *impl; CeedOperator *suboperators; ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); // Overwrite outvec with first output ierr = CeedOperatorApply(suboperators[0], invec, outvec, request); CeedChk(ierr); // Add to outvec with subsequent outputs for (CeedInt i=1; iadd = true; ierr = CeedOperatorApply(suboperators[i], invec, outvec, request); CeedChk(ierr); } return 0; } int CeedOperatorCreate_Ref(CeedOperator op) { int ierr; Ceed ceed; ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); CeedOperator_Ref *impl; ierr = CeedCalloc(1, &impl); CeedChk(ierr); impl->add = false; ierr = CeedOperatorSetData(op, (void *)&impl); CeedChk(ierr); ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", CeedOperatorApply_Ref); CeedChk(ierr); ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", CeedOperatorDestroy_Ref); CeedChk(ierr); return 0; } int CeedCompositeOperatorCreate_Ref(CeedOperator op) { int ierr; Ceed ceed; ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", CeedCompositeOperatorApply_Ref); CeedChk(ierr); return 0; }