/*! @par Revision history: - 21.11.2006, c */ int32 bf_buildFTF( FMField *ftf, FMField *ftf1 ) { int32 iqp, ir, ic, nEPR, nEPC, nQP, dim; float64 *pftf, *pftf1; float64 val; fmf_fillC( ftf, 0.0 ); nEPR = ftf1->nRow; nEPC = ftf1->nCol; nQP = ftf1->nLev; dim = ftf->nRow / nEPR; for (iqp = 0; iqp < nQP; iqp++) { pftf1 = FMF_PtrLevel( ftf1, iqp ); pftf = FMF_PtrLevel( ftf, iqp ); for (ir = 0; ir < nEPR; ir++) { for (ic = 0; ic < nEPC; ic++) { val = pftf1[nEPC*ir+ic]; pftf[dim*nEPC*ir+ic] = val; if (dim == 1) continue; pftf[dim*nEPC*(nEPR+ir)+ic+nEPC] = val; if (dim == 2) continue; pftf[dim*nEPC*(2*nEPR+ir)+ic+2*nEPC] = val; } } } return( RET_OK ); }
/*! @a objA^T. @par Revision history: - 23.05.2005, c */ int32 fmf_sumLevelsTMulF( FMField *objR, FMField *objA, float64 *val ) { int32 il, ir, ic, wr, wc; float64 *pa, *pr; #ifdef DEBUG_FMF if ((objR->nRow != objA->nCol) || (objR->nCol != objA->nRow) || (objR->nLev != 1)) { errput( ErrHead "ERR_BadMatch (%d == %d, %d == %d, %d == 1)\n", objR->nRow, objA->nCol, objR->nCol, objA->nRow, objR->nLev ); } #endif wr = objR->nCol; pr = objR->val; wc = objA->nCol; fmf_fillC( objR, 0.0 ); for (il = 0; il < objA->nLev; il++) { pa = objA->val + objA->nCol * objA->nRow * il; for (ir = 0; ir < objR->nRow; ir++) { for (ic = 0; ic < objR->nCol; ic++) { pr[wr*ir+ic] += pa[wc*ic+ir] * val[il]; } } } return( RET_OK ); }
/*! @a in is a state vector stored as matrix (dim, nEP) - in->nLev == 1. @par Revision history: - 12.12.2005, c - 14.12.2005 */ int32 bf_act( FMField *out, FMField *bf, FMField *in ) { int32 iqp, ir, ic, nEP, nQP, dim; float64 *pout, *pbf; nEP = bf->nCol; nQP = bf->nLev; dim = in->nRow; #ifdef DEBUG_FMF if ((out->nRow != dim) || (out->nCol != 1) || (out->nLev != bf->nLev) || (in->nCol != nEP)) { errput( ErrHead "ERR_BadMatch: (%d %d %d), (%d %d %d), (%d %d %d)\n", out->nLev, out->nRow, out->nCol, bf->nLev, bf->nRow, bf->nCol, in->nLev, in->nRow, in->nCol ); } #endif fmf_fillC( out, 0.0 ); for (iqp = 0; iqp < nQP; iqp++) { pbf = FMF_PtrLevel( bf, iqp ); pout = FMF_PtrLevel( out, iqp ); for (ic = 0; ic < dim; ic++ ) { for (ir = 0; ir < nEP; ir++) { pout[ic] += pbf[ir] * in->val[nEP*ic+ir]; } } } return( RET_OK ); }
int32 eval_bernstein_basis(FMField *funs, FMField *ders, float64 x, uint32 degree) { uint32 ip, ifun; uint32 n_fun = degree + 1; float64 prev, tmp; fmf_fillC(funs, 0.0); fmf_fillC(ders, 0.0); funs->val[0] = 1.0; if (degree == 0) { return(RET_OK); } for (ip = 1; ip < n_fun - 1; ip++) { prev = 0.0; for (ifun = 0; ifun < ip + 1; ifun++) { tmp = x * funs->val[ifun]; funs->val[ifun] = (1.0 - x) * funs->val[ifun] + prev; prev = tmp; } } ders->val[0] = degree * (- funs->val[0]); for (ifun = 1; ifun < n_fun; ifun++) { ders->val[ifun] = degree * (funs->val[ifun - 1] - funs->val[ifun]); } prev = 0.0; for (ifun = 0; ifun < n_fun; ifun++) { tmp = x * funs->val[ifun]; funs->val[ifun] = (1.0 - x) * funs->val[ifun] + prev; prev = tmp; } return(RET_OK); }
/*! @par Revision history: - 28.11.2005, c - 30.05.2007 */ int32 laplace_build_gtg( FMField *out, FMField *gc ) { int32 iqp, ir, ic, nEP, nQP, nCol; float64 *pout, *pg1, *pg2, *pg3; nEP = gc->nCol; nQP = gc->nLev; nCol = out->nCol; fmf_fillC( out, 0.0 ); switch (gc->nRow) { case 3: for (iqp = 0; iqp < nQP; iqp++) { pg1 = FMF_PtrLevel( gc, iqp ); pg2 = pg1 + nEP; pg3 = pg2 + nEP; pout = FMF_PtrLevel( out, iqp ); for (ir = 0; ir < nEP; ir++) { for (ic = 0; ic < nEP; ic++) { pout[ic] = pg1[ir] * pg1[ic] + pg2[ir] * pg2[ic] + pg3[ir] * pg3[ic]; } pout += nCol; } } break; case 2: for (iqp = 0; iqp < nQP; iqp++) { pg1 = FMF_PtrLevel( gc, iqp ); pg2 = pg1 + nEP; pout = FMF_PtrLevel( out, iqp ); for (ir = 0; ir < nEP; ir++) { for (ic = 0; ic < nEP; ic++) { pout[ic] = pg1[ir] * pg1[ic] + pg2[ir] * pg2[ic]; } pout += nCol; } } break; default: errput( ErrHead "ERR_Switch\n" ); return( RET_Fail ); } return( RET_OK ); }
/*! Act transposed. @par Revision history: - 12.12.2005, c - 20.12.2005 */ int32 bf_actt( FMField *out, FMField *bf, FMField *in ) { int32 iqp, ir, ic, ii, nEP, nQP, dim; float64 *pout, *pbf, *pin; nEP = bf->nCol; nQP = bf->nLev; dim = in->nRow; #ifdef DEBUG_FMF if ((out->nCol != in->nCol) || (out->nRow != (dim * nEP)) || (out->nLev != bf->nLev)) { errput( ErrHead "ERR_BadMatch: (%d %d %d), (%d %d %d), (%d %d %d)\n", out->nLev, out->nRow, out->nCol, bf->nLev, bf->nRow, bf->nCol, in->nLev, in->nRow, in->nCol ); } #endif fmf_fillC( out, 0.0 ); for (iqp = 0; iqp < nQP; iqp++) { pbf = FMF_PtrLevel( bf, iqp ); pout = FMF_PtrLevel( out, iqp ); pin = FMF_PtrLevel( in, iqp ); for (ir = 0; ir < dim; ir++) { for (ic = 0; ic < out->nCol; ic++) { for (ii = 0; ii < nEP; ii++) { pout[out->nCol*ii+ic] = pbf[ii] * (*pin); } pin++; } pout += out->nCol * nEP; } } return( RET_OK ); }
/*! @par Revision history: - 26.04.2001, c - 19.01.2004, adopted from rcfem2 */ int32 fmf_sumLevelsMulF( FMField *objR, FMField *objA, float64 *val ) { int32 il, i; float64 *pa; #ifdef DEBUG_FMF if ((objR->nRow != objA->nRow) || (objR->nCol != objA->nCol) || (objR->nLev != 1)) { errput( ErrHead "ERR_BadMatch (%d == %d, %d == %d, %d == 1)\n", objR->nRow, objA->nRow, objR->nCol, objA->nCol, objR->nLev ); } #endif fmf_fillC( objR, 0.0 ); for (il = 0; il < objA->nLev; il++) { pa = objA->val + objA->nCol * objA->nRow * il; for (i = 0; i < (objR->nRow * objR->nCol); i++) { objR->val[i] += pa[i] * val[il]; } } return( RET_OK ); }
int32 refc_find_ref_coors(FMField *ref_coors, int32 *cells, int32 n_cells, int32 *status, int32 n_status, FMField *coors, Mesh *mesh, int32 *candidates, int32 n_candidates, int32 *offsets, int32 n_offsets, int32 allow_extrapolation, float64 qp_eps, float64 close_limit, void *_ctx) { BasisContext *ctx = (BasisContext *) _ctx; int32 ip, ic, ii, imin, ok, xi_ok, ret = RET_OK; int32 D = mesh->topology->max_dim; int32 nc = mesh->geometry->dim; float64 d_min, dist; float64 *mesh_coors = mesh->geometry->coors; float64 buf3[3]; FMField point[1], e_coors[1], xi[1]; Indices cell_vertices[1]; MeshEntity cell_ent[1]; MeshConnectivity *cD0 = 0; // D -> 0 mesh_setup_connectivity(mesh, D, 0); cD0 = mesh->topology->conn[IJ(D, D, 0)]; fmf_pretend_nc(point, coors->nRow, 1, 1, nc, coors->val); fmf_pretend_nc(xi, 1, 1, 1, nc, buf3); fmf_fillC(xi, 0.0); ctx->is_dx = 0; for (ip = 0; ip < coors->nRow; ip++) { FMF_SetCell(point, ip); if (offsets[ip] == offsets[ip+1]) { status[ip] = 5; cells[ip] = 0; for (ii = 0; ii < nc; ii++) { ref_coors->val[nc*ip+ii] = 0.0; } continue; } ok = xi_ok = 0; d_min = 1e10; imin = candidates[offsets[ip]]; for (ic = offsets[ip]; ic < offsets[ip+1]; ic++) { /* output("***** %d %d %d\n", ip, ic, candidates[ic]); */ ctx->iel = candidates[ic]; cell_ent->ii = candidates[ic]; me_get_incident2(cell_ent, cell_vertices, cD0); _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); if (xi_ok) { if (dist < qp_eps) { imin = cell_ent->ii; ok = 1; break; } else if (dist < d_min) { d_min = dist; imin = cell_ent->ii; } } else if (dist < d_min) { d_min = dist; imin = cell_ent->ii; } } /* output("-> %d %d %d %.3e\n", imin, xi_ok, ok, d_min); */ cells[ip] = imin; if (ok != 1) { if (!xi_ok) { status[ip] = 4; } else if (allow_extrapolation) { if (sqrt(d_min) < close_limit) { status[ip] = 1; } else { status[ip] = 2; } } else { status[ip] = 3; } } else { status[ip] = 0; } for (ii = 0; ii < nc; ii++) { ref_coors->val[nc*ip+ii] = xi->val[ii]; } ERR_CheckGo(ret); } end_label: return(ret); }
int32 refc_find_ref_coors_convex(FMField *ref_coors, int32 *cells, int32 n_cells, int32 *status, int32 n_status, FMField *coors, Mesh *mesh, FMField *centroids, FMField *normals0, FMField *normals1, int32 *ics, int32 n_ics, int32 allow_extrapolation, float64 qp_eps, float64 close_limit, void *_ctx) { BasisContext *ctx = (BasisContext *) _ctx; int32 ip, ic, icell, icell_max = 0, ii, imin, ik, ok, ret = RET_OK; int32 xi_ok, hexa_reverse; int32 D = mesh->topology->max_dim; int32 dim = D - 1; int32 nc = mesh->geometry->dim; uint32 tri0[] = {0, 1, 3}; uint32 tri1[] = {2, 3, 1}; uint32 cell, cell0, cell00, facet; uint32 *noffs, *foffs, aux[2]; uint32 *cell_types = mesh->topology->cell_types; float64 d_min, tmin, tt, dist; float64 *mesh_coors = mesh->geometry->coors; float64 buf3[3]; float64 buf9[9]; FMField point[1], centroid[1], _normals0[1], _normals1[1], e_coors[1], xi[1]; Indices cell_vertices[1]; MeshEntity cell_ent[1]; MeshConnectivity *cD0 = 0; // D -> 0 MeshConnectivity *c0D = 0; // 0 -> D MeshConnectivity *cDd = 0; // cell -> facet MeshConnectivity *cdD = 0; // facet -> cell MeshConnectivity *loc = 0; MeshConnectivity **locs = 0; mesh_setup_connectivity(mesh, D, 0); cD0 = mesh->topology->conn[IJ(D, D, 0)]; mesh_setup_connectivity(mesh, 0, D); c0D = mesh->topology->conn[IJ(D, 0, D)]; mesh_setup_connectivity(mesh, D, dim); cDd = mesh->topology->conn[IJ(D, D, dim)]; noffs = cDd->offsets; mesh_setup_connectivity(mesh, dim, D); cdD = mesh->topology->conn[IJ(D, dim, D)]; // Local entities - reference cell edges or faces. locs = (dim == 1) ? mesh->entities->edges : mesh->entities->faces; fmf_pretend_nc(point, coors->nRow, 1, 1, nc, coors->val); fmf_pretend_nc(centroid, centroids->nRow, 1, 1, nc, centroids->val); fmf_pretend_nc(xi, 1, 1, 1, nc, buf3); fmf_fillC(xi, 0.0); ctx->is_dx = 0; for (ip = 0; ip < coors->nRow; ip++) { ic = ics[ip]; /* output("***** %d %d\n", ip, ic); */ FMF_SetCell(point, ip); /* fmf_print(point, stdout, 0); */ cell = cell0 = cell00 = c0D->indices[c0D->offsets[ic]]; ok = icell = hexa_reverse = imin = 0; d_min = 1e10; while (1) { /* output("*** %d %d %d\n", icell, cell, hexa_reverse); */ FMF_SetCell(centroid, cell); /* fmf_print(centroid, stdout, 0); */ ctx->iel = cell; cell_ent->ii = cell; me_get_incident2(cell_ent, cell_vertices, cD0); loc = locs[cell_types[cell]]; foffs = loc->offsets; if (cell_types[cell] != 4) { // No hexahedron -> planar facet. fmf_pretend_nc(_normals0, noffs[cell+1] - noffs[cell], 1, 1, nc, normals0->val + nc * noffs[cell]); tmin = 1e10; for (ii = 0; ii < loc->num; ii++) { FMF_SetCell(_normals0, ii); ik = loc->indices[foffs[ii]]; _intersect_line_plane(&tt, centroid->val, point->val, mesh_coors + nc * cell_vertices->indices[ik], _normals0->val, nc); if ((tt >= -qp_eps) && (tt < (tmin + qp_eps))) { imin = ii; tmin = tt; } } if (tmin >= (1.0 - qp_eps)) { _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); /* fmf_print(e_coors, stdout, 0); */ xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } break; } } else { // Hexahedron -> non-planar facet in general. fmf_pretend_nc(_normals0, noffs[cell+1] - noffs[cell], 1, 1, nc, normals0->val + nc * noffs[cell]); fmf_pretend_nc(_normals1, noffs[cell+1] - noffs[cell], 1, 1, nc, normals1->val + nc * noffs[cell]); for (ii = 0; ii < loc->num; ii++) { FMF_SetCell(_normals0, ii); _get_tri_coors(buf9, loc->indices, foffs[ii], tri0, mesh_coors, cell_vertices->indices); _intersect_line_triangle(&tt, centroid->val, point->val, buf9, _normals0->val); if ((tt >= -qp_eps) && (tt < 1e10)) { ok = 2; imin = ii; if ((tt >= (1.0 - qp_eps)) || hexa_reverse) { _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } else { hexa_reverse = 1; } } break; } FMF_SetCell(_normals1, ii); _get_tri_coors(buf9, loc->indices, foffs[ii], tri1, mesh_coors, cell_vertices->indices); _intersect_line_triangle(&tt, centroid->val, point->val, buf9, _normals1->val); if ((tt >= -qp_eps) && (tt < 1e10)) { ok = 2; imin = ii; if ((tt >= (1.0 - qp_eps)) || hexa_reverse) { _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } else { hexa_reverse = 1; } } break; } } if (ok == 1) { break; } if (ok == 0) { errput("cannot intersect bilinear faces!\n"); ERR_CheckGo(ret); } } facet = cDd->indices[cDd->offsets[cell] + imin]; if ((cdD->offsets[facet+1] - cdD->offsets[facet]) == 2) { aux[0] = cdD->indices[cdD->offsets[facet]]; aux[1] = cdD->indices[cdD->offsets[facet]+1]; cell00 = cell0; cell0 = cell; cell = (aux[0] == cell) ? aux[1] : aux[0]; if (cell == cell00) { // Ping-pong between two cells. hexa_reverse = 1; } } else { // Boundary facet. ctx->iel = cell; cell_ent->ii = cell; me_get_incident2(cell_ent, cell_vertices, cD0); _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } else { ok = 0; } break; } icell++; icell_max = Max(icell, icell_max); if (icell > 10000) { errput("cannot find containing cell!\n"); ERR_CheckGo(ret); } } /* fmf_print(xi, stdout, 0); */ /* output("-> %d %d %d %.3e\n", cell, xi_ok, ok, d_min); */ cells[ip] = cell; if (ok != 1) { if (!xi_ok) { status[ip] = 4; } else if (allow_extrapolation) { // Try using minimum distance xi. if (sqrt(d_min) < close_limit) { status[ip] = 1; } else { status[ip] = 2; } } else { status[ip] = 3; } } else { status[ip] = 0; } for (ii = 0; ii < nc; ii++) { ref_coors->val[nc*ip+ii] = xi->val[ii]; } } /* output("%d\n", icell_max); */ end_label: return(ret); }