Hi

I wrote a code to implement a manifold of an ellipsoid surface embedded in 
3d space using 6 chart manifolds corresponding to the 6 faces of a cube. So 
if the ellipsoid equation is $Ax^2 + By^2 + Cz^2 = R^2$, then I have the 
following equations:

z_plus(x, y) = sqrt(R^2 - Ax^2 - By^2) / C
z_minus(x, y) = - sqrt(R^2 - Ax^2 - By^2) / C

Similarly, I have analogous equations for x_plus(y, z), x_minus(y, z), 
y_plus(z, x), and y_plus(z, x).

1. I make an unrefined hyper_sphere<2,3> mesh which is just a cube.
2. Then I transform the sphere into an ellipsoid based on the values of A, 
B, and C.
3. I reset the SphericalManifold from the triangulation.
4. I detect each of the faces using the face centers and attach one of the 
six manifolds explained above to each of the faces.
5. Then I refine the mesh globally. The manifold id of the children faces 
should be inherited from the original 6 faces.

Expected result:
After a few global refinements, I should get something like an ellipsoid.

The result I get:
[image: Screenshot from 2025-01-30 19-30-24.png]

I have attached my code and the CMakeLists.txt. Please help me understand 
the error.

Regards,
Amit

-- 
The information contained in this electronic communication is intended 
solely for the individual(s) or entity to which it is addressed. It may 
contain proprietary, confidential and/or legally privileged information. 
Any review, retransmission, dissemination, printing, copying or other use 
of, or taking any action in reliance on the contents of this information by 
person(s) or entities other than the intended recipient is strictly 
prohibited and may be unlawful. If you have received this communication in 
error, please notify us by responding to this email or telephone and 
immediately and permanently delete all copies of this message and any 
attachments from your system(s). The contents of this message do not 
necessarily represent the views or policies of BITS Pilani.

-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dealii+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/dealii/3af95a1d-1593-4cf3-ae01-67861baecaf5n%40googlegroups.com.
# #
#  CMake script for the step-3 tutorial program:
# #

# Set the name of the project and target:
# set(TARGET "my_code")
set(TARGET "ellipsoid_mesh")

# Declare all source files the target consists of. Here, this is only
# the one step-X.cc file, but as you expand your project you may wish
# to add other source files as well. If your project becomes much larger,
# you may want to either replace the following statement by something like
#    file(GLOB_RECURSE TARGET_SRC  "source/*.cc")
#    file(GLOB_RECURSE TARGET_INC  "include/*.h")
#    set(TARGET_SRC ${TARGET_SRC}  ${TARGET_INC})
# or switch altogether to the large project CMakeLists.txt file discussed
# in the "CMake in user projects" page accessible from the "User info"
# page of the documentation.
set(TARGET_SRC
  ${TARGET}.cc
  )

# Usually, you will not need to modify anything beyond this point...

cmake_minimum_required(VERSION 3.13.4)

find_package(deal.II 9.4.1
  HINTS ${deal.II_DIR} ${DEAL_II_DIR} ../ ../../ $ENV{DEAL_II_DIR}
  )
if(NOT ${deal.II_FOUND})
  message(FATAL_ERROR "\n"
    "*** Could not locate a (sufficiently recent) version of deal.II. ***\n\n"
    "You may want to either pass a flag -DDEAL_II_DIR=/path/to/deal.II to 
cmake\n"
    "or set an environment variable \"DEAL_II_DIR\" that contains this path."
    )
endif()

deal_ii_initialize_cached_variables()
project(${TARGET})
deal_ii_invoke_autopilot()
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/manifold.h>
#include <deal.II/grid/tria.h>

#include <cmath>
#include <memory>

using namespace dealii;

/**
 * A manifold of the surface Ax^2 + By^2 + Cz^2 = R^2
 */
class EllipsoidalManifold : public ChartManifold<2, 3, 2> {
public:
  enum PatchDirection : int {
    x_plus,
    x_minus,
    y_plus,
    y_minus,
    z_plus,
    z_minus
  };

  EllipsoidalManifold(double R, double A, double B, double C, PatchDirection pd)
      : _R(R), _A(A), _B(B), _C(C), _pd(pd) {}

  Point<3> push_forward(const Point<2> &chart_point) const override {
    double x1 = chart_point[0];
    double x2 = chart_point[1];
    double x3;
    Point<3> output;
    switch (_pd) {
    case x_plus:
      x3 = _push_forward_common(_B, _C, _A, x1, x2, true);
      output[0] = x3;
      output[1] = x1;
      output[2] = x2;
      break;
    case x_minus:
      x3 = _push_forward_common(_B, _C, _A, x1, x2, false);
      output[0] = x3;
      output[1] = x1;
      output[2] = x2;
      break;
    case y_plus:
      x3 = _push_forward_common(_C, _A, _B, x1, x2, true);
      output[0] = x2;
      output[1] = x3;
      output[2] = x1;
      break;
    case y_minus:
      x3 = _push_forward_common(_B, _C, _A, x1, x2, false);
      output[0] = x2;
      output[1] = x3;
      output[2] = x1;
      break;
    case z_plus:
      x3 = _push_forward_common(_A, _B, _C, x1, x2, true);
      output[0] = x1;
      output[1] = x2;
      output[2] = x3;
      break;
    case z_minus:
      x3 = _push_forward_common(_A, _B, _C, x1, x2, false);
      output[0] = x1;
      output[1] = x2;
      output[2] = x3;
      break;
    }
    std::cout << "Push forward: " << chart_point << " -> " << output << std::endl;
    return output;
  }

  Point<2> pull_back(const Point<3> &space_point) const override {
    Point<2> output;
    switch (_pd) {
    case x_plus:
      output[0] = space_point[1];
      output[1] = space_point[2];
      break;
    case x_minus:
      output[0] = space_point[1];
      output[1] = space_point[2];
      break;
    case y_plus:
      output[0] = space_point[2];
      output[1] = space_point[0];
      break;
    case y_minus:
      output[0] = space_point[2];
      output[1] = space_point[0];
      break;
    case z_plus:
      output[0] = space_point[0];
      output[1] = space_point[1];
      break;
    case z_minus:
      output[0] = space_point[0];
      output[1] = space_point[1];
      break;
    }
    std::cout << "Pull back: " << space_point << " -> " << output << std::endl;
    return output;
  }

  std::unique_ptr<Manifold<2, 3>> clone() const override {
    return std::make_unique<EllipsoidalManifold>(_R, _A, _B, _C, _pd);
  }

private:
  double _push_forward_common(double coeff1, double coeff2, double coeff3,
                              double x1, double x2,
                              bool positiveDirection) const {
    double x3 =
        std::sqrt(_R * _R - coeff1 * x1 * x1 - coeff2 * x2 * x2) / coeff3;
    if (!positiveDirection) {
      x3 *= -1;
    }
    return x3;
  }

  double _R, _A, _B, _C;
  PatchDirection _pd;
};

int main(int argc, char **argv) {
  // Make the manifold
  double R = 1;
  double A = 1;
  double B = 16;
  double C = 64;

  EllipsoidalManifold x_plus_manifold(R, A, B, C, EllipsoidalManifold::x_plus);
  EllipsoidalManifold x_minus_manifold(R, A, B, C,
                                       EllipsoidalManifold::x_minus);
  EllipsoidalManifold y_plus_manifold(R, A, B, C, EllipsoidalManifold::y_plus);
  EllipsoidalManifold y_minus_manifold(R, A, B, C,
                                       EllipsoidalManifold::y_minus);
  EllipsoidalManifold z_plus_manifold(R, A, B, C, EllipsoidalManifold::z_plus);
  EllipsoidalManifold z_minus_manifold(R, A, B, C,
                                       EllipsoidalManifold::z_minus);

  for (int i = 0; i < 3; ++i) {
    // Make a spherical mesh
    Triangulation<2, 3> triangulation;
    GridGenerator::hyper_sphere<3>(triangulation, Point<3>(), R);

    // Transform the sphere to an ellipsoid
    GridTools::transform(
        [A, B, C](const Point<3> &p) -> Point<3> {
          return Point<3>(p[0] / std::sqrt(A), p[1] / std::sqrt(B),
                          p[2] / std::sqrt(C));
        },
        triangulation);

    // Make all the manifolds flat
    triangulation.reset_all_manifolds();

    // Set new manifolds on the unrefined hypersphere
    for (auto &cell : triangulation.active_cell_iterators()) {
      Point<3> center = cell->center();
      // A hyper-sphere without any global refinement is a rectangular block
      // with 6 faces
      if (abs(center[1]) < 1e-6 && abs(center[2]) < 1e-6 && center[0] > 0) {
        std::cout << "Found x+ face." << std::endl;
        cell->set_all_manifold_ids(0);
      } else if (abs(center[1]) < 1e-6 && abs(center[2]) < 1e-6 &&
                 center[0] < 0) {
        std::cout << "Found x- face." << std::endl;
        cell->set_all_manifold_ids(1);
      } else if (abs(center[2]) < 1e-6 && abs(center[0]) < 1e-6 &&
                 center[1] > 0) {
        std::cout << "Found y+ face." << std::endl;
        cell->set_all_manifold_ids(2);
      } else if (abs(center[2]) < 1e-6 && abs(center[0]) < 1e-6 &&
                 center[1] < 0) {
        std::cout << "Found y- face." << std::endl;
        cell->set_all_manifold_ids(3);
      } else if (abs(center[0]) < 1e-6 && abs(center[1]) < 1e-6 &&
                 center[2] > 0) {
        std::cout << "Found z+ face." << std::endl;
        cell->set_all_manifold_ids(4);
      } else if (abs(center[0]) < 1e-6 && abs(center[1]) < 1e-6 &&
                 center[2] < 0) {
        std::cout << "Found z- face." << std::endl;
        cell->set_all_manifold_ids(5);
      }
    }
    // Define new manifold ids for the triangulation
    triangulation.set_manifold(0, x_plus_manifold);
    triangulation.set_manifold(1, x_minus_manifold);
    triangulation.set_manifold(2, y_plus_manifold);
    triangulation.set_manifold(3, y_minus_manifold);
    triangulation.set_manifold(4, z_plus_manifold);
    triangulation.set_manifold(5, z_minus_manifold);

    // Refine the mesh globally
    if (i > 0){
      triangulation.refine_global(i);
    }

    // Output the final mesh
    GridOut grid_out;
    const std::string filename = "mesh_" + std::to_string(i) + ".vtu";
    std::ofstream outfile(filename);
    grid_out.write_vtu(triangulation, outfile);
  }
  return 0;
}

Reply via email to