@@ -1551,6 +1551,262 @@ static int CeedOperatorLinearAssembleAddDiagonalAtPoints_Ref(CeedOperator op, Ce
15511551 CeedCallBackend (CeedQFunctionDestroy (& qf ));
15521552 return CEED_ERROR_SUCCESS ;
15531553}
1554+ }
1555+
1556+ //------------------------------------------------------------------------------
1557+ // Assemble Operator AtPoints
1558+ //------------------------------------------------------------------------------
1559+ static int CeedSingleOperatorLinearAssembl_Ref (CeedOperator op , CeedInt offset , CeedVector values ) {
1560+ CeedInt num_points_offset = 0 , num_input_fields , num_output_fields , num_elem , num_comp_active = 1 ;
1561+ CeedScalar * e_data [2 * CEED_FIELD_MAX ] = {0 }, * assembled ;
1562+ Ceed ceed ;
1563+ CeedVector point_coords = NULL , in_vec , out_vec ;
1564+ CeedElemRestriction rstr_points = NULL ;
1565+ CeedQFunctionField * qf_input_fields , * qf_output_fields ;
1566+ CeedQFunction qf ;
1567+ CeedOperatorField * op_input_fields , * op_output_fields ;
1568+ CeedOperator_Ref * impl ;
1569+
1570+ CeedCallBackend (CeedOperatorGetData (op , & impl ));
1571+ CeedCallBackend (CeedOperatorGetNumElements (op , & num_elem ));
1572+ CeedCallBackend (CeedOperatorGetQFunction (op , & qf ));
1573+ CeedCallBackend (CeedOperatorGetFields (op , & num_input_fields , & op_input_fields , & num_output_fields , & op_output_fields ));
1574+ CeedCallBackend (CeedQFunctionGetFields (qf , NULL , & qf_input_fields , NULL , & qf_output_fields ));
1575+
1576+ // Setup
1577+ CeedCallBackend (CeedOperatorSetupAtPoints_Ref (op ));
1578+
1579+ // Ceed
1580+ {
1581+ Ceed ceed_parent ;
1582+
1583+ CeedCallBackend (CeedOperatorGetCeed (op , & ceed ));
1584+ CeedCallBackend (CeedGetParent (ceed , & ceed_parent ));
1585+ CeedCallBackend (CeedReferenceCopy (ceed_parent , & ceed ));
1586+ CeedCallBackend (CeedDestroy (& ceed_parent ));
1587+ }
1588+
1589+ // Point coordinates
1590+ CeedCallBackend (CeedOperatorAtPointsGetPoints (op , & rstr_points , & point_coords ));
1591+
1592+ // Input and output vectors
1593+ {
1594+ CeedSize input_size , output_size ;
1595+
1596+ CeedCallBackend (CeedOperatorGetActiveVectorLengths (op , & input_size , & output_size ));
1597+ CeedCallBackend (CeedVectorCreate (ceed , input_size , & in_vec ));
1598+ CeedCallBackend (CeedVectorCreate (ceed , output_size , & out_vec ));
1599+ CeedCallBackend (CeedVectorSetValue (out_vec , 0.0 ));
1600+ }
1601+
1602+ // Assembled array
1603+ CeedCallBackend (CeedVectorGetArray (values , CEED_MEM_HOST , & assembled ));
1604+
1605+ // Clear input Qvecs
1606+ for (CeedInt i = 0 ; i < num_input_fields ; i ++ ) {
1607+ bool is_active ;
1608+ CeedVector vec ;
1609+
1610+ CeedCallBackend (CeedOperatorFieldGetVector (op_input_fields [i ], & vec ));
1611+ is_active = vec == CEED_VECTOR_ACTIVE ;
1612+ CeedCallBackend (CeedVectorDestroy (& vec ));
1613+ if (!is_active ) continue ;
1614+ CeedCallBackend (CeedVectorSetValue (impl -> q_vecs_in [i ], 0.0 ));
1615+ }
1616+
1617+ // Input Evecs and Restriction
1618+ CeedCallBackend (CeedOperatorSetupInputs_Ref (num_input_fields , qf_input_fields , op_input_fields , NULL , true, e_data , impl , request ));
1619+
1620+ // Loop through elements
1621+ for (CeedInt e = 0 ; e < num_elem ; e ++ ) {
1622+ CeedInt num_points , e_vec_size = 0 ;
1623+
1624+ // Setup points for element
1625+ CeedCallBackend (CeedElemRestrictionApplyAtPointsInElement (rstr_points , e , CEED_NOTRANSPOSE , point_coords , impl -> point_coords_elem , request ));
1626+ CeedCallBackend (CeedElemRestrictionGetNumPointsInElement (rstr_points , e , & num_points ));
1627+
1628+ // Input basis apply for non-active bases
1629+ CeedCallBackend (CeedOperatorInputBasisAtPoints_Ref (e , num_points_offset , num_points , qf_input_fields , op_input_fields , num_input_fields , in_vec ,
1630+ impl -> point_coords_elem , true, e_data , impl , request ));
1631+
1632+ // ---- Clear output
1633+ for (CeedInt k = 0 ; k < elem_size * elem_size ) {
1634+ assembled [offset + e * elem_size * elem_size + k ] = 0.0 ;
1635+ }
1636+
1637+ // Loop over points on element
1638+ for (CeedInt i = 0 ; i < num_input_fields ; i ++ ) {
1639+ bool is_active_at_points = true, is_active ;
1640+ CeedInt elem_size_active = 1 ;
1641+ CeedRestrictionType rstr_type ;
1642+ CeedVector vec ;
1643+ CeedElemRestriction elem_rstr ;
1644+
1645+ // -- Skip non-active input
1646+ CeedCallBackend (CeedOperatorFieldGetVector (op_input_fields [i ], & vec ));
1647+ is_active = vec == CEED_VECTOR_ACTIVE ;
1648+ CeedCallBackend (CeedVectorDestroy (& vec ));
1649+ if (!is_active ) continue ;
1650+
1651+ // -- Get active restriction type
1652+ CeedCallBackend (CeedOperatorFieldGetElemRestriction (op_input_fields [i ], & elem_rstr ));
1653+ CeedCallBackend (CeedElemRestrictionGetType (elem_rstr , & rstr_type ));
1654+ is_active_at_points = rstr_type == CEED_RESTRICTION_POINTS ;
1655+ if (!is_active_at_points ) CeedCallBackend (CeedElemRestrictionGetElementSize (elem_rstr , & elem_size_active ));
1656+ else elem_size_active = num_points ;
1657+ CeedCallBackend (CeedElemRestrictionGetNumComponents (elem_rstr , & num_comp_active ));
1658+ CeedCallBackend (CeedElemRestrictionDestroy (& elem_rstr ));
1659+
1660+ e_vec_size = elem_size_active * num_comp_active ;
1661+ for (CeedInt s = 0 ; s < e_vec_size ; s ++ ) {
1662+ CeedEvalMode eval_mode ;
1663+ CeedBasis basis ;
1664+
1665+ // -- Update unit vector
1666+ {
1667+ CeedScalar * array ;
1668+
1669+ if (s == 0 ) CeedCallBackend (CeedVectorSetValue (impl -> e_vecs_in [i ], 0.0 ));
1670+ CeedCallBackend (CeedVectorGetArray (impl -> e_vecs_in [i ], CEED_MEM_HOST , & array ));
1671+ array [s ] = 1.0 ;
1672+ if (s > 0 ) array [s - 1 ] = 0.0 ;
1673+ CeedCallBackend (CeedVectorRestoreArray (impl -> e_vecs_in [i ], & array ));
1674+ }
1675+ // -- Basis action
1676+ CeedCallBackend (CeedQFunctionFieldGetEvalMode (qf_input_fields [i ], & eval_mode ));
1677+ switch (eval_mode ) {
1678+ case CEED_EVAL_NONE :
1679+ break ;
1680+ // Note - these basis eval modes require FEM fields
1681+ case CEED_EVAL_INTERP :
1682+ case CEED_EVAL_GRAD :
1683+ case CEED_EVAL_DIV :
1684+ case CEED_EVAL_CURL :
1685+ CeedCallBackend (CeedOperatorFieldGetBasis (op_input_fields [i ], & basis ));
1686+ CeedCallBackend (CeedBasisApplyAtPoints (basis , 1 , & num_points , CEED_NOTRANSPOSE , eval_mode , impl -> point_coords_elem , impl -> e_vecs_in [i ],
1687+ impl -> q_vecs_in [i ]));
1688+ CeedCallBackend (CeedBasisDestroy (& basis ));
1689+ break ;
1690+ case CEED_EVAL_WEIGHT :
1691+ break ; // No action
1692+ }
1693+
1694+ // -- Q function
1695+ if (!impl -> is_identity_qf ) {
1696+ CeedCallBackend (CeedQFunctionApply (qf , num_points , impl -> q_vecs_in , impl -> q_vecs_out ));
1697+ }
1698+
1699+ // -- Output basis apply and restriction
1700+ CeedCallBackend (CeedOperatorOutputBasisAtPoints_Ref (e , num_points_offset , num_points , qf_output_fields , op_output_fields , num_input_fields ,
1701+ num_output_fields , impl -> apply_add_basis_out , impl -> skip_rstr_out , op , out_vec ,
1702+ impl -> point_coords_elem , impl , request ));
1703+
1704+ // -- Build element matrix
1705+ for (CeedInt j = 0 ; j < num_output_fields ; j ++ ) {
1706+ bool is_active ;
1707+ CeedInt elem_size = 0 ;
1708+ CeedRestrictionType rstr_type ;
1709+ CeedEvalMode eval_mode ;
1710+ CeedVector vec ;
1711+ CeedElemRestriction elem_rstr ;
1712+ CeedBasis basis ;
1713+
1714+ // ---- Skip non-active output
1715+ CeedCallBackend (CeedOperatorFieldGetVector (op_output_fields [j ], & vec ));
1716+ is_active = vec == CEED_VECTOR_ACTIVE ;
1717+ CeedCallBackend (CeedVectorDestroy (& vec ));
1718+ if (!is_active ) continue ;
1719+
1720+ // ---- Check if elem size matches
1721+ CeedCallBackend (CeedOperatorFieldGetElemRestriction (op_output_fields [j ], & elem_rstr ));
1722+ CeedCallBackend (CeedElemRestrictionGetType (elem_rstr , & rstr_type ));
1723+ if (is_active_at_points && rstr_type != CEED_RESTRICTION_POINTS ) {
1724+ CeedCallBackend (CeedElemRestrictionDestroy (& elem_rstr ));
1725+ continue ;
1726+ }
1727+ if (rstr_type == CEED_RESTRICTION_POINTS ) {
1728+ CeedCallBackend (CeedElemRestrictionGetNumPointsInElement (elem_rstr , e , & elem_size ));
1729+ } else {
1730+ CeedCallBackend (CeedElemRestrictionGetElementSize (elem_rstr , & elem_size ));
1731+ }
1732+ {
1733+ CeedInt num_comp = 0 ;
1734+
1735+ CeedCallBackend (CeedElemRestrictionGetNumComponents (elem_rstr , & num_comp ));
1736+ if (e_vec_size != num_comp * elem_size ) {
1737+ CeedCallBackend (CeedElemRestrictionDestroy (& elem_rstr ));
1738+ continue ;
1739+ }
1740+ }
1741+
1742+ // ---- Basis action
1743+ CeedCallBackend (CeedQFunctionFieldGetEvalMode (qf_output_fields [j ], & eval_mode ));
1744+ switch (eval_mode ) {
1745+ case CEED_EVAL_NONE :
1746+ break ; // No action
1747+ case CEED_EVAL_INTERP :
1748+ case CEED_EVAL_GRAD :
1749+ case CEED_EVAL_DIV :
1750+ case CEED_EVAL_CURL :
1751+ CeedCallBackend (CeedOperatorFieldGetBasis (op_output_fields [j ], & basis ));
1752+ CeedCallBackend (CeedBasisApplyAtPoints (basis , 1 , & num_points , CEED_TRANSPOSE , eval_mode , impl -> point_coords_elem , impl -> q_vecs_out [j ],
1753+ impl -> e_vecs_out [j ]));
1754+ CeedCallBackend (CeedBasisDestroy (& basis ));
1755+ break ;
1756+ // LCOV_EXCL_START
1757+ case CEED_EVAL_WEIGHT : {
1758+ return CeedError (CeedOperatorReturnCeed (op ), CEED_ERROR_BACKEND , "CEED_EVAL_WEIGHT cannot be an output evaluation mode" );
1759+ // LCOV_EXCL_STOP
1760+ }
1761+ }
1762+ // ---- Copy output
1763+ {
1764+ const CeedScalar * output ;
1765+
1766+ CeedCallBackend (CeedVectorGetArray (impl -> e_vecs_out [j ], CEED_MEM_HOST , & output ));
1767+ for (CeedInt k = 0 ; k < elem_size ) {
1768+ assembled [offset + e * elem_size * elem_size + i * elem_size + k ] += output [k ];
1769+ }
1770+ CeedCallBackend (CeedVectorRestoreArray (impl -> e_vecs_out [j ], & output ));
1771+ }
1772+
1773+ // COPIED CODE NEED TO UPDATE ----------------------------------------------------------------------------------------------------------
1774+
1775+ /**
1776+ // Put element matrix in coordinate data structure
1777+ for (CeedInt i = 0; i < elem_size_out; i++) {
1778+ for (CeedInt j = 0; j < elem_size_in; j++) {
1779+ assembled[offset + count] = elem_mat[i * elem_size_in + j];
1780+ count++;
1781+ }
1782+ }
1783+ **/
1784+
1785+ // END OF COPIED CODE ------------------------------------------------------------------------------------------------------------------
1786+
1787+
1788+ // -- Reset unit vector
1789+ if (s == e_vec_size - 1 ) CeedCallBackend (CeedVectorSetValue (impl -> q_vecs_in [i ], 0.0 ));
1790+ }
1791+ }
1792+ num_points_offset += num_points ;
1793+ }
1794+
1795+ // Restore input arrays
1796+ CeedCallBackend (CeedOperatorRestoreInputs_Ref (num_input_fields , qf_input_fields , op_input_fields , true, e_data , impl ));
1797+
1798+ // Restore assembled values
1799+ CeedCallBackend (CeedVectorRestoreArray (values , & assembled ));
1800+
1801+ // Cleanup
1802+ CeedCallBackend (CeedDestroy (& ceed ));
1803+ CeedCallBackend (CeedVectorDestroy (& in_vec ));
1804+ CeedCallBackend (CeedVectorDestroy (& out_vec ));
1805+ CeedCallBackend (CeedVectorDestroy (& point_coords ));
1806+ CeedCallBackend (CeedElemRestrictionDestroy (& rstr_points ));
1807+ CeedCallBackend (CeedQFunctionDestroy (& qf ));
1808+ return CEED_ERROR_SUCCESS ;
1809+ }
15541810
15551811//------------------------------------------------------------------------------
15561812// Operator Destroy
0 commit comments