1 // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 2 // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 3 // All Rights reserved. See files LICENSE and NOTICE for details. 4 // 5 // This file is part of CEED, a collection of benchmarks, miniapps, software 6 // libraries and APIs for efficient high-order finite element and spectral 7 // element discretizations for exascale applications. For more information and 8 // source code availability see http://github.com/ceed. 9 // 10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11 // a collaborative effort of two U.S. Department of Energy organizations (Office 12 // of Science and the National Nuclear Security Administration) responsible for 13 // the planning and preparation of a capable exascale ecosystem, including 14 // software, applications, hardware, advanced system engineering and early 15 // testbed platforms, in support of the nation's exascale computing imperative. 16 17 #include <string.h> 18 #include "ceed-ref.h" 19 20 static int CeedOperatorDestroy_Ref(CeedOperator op) { 21 int ierr; 22 CeedOperator_Ref *impl; 23 ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 24 25 for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 26 ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 27 } 28 ierr = CeedFree(&impl->evecs); CeedChk(ierr); 29 ierr = CeedFree(&impl->edata); CeedChk(ierr); 30 31 for (CeedInt i=0; i<impl->numein; i++) { 32 ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr); 33 } 34 ierr = CeedFree(&impl->qvecsin); CeedChk(ierr); 35 36 for (CeedInt i=0; i<impl->numeout; i++) { 37 ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); 38 } 39 ierr = CeedFree(&impl->qvecsout); CeedChk(ierr); 40 41 ierr = CeedFree(&impl); CeedChk(ierr); 42 return 0; 43 } 44 45 /* 46 Setup infields or outfields 47 */ 48 static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 49 bool inOrOut, CeedVector *evecs, 50 CeedVector *qvecs, CeedInt starte, 51 CeedInt numfields, CeedInt Q) { 52 CeedInt dim, ierr, ncomp; 53 Ceed ceed; 54 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 55 CeedBasis basis; 56 CeedElemRestriction Erestrict; 57 CeedOperatorField *opfields; 58 CeedQFunctionField *qffields; 59 if (inOrOut) { 60 ierr = CeedOperatorGetFields(op, NULL, &opfields); 61 CeedChk(ierr); 62 ierr = CeedQFunctionGetFields(qf, NULL, &qffields); 63 CeedChk(ierr); 64 } else { 65 ierr = CeedOperatorGetFields(op, &opfields, NULL); 66 CeedChk(ierr); 67 ierr = CeedQFunctionGetFields(qf, &qffields, NULL); 68 CeedChk(ierr); 69 } 70 71 // Loop over fields 72 for (CeedInt i=0; i<numfields; i++) { 73 CeedEvalMode emode; 74 ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChk(ierr); 75 76 if (emode != CEED_EVAL_WEIGHT) { 77 ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict); 78 CeedChk(ierr); 79 ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 80 &evecs[i+starte]); 81 CeedChk(ierr); 82 } 83 84 switch(emode) { 85 case CEED_EVAL_NONE: 86 ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 87 CeedChk(ierr); 88 ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 89 break; 90 case CEED_EVAL_INTERP: 91 ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 92 CeedChk(ierr); 93 ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 94 break; 95 case CEED_EVAL_GRAD: 96 ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 97 ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 98 ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 99 ierr = CeedVectorCreate(ceed, Q*ncomp*dim, &qvecs[i]); CeedChk(ierr); 100 break; 101 case CEED_EVAL_WEIGHT: // Only on input fields 102 ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 103 ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 104 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 105 NULL, qvecs[i]); CeedChk(ierr); 106 break; 107 case CEED_EVAL_DIV: 108 break; // Not implimented 109 case CEED_EVAL_CURL: 110 break; // Not implimented 111 } 112 } 113 return 0; 114 } 115 116 /* 117 CeedOperator needs to connect all the named fields (be they active or passive) 118 to the named inputs and outputs of its CeedQFunction. 119 */ 120 static int CeedOperatorSetup_Ref(CeedOperator op) { 121 int ierr; 122 bool setupdone; 123 ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 124 if (setupdone) return 0; 125 Ceed ceed; 126 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 127 CeedOperator_Ref *impl; 128 ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 129 CeedQFunction qf; 130 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 131 CeedInt Q, numinputfields, numoutputfields; 132 ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 133 ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 134 CeedChk(ierr); 135 CeedOperatorField *opinputfields, *opoutputfields; 136 ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 137 CeedChk(ierr); 138 CeedQFunctionField *qfinputfields, *qfoutputfields; 139 ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 140 CeedChk(ierr); 141 142 // Allocate 143 ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 144 CeedChk(ierr); 145 ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 146 CeedChk(ierr); 147 148 ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 149 ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 150 151 impl->numein = numinputfields; impl->numeout = numoutputfields; 152 153 // Set up infield and outfield evecs and qvecs 154 // Infields 155 ierr = CeedOperatorSetupFields_Ref(qf, op, 0, 156 impl->evecs, impl->qvecsin, 0, 157 numinputfields, Q); 158 CeedChk(ierr); 159 160 // Outfields 161 ierr = CeedOperatorSetupFields_Ref(qf, op, 1, 162 impl->evecs, impl->qvecsout, 163 numinputfields, numoutputfields, Q); 164 CeedChk(ierr); 165 166 // Temporary Vector 167 ierr = CeedVectorCreate(ceed, 0, &impl->tempvec); CeedChk(ierr); 168 169 ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 170 171 return 0; 172 } 173 174 static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 175 CeedVector outvec, CeedRequest *request) { 176 int ierr; 177 CeedOperator_Ref *impl; 178 ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 179 CeedQFunction qf; 180 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 181 CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 182 ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 183 ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 184 ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 185 CeedChk(ierr); 186 CeedTransposeMode lmode; 187 CeedOperatorField *opinputfields, *opoutputfields; 188 ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 189 CeedChk(ierr); 190 CeedQFunctionField *qfinputfields, *qfoutputfields; 191 ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 192 CeedChk(ierr); 193 CeedEvalMode emode; 194 CeedVector vec; 195 CeedBasis basis; 196 CeedElemRestriction Erestrict; 197 198 // Setup 199 ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 200 201 // Input Evecs and Restriction 202 for (CeedInt i=0; i<numinputfields; i++) { 203 ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 204 CeedChk(ierr); 205 if (emode == CEED_EVAL_WEIGHT) { // Skip 206 } else { 207 // Get input vector 208 ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 209 if (vec == CEED_VECTOR_ACTIVE) 210 vec = invec; 211 // Restrict 212 ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 213 CeedChk(ierr); 214 ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 215 ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 216 lmode, vec, impl->evecs[i], 217 request); CeedChk(ierr); 218 // Get evec 219 ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 220 (const CeedScalar **) &impl->edata[i]); 221 CeedChk(ierr); 222 } 223 } 224 225 // Output Evecs 226 for (CeedInt i=0; i<numoutputfields; i++) { 227 ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 228 &impl->edata[i + numinputfields]); CeedChk(ierr); 229 } 230 231 // Loop through elements 232 for (CeedInt e=0; e<numelements; e++) { 233 // Input basis apply if needed 234 for (CeedInt i=0; i<numinputfields; i++) { 235 // Get elemsize, emode, ncomp 236 ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 237 CeedChk(ierr); 238 ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 239 CeedChk(ierr); 240 ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 241 CeedChk(ierr); 242 ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 243 CeedChk(ierr); 244 // Basis action 245 switch(emode) { 246 case CEED_EVAL_NONE: 247 ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 248 CEED_USE_POINTER, 249 &impl->edata[i][e*Q*ncomp]); CeedChk(ierr); 250 break; 251 case CEED_EVAL_INTERP: 252 ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 253 ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST, 254 CEED_USE_POINTER, 255 &impl->edata[i][e*elemsize*ncomp]); 256 CeedChk(ierr); 257 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 258 CEED_EVAL_INTERP, impl->tempvec, 259 impl->qvecsin[i]); CeedChk(ierr); 260 break; 261 case CEED_EVAL_GRAD: 262 ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 263 ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST, 264 CEED_USE_POINTER, 265 &impl->edata[i][e*elemsize*ncomp]); 266 CeedChk(ierr); 267 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 268 CEED_EVAL_GRAD, impl->tempvec, 269 impl->qvecsin[i]); CeedChk(ierr); 270 break; 271 case CEED_EVAL_WEIGHT: 272 break; // No action 273 case CEED_EVAL_DIV: 274 break; // Not implimented 275 case CEED_EVAL_CURL: 276 break; // Not implimented 277 } 278 } 279 // Output pointers 280 for (CeedInt i=0; i<numoutputfields; i++) { 281 ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 282 CeedChk(ierr); 283 if (emode == CEED_EVAL_NONE) { 284 ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 285 CeedChk(ierr); 286 ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 287 CEED_USE_POINTER, 288 &impl->edata[i + numinputfields][e*Q*ncomp]); 289 CeedChk(ierr); 290 } 291 } 292 // Q function 293 ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); 294 295 // Output basis apply if needed 296 for (CeedInt i=0; i<numoutputfields; i++) { 297 // Get elemsize, emode, ncomp 298 ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 299 CeedChk(ierr); 300 ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 301 CeedChk(ierr); 302 ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 303 CeedChk(ierr); 304 ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 305 CeedChk(ierr); 306 // Basis action 307 switch(emode) { 308 case CEED_EVAL_NONE: 309 break; // No action 310 case CEED_EVAL_INTERP: 311 ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 312 CeedChk(ierr); 313 ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST, 314 CEED_USE_POINTER, 315 &impl->edata[i + numinputfields][e*elemsize*ncomp]); 316 ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 317 CEED_EVAL_INTERP, impl->qvecsout[i], 318 impl->tempvec); CeedChk(ierr); 319 break; 320 case CEED_EVAL_GRAD: 321 ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 322 CeedChk(ierr); 323 ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST, 324 CEED_USE_POINTER, 325 &impl->edata[i + numinputfields][e*elemsize*ncomp]); 326 ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 327 CEED_EVAL_GRAD, impl->qvecsout[i], 328 impl->tempvec); CeedChk(ierr); 329 break; 330 case CEED_EVAL_WEIGHT: { 331 Ceed ceed; 332 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 333 return CeedError(ceed, 1, 334 "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 335 break; // Should not occur 336 } 337 case CEED_EVAL_DIV: 338 break; // Not implimented 339 case CEED_EVAL_CURL: 340 break; // Not implimented 341 } 342 } 343 } 344 345 // Zero lvecs 346 for (CeedInt i=0; i<numoutputfields; i++) { 347 ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 348 if (vec == CEED_VECTOR_ACTIVE) 349 vec = outvec; 350 ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 351 } 352 353 // Output restriction 354 for (CeedInt i=0; i<numoutputfields; i++) { 355 // Restore evec 356 ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 357 &impl->edata[i + numinputfields]); 358 CeedChk(ierr); 359 // Get output vector 360 ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 361 // Active 362 if (vec == CEED_VECTOR_ACTIVE) 363 vec = outvec; 364 // Restrict 365 ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 366 CeedChk(ierr); 367 ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 368 ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 369 lmode, impl->evecs[i+impl->numein], vec, 370 request); CeedChk(ierr); 371 } 372 373 // Restore input arrays 374 for (CeedInt i=0; i<numinputfields; i++) { 375 ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 376 CeedChk(ierr); 377 if (emode == CEED_EVAL_WEIGHT) { // Skip 378 } else { 379 ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 380 (const CeedScalar **) &impl->edata[i]); 381 CeedChk(ierr); 382 } 383 } 384 385 return 0; 386 } 387 388 int CeedOperatorCreate_Ref(CeedOperator op) { 389 int ierr; 390 Ceed ceed; 391 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 392 CeedOperator_Ref *impl; 393 394 ierr = CeedCalloc(1, &impl); CeedChk(ierr); 395 ierr = CeedOperatorSetData(op, (void*)&impl); 396 397 ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 398 CeedOperatorApply_Ref); CeedChk(ierr); 399 ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 400 CeedOperatorDestroy_Ref); CeedChk(ierr); 401 return 0; 402 } 403