@@ -132,7 +132,10 @@ static int CeedOperatorCreateFallback(CeedOperator op) {
132132 }
133133 CeedCall (CeedOperatorSetName (op_fallback , op -> name ));
134134 CeedCall (CeedOperatorCheckReady (op_fallback ));
135- op -> op_fallback = op_fallback ;
135+ // Note: No ref-counting here so we don't get caught in a reference loop.
136+ // The op holds the only reference to op_fallback and is responsible for deleting itself and op_fallback.
137+ op -> op_fallback = op_fallback ;
138+ op_fallback -> op_fallback_parent = op ;
136139
137140 return CEED_ERROR_SUCCESS ;
138141}
@@ -1537,10 +1540,25 @@ int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled,
15371540 @ref User
15381541**/
15391542int CeedOperatorLinearAssembleQFunctionBuildOrUpdate (CeedOperator op , CeedVector * assembled , CeedElemRestriction * rstr , CeedRequest * request ) {
1543+ int (* LinearAssembleQFunctionUpdate )(CeedOperator , CeedVector , CeedElemRestriction , CeedRequest * ) = NULL ;
1544+ CeedOperator op_assemble = NULL ;
1545+
15401546 CeedCall (CeedOperatorCheckReady (op ));
15411547
1542- if (op -> LinearAssembleQFunctionUpdate ) {
1543- // Backend version
1548+ // Determine if fallback parent or operator has implementation
1549+ if (op -> op_fallback_parent && op -> op_fallback_parent -> LinearAssembleQFunctionUpdate ) {
1550+ // -- Backend version for op fallback parent is faster, if it exists
1551+ LinearAssembleQFunctionUpdate = op -> op_fallback_parent -> LinearAssembleQFunctionUpdate ;
1552+ op_assemble = op -> op_fallback_parent ;
1553+ } else if (op -> LinearAssembleQFunctionUpdate ) {
1554+ // -- Backend version for op
1555+ LinearAssembleQFunctionUpdate = op -> LinearAssembleQFunctionUpdate ;
1556+ op_assemble = op ;
1557+ }
1558+
1559+ // Assemble QFunction
1560+ if (LinearAssembleQFunctionUpdate ) {
1561+ // Backend or fallback parent version
15441562 bool qf_assembled_is_setup ;
15451563 CeedVector assembled_vec = NULL ;
15461564 CeedElemRestriction assembled_rstr = NULL ;
@@ -1551,9 +1569,9 @@ int CeedOperatorLinearAssembleQFunctionBuildOrUpdate(CeedOperator op, CeedVector
15511569
15521570 CeedCall (CeedQFunctionAssemblyDataGetObjects (op -> qf_assembled , & assembled_vec , & assembled_rstr ));
15531571 CeedCall (CeedQFunctionAssemblyDataIsUpdateNeeded (op -> qf_assembled , & update_needed ));
1554- if (update_needed ) CeedCall (op -> LinearAssembleQFunctionUpdate (op , assembled_vec , assembled_rstr , request ));
1572+ if (update_needed ) CeedCall (LinearAssembleQFunctionUpdate (op_assemble , assembled_vec , assembled_rstr , request ));
15551573 } else {
1556- CeedCall (op -> LinearAssembleQFunction ( op , & assembled_vec , & assembled_rstr , request ));
1574+ CeedCall (CeedOperatorLinearAssembleQFunction ( op_assemble , & assembled_vec , & assembled_rstr , request ));
15571575 CeedCall (CeedQFunctionAssemblyDataSetObjects (op -> qf_assembled , assembled_vec , assembled_rstr ));
15581576 }
15591577 CeedCall (CeedQFunctionAssemblyDataSetUpdateNeeded (op -> qf_assembled , false));
0 commit comments