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 "ceed-ref.h" 18 19 //------------------------------------------------------------------------------ 20 // Setup Input/Output Fields 21 //------------------------------------------------------------------------------ 22 static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 23 bool inOrOut, 24 CeedVector *fullevecs, CeedVector *evecs, 25 CeedVector *qvecs, CeedInt starte, 26 CeedInt numfields, CeedInt Q) { 27 CeedInt dim, ierr, size, P; 28 Ceed ceed; 29 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 30 CeedBasis basis; 31 CeedElemRestriction Erestrict; 32 CeedOperatorField *opfields; 33 CeedQFunctionField *qffields; 34 if (inOrOut) { 35 ierr = CeedOperatorGetFields(op, NULL, &opfields); CeedChk(ierr); 36 ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChk(ierr); 37 } else { 38 ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChk(ierr); 39 ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); 40 } 41 42 // Loop over fields 43 for (CeedInt i=0; i<numfields; i++) { 44 CeedEvalMode emode; 45 ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChk(ierr); 46 47 if (emode != CEED_EVAL_WEIGHT) { 48 ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict); 49 CeedChk(ierr); 50 ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 51 &fullevecs[i+starte]); 52 CeedChk(ierr); 53 } 54 55 switch(emode) { 56 case CEED_EVAL_NONE: 57 ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChk(ierr); 58 ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChk(ierr); 59 break; 60 case CEED_EVAL_INTERP: 61 ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChk(ierr); 62 ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 63 CeedChk(ierr); 64 ierr = CeedVectorCreate(ceed, P*size, &evecs[i]); CeedChk(ierr); 65 ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChk(ierr); 66 break; 67 case CEED_EVAL_GRAD: 68 ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 69 ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChk(ierr); 70 ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 71 ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 72 CeedChk(ierr); 73 ierr = CeedVectorCreate(ceed, P*size/dim, &evecs[i]); CeedChk(ierr); 74 ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChk(ierr); 75 break; 76 case CEED_EVAL_WEIGHT: // Only on input fields 77 ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 78 ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 79 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 80 CEED_VECTOR_NONE, qvecs[i]); CeedChk(ierr); 81 break; 82 case CEED_EVAL_DIV: 83 break; // Not implemented 84 case CEED_EVAL_CURL: 85 break; // Not implemented 86 } 87 } 88 return 0; 89 } 90 91 //------------------------------------------------------------------------------ 92 // Setup Operator 93 //------------------------------------------------------------------------------/* 94 static int CeedOperatorSetup_Ref(CeedOperator op) { 95 int ierr; 96 bool setupdone; 97 ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 98 if (setupdone) return 0; 99 Ceed ceed; 100 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 101 CeedOperator_Ref *impl; 102 ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 103 CeedQFunction qf; 104 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 105 CeedInt Q, numinputfields, numoutputfields; 106 ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 107 ierr = CeedQFunctionGetIdentityStatus(qf, &impl->identityqf); CeedChk(ierr); 108 ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 109 CeedChk(ierr); 110 CeedOperatorField *opinputfields, *opoutputfields; 111 ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 112 CeedChk(ierr); 113 CeedQFunctionField *qfinputfields, *qfoutputfields; 114 ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 115 CeedChk(ierr); 116 117 // Allocate 118 ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 119 CeedChk(ierr); 120 ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 121 CeedChk(ierr); 122 123 ierr = CeedCalloc(16, &impl->inputstate); CeedChk(ierr); 124 ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); 125 ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); 126 ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 127 ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 128 129 impl->numein = numinputfields; impl->numeout = numoutputfields; 130 131 // Set up infield and outfield evecs and qvecs 132 // Infields 133 ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 134 impl->evecsin, impl->qvecsin, 0, 135 numinputfields, Q); 136 CeedChk(ierr); 137 // Outfields 138 ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 139 impl->evecsout, impl->qvecsout, 140 numinputfields, numoutputfields, Q); 141 CeedChk(ierr); 142 143 // Identity QFunctions 144 if (impl->identityqf) { 145 CeedEvalMode inmode, outmode; 146 CeedQFunctionField *infields, *outfields; 147 ierr = CeedQFunctionGetFields(qf, &infields, &outfields); CeedChk(ierr); 148 149 for (CeedInt i=0; i<numinputfields; i++) { 150 ierr = CeedQFunctionFieldGetEvalMode(infields[i], &inmode); 151 CeedChk(ierr); 152 ierr = CeedQFunctionFieldGetEvalMode(outfields[i], &outmode); 153 CeedChk(ierr); 154 155 ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); 156 impl->qvecsout[i] = impl->qvecsin[i]; 157 ierr = CeedVectorAddReference(impl->qvecsin[i]); CeedChk(ierr); 158 } 159 } 160 161 ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 162 163 return 0; 164 } 165 166 //------------------------------------------------------------------------------ 167 // Setup Operator Inputs 168 //------------------------------------------------------------------------------ 169 static inline int CeedOperatorSetupInputs_Ref(CeedInt numinputfields, 170 CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 171 CeedVector invec, const bool skipactive, CeedOperator_Ref *impl, 172 CeedRequest *request) { 173 CeedInt ierr; 174 CeedEvalMode emode; 175 CeedVector vec; 176 CeedElemRestriction Erestrict; 177 CeedTransposeMode lmode; 178 uint64_t state; 179 180 for (CeedInt i=0; i<numinputfields; i++) { 181 // Get input vector 182 ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 183 if (vec == CEED_VECTOR_ACTIVE) { 184 if (skipactive) 185 continue; 186 else 187 vec = invec; 188 } 189 190 ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 191 CeedChk(ierr); 192 // Restrict and Evec 193 if (emode == CEED_EVAL_WEIGHT) { // Skip 194 } else { 195 // Restrict 196 ierr = CeedVectorGetState(vec, &state); CeedChk(ierr); 197 // Skip restriction if input is unchanged 198 if (state != impl->inputstate[i] || vec == invec) { 199 ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 200 CeedChk(ierr); 201 ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); 202 CeedChk(ierr); 203 ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 204 lmode, vec, impl->evecs[i], 205 request); CeedChk(ierr); 206 impl->inputstate[i] = state; 207 } 208 // Get evec 209 ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 210 (const CeedScalar **) &impl->edata[i]); 211 CeedChk(ierr); 212 } 213 } 214 return 0; 215 } 216 217 //------------------------------------------------------------------------------ 218 // Input Basis Action 219 //------------------------------------------------------------------------------ 220 static inline int CeedOperatorInputBasis_Ref(CeedInt e, CeedInt Q, 221 CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 222 CeedInt numinputfields, const bool skipactive, CeedOperator_Ref *impl) { 223 CeedInt ierr; 224 CeedInt dim, elemsize, size; 225 CeedElemRestriction Erestrict; 226 CeedEvalMode emode; 227 CeedBasis basis; 228 229 for (CeedInt i=0; i<numinputfields; i++) { 230 // Skip active input 231 if (skipactive) { 232 CeedVector vec; 233 ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 234 if (vec == CEED_VECTOR_ACTIVE) 235 continue; 236 } 237 // Get elemsize, emode, size 238 ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 239 CeedChk(ierr); 240 ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 241 CeedChk(ierr); 242 ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 243 CeedChk(ierr); 244 ierr = CeedQFunctionFieldGetSize(qfinputfields[i], &size); CeedChk(ierr); 245 // Basis action 246 switch(emode) { 247 case CEED_EVAL_NONE: 248 ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 249 CEED_USE_POINTER, 250 &impl->edata[i][e*Q*size]); CeedChk(ierr); 251 break; 252 case CEED_EVAL_INTERP: 253 ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 254 ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 255 CEED_USE_POINTER, 256 &impl->edata[i][e*elemsize*size]); 257 CeedChk(ierr); 258 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 259 CEED_EVAL_INTERP, impl->evecsin[i], 260 impl->qvecsin[i]); CeedChk(ierr); 261 break; 262 case CEED_EVAL_GRAD: 263 ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 264 ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 265 ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 266 CEED_USE_POINTER, 267 &impl->edata[i][e*elemsize*size/dim]); 268 CeedChk(ierr); 269 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 270 CEED_EVAL_GRAD, impl->evecsin[i], 271 impl->qvecsin[i]); CeedChk(ierr); 272 break; 273 case CEED_EVAL_WEIGHT: 274 break; // No action 275 case CEED_EVAL_DIV: 276 case CEED_EVAL_CURL: { 277 // LCOV_EXCL_START 278 ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); 279 CeedChk(ierr); 280 Ceed ceed; 281 ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 282 return CeedError(ceed, 1, "Ceed evaluation mode not implemented"); 283 // LCOV_EXCL_STOP 284 break; // Not implemented 285 } 286 } 287 } 288 return 0; 289 } 290 291 //------------------------------------------------------------------------------ 292 // Output Basis Action 293 //------------------------------------------------------------------------------ 294 static inline int CeedOperatorOutputBasis_Ref(CeedInt e, CeedInt Q, 295 CeedQFunctionField *qfoutputfields, CeedOperatorField *opoutputfields, 296 CeedInt numinputfields, CeedInt numoutputfields, CeedOperator op, 297 CeedOperator_Ref *impl) { 298 CeedInt ierr; 299 CeedInt dim, elemsize, size; 300 CeedElemRestriction Erestrict; 301 CeedEvalMode emode; 302 CeedBasis basis; 303 304 for (CeedInt i=0; i<numoutputfields; i++) { 305 // Get elemsize, emode, size 306 ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 307 CeedChk(ierr); 308 ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 309 CeedChk(ierr); 310 ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 311 CeedChk(ierr); 312 ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); CeedChk(ierr); 313 // Basis action 314 switch(emode) { 315 case CEED_EVAL_NONE: 316 break; // No action 317 case CEED_EVAL_INTERP: 318 ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 319 CeedChk(ierr); 320 ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 321 CEED_USE_POINTER, 322 &impl->edata[i + numinputfields][e*elemsize*size]); 323 CeedChk(ierr); 324 ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 325 CEED_EVAL_INTERP, impl->qvecsout[i], 326 impl->evecsout[i]); CeedChk(ierr); 327 break; 328 case CEED_EVAL_GRAD: 329 ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 330 CeedChk(ierr); 331 ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 332 ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 333 CEED_USE_POINTER, 334 &impl->edata[i + numinputfields][e*elemsize*size/dim]); 335 CeedChk(ierr); 336 ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 337 CEED_EVAL_GRAD, impl->qvecsout[i], 338 impl->evecsout[i]); CeedChk(ierr); 339 break; 340 case CEED_EVAL_WEIGHT: { 341 // LCOV_EXCL_START 342 Ceed ceed; 343 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 344 return CeedError(ceed, 1, "CEED_EVAL_WEIGHT cannot be an output " 345 "evaluation mode"); 346 // LCOV_EXCL_STOP 347 break; // Should not occur 348 } 349 case CEED_EVAL_DIV: 350 case CEED_EVAL_CURL: { 351 // LCOV_EXCL_START 352 Ceed ceed; 353 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 354 return CeedError(ceed, 1, "Ceed evaluation mode not implemented"); 355 // LCOV_EXCL_STOP 356 break; // Not implemented 357 } 358 } 359 } 360 return 0; 361 } 362 363 //------------------------------------------------------------------------------ 364 // Restore Input Vectors 365 //------------------------------------------------------------------------------ 366 static inline int CeedOperatorRestoreInputs_Ref(CeedInt numinputfields, 367 CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 368 const bool skipactive, CeedOperator_Ref *impl) { 369 CeedInt ierr; 370 CeedEvalMode emode; 371 372 for (CeedInt i=0; i<numinputfields; i++) { 373 // Skip active inputs 374 if (skipactive) { 375 CeedVector vec; 376 ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 377 if (vec == CEED_VECTOR_ACTIVE) 378 continue; 379 } 380 // Restore input 381 ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 382 CeedChk(ierr); 383 if (emode == CEED_EVAL_WEIGHT) { // Skip 384 } else { 385 ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 386 (const CeedScalar **) &impl->edata[i]); 387 CeedChk(ierr); 388 } 389 } 390 return 0; 391 } 392 393 //------------------------------------------------------------------------------ 394 // Operator Apply 395 //------------------------------------------------------------------------------ 396 static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 397 CeedVector outvec, CeedRequest *request) { 398 int ierr; 399 CeedOperator_Ref *impl; 400 ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 401 CeedQFunction qf; 402 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 403 CeedInt Q, numelements, numinputfields, numoutputfields, size; 404 ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 405 ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 406 ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 407 CeedChk(ierr); 408 CeedTransposeMode lmode; 409 CeedOperatorField *opinputfields, *opoutputfields; 410 ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 411 CeedChk(ierr); 412 CeedQFunctionField *qfinputfields, *qfoutputfields; 413 ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 414 CeedChk(ierr); 415 CeedEvalMode emode; 416 CeedVector vec; 417 CeedElemRestriction Erestrict; 418 419 // Setup 420 ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 421 422 // Input Evecs and Restriction 423 ierr = CeedOperatorSetupInputs_Ref(numinputfields, qfinputfields, 424 opinputfields, invec, false, impl, 425 request); CeedChk(ierr); 426 427 // Output Evecs 428 for (CeedInt i=0; i<numoutputfields; i++) { 429 ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 430 &impl->edata[i + numinputfields]); CeedChk(ierr); 431 } 432 433 // Loop through elements 434 for (CeedInt e=0; e<numelements; e++) { 435 // Output pointers 436 for (CeedInt i=0; i<numoutputfields; i++) { 437 ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 438 CeedChk(ierr); 439 if (emode == CEED_EVAL_NONE) { 440 ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); 441 CeedChk(ierr); 442 ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 443 CEED_USE_POINTER, 444 &impl->edata[i + numinputfields][e*Q*size]); 445 CeedChk(ierr); 446 } 447 } 448 449 // Input basis apply 450 ierr = CeedOperatorInputBasis_Ref(e, Q, qfinputfields, opinputfields, 451 numinputfields, false, impl); 452 CeedChk(ierr); 453 454 // Q function 455 if (!impl->identityqf) { 456 ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); 457 CeedChk(ierr); 458 } 459 460 // Output basis apply 461 ierr = CeedOperatorOutputBasis_Ref(e, Q, qfoutputfields, opoutputfields, 462 numinputfields, numoutputfields, op, impl); 463 CeedChk(ierr); 464 } 465 466 // Output restriction 467 for (CeedInt i=0; i<numoutputfields; i++) { 468 // Restore evec 469 ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 470 &impl->edata[i + numinputfields]); 471 CeedChk(ierr); 472 // Get output vector 473 ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 474 // Active 475 if (vec == CEED_VECTOR_ACTIVE) 476 vec = outvec; 477 // Restrict 478 ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 479 CeedChk(ierr); 480 ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 481 ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 482 lmode, impl->evecs[i+impl->numein], vec, 483 request); CeedChk(ierr); 484 } 485 486 // Restore input arrays 487 ierr = CeedOperatorRestoreInputs_Ref(numinputfields, qfinputfields, 488 opinputfields, false, impl); 489 CeedChk(ierr); 490 491 return 0; 492 } 493 494 //------------------------------------------------------------------------------ 495 // Assemble Linear QFunction 496 //------------------------------------------------------------------------------ 497 static int CeedOperatorAssembleLinearQFunction_Ref(CeedOperator op, 498 CeedVector *assembled, CeedElemRestriction *rstr, CeedRequest *request) { 499 int ierr; 500 CeedOperator_Ref *impl; 501 ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 502 CeedQFunction qf; 503 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 504 CeedInt Q, numelements, numinputfields, numoutputfields, size; 505 ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 506 ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 507 ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 508 CeedChk(ierr); 509 CeedOperatorField *opinputfields, *opoutputfields; 510 ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 511 CeedChk(ierr); 512 CeedQFunctionField *qfinputfields, *qfoutputfields; 513 ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 514 CeedChk(ierr); 515 CeedVector vec; 516 CeedInt numactivein = 0, numactiveout = 0; 517 CeedVector *activein = NULL; 518 CeedScalar *a, *tmp; 519 Ceed ceed, ceedparent; 520 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 521 ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceedparent); CeedChk(ierr); 522 ceedparent = ceedparent ? ceedparent : ceed; 523 524 // Setup 525 ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 526 527 // Check for identity 528 if (impl->identityqf) 529 // LCOV_EXCL_START 530 return CeedError(ceed, 1, "Assembling identity qfunctions not supported"); 531 // LCOV_EXCL_STOP 532 533 // Input Evecs and Restriction 534 ierr = CeedOperatorSetupInputs_Ref(numinputfields, qfinputfields, 535 opinputfields, NULL, true, impl, request); 536 CeedChk(ierr); 537 538 // Count number of active input fields 539 for (CeedInt i=0; i<numinputfields; i++) { 540 // Get input vector 541 ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 542 // Check if active input 543 if (vec == CEED_VECTOR_ACTIVE) { 544 ierr = CeedQFunctionFieldGetSize(qfinputfields[i], &size); CeedChk(ierr); 545 ierr = CeedVectorSetValue(impl->qvecsin[i], 0.0); CeedChk(ierr); 546 ierr = CeedVectorGetArray(impl->qvecsin[i], CEED_MEM_HOST, &tmp); 547 CeedChk(ierr); 548 ierr = CeedRealloc(numactivein + size, &activein); CeedChk(ierr); 549 for (CeedInt field=0; field<size; field++) { 550 ierr = CeedVectorCreate(ceed, Q, &activein[numactivein+field]); 551 CeedChk(ierr); 552 ierr = CeedVectorSetArray(activein[numactivein+field], CEED_MEM_HOST, 553 CEED_USE_POINTER, &tmp[field*Q]); 554 CeedChk(ierr); 555 } 556 numactivein += size; 557 ierr = CeedVectorRestoreArray(impl->qvecsin[i], &tmp); CeedChk(ierr); 558 } 559 } 560 561 // Count number of active output fields 562 for (CeedInt i=0; i<numoutputfields; i++) { 563 // Get output vector 564 ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 565 // Check if active output 566 if (vec == CEED_VECTOR_ACTIVE) { 567 ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); CeedChk(ierr); 568 numactiveout += size; 569 } 570 } 571 572 // Check sizes 573 if (!numactivein || !numactiveout) 574 // LCOV_EXCL_START 575 return CeedError(ceed, 1, "Cannot assemble QFunction without active inputs " 576 "and outputs"); 577 // LCOV_EXCL_STOP 578 579 // Create output restriction 580 ierr = CeedElemRestrictionCreateIdentity(ceedparent, numelements, Q, 581 numelements*Q, numactivein*numactiveout, rstr); CeedChk(ierr); 582 // Create assembled vector 583 ierr = CeedVectorCreate(ceedparent, numelements*Q*numactivein*numactiveout, 584 assembled); CeedChk(ierr); 585 ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr); 586 ierr = CeedVectorGetArray(*assembled, CEED_MEM_HOST, &a); CeedChk(ierr); 587 588 // Loop through elements 589 for (CeedInt e=0; e<numelements; e++) { 590 // Input basis apply 591 ierr = CeedOperatorInputBasis_Ref(e, Q, qfinputfields, opinputfields, 592 numinputfields, true, impl); 593 CeedChk(ierr); 594 595 // Assemble QFunction 596 for (CeedInt in=0; in<numactivein; in++) { 597 // Set Inputs 598 ierr = CeedVectorSetValue(activein[in], 1.0); CeedChk(ierr); 599 if (numactivein > 1) { 600 ierr = CeedVectorSetValue(activein[(in+numactivein-1)%numactivein], 601 0.0); CeedChk(ierr); 602 } 603 // Set Outputs 604 for (CeedInt out=0; out<numoutputfields; out++) { 605 // Get output vector 606 ierr = CeedOperatorFieldGetVector(opoutputfields[out], &vec); 607 CeedChk(ierr); 608 // Check if active output 609 if (vec == CEED_VECTOR_ACTIVE) { 610 CeedVectorSetArray(impl->qvecsout[out], CEED_MEM_HOST, 611 CEED_USE_POINTER, a); CeedChk(ierr); 612 ierr = CeedQFunctionFieldGetSize(qfoutputfields[out], &size); 613 CeedChk(ierr); 614 a += size*Q; // Advance the pointer by the size of the output 615 } 616 } 617 // Apply QFunction 618 ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); 619 CeedChk(ierr); 620 } 621 } 622 623 // Un-set output Qvecs to prevent accidental overwrite of Assembled 624 for (CeedInt out=0; out<numoutputfields; out++) { 625 // Get output vector 626 ierr = CeedOperatorFieldGetVector(opoutputfields[out], &vec); 627 CeedChk(ierr); 628 // Check if active output 629 if (vec == CEED_VECTOR_ACTIVE) { 630 CeedVectorSetArray(impl->qvecsout[out], CEED_MEM_HOST, CEED_COPY_VALUES, 631 NULL); CeedChk(ierr); 632 } 633 } 634 635 // Restore input arrays 636 ierr = CeedOperatorRestoreInputs_Ref(numinputfields, qfinputfields, 637 opinputfields, true, impl); 638 CeedChk(ierr); 639 640 // Restore output 641 ierr = CeedVectorRestoreArray(*assembled, &a); CeedChk(ierr); 642 643 // Cleanup 644 for (CeedInt i=0; i<numactivein; i++) { 645 ierr = CeedVectorDestroy(&activein[i]); CeedChk(ierr); 646 } 647 ierr = CeedFree(&activein); CeedChk(ierr); 648 649 return 0; 650 } 651 652 //------------------------------------------------------------------------------ 653 // Get Basis Emode Pointer 654 //------------------------------------------------------------------------------ 655 static inline void CeedOperatorGetBasisPointer_Ref(CeedScalar **basisptr, 656 CeedEvalMode emode, CeedScalar *identity, CeedScalar *interp, 657 CeedScalar *grad) { 658 switch (emode) { 659 case CEED_EVAL_NONE: 660 *basisptr = identity; 661 break; 662 case CEED_EVAL_INTERP: 663 *basisptr = interp; 664 break; 665 case CEED_EVAL_GRAD: 666 *basisptr = grad; 667 break; 668 case CEED_EVAL_WEIGHT: 669 case CEED_EVAL_DIV: 670 case CEED_EVAL_CURL: 671 break; // Caught by QF Assembly 672 } 673 } 674 675 //------------------------------------------------------------------------------ 676 // Assemble Linear Diagonal 677 //------------------------------------------------------------------------------ 678 static int CeedOperatorAssembleLinearDiagonal_Ref(CeedOperator op, 679 CeedVector *assembled, CeedRequest *request) { 680 int ierr; 681 682 // Assemble QFunction 683 CeedQFunction qf; 684 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 685 CeedInt numinputfields, numoutputfields; 686 ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 687 CeedChk(ierr); 688 CeedVector assembledqf; 689 CeedElemRestriction rstr; 690 ierr = CeedOperatorAssembleLinearQFunction(op, &assembledqf, &rstr, request); 691 CeedChk(ierr); 692 ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr); 693 694 // Determine active input basis 695 CeedOperatorField *opfields; 696 CeedQFunctionField *qffields; 697 ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChk(ierr); 698 ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); 699 CeedInt numemodein = 0, ncomp, dim = 1; 700 CeedEvalMode *emodein = NULL; 701 CeedBasis basisin = NULL; 702 CeedElemRestriction rstrin = NULL; 703 for (CeedInt i=0; i<numinputfields; i++) { 704 CeedVector vec; 705 ierr = CeedOperatorFieldGetVector(opfields[i], &vec); CeedChk(ierr); 706 if (vec == CEED_VECTOR_ACTIVE) { 707 ierr = CeedOperatorFieldGetBasis(opfields[i], &basisin); 708 CeedChk(ierr); 709 ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr); 710 ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 711 ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &rstrin); 712 CeedChk(ierr); 713 CeedEvalMode emode; 714 ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 715 CeedChk(ierr); 716 switch (emode) { 717 case CEED_EVAL_NONE: 718 case CEED_EVAL_INTERP: 719 ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 720 emodein[numemodein] = emode; 721 numemodein += 1; 722 break; 723 case CEED_EVAL_GRAD: 724 ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 725 for (CeedInt d=0; d<dim; d++) 726 emodein[numemodein+d] = emode; 727 numemodein += dim; 728 break; 729 case CEED_EVAL_WEIGHT: 730 case CEED_EVAL_DIV: 731 case CEED_EVAL_CURL: 732 break; // Caught by QF Assembly 733 } 734 } 735 } 736 737 // Determine active output basis 738 ierr = CeedOperatorGetFields(op, NULL, &opfields); CeedChk(ierr); 739 ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChk(ierr); 740 CeedInt numemodeout = 0; 741 CeedEvalMode *emodeout = NULL; 742 CeedBasis basisout = NULL; 743 CeedElemRestriction rstrout = NULL; 744 CeedTransposeMode lmodeout = CEED_NOTRANSPOSE; 745 for (CeedInt i=0; i<numoutputfields; i++) { 746 CeedVector vec; 747 ierr = CeedOperatorFieldGetVector(opfields[i], &vec); CeedChk(ierr); 748 if (vec == CEED_VECTOR_ACTIVE) { 749 ierr = CeedOperatorFieldGetBasis(opfields[i], &basisout); 750 CeedChk(ierr); 751 ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &rstrout); 752 CeedChk(ierr); 753 ierr = CeedOperatorFieldGetLMode(opfields[i], &lmodeout); 754 CeedChk(ierr); 755 CeedEvalMode emode; 756 ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 757 CeedChk(ierr); 758 switch (emode) { 759 case CEED_EVAL_NONE: 760 case CEED_EVAL_INTERP: 761 ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 762 emodeout[numemodeout] = emode; 763 numemodeout += 1; 764 break; 765 case CEED_EVAL_GRAD: 766 ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 767 for (CeedInt d=0; d<dim; d++) 768 emodeout[numemodeout+d] = emode; 769 numemodeout += dim; 770 break; 771 case CEED_EVAL_WEIGHT: 772 case CEED_EVAL_DIV: 773 case CEED_EVAL_CURL: 774 break; // Caught by QF Assembly 775 } 776 } 777 } 778 779 // Create diagonal vector 780 CeedVector elemdiag; 781 ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag); 782 CeedChk(ierr); 783 784 // Assemble element operator diagonals 785 CeedScalar *elemdiagarray, *assembledqfarray; 786 ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr); 787 ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray); 788 CeedChk(ierr); 789 ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray); 790 CeedChk(ierr); 791 CeedInt nelem, nnodes, nqpts; 792 ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 793 ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr); 794 ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 795 // Basis matrices 796 CeedScalar *identity = NULL, *interpin, *interpout, *gradin, *gradout; 797 bool evalNone = false; 798 for (CeedInt i=0; i<numemodein; i++) 799 evalNone = evalNone || (emodein[i] == CEED_EVAL_NONE); 800 for (CeedInt i=0; i<numemodeout; i++) 801 evalNone = evalNone || (emodeout[i] == CEED_EVAL_NONE); 802 if (evalNone) { 803 ierr = CeedCalloc(nqpts*nnodes, &identity); CeedChk(ierr); 804 for (CeedInt i=0; i<(nnodes<nqpts?nnodes:nqpts); i++) 805 identity[i*nnodes+i] = 1.0; 806 } 807 ierr = CeedBasisGetInterp(basisin, &interpin); CeedChk(ierr); 808 ierr = CeedBasisGetInterp(basisout, &interpout); CeedChk(ierr); 809 ierr = CeedBasisGetGrad(basisin, &gradin); CeedChk(ierr); 810 ierr = CeedBasisGetGrad(basisout, &gradout); CeedChk(ierr); 811 // Compute the diagonal of B^T D B 812 // Each element 813 for (CeedInt e=0; e<nelem; e++) { 814 CeedInt dout = -1; 815 // Each basis eval mode pair 816 for (CeedInt eout=0; eout<numemodeout; eout++) { 817 CeedScalar *bt = NULL; 818 if (emodeout[eout] == CEED_EVAL_GRAD) 819 dout += 1; 820 CeedOperatorGetBasisPointer_Ref(&bt, emodeout[eout], identity, interpout, 821 &gradout[dout*nqpts*nnodes]); 822 CeedInt din = -1; 823 for (CeedInt ein=0; ein<numemodein; ein++) { 824 CeedScalar *b = NULL; 825 if (emodein[ein] == CEED_EVAL_GRAD) 826 din += 1; 827 CeedOperatorGetBasisPointer_Ref(&b, emodein[ein], identity, interpin, 828 &gradin[din*nqpts*nnodes]); 829 // Each component pair 830 for (CeedInt cout=0; cout<ncomp; cout++) 831 for (CeedInt cin=0; cin<ncomp; cin++) 832 // Each qpoint/node pair 833 for (CeedInt q=0; q<nqpts; q++) 834 for (CeedInt n=0; n<nnodes; n++) 835 elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt[q*nnodes+n] * 836 assembledqfarray[((((e*numemodein+ein)*ncomp+cin)* 837 numemodeout+eout)*ncomp+cout)*nqpts+q] * 838 b[q*nnodes+n]; 839 } 840 } 841 } 842 ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr); 843 ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr); 844 845 // Assemble local operator diagonal 846 ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr); 847 ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag, 848 *assembled, request); CeedChk(ierr); 849 850 // Cleanup 851 ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 852 ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr); 853 ierr = CeedFree(&emodein); CeedChk(ierr); 854 ierr = CeedFree(&emodeout); CeedChk(ierr); 855 ierr = CeedFree(&identity); CeedChk(ierr); 856 857 return 0; 858 } 859 860 //------------------------------------------------------------------------------ 861 // Create FDM Element Inverse 862 //------------------------------------------------------------------------------ 863 int CeedOperatorCreateFDMElementInverse_Ref(CeedOperator op, 864 CeedOperator *fdminv, 865 CeedRequest *request) { 866 int ierr; 867 Ceed ceed, ceedparent; 868 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 869 ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceedparent); CeedChk(ierr); 870 ceedparent = ceedparent ? ceedparent : ceed; 871 CeedQFunction qf; 872 ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 873 874 // Determine active input basis 875 bool interp = false, grad = false; 876 CeedBasis basis = NULL; 877 CeedElemRestriction rstr = NULL; 878 CeedOperatorField *opfields; 879 CeedQFunctionField *qffields; 880 ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChk(ierr); 881 ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); 882 CeedInt numinputfields; 883 ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, NULL); CeedChk(ierr); 884 for (CeedInt i=0; i<numinputfields; i++) { 885 CeedVector vec; 886 ierr = CeedOperatorFieldGetVector(opfields[i], &vec); CeedChk(ierr); 887 if (vec == CEED_VECTOR_ACTIVE) { 888 CeedEvalMode emode; 889 ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChk(ierr); 890 interp = interp || emode == CEED_EVAL_INTERP; 891 grad = grad || emode == CEED_EVAL_GRAD; 892 ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 893 ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &rstr); 894 CeedChk(ierr); 895 } 896 } 897 if (!basis) 898 // LCOV_EXCL_START 899 return CeedError(ceed, 1, "No active field set"); 900 // LCOV_EXCL_STOP 901 CeedInt P1d, Q1d, elemsize, nqpts, dim, ncomp = 1, nelem = 1, nnodes = 1; 902 ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChk(ierr); 903 ierr = CeedBasisGetNumNodes(basis, &elemsize); CeedChk(ierr); 904 ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChk(ierr); 905 ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpts); CeedChk(ierr); 906 ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 907 ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChk(ierr); 908 ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChk(ierr); 909 ierr = CeedElemRestrictionGetNumNodes(rstr, &nnodes); CeedChk(ierr); 910 911 // Build and diagonalize 1D Mass and Laplacian 912 bool tensorbasis; 913 ierr = CeedBasisGetTensorStatus(basis, &tensorbasis); CeedChk(ierr); 914 if (!tensorbasis) 915 // LCOV_EXCL_START 916 return CeedError(ceed, 1, "FDMElementInverse only supported for tensor " 917 "bases"); 918 // LCOV_EXCL_STOP 919 CeedScalar *work, *mass, *laplace, *x, *x2, *lambda; 920 ierr = CeedMalloc(Q1d*P1d, &work); CeedChk(ierr); 921 ierr = CeedMalloc(P1d*P1d, &mass); CeedChk(ierr); 922 ierr = CeedMalloc(P1d*P1d, &laplace); CeedChk(ierr); 923 ierr = CeedMalloc(P1d*P1d, &x); CeedChk(ierr); 924 ierr = CeedMalloc(P1d*P1d, &x2); CeedChk(ierr); 925 ierr = CeedMalloc(P1d, &lambda); CeedChk(ierr); 926 // -- Mass 927 CeedScalar *interp1d, *grad1d, *qweight1d; 928 ierr = CeedBasisGetInterp1D(basis, &interp1d); CeedChk(ierr); 929 ierr = CeedBasisGetGrad1D(basis, &grad1d); CeedChk(ierr); 930 ierr = CeedBasisGetQWeights(basis, &qweight1d); CeedChk(ierr); 931 for (CeedInt i=0; i<Q1d; i++) 932 for (CeedInt j=0; j<P1d; j++) 933 work[i+j*Q1d] = interp1d[i*P1d+j]*qweight1d[i]; 934 ierr = CeedMatrixMultiply(ceed, (const CeedScalar *)work, 935 (const CeedScalar *)interp1d, mass, P1d, P1d, Q1d); 936 CeedChk(ierr); 937 // -- Laplacian 938 for (CeedInt i=0; i<Q1d; i++) 939 for (CeedInt j=0; j<P1d; j++) 940 work[i+j*Q1d] = grad1d[i*P1d+j]*qweight1d[i]; 941 ierr = CeedMatrixMultiply(ceed, (const CeedScalar *)work, 942 (const CeedScalar *)grad1d, laplace, P1d, P1d, Q1d); 943 CeedChk(ierr); 944 // -- Diagonalize 945 ierr = CeedSimultaneousDiagonalization(ceed, laplace, mass, x, lambda, P1d); 946 CeedChk(ierr); 947 ierr = CeedFree(&work); CeedChk(ierr); 948 ierr = CeedFree(&mass); CeedChk(ierr); 949 ierr = CeedFree(&laplace); CeedChk(ierr); 950 for (CeedInt i=0; i<P1d; i++) 951 for (CeedInt j=0; j<P1d; j++) 952 x2[i+j*P1d] = x[j+i*P1d]; 953 ierr = CeedFree(&x); CeedChk(ierr); 954 955 // Assemble QFunction 956 CeedVector assembled; 957 CeedElemRestriction rstr_qf; 958 ierr = CeedOperatorAssembleLinearQFunction(op, &assembled, &rstr_qf, 959 request); CeedChk(ierr); 960 ierr = CeedElemRestrictionDestroy(&rstr_qf); CeedChk(ierr); 961 962 // Calculate element averages 963 CeedInt nfields = ((interp?1:0) + (grad?dim:0))*((interp?1:0) + (grad?dim:0)); 964 CeedScalar *elemavg; 965 const CeedScalar *assembledarray, *qweightsarray; 966 CeedVector qweights; 967 ierr = CeedVectorCreate(ceedparent, nqpts, &qweights); CeedChk(ierr); 968 ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 969 CEED_VECTOR_NONE, qweights); CeedChk(ierr); 970 ierr = CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembledarray); 971 CeedChk(ierr); 972 ierr = CeedVectorGetArrayRead(qweights, CEED_MEM_HOST, &qweightsarray); 973 CeedChk(ierr); 974 ierr = CeedCalloc(nelem, &elemavg); CeedChk(ierr); 975 for (CeedInt e=0; e<nelem; e++) { 976 CeedInt count = 0; 977 for (CeedInt q=0; q<nqpts; q++) 978 for (CeedInt i=0; i<ncomp*ncomp*nfields; i++) 979 if (fabs(assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 980 i*nqpts + q]) > CEED_EPSILON) { 981 elemavg[e] += assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 982 i*nqpts + q] / qweightsarray[q]; 983 count++; 984 } 985 if (count) 986 elemavg[e] /= count; 987 } 988 ierr = CeedVectorRestoreArrayRead(assembled, &assembledarray); CeedChk(ierr); 989 ierr = CeedVectorDestroy(&assembled); CeedChk(ierr); 990 ierr = CeedVectorRestoreArrayRead(qweights, &qweightsarray); CeedChk(ierr); 991 ierr = CeedVectorDestroy(&qweights); CeedChk(ierr); 992 993 // Build FDM diagonal 994 CeedVector qdata; 995 CeedScalar *qdataarray; 996 ierr = CeedVectorCreate(ceedparent, nelem*ncomp*nnodes, &qdata); CeedChk(ierr); 997 ierr = CeedVectorSetArray(qdata, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 998 CeedChk(ierr); 999 ierr = CeedVectorGetArray(qdata, CEED_MEM_HOST, &qdataarray); CeedChk(ierr); 1000 for (CeedInt e=0; e<nelem; e++) 1001 for (CeedInt c=0; c<ncomp; c++) 1002 for (CeedInt n=0; n<nnodes; n++) { 1003 if (interp) 1004 qdataarray[(e*ncomp+c)*nnodes+n] = 1; 1005 if (grad) 1006 for (CeedInt d=0; d<dim; d++) { 1007 CeedInt i = (n / CeedIntPow(P1d, d)) % P1d; 1008 qdataarray[(e*ncomp+c)*nnodes+n] += lambda[i]; 1009 } 1010 qdataarray[(e*ncomp+c)*nnodes+n] = 1 / (elemavg[e] * 1011 qdataarray[(e*ncomp+c)*nnodes+n]); 1012 } 1013 ierr = CeedFree(&elemavg); CeedChk(ierr); 1014 ierr = CeedVectorRestoreArray(qdata, &qdataarray); CeedChk(ierr); 1015 1016 // Setup FDM operator 1017 // -- Basis 1018 CeedBasis fdm_basis; 1019 CeedScalar *graddummy, *qrefdummy, *qweightdummy; 1020 ierr = CeedCalloc(P1d*P1d, &graddummy); CeedChk(ierr); 1021 ierr = CeedCalloc(P1d, &qrefdummy); CeedChk(ierr); 1022 ierr = CeedCalloc(P1d, &qweightdummy); CeedChk(ierr); 1023 ierr = CeedBasisCreateTensorH1(ceedparent, dim, ncomp, P1d, P1d, x2, 1024 graddummy, qrefdummy, qweightdummy, 1025 &fdm_basis); CeedChk(ierr); 1026 ierr = CeedFree(&graddummy); CeedChk(ierr); 1027 ierr = CeedFree(&qrefdummy); CeedChk(ierr); 1028 ierr = CeedFree(&qweightdummy); CeedChk(ierr); 1029 ierr = CeedFree(&x2); CeedChk(ierr); 1030 ierr = CeedFree(&lambda); CeedChk(ierr); 1031 1032 // -- Restriction 1033 CeedElemRestriction rstr_i; 1034 ierr = CeedElemRestrictionCreateIdentity(ceedparent, nelem, nnodes, 1035 nnodes*nelem, ncomp, &rstr_i); CeedChk(ierr); 1036 // -- QFunction 1037 CeedQFunction mass_qf; 1038 ierr = CeedQFunctionCreateInteriorByName(ceedparent, "MassApply", &mass_qf); 1039 CeedChk(ierr); 1040 // -- Operator 1041 ierr = CeedOperatorCreate(ceedparent, mass_qf, NULL, NULL, fdminv); 1042 CeedChk(ierr); 1043 CeedOperatorSetField(*fdminv, "u", rstr_i, CEED_NOTRANSPOSE, 1044 fdm_basis, CEED_VECTOR_ACTIVE); CeedChk(ierr); 1045 CeedOperatorSetField(*fdminv, "qdata", rstr_i, CEED_NOTRANSPOSE, 1046 CEED_BASIS_COLLOCATED, qdata); CeedChk(ierr); 1047 CeedOperatorSetField(*fdminv, "v", rstr_i, CEED_NOTRANSPOSE, 1048 fdm_basis, CEED_VECTOR_ACTIVE); CeedChk(ierr); 1049 1050 // Cleanup 1051 ierr = CeedVectorDestroy(&qdata); CeedChk(ierr); 1052 ierr = CeedBasisDestroy(&fdm_basis); CeedChk(ierr); 1053 ierr = CeedElemRestrictionDestroy(&rstr_i); CeedChk(ierr); 1054 ierr = CeedQFunctionDestroy(&mass_qf); CeedChk(ierr); 1055 1056 return 0; 1057 } 1058 1059 //------------------------------------------------------------------------------ 1060 // Operator Destroy 1061 //------------------------------------------------------------------------------ 1062 static int CeedOperatorDestroy_Ref(CeedOperator op) { 1063 int ierr; 1064 CeedOperator_Ref *impl; 1065 ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1066 1067 for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 1068 ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 1069 } 1070 ierr = CeedFree(&impl->evecs); CeedChk(ierr); 1071 ierr = CeedFree(&impl->edata); CeedChk(ierr); 1072 ierr = CeedFree(&impl->inputstate); CeedChk(ierr); 1073 1074 for (CeedInt i=0; i<impl->numein; i++) { 1075 ierr = CeedVectorDestroy(&impl->evecsin[i]); CeedChk(ierr); 1076 ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr); 1077 } 1078 ierr = CeedFree(&impl->evecsin); CeedChk(ierr); 1079 ierr = CeedFree(&impl->qvecsin); CeedChk(ierr); 1080 1081 for (CeedInt i=0; i<impl->numeout; i++) { 1082 ierr = CeedVectorDestroy(&impl->evecsout[i]); CeedChk(ierr); 1083 ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); 1084 } 1085 ierr = CeedFree(&impl->evecsout); CeedChk(ierr); 1086 ierr = CeedFree(&impl->qvecsout); CeedChk(ierr); 1087 1088 ierr = CeedFree(&impl); CeedChk(ierr); 1089 return 0; 1090 } 1091 1092 //------------------------------------------------------------------------------ 1093 // Operator Create 1094 //------------------------------------------------------------------------------ 1095 int CeedOperatorCreate_Ref(CeedOperator op) { 1096 int ierr; 1097 Ceed ceed; 1098 ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 1099 CeedOperator_Ref *impl; 1100 1101 ierr = CeedCalloc(1, &impl); CeedChk(ierr); 1102 ierr = CeedOperatorSetData(op, (void *)&impl); CeedChk(ierr); 1103 1104 ierr = CeedSetBackendFunction(ceed, "Operator", op, "AssembleLinearQFunction", 1105 CeedOperatorAssembleLinearQFunction_Ref); 1106 CeedChk(ierr); 1107 ierr = CeedSetBackendFunction(ceed, "Operator", op, "AssembleLinearDiagonal", 1108 CeedOperatorAssembleLinearDiagonal_Ref); 1109 CeedChk(ierr); 1110 ierr = CeedSetBackendFunction(ceed, "Operator", op, "CreateFDMElementInverse", 1111 CeedOperatorCreateFDMElementInverse_Ref); 1112 CeedChk(ierr); 1113 ierr = CeedSetBackendFunction(ceed, "Operator", op, "ApplyAdd", 1114 CeedOperatorApply_Ref); CeedChk(ierr); 1115 ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 1116 CeedOperatorDestroy_Ref); CeedChk(ierr); 1117 return 0; 1118 } 1119 //------------------------------------------------------------------------------ 1120