// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. // Finite Element classes on Pyramid shaped elements #include "fe_pyramid.hpp" namespace mfem { using namespace std; Vector FuentesPyramid::grad_lam1(real_t x, real_t y, real_t z) { return Vector({CheckZ(z) ? - (1.0 - y - z) / (1.0 - z) : -0.5, CheckZ(z) ? - (1.0 - x - z) / (1.0 - z) : -0.5, CheckZ(z) ? x * y / ((1.0 - z) * (1.0 - z)) - 1.0 : -0.75}); } Vector FuentesPyramid::grad_lam2(real_t x, real_t y, real_t z) { return Vector({CheckZ(z) ? (1.0 - y - z) / (1.0 - z) : 0.5, CheckZ(z) ? - x / (1.0 - z) : -0.5, CheckZ(z) ? - x * y / ((1.0 - z) * (1.0 - z)) : -0.25}); } Vector FuentesPyramid::grad_lam3(real_t x, real_t y, real_t z) { return Vector({CheckZ(z) ? y / (1.0 - z) : 0.5, CheckZ(z) ? x / (1.0 - z) : 0.5, CheckZ(z) ? x * y / ((1.0 - z) * (1.0 - z)) : 0.25}); } Vector FuentesPyramid::grad_lam4(real_t x, real_t y, real_t z) { return Vector({CheckZ(z) ? - y / (1.0 - z) : -0.5, CheckZ(z) ? (1.0 - x - z) / (1.0 - z) : 0.5, CheckZ(z) ? - x * y / ((1.0 - z) * (1.0 - z)) : -0.25}); } Vector FuentesPyramid::grad_lam5(real_t x, real_t y, real_t z) { return Vector({0.0, 0.0, 1.0}); } DenseMatrix FuentesPyramid::grad_lam15(real_t x, real_t y, real_t z) { DenseMatrix dlam(2, 3); dlam.SetRow(0, grad_lam1(x, y, z)); dlam.SetRow(1, grad_lam5(x, y, z)); return dlam; } DenseMatrix FuentesPyramid::grad_lam25(real_t x, real_t y, real_t z) { DenseMatrix dlam(2, 3); dlam.SetRow(0, grad_lam2(x, y, z)); dlam.SetRow(1, grad_lam5(x, y, z)); return dlam; } DenseMatrix FuentesPyramid::grad_lam35(real_t x, real_t y, real_t z) { DenseMatrix dlam(2, 3); dlam.SetRow(0, grad_lam3(x, y, z)); dlam.SetRow(1, grad_lam5(x, y, z)); return dlam; } DenseMatrix FuentesPyramid::grad_lam45(real_t x, real_t y, real_t z) { DenseMatrix dlam(2, 3); dlam.SetRow(0, grad_lam4(x, y, z)); dlam.SetRow(1, grad_lam5(x, y, z)); return dlam; } Vector FuentesPyramid::lam15_grad_lam15(real_t x, real_t y, real_t z) { Vector lam = lam15(x, y, z); Vector lamdlam(3); add(lam(0), grad_lam5(x, y, z), -lam(1), grad_lam1(x, y, z), lamdlam); return lamdlam; } Vector FuentesPyramid::lam25_grad_lam25(real_t x, real_t y, real_t z) { Vector lam = lam25(x, y, z); Vector lamdlam(3); add(lam(0), grad_lam5(x, y, z), -lam(1), grad_lam2(x, y, z), lamdlam); return lamdlam; } Vector FuentesPyramid::lam35_grad_lam35(real_t x, real_t y, real_t z) { Vector lam = lam35(x, y, z); Vector lamdlam(3); add(lam(0), grad_lam5(x, y, z), -lam(1), grad_lam3(x, y, z), lamdlam); return lamdlam; } Vector FuentesPyramid::lam45_grad_lam45(real_t x, real_t y, real_t z) { Vector lam = lam45(x, y, z); Vector lamdlam(3); add(lam(0), grad_lam5(x, y, z), -lam(1), grad_lam4(x, y, z), lamdlam); return lamdlam; } Vector FuentesPyramid::lam125_grad_lam125(real_t x, real_t y, real_t z) { Vector lgl({-x * z / (one - z), y - one, z}); lgl *= (one - y - z) / (one - z); return lgl; } Vector FuentesPyramid::lam235_grad_lam235(real_t x, real_t y, real_t z) { Vector lgl({x, -y * z / (one - z), z}); lgl *= x / (one - z); return lgl; } Vector FuentesPyramid::lam345_grad_lam345(real_t x, real_t y, real_t z) { Vector lgl({-x * z / (one - z), y, z}); lgl *= y / (one - z); return lgl; } Vector FuentesPyramid::lam435_grad_lam435(real_t x, real_t y, real_t z) { Vector lgl({x * z / (one - z), -y, -z}); lgl *= y / (one - z); return lgl; } Vector FuentesPyramid::lam415_grad_lam415(real_t x, real_t y, real_t z) { Vector lgl({x - one, -y * z / (one - z), z}); lgl *= (one - x - z) / (one - z); return lgl; } Vector FuentesPyramid::lam145_grad_lam145(real_t x, real_t y, real_t z) { Vector lgl({one - x, y * z / (one - z), -z}); lgl *= (one - x - z) / (one - z); return lgl; } real_t FuentesPyramid::div_lam125_grad_lam125(real_t x, real_t y, real_t z) { return (1.0 - z - y) / (1.0 - z); } real_t FuentesPyramid::div_lam235_grad_lam235(real_t x, real_t y, real_t z) { return x / (1.0 - z); } real_t FuentesPyramid::div_lam345_grad_lam345(real_t x, real_t y, real_t z) { return y / (1.0 - z); } real_t FuentesPyramid::div_lam435_grad_lam435(real_t x, real_t y, real_t z) { return -y / (1.0 - z); } real_t FuentesPyramid::div_lam415_grad_lam415(real_t x, real_t y, real_t z) { return (1.0 - z - x) / (1.0 - z); } real_t FuentesPyramid::div_lam145_grad_lam145(real_t x, real_t y, real_t z) { return -(1.0 - z - x) / (1.0 - z); } DenseMatrix FuentesPyramid::grad_mu01(real_t z) { DenseMatrix dmu(2, 3); dmu.SetRow(0, grad_mu0(z)); dmu.SetRow(1, grad_mu1(z)); return dmu; } Vector FuentesPyramid::grad_mu0(real_t z, const Vector xy, unsigned int ab) { Vector dmu({0.0, 0.0, - xy[ab-1] / pow(1.0 - z, 2)}); dmu[ab-1] = -1.0 / (1.0 - z); return dmu; } Vector FuentesPyramid::grad_mu1(real_t z, const Vector xy, unsigned int ab) { Vector dmu({0.0, 0.0, xy[ab-1] / pow(1.0 - z, 2)}); dmu[ab-1] = 1.0 / (1.0 - z); return dmu; } DenseMatrix FuentesPyramid::grad_mu01(real_t z, Vector xy, unsigned int ab) { DenseMatrix dmu(2, 3); dmu.SetRow(0, grad_mu0(z, xy, ab)); dmu.SetRow(1, grad_mu1(z, xy, ab)); return dmu; } Vector FuentesPyramid::mu01_grad_mu01(real_t z, Vector xy, unsigned int ab) { Vector mu = mu01(z, xy, ab); Vector mudmu(3); add(mu(0), grad_mu1(z, xy, ab), -mu(1), grad_mu0(z, xy, ab), mudmu); return mudmu; } Vector FuentesPyramid::grad_nu0(real_t z, const Vector xy, unsigned int ab) { Vector dnu({0.0, 0.0, -1.0}); dnu[ab-1] = -1.0; return dnu; } Vector FuentesPyramid::grad_nu1(real_t z, const Vector xy, unsigned int ab) { Vector dnu({0.0, 0.0, 0.0}); dnu[ab-1] = 1.0; return dnu; } Vector FuentesPyramid::grad_nu2(real_t z, const Vector xy, unsigned int ab) { return Vector({0.0, 0.0, 1.0}); } DenseMatrix FuentesPyramid::grad_nu01(real_t z, Vector xy, unsigned int ab) { DenseMatrix dnu(2, 3); dnu.SetRow(0, grad_nu0(z, xy, ab)); dnu.SetRow(1, grad_nu1(z, xy, ab)); return dnu; } DenseMatrix FuentesPyramid::grad_nu012(real_t z, Vector xy, unsigned int ab) { DenseMatrix dnu(3, 3); dnu.SetRow(0, grad_nu0(z, xy, ab)); dnu.SetRow(1, grad_nu1(z, xy, ab)); dnu.SetRow(2, grad_nu2(z, xy, ab)); return dnu; } DenseMatrix FuentesPyramid::grad_nu120(real_t z, Vector xy, unsigned int ab) { DenseMatrix dnu(3, 3); dnu.SetRow(0, grad_nu1(z, xy, ab)); dnu.SetRow(1, grad_nu2(z, xy, ab)); dnu.SetRow(2, grad_nu0(z, xy, ab)); return dnu; } Vector FuentesPyramid::nu01_grad_nu01(real_t z, Vector xy, unsigned int ab) { Vector nu = nu01(z, xy, ab); Vector nudnu(3); add(nu(0), grad_nu1(z, xy, ab), -nu(1), grad_nu0(z, xy, ab), nudnu); return nudnu; } Vector FuentesPyramid::nu12_grad_nu12(real_t z, Vector xy, unsigned int ab) { Vector nu = nu12(z, xy, ab); Vector nudnu(3); add(nu(0), grad_nu2(z, xy, ab), -nu(1), grad_nu1(z, xy, ab), nudnu); return nudnu; } Vector FuentesPyramid::nu012_grad_nu012(real_t z, Vector xy, unsigned int ab) { Vector nu(nu012(z, xy, ab)); Vector dnu0(grad_nu0(z, xy, ab)); Vector dnu1(grad_nu1(z, xy, ab)); Vector dnu2(grad_nu2(z, xy, ab)); Vector v01(3), v12(3), v20(3); dnu0.cross3D(dnu1, v01); dnu1.cross3D(dnu2, v12); dnu2.cross3D(dnu0, v20); Vector nudnu(3); add(nu(0), v12, nu(1), v20, nudnu); nudnu.Add(nu(2), v01); return nudnu; } void FuentesPyramid::CalcScaledLegendre(int p, real_t x, real_t t, real_t *u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); if (t > 0.0) { Poly_1D::CalcLegendre(p, x / t, u); for (int i = 1; i <= p; i++) { u[i] *= pow(t, i); } } else { // This assumes x = 0 as well as t = 0 since x \in [0,t] u[0] = 1.0; for (int i = 1; i <= p; i++) { u[i] = 0.0; } } } void FuentesPyramid::CalcScaledLegendre(int p, real_t x, real_t t, real_t *u, real_t *dudx, real_t *dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); if (t > 0.0) { Poly_1D::CalcLegendre(p, x / t, u, dudx); dudx[0] = 0.0; dudt[0] = - dudx[0] * x / t; for (int i = 1; i <= p; i++) { u[i] *= pow(t, i); dudx[i] *= pow(t, i - 1); dudt[i] = (u[i] * i - dudx[i] * x) / t; } } else { // This assumes x = 0 as well as t = 0 since x \in [0,t] u[0] = 1.0; dudx[0] = 0.0; dudt[0] = 0.0; if (p >=1) { u[1] = 0.0; dudx[1] = 2.0; dudt[1] = -1.0; } for (int i = 2; i <= p; i++) { u[i] = 0.0; dudx[i] = 0.0; dudt[i] = 0.0; } } } void FuentesPyramid::CalcScaledLegendre(int p, real_t x, real_t t, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcScaledLegendre(p, x, t, u.GetData()); } void FuentesPyramid::CalcScaledLegendre(int p, real_t x, real_t t, Vector &u, Vector &dudx, Vector &dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(dudx.Size() >= p+1, "Size of dudx is too small"); MFEM_ASSERT(dudt.Size() >= p+1, "Size of dudt is too small"); CalcScaledLegendre(p, x, t, u.GetData(), dudx.GetData(), dudt.GetData()); } void FuentesPyramid::CalcIntegratedLegendre(int p, real_t x, real_t t, real_t *u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); if (t > 0.0) { CalcScaledLegendre(p, x, t, u); for (int i = p; i >= 2; i--) { u[i] = (u[i] - t * t * u[i-2]) / (4.0 * i - 2.0); } if (p >= 1) { u[1] = x; } u[0] = 0.0; } else { for (int i = 0; i <= p; i++) { u[i] = 0.0; } } } void FuentesPyramid::CalcIntegratedLegendre(int p, real_t x, real_t t, real_t *u, real_t *dudx, real_t *dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); if (t > 0.0) { CalcScaledLegendre(p, x, t, u, dudx, dudt); for (int i = p; i >= 2; i--) { u[i] = (u[i] - t * t * u[i-2]) / (4.0 * i - 2.0); dudx[i] = (dudx[i] - t * t * dudx[i-2]) / (4.0 * i - 2.0); dudt[i] = (dudt[i] - t * t * dudt[i-2] - 2.0 * t * u[i-2]) / (4.0 * i - 2.0); } if (p >= 1) { u[1] = x; dudx[1] = 1.0; dudt[1] = 0.0; } u[0] = 0.0; dudx[0] = 0.0; dudt[0] = 0.0; } else { for (int i = 0; i <= p; i++) { u[i] = 0.0; dudx[i] = 0.0; dudt[i] = 0.0; } } } void FuentesPyramid::CalcIntegratedLegendre(int p, real_t x, real_t t, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcIntegratedLegendre(p, x, t, u.GetData()); } void FuentesPyramid::CalcIntegratedLegendre(int p, real_t x, real_t t, Vector &u, Vector &dudx, Vector &dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(dudx.Size() >= p+1, "Size of dudx is too small"); MFEM_ASSERT(dudt.Size() >= p+1, "Size of dudt is too small"); CalcIntegratedLegendre(p, x, t, u.GetData(), dudx.GetData(), dudt.GetData()); } void FuentesPyramid::CalcHomogenizedScaLegendre(int p, real_t s0, real_t s1, real_t *u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcScaledLegendre(p, s1, s0 + s1, u); } void FuentesPyramid::CalcHomogenizedScaLegendre(int p, real_t s0, real_t s1, real_t *u, real_t *duds0, real_t *duds1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcScaledLegendre(p, s1, s0+s1, u, duds1, duds0); for (int i = 0; i <= p; i++) { duds1[i] += duds0[i]; } } void FuentesPyramid::CalcHomogenizedScaLegendre(int p, real_t s0, real_t s1, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcHomogenizedScaLegendre(p, s0, s1, u.GetData()); } void FuentesPyramid::CalcHomogenizedScaLegendre(int p, real_t s0, real_t s1, Vector &u, Vector &duds0, Vector &duds1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(duds0.Size() >= p+1, "Size of duds0 is too small"); MFEM_ASSERT(duds1.Size() >= p+1, "Size of duds1 is too small"); CalcHomogenizedScaLegendre(p, s0, s1, u.GetData(), duds0.GetData(), duds1.GetData()); } void FuentesPyramid::CalcHomogenizedIntLegendre(int p, real_t t0, real_t t1, real_t *u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcIntegratedLegendre(p, t1, t0 + t1, u); } void FuentesPyramid::CalcHomogenizedIntLegendre(int p, real_t t0, real_t t1, real_t *u, real_t *dudt0, real_t *dudt1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcIntegratedLegendre(p, t1, t0+t1, u, dudt1, dudt0); for (int i = 0; i <= p; i++) { dudt1[i] += dudt0[i]; } } void FuentesPyramid::CalcHomogenizedIntLegendre(int p, real_t t0, real_t t1, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcHomogenizedIntLegendre(p, t0, t1, u.GetData()); } void FuentesPyramid::CalcHomogenizedIntLegendre(int p, real_t t0, real_t t1, Vector &u, Vector &dudt0, Vector &dudt1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(dudt0.Size() >= p+1, "Size of dudt0 is too small"); MFEM_ASSERT(dudt1.Size() >= p+1, "Size of dudt1 is too small"); CalcHomogenizedIntLegendre(p, t0, t1, u.GetData(), dudt0.GetData(), dudt1.GetData()); } void FuentesPyramid::CalcIntegratedJacobi(int p, real_t alpha, real_t x, real_t t, real_t *u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); if (t > 0.0) { CalcScaledJacobi(p, alpha, x, t, u); for (int i = p; i >= 2; i--) { real_t d0 = 2.0 * i + alpha; real_t d1 = d0 - 1.0; real_t d2 = d0 - 2.0; real_t a = (alpha + i) / (d0 * d1); real_t b = alpha / (d0 * d2); real_t c = (real_t)(i - 1) / (d1 * d2); u[i] = a * u[i] + b * t * u[i - 1] - c * t * t * u[i - 2]; } if (p >= 1) { u[1] = x; } u[0] = 0.0; } else { u[0] = 1.0; for (int i = 1; i <= p; i++) { u[i] = 0.0; } } } void FuentesPyramid::CalcIntegratedJacobi(int p, real_t alpha, real_t x, real_t t, real_t *u, real_t *dudx, real_t *dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcScaledJacobi(p, alpha, x, t, u, dudx, dudt); for (int i = p; i >= 2; i--) { real_t d0 = 2.0 * i + alpha; real_t d1 = d0 - 1.0; real_t d2 = d0 - 2.0; real_t a = (alpha + i) / (d0 * d1); real_t b = alpha / (d0 * d2); real_t c = (real_t)(i - 1) / (d1 * d2); u[i] = a * u[i] + b * t * u[i - 1] - c * t * t * u[i - 2]; dudx[i] = a * dudx[i] + b * t * dudx[i - 1] - c * t * t * dudx[i - 2]; dudt[i] = a * dudt[i] + b * t * dudt[i - 1] + b * u[i - 1] - c * t * t * dudt[i - 2] - 2.0 * c * t * u[i - 2]; } if (p >= 1) { u[1] = x; dudx[1] = 1.0; dudt[1] = 0.0; } u[0] = 0.0; dudx[0] = 0.0; dudt[0] = 0.0; } void FuentesPyramid::CalcScaledJacobi(int p, real_t alpha, real_t x, real_t t, real_t *u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); u[0] = 1.0; if (p >= 1) { u[1] = (2.0 + alpha) * x - t; } for (int i = 2; i <= p; i++) { real_t a = 2.0 * i * (alpha + i) * (2.0 * i + alpha - 2.0); real_t b = 2.0 * i + alpha - 1.0; real_t c = (2.0 * i + alpha) * (2.0 * i + alpha - 2.0); real_t d = 2.0 * (alpha + i - 1.0) * (i - 1) * (2.0 * i + alpha); u[i] = (b * (c * (2.0 * x - t) + alpha * alpha * t) * u[i - 1] - d * t * t * u[i - 2]) / a; } } void FuentesPyramid::CalcScaledJacobi(int p, real_t alpha, real_t x, real_t t, real_t *u, real_t *dudx, real_t *dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); u[0] = 1.0; dudx[0] = 0.0; dudt[0] = 0.0; if (p >= 1) { u[1] = (2.0 + alpha) * x - t; dudx[1] = 2.0 + alpha; dudt[1] = -1.0; } for (int i = 2; i <= p; i++) { real_t a = 2.0 * i * (alpha + i) * (2.0 * i + alpha - 2.0); real_t b = 2.0 * i + alpha - 1.0; real_t c = (2.0 * i + alpha) * (2.0 * i + alpha - 2.0); real_t d = 2.0 * (alpha + i - 1.0) * (i - 1) * (2.0 * i + alpha); u[i] = (b * (c * (2.0 * x - t) + alpha * alpha * t) * u[i - 1] - d * t * t * u[i - 2]) / a; dudx[i] = (b * ((c * (2.0 * x - t) + alpha * alpha * t) * dudx[i - 1] + 2.0 * c * u[i - 1]) - d * t * t * dudx[i - 2]) / a; dudt[i] = (b * ((c * (2.0 * x - t) + alpha * alpha * t) * dudt[i - 1] + (alpha * alpha - c) * u[i - 1]) - d * t * t * dudt[i - 2] - 2.0 * d * t * u[i - 2]) / a; } } void FuentesPyramid::CalcScaledJacobi(int p, real_t alpha, real_t x, real_t t, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcScaledJacobi(p, alpha, x, t, u.GetData()); } void FuentesPyramid::CalcScaledJacobi(int p, real_t alpha, real_t x, real_t t, Vector &u, Vector &dudx, Vector &dudt) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(dudx.Size() >= p+1, "Size of dudx is too small"); MFEM_ASSERT(dudt.Size() >= p+1, "Size of dudt is too small"); CalcScaledJacobi(p, alpha, x, t, u.GetData(), dudx.GetData(), dudt.GetData()); } void FuentesPyramid::CalcHomogenizedScaJacobi(int p, real_t alpha, real_t t0, real_t t1, real_t *u, real_t *dudt0, real_t *dudt1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcScaledJacobi(p, alpha, t1, t0+t1, u, dudt1, dudt0); for (int i = 0; i <= p; i++) { dudt1[i] += dudt0[i]; } } void FuentesPyramid::CalcHomogenizedScaJacobi(int p, real_t alpha, real_t t0, real_t t1, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcHomogenizedScaJacobi(p, alpha, t0, t1, u.GetData()); } void FuentesPyramid::CalcHomogenizedScaJacobi(int p, real_t alpha, real_t t0, real_t t1, Vector &u, Vector &dudt0, Vector &dudt1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(dudt0.Size() >= p+1, "Size of dudt0 is too small"); MFEM_ASSERT(dudt1.Size() >= p+1, "Size of dudt1 is too small"); CalcHomogenizedScaJacobi(p, alpha, t0, t1, u.GetData(), dudt0.GetData(), dudt1.GetData()); } void FuentesPyramid::CalcHomogenizedIntJacobi(int p, real_t alpha, real_t t0, real_t t1, real_t *u, real_t *dudt0, real_t *dudt1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); CalcIntegratedJacobi(p, alpha, t1, t0+t1, u, dudt1, dudt0); for (int i = 0; i <= p; i++) { dudt1[i] += dudt0[i]; } } void FuentesPyramid::CalcHomogenizedIntJacobi(int p, real_t alpha, real_t t0, real_t t1, Vector &u) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); CalcHomogenizedIntJacobi(p, alpha, t0, t1, u.GetData()); } void FuentesPyramid::CalcHomogenizedIntJacobi(int p, real_t alpha, real_t t0, real_t t1, Vector &u, Vector &dudt0, Vector &dudt1) { MFEM_ASSERT(p >= 0, "Polynomial order must be zero or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(dudt0.Size() >= p+1, "Size of dudt0 is too small"); MFEM_ASSERT(dudt1.Size() >= p+1, "Size of dudt1 is too small"); CalcHomogenizedIntJacobi(p, alpha, t0, t1, u.GetData(), dudt0.GetData(), dudt1.GetData()); } void FuentesPyramid::phi_E(int p, real_t s0, real_t s1, real_t *u) { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); CalcHomogenizedIntLegendre(p, s0, s1, u); } void FuentesPyramid::phi_E(int p, real_t s0, real_t s1, real_t *u, real_t *duds0, real_t *duds1) { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); CalcHomogenizedIntLegendre(p, s0, s1, u, duds0, duds1); } void FuentesPyramid::phi_E(int p, Vector s, Vector &u) { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); phi_E(p, s[0], s[1], u.GetData()); } void FuentesPyramid::phi_E(int p, Vector s, Vector &u, DenseMatrix &duds) { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(duds.Height() >= p+1, "First dimension of duds is too small"); MFEM_ASSERT(duds.Width() >= 2, "Second dimension of duds must be 2 or larger"); phi_E(p, s[0], s[1], u.GetData(), duds.GetColumn(0), duds.GetColumn(1)); } void FuentesPyramid::phi_E(int p, Vector s, const DenseMatrix &grad_s, Vector &u, DenseMatrix &grad_u) const { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(grad_s.Height() >= 2, "First dimension of grad_s must be 2"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3"); MFEM_ASSERT(u.Size() >= p+1, "Size of u is too small"); MFEM_ASSERT(grad_u.Height() >= p+1, "First dimension of grad_u is too small"); MFEM_ASSERT(grad_u.Width() == grad_s.Width(), "Second dimension of grad_u must match that of grad_s"); #ifdef MFEM_THREAD_SAFE DenseMatrix phi_E_mtmp; #endif DenseMatrix &duds = phi_E_mtmp; duds.SetSize(p + 1, grad_s.Height()); phi_E(p, s[0], s[1], u.GetData(), duds.GetColumn(0), duds.GetColumn(1)); Mult(duds, grad_s, grad_u); } void FuentesPyramid::phi_Q(int p, Vector s, Vector t, DenseMatrix &u) const { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(t.Size() >= 2, "Size of t must be 2 or larger"); MFEM_ASSERT(u.Height() >= p+1, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= p+1, "Second dimension of u is too small"); #ifdef MFEM_THREAD_SAFE Vector phi_Q_vtmp1; Vector phi_Q_vtmp2; #endif Vector &phi_E_i = phi_Q_vtmp1; Vector &phi_E_j = phi_Q_vtmp2; phi_E_i.SetSize(p+1); phi_E(p, s, phi_E_i); phi_E_j.SetSize(p+1); phi_E(p, t, phi_E_j); for (int j=0; j<=p; j++) for (int i=0; i<=p; i++) { u(i,j) = phi_E_i[i] * phi_E_j[j]; } } void FuentesPyramid::phi_Q(int p, Vector s, const DenseMatrix &grad_s, Vector t, const DenseMatrix &grad_t, DenseMatrix &u, DenseTensor &grad_u) const { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(grad_s.Height() >= 2, "First dimension of grad_s must be 2 or larger"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3 or larger"); MFEM_ASSERT(t.Size() >= 2, "Size of t must be 2 or larger"); MFEM_ASSERT(grad_t.Height() >= 2, "First dimension of grad_t must be 2 or larger"); MFEM_ASSERT(grad_t.Width() >= 3, "Second dimension of grad_t must be 3 or larger"); MFEM_ASSERT(u.Height() >= p+1, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= p+1, "First dimension of u is too small"); MFEM_ASSERT(grad_u.SizeI() >= p+1, "First dimension of grad_u is too small"); MFEM_ASSERT(grad_u.SizeJ() >= p+1, "Second dimension of grad_u is too small"); MFEM_ASSERT(grad_u.SizeK() >= 3, "Third dimension of grad_u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector phi_Q_vtmp1; Vector phi_Q_vtmp2; DenseMatrix phi_Q_mtmp1; DenseMatrix phi_Q_mtmp2; #endif Vector &phi_E_i = phi_Q_vtmp1; Vector &phi_E_j = phi_Q_vtmp2; DenseMatrix &dphi_E_i = phi_Q_mtmp1; DenseMatrix &dphi_E_j = phi_Q_mtmp2; phi_E_i.SetSize(p+1); dphi_E_i.SetSize(p+1, grad_s.Width()); phi_E(p, s, grad_s, phi_E_i, dphi_E_i); phi_E_j.SetSize(p+1); dphi_E_j.SetSize(p+1, grad_t.Width()); phi_E(p, t, grad_t, phi_E_j, dphi_E_j); for (int j=0; j<=p; j++) for (int i=0; i<=p; i++) { u(i,j) = phi_E_i[i] * phi_E_j[j]; for (int k=0; k<3; k++) grad_u(i,j,k) = phi_E_i(i) * dphi_E_j(j,k) + dphi_E_i(i,k) * phi_E_j(j); } } void FuentesPyramid::phi_T(int p, Vector s, DenseMatrix &u) const { MFEM_ASSERT(p >= 3, "Polynomial order must be three or larger"); MFEM_ASSERT(s.Size() >= 3, "Size of s must be 3 or larger"); MFEM_ASSERT(u.Height() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= p-1, "Second dimension of u is too small"); #ifdef MFEM_THREAD_SAFE Vector phi_T_vtmp1; Vector phi_T_vtmp2; #endif Vector &phi_E_i = phi_T_vtmp1; Vector &L_j = phi_T_vtmp2; phi_E_i.SetSize(p); phi_E(p-1, s, phi_E_i); L_j.SetSize(p-1); u = 0.0; for (int i = 2; i < p; i++) { const real_t alpha = 2.0 * i; CalcHomogenizedIntJacobi(p-2, alpha, s[0] + s[1], s[2], L_j); for (int j = 1; i + j <= p; j++) { u(i,j) = phi_E_i[i] * L_j[j]; } } } void FuentesPyramid::phi_T(int p, Vector s, const DenseMatrix &grad_s, DenseMatrix &u, DenseTensor &grad_u) const { MFEM_ASSERT(p >= 3, "Polynomial order must be three or larger"); MFEM_ASSERT(s.Size() >= 3, "Size of s must be 3 or larger"); MFEM_ASSERT(grad_s.Height() >= 3, "First dimension of grad_s must be 2 or larger"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3 or larger"); MFEM_ASSERT(u.Height() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= p-1, "Second dimension of u is too small"); MFEM_ASSERT(grad_u.SizeI() >= p, "First dimension of grad_u is too small"); MFEM_ASSERT(grad_u.SizeJ() >= p-1, "Second dimension of grad_u is too small"); MFEM_ASSERT(grad_u.SizeK() >= 3, "Third dimension of grad_u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector phi_T_vtmp1; Vector phi_T_vtmp2; Vector phi_T_vtmp3; Vector phi_T_vtmp4; DenseMatrix phi_T_mtmp1; #endif Vector &phi_E_i = phi_T_vtmp1; DenseMatrix &dphi_E_i = phi_T_mtmp1; Vector &L_j = phi_T_vtmp2; Vector &dL_j_dx = phi_T_vtmp3; Vector &dL_j_dt = phi_T_vtmp4; phi_E_i.SetSize(p); dphi_E_i.SetSize(p, 3); phi_E(p-1, s, grad_s, phi_E_i, dphi_E_i); L_j.SetSize(p-1); dL_j_dx.SetSize(p-1); dL_j_dt.SetSize(p-1); u = 0.0; grad_u = 0.0; for (int i = 2; i < p; i++) { const real_t alpha = 2.0 * i; CalcHomogenizedIntJacobi(p-2, alpha, s[0] + s[1], s[2], L_j, dL_j_dx, dL_j_dt); for (int j = 1; i + j <= p; j++) { u(i,j) = phi_E_i[i] * L_j[j]; for (int d=0; d<3; d++) grad_u(i, j, d) = dphi_E_i(i, d) * L_j[j] + phi_E_i[i] * (dL_j_dx[j] * (grad_s(0, d) + grad_s(1, d)) + dL_j_dt[j] * grad_s(2, d)); } } } void FuentesPyramid::E_E(int p, Vector s, Vector sds, DenseMatrix &u) const { MFEM_ASSERT(p >= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sds.Size() >= 3, "Size of sds must be 3 or larger"); MFEM_ASSERT(u.Height() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= 3, "Second dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector E_E_vtmp; #endif Vector &P_i = E_E_vtmp; P_i.SetSize(p); CalcHomogenizedScaLegendre(p - 1, s[0], s[1], P_i); for (int i=0; i= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(grad_s.Height() >= 2, "First dimension of grad_s must be 2 or larger"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3 or larger"); MFEM_ASSERT(u.Height() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= 3, "Second dimension of u must be 3 or larger"); MFEM_ASSERT(curl_u.Height() >= p, "First dimension of curl_u is too small"); MFEM_ASSERT(curl_u.Width() >= 3, "Second dimension of curl_u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector E_E_vtmp; #endif Vector &P_i = E_E_vtmp; P_i.SetSize(p); CalcHomogenizedScaLegendre(p - 1, s[0], s[1], P_i); Vector grad_s0({grad_s(0,0), grad_s(0,1), grad_s(0,2)}); Vector grad_s1({grad_s(1,0), grad_s(1,1), grad_s(1,2)}); Vector sds(3); add(s(0), grad_s1, -s(1), grad_s0, sds); Vector dsxds(3); grad_s0.cross3D(grad_s1, dsxds); for (int i=0; i= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sds.Size() >= 3, "Size of sds must be 3 or larger"); MFEM_ASSERT(t.Size() >= 2, "Size of t must be 2 or larger"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p+1, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector E_Q_vtmp; DenseMatrix E_Q_mtmp1; #endif DenseMatrix &E_E_i = E_Q_mtmp1; Vector &phi_E_j = E_Q_vtmp; E_E_i.SetSize(p, 3); E_E(p, s, sds, E_E_i); phi_E_j.SetSize(p + 1); phi_E(p, t, phi_E_j); for (int k=0; k<3; k++) { u(k).SetCol(0, 0.0); u(k).SetCol(1, 0.0); } for (int j=2; j<=p; j++) for (int i=0; i= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(grad_s.Height() >= 2, "First dimension of grad_s must be 2"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3"); MFEM_ASSERT(t.Size() >= 2, "Size of t must be 2 or larger"); MFEM_ASSERT(grad_t.Height() >= 2, "First dimension of grad_t must be 2"); MFEM_ASSERT(grad_t.Width() >= 3, "Second dimension of grad_t must be 3"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p+1, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); MFEM_ASSERT(curl_u.SizeI() >= p, "First dimension of curl_u is too small"); MFEM_ASSERT(curl_u.SizeJ() >= p+1, "Second dimension of curl_u is too small"); MFEM_ASSERT(curl_u.SizeK() >= 3, "Third dimension of curl_u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector E_Q_vtmp; DenseMatrix E_Q_mtmp1; DenseMatrix E_Q_mtmp2; DenseMatrix E_Q_mtmp3; #endif Vector &phi_E_j = E_Q_vtmp; DenseMatrix &dphi_E_j = E_Q_mtmp1; DenseMatrix &E_E_i = E_Q_mtmp2; DenseMatrix &dE_E_i = E_Q_mtmp3; phi_E_j.SetSize(p + 1); dphi_E_j.SetSize(p + 1, grad_t.Width()); phi_E(p, t, grad_t, phi_E_j, dphi_E_j); E_E_i.SetSize(p, 3); dE_E_i.SetSize(p, 3); E_E(p, s, grad_s, E_E_i, dE_E_i); for (int k=0; k<3; k++) { u(k).SetCol(0, 0.0); u(k).SetCol(1, 0.0); curl_u(k).SetCol(0, 0.0); curl_u(k).SetCol(1, 0.0); } for (int j=2; j<=p; j++) for (int i=0; i= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 3, "Size of s must be 3 or larger"); MFEM_ASSERT(sds.Size() >= 3, "Size of sds must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p - 1, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector E_T_vtmp1; DenseMatrix E_T_mtmp1; #endif Vector &L_j = E_T_vtmp1; DenseMatrix &E_E_i = E_T_mtmp1; E_E_i.SetSize(p - 1, 3); E_E(p - 1, s, sds, E_E_i); L_j.SetSize(p); for (int i=0; i= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 3, "Size of s must be 3 or larger"); MFEM_ASSERT(grad_s.Height() >= 3, "First dimension of grad_s must be 3"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3"); MFEM_ASSERT(u.SizeI() >= p - 1, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); MFEM_ASSERT(curl_u.SizeI() >= p - 1, "First dimension of curl_u is too small"); MFEM_ASSERT(curl_u.SizeJ() >= p, "Second dimension of curl_u is too small"); MFEM_ASSERT(curl_u.SizeK() >= 3, "Third dimension of curl_u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector E_T_vtmp1; Vector E_T_vtmp2; Vector E_T_vtmp3; DenseMatrix E_T_mtmp1; DenseMatrix E_T_mtmp2; #endif Vector &L_j = E_T_vtmp1; Vector &dL_j_dx = E_T_vtmp2; Vector &dL_j_dt = E_T_vtmp3; DenseMatrix & E_E_i = E_T_mtmp1; DenseMatrix &dE_E_i = E_T_mtmp2; Vector dL(3), grad_L(3); E_E_i.SetSize(p - 1, 3); dE_E_i.SetSize(p - 1, 3); E_E(p - 1, s, grad_s, E_E_i, dE_E_i); L_j.SetSize(p); dL_j_dx.SetSize(p); dL_j_dt.SetSize(p); for (int i=0; i= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sds.Size() >= 3, "Size of sds must be 3 or larger"); MFEM_ASSERT(t.Size() >= 2, "Size of t must be 2 or larger"); MFEM_ASSERT(tdt.Size() >= 3, "Size of tdt must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE DenseMatrix V_Q_mtmp1; DenseMatrix V_Q_mtmp2; #endif DenseMatrix &E_E_i = V_Q_mtmp1; DenseMatrix &E_E_j = V_Q_mtmp2; E_E_i.SetSize(p, 3); E_E(p, s, sds, E_E_i); E_E_j.SetSize(p, 3); E_E(p, t, tdt, E_E_j); for (int j=0; j= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sdsxds.Size() >= 3, "Size of sdsxds must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector V_T_vtmp1; Vector V_T_vtmp2; #endif Vector &P_i = V_T_vtmp1; Vector &P_j = V_T_vtmp2; P_i.SetSize(p); CalcHomogenizedScaLegendre(p-1, s[0], s[1], P_i); P_j.SetSize(p); for (int i=0; i= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sdsxds.Size() >= 3, "Size of sdsxds must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); MFEM_ASSERT(du.Height() >= p, "First dimension of du is too small"); MFEM_ASSERT(du.Width() >= p, "Second dimension of du is too small"); #ifdef MFEM_THREAD_SAFE Vector V_T_vtmp1; Vector V_T_vtmp2; #endif Vector &P_i = V_T_vtmp1; Vector &P_j = V_T_vtmp2; P_i.SetSize(p); CalcHomogenizedScaLegendre(p-1, s[0], s[1], P_i); P_j.SetSize(p); for (int i=0; i= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sds.Size() >= 3, "Size of sds must be 3 or larger"); MFEM_ASSERT(sdsxds.Size() >= 3, "Size of sdsxds must be 3 or larger"); MFEM_ASSERT(grad_mu.Size() >= 3, "Size of grad_mu must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector VT_T_vtmp1; Vector VT_T_vtmp2; DenseMatrix VT_T_mtmp1; DenseTensor VT_T_ttmp1; #endif Vector ms({mu * s(0), mu * s(1), s(2)}); Vector s2(s.GetData(), 2); Vector &P_i = VT_T_vtmp1; P_i.SetSize(p); CalcHomogenizedScaLegendre(p-1, ms[0], ms[1], P_i); DenseMatrix &EE0 = VT_T_mtmp1; EE0.SetSize(1,3); Vector EE(EE0.GetData(), 3); E_E(1, s2, sds, EE0); Vector dmuxEE(3); grad_mu.cross3D(EE, dmuxEE); DenseTensor &VT00 = VT_T_ttmp1; VT00.SetSize(1,1,3); V_T(1, s, sdsxds, VT00); Vector &J_j = VT_T_vtmp2; J_j.SetSize(p); u = 0.0; for (int i=0; i= 1, "Polynomial order must be one or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(sds.Size() >= 3, "Size of sds must be 3 or larger"); MFEM_ASSERT(sdsxds.Size() >= 3, "Size of sdsxds must be 3 or larger"); MFEM_ASSERT(grad_s2.Size() >= 3, "Size of grad_s2 must be 3 or larger"); MFEM_ASSERT(grad_mu.Size() >= 3, "Size of grad_mu must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); MFEM_ASSERT(du.Height() >= p, "First dimension of du is too small"); MFEM_ASSERT(du.Width() >= p, "Second dimension of du is too small"); #ifdef MFEM_THREAD_SAFE Vector VT_T_vtmp1; Vector VT_T_vtmp2; DenseMatrix VT_T_mtmp1; DenseTensor VT_T_ttmp1; #endif Vector ms({mu * s(0), mu * s(1), s(2)}); Vector s2(s.GetData(), 2); Vector &P_i = VT_T_vtmp1; P_i.SetSize(p); CalcHomogenizedScaLegendre(p-1, ms[0], ms[1], P_i); DenseMatrix &EE0 = VT_T_mtmp1; EE0.SetSize(1,3); Vector EE(EE0.GetData(), 3); E_E(1, s2, sds, EE0); Vector dmuxEE(3); grad_mu.cross3D(EE, dmuxEE); Vector EExds2(3); EE.cross3D(grad_s2, EExds2); DenseTensor &VT00 = VT_T_ttmp1; VT00.SetSize(1,1,3); V_T(1, s, sdsxds, VT00); Vector &J_j = VT_T_vtmp2; J_j.SetSize(p); Vector EV(3); u = 0.0; du = 0.0; for (int i=0; i= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(sx.Size() >= 2, "Size of sx must be 2 or larger"); MFEM_ASSERT(grad_sx.Height() >= 2, "First dimension of grad_sx must be 2 or larger"); MFEM_ASSERT(grad_sx.Width() >= 3, "Second dimension of grad_sx must be 3 or larger"); MFEM_ASSERT(sy.Size() >= 2, "Size of sy must be 2 or larger"); MFEM_ASSERT(grad_sy.Height() >= 2, "First dimension of grad_sy must be 2 or larger"); MFEM_ASSERT(grad_sy.Width() >= 3, "Second dimension of grad_sy must be 3 or larger"); MFEM_ASSERT(grad_t.Size() >= 3, "Size of grad_t must be 3 or larger"); MFEM_ASSERT(u.SizeI() >= p+1, "First dimension of u is too small"); MFEM_ASSERT(u.SizeJ() >= p+1, "Second dimension of u is too small"); MFEM_ASSERT(u.SizeK() >= 3, "Third dimension of u must be 3 or larger"); #ifdef MFEM_THREAD_SAFE Vector V_L_vtmp1; Vector V_L_vtmp2; DenseMatrix V_L_mtmp1; DenseMatrix V_L_mtmp2; #endif Vector &phi_E_i = V_L_vtmp1; Vector &phi_E_j = V_L_vtmp2; DenseMatrix &dphi_E_i = V_L_mtmp1; DenseMatrix &dphi_E_j = V_L_mtmp2; Vector grad_t3(grad_t.GetData(), 3); phi_E_i.SetSize(p+1); dphi_E_i.SetSize(p+1, grad_sx.Width()); phi_E(p, sx, grad_sx, phi_E_i, dphi_E_i); phi_E_j.SetSize(p+1); dphi_E_j.SetSize(p+1, grad_sy.Width()); phi_E(p, sy, grad_sy, phi_E_j, dphi_E_j); Vector dphii(3); Vector dphij(3); Vector dphidphi(3); Vector phidphi(3); Vector dtphidphi(3); for (int j=2; j<=p; j++) { for (int l=0; l<3; l++) { dphij[l] = dphi_E_j(j, l); } for (int i=2; i<=p; i++) { for (int l=0; l<3; l++) { dphii[l] = dphi_E_i(i, l); } dphii.cross3D(dphij, dphidphi); add(phi_E_i(i), dphij, -phi_E_j(j), dphii, phidphi); grad_t3.cross3D(phidphi, dtphidphi); for (int l=0; l<3; l++) { u(i, j, l) = t * (t * dphidphi(l) + dtphidphi(l)); } } } } void FuentesPyramid::V_R(int p, Vector s, const DenseMatrix &grad_s, real_t mu, Vector dmu, real_t t, Vector dt, DenseMatrix &u) const { MFEM_ASSERT(p >= 2, "Polynomial order must be two or larger"); MFEM_ASSERT(s.Size() >= 2, "Size of s must be 2 or larger"); MFEM_ASSERT(grad_s.Height() >= 2, "First dimension of grad_s must be 2"); MFEM_ASSERT(grad_s.Width() >= 3, "Second dimension of grad_s must be 3"); MFEM_ASSERT(dmu.Size() >= 3, "Size of dmu must be 3 or larger"); MFEM_ASSERT(dt.Size() >= 3, "Size of dt must be 3 or larger"); MFEM_ASSERT(u.Height() >= p+1, "First dimension of u is too small"); MFEM_ASSERT(u.Width() >= 3, "Second dimension of u is too small"); #ifdef MFEM_THREAD_SAFE Vector V_R_vtmp; DenseMatrix V_R_mtmp; #endif Vector &phi_E_i = V_R_vtmp; DenseMatrix &dphi_E_i = V_R_mtmp; phi_E_i.SetSize(p+1); dphi_E_i.SetSize(p+1, grad_s.Width()); phi_E(p, s, grad_s, phi_E_i, dphi_E_i); u.SetRow(0, 0.0); u.SetRow(1, 0.0); Vector dmu3(dmu.GetData(), 3); Vector dt3(dt.GetData(), 3); Vector dphit2(3); Vector dphixdmu(3); Vector dphi(3); for (int i=2; i<=p; i++) { // dphi_E_i.GetRow(i, dphi); for (int l=0; l<3; l++) { dphi[l] = dphi_E_i(i, l); } add(t * t, dphi, 2.0 * t * phi_E_i(i), dt3, dphit2); dphit2.cross3D(dmu3, dphixdmu); // u.SetRow(i, dphixdmu); for (int l=0; l<3; l++) { u(i, l) = dphixdmu(l); } } } } // namespace mfem