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