Source code for finat.argyris

import numpy

import FIAT

from gem import Literal, ListTensor

from finat.fiat_elements import ScalarFiatElement
from finat.physically_mapped import PhysicallyMappedElement, Citations


[docs]class Argyris(PhysicallyMappedElement, ScalarFiatElement): def __init__(self, cell, degree): if degree != 5: raise ValueError("Degree must be 5 for Argyris element") if Citations is not None: Citations().register("Argyris1968") super().__init__(FIAT.QuinticArgyris(cell))
[docs] def basis_transformation(self, coordinate_mapping): # Jacobians at edge midpoints J = coordinate_mapping.jacobian_at([1/3, 1/3]) rns = coordinate_mapping.reference_normals() pns = coordinate_mapping.physical_normals() pts = coordinate_mapping.physical_tangents() pel = coordinate_mapping.physical_edge_lengths() V = numpy.zeros((21, 21), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) for v in range(3): s = 6*v V[s, s] = Literal(1) for i in range(2): for j in range(2): V[s+1+i, s+1+j] = J[j, i] V[s+3, s+3] = J[0, 0]*J[0, 0] V[s+3, s+4] = 2*J[0, 0]*J[1, 0] V[s+3, s+5] = J[1, 0]*J[1, 0] V[s+4, s+3] = J[0, 0]*J[0, 1] V[s+4, s+4] = J[0, 0]*J[1, 1] + J[1, 0]*J[0, 1] V[s+4, s+5] = J[1, 0]*J[1, 1] V[s+5, s+3] = J[0, 1]*J[0, 1] V[s+5, s+4] = 2*J[0, 1]*J[1, 1] V[s+5, s+5] = J[1, 1]*J[1, 1] for e in range(3): v0id, v1id = [i for i in range(3) if i != e] # nhat . J^{-T} . t foo = (rns[e, 0]*(J[0, 0]*pts[e, 0] + J[1, 0]*pts[e, 1]) + rns[e, 1]*(J[0, 1]*pts[e, 0] + J[1, 1]*pts[e, 1])) # vertex points V[18+e, 6*v0id] = -15/8 * (foo / pel[e]) V[18+e, 6*v1id] = 15/8 * (foo / pel[e]) # vertex derivatives for i in (0, 1): V[18+e, 6*v0id+1+i] = -7/16*foo*pts[e, i] V[18+e, 6*v1id+1+i] = V[18+e, 6*v0id+1+i] # second derivatives tau = [pts[e, 0]*pts[e, 0], 2*pts[e, 0]*pts[e, 1], pts[e, 1]*pts[e, 1]] for i in (0, 1, 2): V[18+e, 6*v0id+3+i] = -1/32 * (pel[e]*foo*tau[i]) V[18+e, 6*v1id+3+i] = 1/32 * (pel[e]*foo*tau[i]) V[18+e, 18+e] = (rns[e, 0]*(J[0, 0]*pns[e, 0] + J[1, 0]*pns[e, 1]) + rns[e, 1]*(J[0, 1]*pns[e, 0] + J[1, 1]*pns[e, 1])) # Patch up conditioning h = coordinate_mapping.cell_size() for v in range(3): for k in range(2): for i in range(21): V[i, 6*v+1+k] = V[i, 6*v+1+k] / h[v] for k in range(3): for i in range(21): V[i, 6*v+3+k] = V[i, 6*v+3+k] / (h[v]*h[v]) for e in range(3): v0id, v1id = [i for i in range(3) if i != e] for i in range(21): V[i, 18+e] = 2*V[i, 18+e] / (h[v0id] + h[v1id]) return ListTensor(V.T)