Source code for fastvpinns.FE.quad_affine

"""
The file `quad_affine.py` defines the Quad Affine transformation of the reference element.
The implementation is referenced from the ParMooN project  (File: QuadAffine.C).

Author: Thivin Anandh D

Changelog: 30/Aug/2023 - Initial version

Known issues: None

Dependencies: None specified
"""

import numpy as np
from .fe_transformation_2d import FETransforamtion2D


[docs] class QuadAffin(FETransforamtion2D): """ Defines the Quad Affine transformation of the reference element. :param co_ordinates: The coordinates of the reference element. :type co_ordinates: numpy.ndarray """ def __init__(self, co_ordinates) -> None: """ Constructor for the QuadAffin class. :param co_ordinates: The coordinates of the reference element. :type co_ordinates: numpy.ndarray """ self.co_ordinates = co_ordinates self.set_cell() self.get_jacobian( 0, 0 ) # 0,0 is just a dummy value # this sets the jacobian and the inverse of the jacobian
[docs] def set_cell(self): """ Set the cell coordinates, which will be used to calculate the Jacobian and actual values. :param None: There are no parameters for this method. :returns None: This method does not return anything. """ self.x0 = self.co_ordinates[0][0] self.x1 = self.co_ordinates[1][0] self.x2 = self.co_ordinates[2][0] self.x3 = self.co_ordinates[3][0] # get the y-coordinates of the cell self.y0 = self.co_ordinates[0][1] self.y1 = self.co_ordinates[1][1] self.y2 = self.co_ordinates[2][1] self.y3 = self.co_ordinates[3][1] self.xc0 = (self.x1 + self.x3) * 0.5 self.xc1 = (self.x1 - self.x0) * 0.5 self.xc2 = (self.x3 - self.x0) * 0.5 self.yc0 = (self.y1 + self.y3) * 0.5 self.yc1 = (self.y1 - self.y0) * 0.5 self.yc2 = (self.y3 - self.y0) * 0.5
[docs] def get_original_from_ref(self, xi, eta): """ Returns the original coordinates from the reference coordinates. :param float xi: The xi coordinate. :param float eta: The eta coordinate. :return: numpy.ndarray The original coordinates. """ x = self.xc0 + self.xc1 * xi + self.xc2 * eta y = self.yc0 + self.yc1 * xi + self.yc2 * eta return np.array([x, y])
[docs] def get_jacobian(self, xi, eta): """ Returns the Jacobian of the transformation. :param xi: The xi coordinate. :type xi: float :param eta: The eta coordinate. :type eta: float :return: The Jacobian of the transformation. :rtype: float """ self.detjk = self.xc1 * self.yc2 - self.xc2 * self.yc1 self.rec_detjk = 1 / self.detjk return abs(self.detjk)
[docs] def get_orig_from_ref_derivative(self, ref_gradx, ref_grady, xi, eta): """ Returns the derivatives of the original coordinates with respect to the reference coordinates. :param ref_gradx: The reference gradient in the x-direction. :type ref_gradx: numpy.ndarray :param ref_grady: The reference gradient in the y-direction. :type ref_grady: numpy.ndarray :param xi: The xi coordinate. :type xi: float :param eta: The eta coordinate. :type eta: float :return: The derivatives of the original coordinates with respect to the reference coordinates. :rtype: tuple """ gradx_orig = np.zeros(ref_gradx.shape) grady_orig = np.zeros(ref_grady.shape) for i in range(ref_gradx.shape[0]): gradx_orig[i] = (self.yc2 * ref_gradx[i] - self.yc1 * ref_grady[i]) * self.rec_detjk grady_orig[i] = (-self.xc2 * ref_gradx[i] + self.xc1 * ref_grady[i]) * self.rec_detjk return gradx_orig, grady_orig
[docs] def get_orig_from_ref_second_derivative(self, grad_xx_ref, grad_xy_ref, grad_yy_ref, xi, eta): """ Returns the second derivatives (xx, xy, yy) of the original coordinates with respect to the reference coordinates. :param grad_xx_ref: The reference second derivative in the xx-direction. :type grad_xx_ref: numpy.ndarray :param grad_xy_ref: The reference second derivative in the xy-direction. :type grad_xy_ref: numpy.ndarray :param grad_yy_ref: The reference second derivative in the yy-direction. :type grad_yy_ref: numpy.ndarray :param xi: The xi coordinate. :type xi: float :param eta: The eta coordinate. :type eta: float :return: The second derivatives (xx, xy, yy) of the original coordinates with respect to the reference coordinates. :rtype: tuple """ GeoData = np.zeros((3, 3)) Eye = np.identity(3) # Populate GeoData (assuming xc1, xc2, yc1, yc2 are defined) GeoData[0, 0] = self.xc1 * self.xc1 GeoData[0, 1] = 2 * self.xc1 * self.yc1 GeoData[0, 2] = self.yc1 * self.yc1 GeoData[1, 0] = self.xc1 * self.xc2 GeoData[1, 1] = self.yc1 * self.xc2 + self.xc1 * self.yc2 GeoData[1, 2] = self.yc1 * self.yc2 GeoData[2, 0] = self.xc2 * self.xc2 GeoData[2, 1] = 2 * self.xc2 * self.yc2 GeoData[2, 2] = self.yc2 * self.yc2 # solve the linear system solution = np.linalg.solve(GeoData, Eye) # generate empty arrays for the original second derivatives grad_xx_orig = np.zeros(grad_xx_ref.shape) grad_xy_orig = np.zeros(grad_xy_ref.shape) grad_yy_orig = np.zeros(grad_yy_ref.shape) for j in range(grad_xx_ref.shape[0]): r20 = grad_xx_ref[j] r11 = grad_xy_ref[j] r02 = grad_yy_ref[j] grad_xx_orig[j] = solution[0, 0] * r20 + solution[0, 1] * r11 + solution[0, 2] * r02 grad_xy_orig[j] = solution[1, 0] * r20 + solution[1, 1] * r11 + solution[1, 2] * r02 grad_yy_orig[j] = solution[2, 0] * r20 + solution[2, 1] * r11 + solution[2, 2] * r02 return grad_xx_orig, grad_xy_orig, grad_yy_orig