28int main(
int argc,
char *argv[]) {
34 moab::Core mb_instance;
35 moab::Interface &moab = mb_instance;
37 MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
40 PetscBool flg_mesh_file = PETSC_TRUE;
41 PetscBool flg_out_file = PETSC_TRUE;
42 PetscBool flg_data_file = PETSC_TRUE;
44 char mesh_file_name[255];
46 char data_file_name[255];
48 int nb_side_nodes = 1;
49 double side_length = 1.0;
50 double mesh_height = 1.0;
51 double mesh_scale = 1.0;
55 PetscOptionsBegin(PETSC_COMM_WORLD,
"",
"Project Roughness",
nullptr);
56 CHKERR PetscOptionsString(
"-file_name",
"mesh file name",
"",
"mesh.h5m",
57 mesh_file_name, 255, &flg_mesh_file);
58 CHKERR PetscOptionsString(
"-output_file",
"out file name",
"",
"out.h5m",
60 CHKERR PetscOptionsString(
"-surface_data_file",
"data file name",
"",
61 "data.txt", data_file_name, 255, &flg_data_file);
63 CHKERR PetscOptionsInt(
"-mesh_side_nodes_num",
64 "number of nodes on each side",
"", nb_side_nodes,
65 &nb_side_nodes, PETSC_NULLPTR);
66 CHKERR PetscOptionsReal(
"-mesh_side_length",
"side length",
"", side_length,
67 &side_length, PETSC_NULLPTR);
68 CHKERR PetscOptionsReal(
"-mesh_scale",
"mesh scale",
"", mesh_scale,
69 &mesh_scale, PETSC_NULLPTR);
70 CHKERR PetscOptionsReal(
"-mesh_height",
"vertical height of the mesh",
"",
71 mesh_height, &mesh_height, PETSC_NULLPTR);
72 CHKERR PetscOptionsReal(
"-tolerance",
"Tolerance for coordinate matching",
73 "",
tol, &
tol, PETSC_NULLPTR);
74 CHKERR PetscOptionsInt(
"-atom_test",
"atom test number",
"", 0, &
atom_test,
81 MOFEM_LOG_C(
"SELF", Sev::inform,
"Mesh side length: %.2f", side_length);
82 MOFEM_LOG_C(
"SELF", Sev::inform,
"Mesh height: %.2f", mesh_height);
83 MOFEM_LOG_C(
"SELF", Sev::inform,
"Number of nodes on each side: %d",
86 std::ifstream infile(data_file_name, std::ios::in);
87 std::vector<double> surface_data;
88 std::vector<bool> surface_check;
90 if (!infile.is_open()) {
92 "Could not open surface data file");
96 while (std::getline(infile, line)) {
97 std::istringstream iss(line);
100 surface_data.push_back(num);
104 int expected_surface_nodes = nb_side_nodes * nb_side_nodes;
106 if ((
int)surface_data.size() != expected_surface_nodes) {
108 "Surface data size mismatch: expected %d nodes (%d x %d), got %d",
109 expected_surface_nodes, nb_side_nodes, nb_side_nodes,
110 (
int)surface_data.size());
112 double max_surf_height =
113 *std::max_element(std::begin(surface_data), std::end(surface_data));
114 for (
auto &node_data : surface_data) {
115 node_data -= max_surf_height;
118 surface_check.resize(surface_data.size());
119 std::fill(surface_check.begin(), surface_check.end(),
false);
121 if (flg_mesh_file != PETSC_TRUE) {
122 SETERRQ(PETSC_COMM_SELF, 1,
"*** ERROR -my_file (MESH FILE NEEDED)");
128 CHKERR moab.load_file(mesh_file_name, 0, option);
129 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab,
MYPCOMM_INDEX);
131 pcomm =
new ParallelComm(&moab, PETSC_COMM_WORLD);
135 "Projecting surface data on the mesh");
137 Range elastic_elems, elastic_nodes;
138 CHKERR moab.get_entities_by_dimension(
139 0, 3, elastic_elems);
140 CHKERR moab.get_connectivity(elastic_elems, elastic_nodes);
142 const double edge_length = side_length / (
double)(nb_side_nodes - 1);
144 MOFEM_LOG_C(
"SELF", Sev::inform,
"Actual edge length per element: %.8f",
147 auto flat_ind = [&](
int i,
int j) {
return j * nb_side_nodes +
i; };
149 for (Range::iterator nit = elastic_nodes.begin();
150 nit != elastic_nodes.end(); nit++) {
152 CHKERR moab.get_coords(&*nit, 1, coords);
153 double x = coords[0];
154 double y = coords[1];
155 double z = coords[2];
156 double height_coef = (mesh_height + z) / mesh_height;
159 double pos_x = x / edge_length;
160 double pos_y = y / edge_length;
162 double pos_x_round = std::round(pos_x);
163 double pos_y_round = std::round(pos_y);
165 if (std::abs(pos_x_round - pos_x) <
tol) {
168 if (std::abs(pos_y_round - pos_y) <
tol) {
172 int i,
j, i_next, j_next;
173 i = i_next = (int)std::floor(pos_x);
174 j = j_next = (int)std::floor(pos_y);
176 if (std::abs(pos_x - std::floor(pos_x)) <
tol) {
179 ksi = (pos_x - std::floor(pos_x)) * 2.0 - 1.0;
180 if (ksi < -1. - tol || ksi > 1. +
tol) {
182 "Wrong ksi for i = %d, j = %d",
i,
j);
186 if (std::abs(pos_y - std::floor(pos_y)) <
tol) {
189 eta = (pos_y - std::floor(pos_y)) * 2.0 - 1.0;
190 if (eta < -1. - tol || eta > 1. +
tol) {
192 "Wrong eta for i = %d, j = %d",
i,
j);
196 if (std::abs(z) <
tol) {
197 if (std::abs(pos_x - std::floor(pos_x)) >
tol ||
198 std::abs(pos_y - std::floor(pos_y)) >
tol) {
200 "Cannot find data for surface node i = %d, j = %d",
i,
j);
202 if (surface_check[flat_ind(
i,
j)]) {
204 "Data used twice for surface node i = %d, j = %d",
i,
j);
206 surface_check[flat_ind(
i,
j)] =
true;
210 std::array<double, 4> shape_quad;
211 shape_quad[0] = 0.25 * (1.0 - ksi) * (1.0 -
eta);
212 shape_quad[1] = 0.25 * (1.0 + ksi) * (1.0 -
eta);
213 shape_quad[2] = 0.25 * (1.0 + ksi) * (1.0 +
eta);
214 shape_quad[3] = 0.25 * (1.0 - ksi) * (1.0 +
eta);
216 std::array<double, 4> gap_quad;
217 gap_quad[0] = surface_data[flat_ind(
i,
j)];
218 gap_quad[1] = surface_data[flat_ind(i_next,
j)];
219 gap_quad[2] = surface_data[flat_ind(i_next, j_next)];
220 gap_quad[3] = surface_data[flat_ind(
i, j_next)];
222 for (
int k : {0, 1, 2, 3}) {
223 coords[2] += shape_quad[
k] * gap_quad[
k] * height_coef;
225 CHKERR moab.set_coords(&*nit, 1, coords);
228 for (
int i = 0;
i < nb_side_nodes;
i++) {
229 for (
int j = 0;
j < nb_side_nodes;
j++) {
230 if (!surface_check[flat_ind(
i,
j)]) {
232 "Data not used for surface node i = %d, j = %d",
i,
j);
236 MOFEM_LOG_C(
"SELF", Sev::inform,
"%s",
"Scaling the mesh");
238 for (Range::iterator nit = elastic_nodes.begin();
239 nit != elastic_nodes.end(); nit++) {
241 CHKERR moab.get_coords(&*nit, 1, coords);
242 for (
int i : {0, 1, 2}) {
243 coords[
i] *= mesh_scale;
245 CHKERR moab.set_coords(&*nit, 1, coords);
249 CHKERR moab.get_entities_by_type(0, MBTET, tets);
253 "No tetrahedral elements found, skipping quality and volume checks");
256 double total_volume = 0.0;
257 double min_quality = std::numeric_limits<double>::max();
259 for (
auto tet : tets) {
264 CHKERR moab.get_connectivity(tet, conn, num_nodes,
true);
265 CHKERR moab.get_coords(conn, num_nodes, coords);
268 if (!std::isnormal(q) || q <= 0) {
270 "invalid tet quality %.6e", q);
272 min_quality = std::min(min_quality, q);
277 MOFEM_LOG_C(
"SELF", Sev::inform,
"Min quality of the final mesh = %.6e",
279 MOFEM_LOG_C(
"SELF", Sev::inform,
"Total volume of the final mesh: %.4f",
283 double expected_volume = 1.98;
284 double diff = std::abs(total_volume - expected_volume);
288 "Atom test %d failed: Unexpected total tet volume computed: "
289 "%.6e (Expected %.6e)",
290 atom_test, total_volume, expected_volume);