Salome HOME
4b144631558e2c979dbe574deabddc9f7a7bbfd6
[modules/hexablock.git] / src / HEXABLOCK / HexElements_ter.cxx
1 // C++ : Table d'hexaedres (Evol Versions 3)
2
3 // Copyright (C) 2009-2023  CEA, EDF
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 //
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 //
21
22 #include "HexElements.hxx"
23
24 #include "HexDocument.hxx"
25 #include "HexVector.hxx"
26 #include "HexVertex.hxx"
27 #include "HexEdge.hxx"
28 #include "HexHexa.hxx"
29 #include "HexMatrix.hxx"
30 #include "HexGlobale.hxx"
31
32 #include "HexNewShape.hxx"
33 #include "HexEdgeShape.hxx"
34 #include "HexAssoEdge.hxx"
35
36 #include <cmath>
37
38 BEGIN_NAMESPACE_HEXA
39
40 static bool db=false;
41
42 // ====================================================== getCylPoint
43 int Elements::getCylPoint (int nr, int na, int nh, double& px, double& py,
44                            double& pz)
45 {
46    if (grid_type == GR_CYLINDRIC)
47       {
48       px = cyl_radext * cos (na*cyl_dtheta);
49       py = cyl_radext * sin (na*cyl_dtheta);
50       pz = cyl_length * nh;
51       return HOK;
52       }
53
54    bool   rind   = (grid_type == GR_RIND || grid_type == GR_PART_RIND);
55    double sinphi = sin (cyl_phi0 + nh*cyl_dphi);
56    double cosphi = cos (cyl_phi0 + nh*cyl_dphi);
57
58    double rayon = 0;
59    if (rind)
60       {
61       rayon = cyl_radint + nr*(cyl_radext-cyl_radint)/size_hx;
62       pz    = rayon*sinphi;
63       rayon = rayon*cosphi;
64       }
65    else
66       {
67       pz    = cyl_radext*sinphi;
68       rayon = cyl_radhole + nr*(cyl_radext*cosphi - cyl_radhole)/size_hx;
69       rayon = std::max (cyl_radhole, rayon);
70       }
71
72    px = rayon * cos (na*cyl_dtheta);
73    py = rayon * sin (na*cyl_dtheta);
74
75    return HOK;
76 }
77 // ====================================================== controlRind
78 int Elements::controlRind (EnumGrid type, Vertex* cx, Vector* vx, Vector* vz,
79                            double rext, double rint, double rhole,
80                            Vertex* px, double angle,
81                            int nrad, int nang, int nhaut,
82                            double &phi0, double &phi1)
83 {
84    const double Epsil1 = 1e-6;
85    phi0  = phi1 = 0;
86
87    if (cx == NULL || vx == NULL || vz == NULL)
88       return HERR;
89
90    if (nrad<=0 || nang<=0 || nhaut<=0)
91       return HERR;
92
93    if (rext <= 0.0)
94       return HERR;
95
96    if (rint >= rext)
97       return HERR;
98
99    if (rhole > rint)
100       return HERR;
101
102    double nvx = vx->getNorm();
103    double nvz = vz->getNorm();
104
105    if (nvx < Epsil1 || nvz <  Epsil1)
106       return HERR;
107
108    double alpha = asin (rhole/rext);
109    double beta  = -M_PI*DEMI;
110    if (type==GR_HEMISPHERIC || type==GR_PART_SPHERIC)
111        alpha = 2*alpha;
112
113    if (px!=NULL)
114       {
115           // oh = oa.n/|n|
116       double oh = ((px->getX() - cx->getX()) * vz->getDx()
117                 +  (px->getY() - cx->getY()) * vz->getDy()
118                 +  (px->getZ() - cx->getZ()) * vz->getDz()) / nvz;
119       if (oh > rext)
120          return HERR;
121       else if (oh > -rext)
122          beta  = asin (oh/rext);
123       }
124
125    phi0 = std::max (alpha - M_PI*DEMI, beta);
126    phi1 = M_PI*DEMI - alpha;
127    return HOK;
128 }
129 // ====================================================== getHexas
130 int Elements::getHexas (Hexas& liste)
131 {
132    liste.clear ();
133    for (int nro = 0 ; nro<nbr_hexas ; nro++)
134        {
135        Hexa* cell = tab_hexa [nro];
136        if (cell!=NULL && cell->isValid())
137           liste.push_back (cell);
138        }
139    return HOK;
140 }
141 // ====================================================== assoCylinder
142 void Elements::assoCylinder (Vertex* ori, Vector* normal, double angle)
143 {
144    if (normal==NULL || ori==NULL)
145        return;
146
147    RealVector tangles;
148    Real3      vz, center;
149    normal->getCoord (vz);
150    ori   ->getPoint (center);
151    assoCylinders (center, vz, angle, tangles);
152 }
153 // ====================================================== assoCylinders
154 void Elements::assoCylinders (Vertex* ori, Vector* normal, double angle,
155                               RealVector& t_angles)
156 {
157    if (normal==NULL || ori==NULL)
158        return;
159
160    Real3 vz, center;
161    normal->getCoord (vz);
162    ori   ->getPoint (center);
163    assoCylinders (center, vz, angle, t_angles);
164 }
165 // ====================================================== assoCylinders
166 void Elements::assoCylinders (double* ori, double* vk, double angle,
167                               RealVector& t_angles)
168 {
169    char     name [12];
170    sprintf (name, "grid_%02d", el_id);
171    NewShape* geom = el_root->addShape (name, SH_CYLINDER);
172    geom -> openShape();
173
174    std::string brep;
175    // Real3 vk = { normal->getDx(), normal->getDy(), normal->getDz() };
176    // normer_vecteur (vk);
177
178    for (int nz=0 ; nz<size_vz ; nz++)
179        {
180        for (int nx=0 ; nx<size_vx ; nx++)
181            {
182            Vertex* pm = getVertexIJK (nx, 0, nz);
183            Real3   om = { pm->getX() - ori[dir_x], 
184                           pm->getY() - ori[dir_y], 
185                           pm->getZ() - ori[dir_z] };
186
187            double oh     = prod_scalaire (om, vk);
188            double rayon  = 0;
189            Real3  ph, hm;
190            for (int dd=dir_x; dd<=dir_z ; dd++)
191                {
192                ph [dd] = ori[dd] + oh*vk[dd];
193                hm [dd] = pm ->getCoord(dd) - ph[dd];
194                rayon  += hm[dd] * hm[dd];
195                }
196
197            rayon = sqrt (rayon);
198            int subid = geom->addCircle (ph, rayon, vk, hm);
199
200            for (int ny=0 ; ny<size_hy ; ny++)
201                {
202                double pmin = t_angles [ny]/360;
203                double pmax = t_angles [ny+1]/360;
204                Edge*  edge = getEdgeJ (nx, ny, nz);
205                geom->addAssociation (edge, subid, pmin, pmax);
206                if (db) std::cout << " assoCylinders : ny= " << ny 
207                                  << ", nz= " << nz << " param = (" 
208                                  << pmin << ", " << pmax  << ")\n";
209                }
210            }
211        }
212    // Association automatique des vertex non associes -> bph
213    // Traitement des faces spheriques
214
215    Real3 vi = { -vk[dir_x],  -vk[dir_y],  -vk[dir_z] };
216
217    switch (grid_type)
218       {
219       case GR_HEMISPHERIC  :    // Pour l'exterieur
220       case GR_PART_SPHERIC :
221            assoRind (ori, vi, size_vx-1, geom);
222            break;
223       case GR_PART_RIND    :    // Exterieur + interieur
224       case GR_RIND         :
225            assoRind (ori, vi, 0, geom);
226            assoRind (ori, vi, size_vx-1, geom);
227            break;
228       default :
229            break;
230       }
231    geom->closeShape ();
232 }
233 // ====================================================== calcul_param
234 double calcul_param (double* ori, double* vi, Vertex* vert)
235 {
236    Real3  pnt, vj;
237    vert->getPoint (pnt);
238    calc_vecteur (ori, pnt, vj);
239    normer_vecteur  (vj);
240    double kos = prod_scalaire (vi, vj);
241    double alpha = acos (kos) / (2*M_PI);
242    return alpha;
243 }
244 // ====================================================== assoRind
245 // Association des meridiennes
246 // Creation sphere geometrique + association faces
247 void Elements::assoRind (double* ori, double* vi, int nx, NewShape* geom)
248 {
249    Real3  vk;
250    double radius  = nx==0 ? cyl_radint : cyl_radext;
251    int    sphid   = geom->addSphere (ori, radius);
252
253    int nz1 = size_vz/2;
254    int nb_secteurs = cyl_closed ? size_vy-1 : size_vy;
255
256    for (int ny=0 ; ny<nb_secteurs ; ny++)
257        {
258        Vertex* pm = getVertexIJK (nx, ny, nz1);
259        Real3   vj = { pm->getX(), pm->getY(), pm->getZ() };
260        prod_vectoriel (vi, vj, vk);
261        double rayon = cyl_radint + nx*(cyl_radext-cyl_radint)/size_hx;
262        int    subid = geom->addCircle (ori, rayon, vk, vi);
263
264        for (int nz=0 ; nz<size_hz ; nz++)
265            {
266            Quad* quad  = getQuadJK (nx, ny, nz);
267            Edge* edge  = getEdgeK  (nx, ny, nz);
268            Vertex* nd1 = edge->getVertex (V_AMONT);
269            Vertex* nd2 = edge->getVertex (V_AVAL);
270            double pmin = calcul_param (ori, vi, nd1);
271            double pmax = calcul_param (ori, vi, nd2);
272            std::cout << " assoRind : ny= " << ny << ", nz= " << nz 
273                      << " param = (" << pmin << ", " << pmax  << ")\n";
274
275            geom->addAssociation (edge, subid, pmin, pmax);
276            geom->addAssociation (quad, sphid);
277            }
278        }
279 }
280 // ====================================================== assoCircle
281 // ==== utilise pour les spheres carrees
282 void Elements::assoCircle (double* center, Edge* ed1, Edge* ed2, NewShape* geom)
283 {
284    Real3 oa,  ob, normal;
285    Real3 pta, ptb, ptc, ptd;
286    std::string brep;
287
288 //  Les 2 edges dont les petits cotes d'un rectangle de rapport L/l=sqrt(2)
289 //  Soit le cercle circonscrit a ce rectangle.
290 //    * la largeur est balayee par l'angle alpha
291 //    * la longueur par l'angle beta = pi -alpha
292
293    ed1->getVertex(V_AMONT)->getPoint (pta);
294    ed1->getVertex(V_AVAL )->getPoint (ptb);
295    ed2->getVertex(V_AMONT)->getPoint (ptc);
296    ed2->getVertex(V_AVAL )->getPoint (ptd);
297
298    double d1 = calc_distance (pta, ptc);
299    double d2 = calc_distance (pta, ptd);
300
301    if (d1 < d2)
302       {
303       ed2->getVertex(V_AMONT)->getPoint (ptd);
304       ed2->getVertex(V_AVAL )->getPoint (ptc);
305       }
306
307    calc_vecteur   (center, pta, oa);
308    calc_vecteur   (center, ptb, ob);
309    prod_vectoriel (oa, ob, normal);
310
311    double rayon = calc_norme (oa);
312    int    subid = geom->addCircle (center, rayon, normal, oa);
313
314    const double alpha = atan (sqrt(2.)/2)/M_PI; //  angle proche de 70.528 degres
315    // asso1->setBounds (0,   alpha);
316    // asso2->setBounds (0.5, alpha + 0.5);
317
318    geom->addAssociation (ed1, subid, 0.0, alpha);
319    geom->addAssociation (ed2, subid, 0.5, alpha+0.5);
320 }
321 // ====================================================== assoSphere
322 void Elements::assoSphere (double* center, Edge* t_edge[], Quad* t_quad[])
323 {
324    char     name [12];
325    sprintf (name, "grid_%02d", el_id);
326    NewShape* geom = el_root->addShape (name, SH_SPHERE);
327    geom -> openShape ();
328
329    Real3 sommet;
330
331    assoCircle (center, t_edge [E_AC], t_edge [E_BD], geom);
332    assoCircle (center, t_edge [E_AD], t_edge [E_BC], geom);
333    assoCircle (center, t_edge [E_AE], t_edge [E_BF], geom);
334    assoCircle (center, t_edge [E_AF], t_edge [E_BE], geom);
335    assoCircle (center, t_edge [E_CE], t_edge [E_DF], geom);
336    assoCircle (center, t_edge [E_CF], t_edge [E_DE], geom);
337
338    t_edge[E_AC]->getVertex(V_AMONT)->getPoint (sommet);
339    double radius = calc_distance (center, sommet);
340
341    int sphid = geom -> addSphere (center, radius);
342    geom->closeShape();
343
344    for (int nf=0 ; nf < HQ_MAXI ; nf++)
345        t_quad[nf]->addAssociation (geom, sphid);
346 }
347 // ==================================================== propagateAssociation
348 int Elements::propagateAssociation (Edge* orig, Edge* dest, Edge* dir)
349 {
350     return HERR;
351 #if 0
352    if (revo_lution || orig==NULL || dest==NULL || dir==NULL)
353       return HERR;
354
355    const Shapes& tab_shapes = orig->getAssociations ();
356    const Shapes& tab_dest   = dest->getAssociations ();
357    int   nbdest             = tab_dest.size();
358    int   nbshapes           = tab_shapes.size();
359    bool  on_edge            = nbshapes!=0 && nbdest==0;
360
361    Vertex* vo1 = orig->commonVertex  (dir);
362    Vertex* vd1 = dest->commonVertex  (dir);
363    Vertex* vo2 = orig->opposedVertex (vo1);
364    Vertex* vd2 = dest->opposedVertex (vd1);
365
366    if (vo1==NULL || vd1==NULL)
367       return HERR;
368
369    std::string  trep;
370    Real3   pa, pb, vdir1, vdir2;
371    calc_vecteur (vo1->getPoint (pa), vd1->getPoint (pb), vdir1);
372    calc_vecteur (vo2->getPoint (pa), vd2->getPoint (pb), vdir2);
373
374    double dd = calc_distance (vdir1, vdir2);
375    bool para = dd < 1.0e-3;
376
377    if (para && on_edge)
378       {
379       for (int nro=0 ; nro<nbshapes ; nro++)
380           {
381           Shape* shape  = tab_shapes[nro];
382           if (shape!=NULL)
383              {
384              std::string brep   = shape->getBrep();
385              translate_brep (brep, vdir1, trep);
386              // Shape* tshape = new Shape (trep);
387              // tshape->setBounds (shape->getStart(), shape->getEnd());
388              // dest->addAssociation (tshape);
389              }
390           }
391       }
392
393    double* vdir = vdir1;
394    for (int nro=V_AMONT ; nro<=V_AVAL ; nro++)
395        {
396        Shape* shape = vo1->getAssociation ();
397        if (shape!=NULL && vd1->getAssociation ()==NULL)
398           {
399           std::string brep   = shape->getBrep();
400           translate_brep (brep, vdir, trep);
401           // Shape* tshape = new Shape (trep);
402           // vd1->setAssociation (tshape);
403           }
404        vo1  = vo2;
405        vd1  = vd2;
406        vdir = vdir2;
407        }
408    return HOK;
409 #endif
410 }
411 // ==================================================== prismAssociation
412 int Elements::prismAssociation (Edge* lorig, Edge* ldest, int nh)
413 {
414    if (lorig==NULL || ldest==NULL)
415       return HERR;
416
417    updateMatrix (nh);
418    int nbshapes = lorig->countAssociation ();
419    if (nbshapes==0)
420        return HOK;
421
422    NewShape* new_shape = getShape ();
423    for (int nro=0 ; nro<nbshapes ; nro++)
424        {
425        AssoEdge*  asso  = lorig->getAssociation (nro);
426        EdgeShape* shape = asso ->getEdgeShape();
427        double     p1    = asso ->getStart();
428        double     p2    = asso ->getEnd  ();
429        int        subid = 0;
430        char       name [24];
431
432        sprintf (name, "0x%lx#%d", (unsigned long) shape, nh);
433        std::map<std::string,int>::iterator iter = map_shape.find (name);
434        if (iter != map_shape.end())
435           subid = iter->second;
436        else
437           subid = map_shape[name] = new_shape->transfoShape (cum_matrix, shape);
438
439        new_shape->addAssociation (ldest, subid, p1, p2);
440        printf (" prismAsso : %s -> %s(%d)  = %s [ %g , %g]\n",
441                  lorig->getName(), ldest->getName(), nh, name, p1, p2);
442        }
443    return HOK;
444 }
445 // ====================================================== assoResiduelle
446 void Elements::assoResiduelle ()
447 {
448    // int nbre = tab_vertex.size();
449    // for (int nv=0 ; nv<nbre ; nv++)
450        // {
451        // geom_asso_point (tab_vertex [nv]);
452        // }
453 }
454 // ====================================================== moveDisco
455 void Elements::moveDisco (Hexa* hexa)
456 {
457    Real3  center;
458    Matrix matrix;
459    hexa->getCenter (center);
460    matrix.defScale (center, 0.55);
461
462    int nbre = tab_vertex.size();
463    for (int nv=0 ; nv<nbre ; nv++)
464        {
465        matrix.perform (tab_vertex [nv]);
466        }
467 }
468 // =================================================== getStrate
469 Hexa* Elements::getStrate (int couche, EnumHQuad nroface)
470 {
471    Hexa* cell = NULL;
472    int   nro  = couche <= 0 ? 0 : (couche-1)*HQ_MAXI + nroface + 1;
473
474    if (nbr_hexas==0 || nro >= nbr_hexas)
475       cell = NULL;
476    else
477       cell = tab_hexa [nro];
478
479    return cell;
480 }
481 // ============================================================  setHexa
482 void Elements::setHexa (Hexa* elt, int nro)
483 {
484    if (nro >=0 && nro < nbr_hexas)
485        tab_hexa [nro] = elt;
486 }
487 // ============================================================  setQuad
488 void Elements::setQuad (Quad* elt, int nro)
489 {
490    if (nro >=0 && nro < nbr_quads)
491        tab_quad [nro] = elt;
492 }
493 // ============================================================  setEdge
494 void Elements::setEdge (Edge* elt, int nro)
495 {
496    if (nro >=0 && nro < nbr_edges)
497        tab_edge [nro] = elt;
498 }
499 // ============================================================  setVertex
500 void Elements::setVertex (Vertex* elt, int nro)
501 {
502    if (nro >=0 && nro < nbr_vertex)
503        tab_vertex [nro] = elt;
504 }
505 // -----------------------------------------------------------------------
506 // -----------------------------------------------------------------------
507 // ============================================================  getHexa
508 Hexa* Elements::getHexa (int nro)
509 {
510    DumpStart ("getHexa", nro);
511
512    Hexa* elt = NULL;
513    int  nombre=tab_hexa.size();
514    // if (nro >=0 && nro < nbr_hexas && el_status == HOK Abu 2010/05/06
515    if (nro >=0 && nro < nombre && el_status == HOK
516                && tab_hexa [nro] != NULL && tab_hexa [nro]->isValid())
517       elt = tab_hexa [nro];
518
519    DumpReturn (elt);
520    return elt;
521 }
522 // ============================================================  getQuad
523 Quad* Elements::getQuad (int nro)
524 {
525    DumpStart ("getQuad", nro);
526
527    Quad* elt = NULL;
528    if (nro >=0 && nro < nbr_quads && el_status == HOK
529                && tab_quad [nro] != NULL && tab_quad [nro]->isValid())
530       elt = tab_quad [nro];
531
532    DumpReturn (elt);
533    return elt;
534 }
535 // ============================================================  getEdge
536 Edge* Elements::getEdge (int nro)
537 {
538    DumpStart ("getEdge", nro);
539
540    Edge* elt = NULL;
541    if (nro >=0 && nro < nbr_edges && el_status == HOK
542                && tab_edge [nro] != NULL && tab_edge [nro]->isValid())
543       elt = tab_edge [nro];
544
545    DumpReturn (elt);
546    return elt;
547 }
548 // ============================================================  getVertex
549 Vertex* Elements::getVertex (int nro)
550 {
551    DumpStart ("getVertex", nro);
552
553    Vertex* elt = NULL;
554    if (nro >=0 && nro <  nbr_vertex && el_status == HOK
555                && tab_vertex [nro] != NULL && tab_vertex [nro]->isValid())
556       elt = tab_vertex [nro];
557
558    DumpReturn (elt);
559    return elt;
560 }
561 // ============================================================  indVertex
562 int Elements::indVertex (int nquad, int nsommet, int nh)
563 {
564    int nro = nsommet  + QUAD4*nquad + nbr_orig*QUAD4*(nh+1);
565    return nro;
566 }
567 // ============================================================  nroVertex
568 int Elements::nroVertex (int nquad, int nsommet, int nh)
569 {
570    int nro = nsommet  + QUAD4*nquad + nbr_orig*QUAD4*nh;
571    return nro;
572 }
573 // ============================================================  indVertex
574 int Elements::indVertex (int ref_edge, int nh)
575 {
576    int    nro = ref_edge + nbr_orig*QUAD4*nh;
577    return nro;
578 }
579 // ============================================================  nroEdgeH
580 int Elements::nroEdgeH (int nvertex)
581 {
582    return QUAD4*nbr_orig*gr_hauteur + nvertex;
583 }
584 // ============================================================  nroEdgeH
585 int Elements::nroEdgeH (int nquad, int nsommet, int nh)
586 {
587    return QUAD4*nbr_orig*gr_hauteur + indVertex (nquad, nsommet, nh);
588 }
589 // ============================================================  nroHexa
590 int Elements::nroHexa (int nquad, int nh)
591 {
592    int nro = gr_hauteur*nquad + nh;
593    return nro;
594 }
595
596 // ============================================================  addHexa
597 void Elements::addHexa (Hexa* element)
598 {
599    tab_hexa.push_back (element);
600    nbr_hexas ++;
601 }
602 // ============================================================  addQuad
603 void Elements::addQuad (Quad* element)
604 {
605    tab_quad.push_back (element);
606    nbr_quads ++;
607 }
608 // ============================================================  addEdge
609 void Elements::addEdge (Edge* element)
610 {
611    tab_edge.push_back (element);
612    nbr_edges ++;
613 }
614 // ============================================================  addVertex
615 void Elements::addVertex (Vertex* element)
616 {
617    tab_vertex.push_back (element);
618    nbr_vertex ++;
619 }
620 // ============================================================  findHexa
621 int Elements::findHexa (Hexa* element)
622 {
623    int nbre = tab_hexa.size();
624    for (int nro=0 ; nro<nbre ; nro++)
625        if (tab_hexa [nro] == element)
626           return nro;
627    return NOTHING;
628 }
629 // ============================================================  findQuad
630 int Elements::findQuad (Quad* element)
631 {
632    int nbre = tab_quad.size();
633    for (int nro=0 ; nro<nbre ; nro++)
634        if (tab_quad [nro] == element)
635           return nro;
636    return NOTHING;
637 }
638 // ============================================================  findEdge
639 int Elements::findEdge (Edge* element)
640 {
641    int nbre = tab_edge.size();
642    for (int nro=0 ; nro<nbre ; nro++)
643        if (tab_edge [nro] == element)
644           return nro;
645    return NOTHING;
646 }
647 // ============================================================  findVertex
648 int Elements::findVertex (Vertex* element)
649 {
650    int nbre = tab_vertex.size();
651    for (int nro=0 ; nro<nbre ; nro++)
652        if (tab_vertex [nro] == element)
653           return nro;
654    return NOTHING;
655 }
656 // ========================================================= saveVtk (avec nro)
657 int Elements::saveVtk  (cpchar radical, int &nro)
658 {
659    char num[8];
660    sprintf (num, "%d", nro);
661    nro ++;
662
663    std::string filename = radical;
664    filename += num;
665    filename += ".vtk";
666    int ier = saveVtk (filename.c_str());
667    return ier;
668 }
669
670 END_NAMESPACE_HEXA