Salome HOME
e3f2aa41d5e984f48ee41d318f9caa1a67a5029a
[modules/hexablock.git] / src / HEXABLOCK / HexElements_ter.cxx
1 // C++ : Table d'hexaedres (Evol Versions 3)
2
3 // Copyright (C) 2009-2013  CEA/DEN, EDF R&D
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.
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    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                cout << " assoCylinders : ny= " << ny << ", nz= " << nz 
207                     << " param = (" << pmin << ", " << pmax  << ")\n";
208                }
209            }
210        }
211    // Association automatique des vertex non associes -> bph
212    // Traitement des faces spheriques
213
214    Real3 vi = { -vk[dir_x],  -vk[dir_y],  -vk[dir_z] };
215
216    switch (grid_type)
217       {
218       case GR_HEMISPHERIC  :    // Pour l'exterieur
219       case GR_PART_SPHERIC :
220            assoRind (ori, vi, size_vx-1, geom);
221            break;
222       case GR_PART_RIND    :    // Exterieur + interieur
223       case GR_RIND         :
224            assoRind (ori, vi, 0, geom);
225            assoRind (ori, vi, size_vx-1, geom);
226            break;
227       default :
228            break;
229       }
230    geom->closeShape ();
231 }
232 // ====================================================== calcul_param
233 double calcul_param (double* ori, double* vi, Vertex* vert)
234 {
235    Real3  pnt, vj;
236    vert->getPoint (pnt);
237    calc_vecteur (ori, pnt, vj);
238    normer_vecteur  (vj);
239    double kos = prod_scalaire (vi, vj);
240    double alpha = acos (kos) / (2*M_PI);
241    return alpha;
242 }
243 // ====================================================== assoRind
244 // Association des meridiennes
245 // Creation sphere geometrique + association faces
246 void Elements::assoRind (double* ori, double* vi, int nx, NewShape* geom)
247 {
248    Real3  vk;
249    double radius  = nx==0 ? cyl_radint : cyl_radext;
250    int    sphid   = geom->addSphere (ori, radius);
251
252    int nz1 = size_vz/2;
253    int nb_secteurs = cyl_closed ? size_vy-1 : size_vy;
254
255    for (int ny=0 ; ny<nb_secteurs ; ny++)
256        {
257        Vertex* pm = getVertexIJK (nx, ny, nz1);
258        Real3   vj = { pm->getX(), pm->getY(), pm->getZ() };
259        prod_vectoriel (vi, vj, vk);
260        double rayon = cyl_radint + nx*(cyl_radext-cyl_radint)/size_hx;
261        int    subid = geom->addCircle (ori, rayon, vk, vi);
262
263        for (int nz=0 ; nz<size_hz ; nz++)
264            {
265            Quad* quad  = getQuadJK (nx, ny, nz);
266            Edge* edge  = getEdgeK  (nx, ny, nz);
267            Vertex* nd1 = edge->getVertex (V_AMONT);
268            Vertex* nd2 = edge->getVertex (V_AVAL);
269            double pmin = calcul_param (ori, vi, nd1);
270            double pmax = calcul_param (ori, vi, nd2);
271            cout << " assoRind : ny= " << ny << ", nz= " << nz 
272                 << " param = (" << pmin << ", " << pmax  << ")\n";
273
274            geom->addAssociation (edge, subid, pmin, pmax);
275            geom->addAssociation (quad, sphid);
276            }
277        }
278 }
279 // ====================================================== assoCircle
280 // ==== utilise pour les spheres carrees
281 void Elements::assoCircle (double* center, Edge* ed1, Edge* ed2, NewShape* geom)
282 {
283    Real3 oa,  ob, normal;
284    Real3 pta, ptb, ptc, ptd;
285    string brep;
286
287 //  Les 2 edges dont les petits cotes d'un rectangle de rapport L/l=sqrt(2)
288 //  Soit le cercle circonscrit a ce rectangle.
289 //    * la largeur est balayee par l'angle alpha
290 //    * la longueur par l'angle beta = pi -alpha
291
292    ed1->getVertex(V_AMONT)->getPoint (pta);
293    ed1->getVertex(V_AVAL )->getPoint (ptb);
294    ed2->getVertex(V_AMONT)->getPoint (ptc);
295    ed2->getVertex(V_AVAL )->getPoint (ptd);
296
297    double d1 = calc_distance (pta, ptc);
298    double d2 = calc_distance (pta, ptd);
299
300    if (d1 < d2)
301       {
302       ed2->getVertex(V_AMONT)->getPoint (ptd);
303       ed2->getVertex(V_AVAL )->getPoint (ptc);
304       }
305
306    calc_vecteur   (center, pta, oa);
307    calc_vecteur   (center, ptb, ob);
308    prod_vectoriel (oa, ob, normal);
309
310    double rayon = calc_norme (oa);
311    int    subid = geom->addCircle (center, rayon, normal, oa);
312
313    const double alpha = atan (sqrt(2.)/2)/M_PI; //  angle proche de 70.528 degres
314    // asso1->setBounds (0,   alpha);
315    // asso2->setBounds (0.5, alpha + 0.5);
316
317    geom->addAssociation (ed1, subid, 0.0, alpha);
318    geom->addAssociation (ed2, subid, 0.5, alpha+0.5);
319 }
320 // ====================================================== assoSphere
321 void Elements::assoSphere (double* center, Edge* t_edge[], Quad* t_quad[])
322 {
323    char     name [12];
324    sprintf (name, "grid_%02d", el_id);
325    NewShape* geom = el_root->addShape (name, SH_SPHERE);
326    geom -> openShape ();
327
328    Real3 sommet;
329
330    assoCircle (center, t_edge [E_AC], t_edge [E_BD], geom);
331    assoCircle (center, t_edge [E_AD], t_edge [E_BC], geom);
332    assoCircle (center, t_edge [E_AE], t_edge [E_BF], geom);
333    assoCircle (center, t_edge [E_AF], t_edge [E_BE], geom);
334    assoCircle (center, t_edge [E_CE], t_edge [E_DF], geom);
335    assoCircle (center, t_edge [E_CF], t_edge [E_DE], geom);
336
337    t_edge[E_AC]->getVertex(V_AMONT)->getPoint (sommet);
338    double radius = calc_distance (center, sommet);
339
340    int sphid = geom -> addSphere (center, radius);
341    geom->closeShape();
342
343    for (int nf=0 ; nf < HQ_MAXI ; nf++)
344        t_quad[nf]->addAssociation (geom, sphid);
345 }
346 // ==================================================== propagateAssociation
347 int Elements::propagateAssociation (Edge* orig, Edge* dest, Edge* dir)
348 {
349     return HERR;
350 #if 0
351    if (revo_lution || orig==NULL || dest==NULL || dir==NULL)
352       return HERR;
353
354    const Shapes& tab_shapes = orig->getAssociations ();
355    const Shapes& tab_dest   = dest->getAssociations ();
356    int   nbdest             = tab_dest.size();
357    int   nbshapes           = tab_shapes.size();
358    bool  on_edge            = nbshapes!=0 && nbdest==0;
359
360    Vertex* vo1 = orig->commonVertex  (dir);
361    Vertex* vd1 = dest->commonVertex  (dir);
362    Vertex* vo2 = orig->opposedVertex (vo1);
363    Vertex* vd2 = dest->opposedVertex (vd1);
364
365    if (vo1==NULL || vd1==NULL)
366       return HERR;
367
368    string  trep;
369    Real3   pa, pb, vdir1, vdir2;
370    calc_vecteur (vo1->getPoint (pa), vd1->getPoint (pb), vdir1);
371    calc_vecteur (vo2->getPoint (pa), vd2->getPoint (pb), vdir2);
372
373    double dd = calc_distance (vdir1, vdir2);
374    bool para = dd < 1.0e-3;
375
376    if (para && on_edge)
377       {
378       for (int nro=0 ; nro<nbshapes ; nro++)
379           {
380           Shape* shape  = tab_shapes[nro];
381           if (shape!=NULL)
382              {
383              string brep   = shape->getBrep();
384              translate_brep (brep, vdir1, trep);
385              // Shape* tshape = new Shape (trep);
386              // tshape->setBounds (shape->getStart(), shape->getEnd());
387              // dest->addAssociation (tshape);
388              }
389           }
390       }
391
392    double* vdir = vdir1;
393    for (int nro=V_AMONT ; nro<=V_AVAL ; nro++)
394        {
395        Shape* shape = vo1->getAssociation ();
396        if (shape!=NULL && vd1->getAssociation ()==NULL)
397           {
398           string brep   = shape->getBrep();
399           translate_brep (brep, vdir, trep);
400           // Shape* tshape = new Shape (trep);
401           // vd1->setAssociation (tshape);
402           }
403        vo1  = vo2;
404        vd1  = vd2;
405        vdir = vdir2;
406        }
407    return HOK;
408 #endif
409 }
410 // ==================================================== prismAssociation
411 int Elements::prismAssociation (Edge* lorig, Edge* ldest, int nh)
412 {
413    if (lorig==NULL || ldest==NULL)
414       return HERR;
415
416    updateMatrix (nh);
417    int nbshapes = lorig->countAssociation ();
418    if (nbshapes==0)
419        return HOK;
420
421    NewShape* new_shape = getShape ();
422    for (int nro=0 ; nro<nbshapes ; nro++)
423        {
424        AssoEdge*  asso  = lorig->getAssociation (nro);
425        EdgeShape* shape = asso ->getEdgeShape();
426        double     p1    = asso ->getStart();
427        double     p2    = asso ->getEnd  ();
428        int        subid = 0;
429        char       name [24];
430
431        sprintf (name, "0x%lx#%d", (unsigned long) shape, nh);
432        map<string,int>::iterator iter = map_shape.find (name);
433        if (iter != map_shape.end())
434           subid = iter->second;
435        else
436           subid = map_shape[name] = new_shape->transfoShape (cum_matrix, shape);
437
438        new_shape->addAssociation (ldest, subid, p1, p2);
439        printf (" prismAsso : %s -> %s(%d)  = %s [ %g , %g]\n",
440                  lorig->getName(), ldest->getName(), nh, name, p1, p2);
441        }
442    return HOK;
443 }
444 // ====================================================== assoResiduelle
445 void Elements::assoResiduelle ()
446 {
447    // int nbre = tab_vertex.size();
448    // for (int nv=0 ; nv<nbre ; nv++)
449        // {
450        // geom_asso_point (tab_vertex [nv]);
451        // }
452 }
453 // ====================================================== moveDisco
454 void Elements::moveDisco (Hexa* hexa)
455 {
456    Real3  center;
457    Matrix matrix;
458    hexa->getCenter (center);
459    matrix.defScale (center, 0.55);
460
461    int nbre = tab_vertex.size();
462    for (int nv=0 ; nv<nbre ; nv++)
463        {
464        matrix.perform (tab_vertex [nv]);
465        }
466 }
467 // =================================================== getStrate
468 Hexa* Elements::getStrate (int couche, EnumHQuad nroface)
469 {
470    Hexa* cell = NULL;
471    int   nro  = couche <= 0 ? 0 : (couche-1)*HQ_MAXI + nroface + 1;
472
473    if (nbr_hexas==0 || nro >= nbr_hexas)
474       cell = NULL;
475    else
476       cell = tab_hexa [nro];
477
478    return cell;
479 }
480 // ============================================================  setHexa
481 void Elements::setHexa (Hexa* elt, int nro)
482 {
483    if (nro >=0 && nro < nbr_hexas)
484        tab_hexa [nro] = elt;
485 }
486 // ============================================================  setQuad
487 void Elements::setQuad (Quad* elt, int nro)
488 {
489    if (nro >=0 && nro < nbr_quads)
490        tab_quad [nro] = elt;
491 }
492 // ============================================================  setEdge
493 void Elements::setEdge (Edge* elt, int nro)
494 {
495    if (nro >=0 && nro < nbr_edges)
496        tab_edge [nro] = elt;
497 }
498 // ============================================================  setVertex
499 void Elements::setVertex (Vertex* elt, int nro)
500 {
501    if (nro >=0 && nro < nbr_vertex)
502        tab_vertex [nro] = elt;
503 }
504 // -----------------------------------------------------------------------
505 // -----------------------------------------------------------------------
506 // ============================================================  getHexa
507 Hexa* Elements::getHexa (int nro)
508 {
509    DumpStart ("getHexa", nro);
510
511    Hexa* elt = NULL;
512    int  nombre=tab_hexa.size();
513    // if (nro >=0 && nro < nbr_hexas && el_status == HOK Abu 2010/05/06
514    if (nro >=0 && nro < nombre && el_status == HOK
515                && tab_hexa [nro] != NULL && tab_hexa [nro]->isValid())
516       elt = tab_hexa [nro];
517
518    DumpReturn (elt);
519    return elt;
520 }
521 // ============================================================  getQuad
522 Quad* Elements::getQuad (int nro)
523 {
524    DumpStart ("getQuad", nro);
525
526    Quad* elt = NULL;
527    if (nro >=0 && nro < nbr_quads && el_status == HOK
528                && tab_quad [nro] != NULL && tab_quad [nro]->isValid())
529       elt = tab_quad [nro];
530
531    DumpReturn (elt);
532    return elt;
533 }
534 // ============================================================  getEdge
535 Edge* Elements::getEdge (int nro)
536 {
537    DumpStart ("getEdge", nro);
538
539    Edge* elt = NULL;
540    if (nro >=0 && nro < nbr_edges && el_status == HOK
541                && tab_edge [nro] != NULL && tab_edge [nro]->isValid())
542       elt = tab_edge [nro];
543
544    DumpReturn (elt);
545    return elt;
546 }
547 // ============================================================  getVertex
548 Vertex* Elements::getVertex (int nro)
549 {
550    DumpStart ("getVertex", nro);
551
552    Vertex* elt = NULL;
553    if (nro >=0 && nro <  nbr_vertex && el_status == HOK
554                && tab_vertex [nro] != NULL && tab_vertex [nro]->isValid())
555       elt = tab_vertex [nro];
556
557    DumpReturn (elt);
558    return elt;
559 }
560 // ============================================================  indVertex
561 int Elements::indVertex (int nquad, int nsommet, int nh)
562 {
563    int nro = nsommet  + QUAD4*nquad + nbr_orig*QUAD4*(nh+1);
564    return nro;
565 }
566 // ============================================================  nroVertex
567 int Elements::nroVertex (int nquad, int nsommet, int nh)
568 {
569    int nro = nsommet  + QUAD4*nquad + nbr_orig*QUAD4*nh;
570    return nro;
571 }
572 // ============================================================  indVertex
573 int Elements::indVertex (int ref_edge, int nh)
574 {
575    int    nro = ref_edge + nbr_orig*QUAD4*nh;
576    return nro;
577 }
578 // ============================================================  nroEdgeH
579 int Elements::nroEdgeH (int nvertex)
580 {
581    return QUAD4*nbr_orig*gr_hauteur + nvertex;
582 }
583 // ============================================================  nroEdgeH
584 int Elements::nroEdgeH (int nquad, int nsommet, int nh)
585 {
586    return QUAD4*nbr_orig*gr_hauteur + indVertex (nquad, nsommet, nh);
587 }
588 // ============================================================  nroHexa
589 int Elements::nroHexa (int nquad, int nh)
590 {
591    int nro = gr_hauteur*nquad + nh;
592    return nro;
593 }
594
595 // ============================================================  addHexa
596 void Elements::addHexa (Hexa* element)
597 {
598    tab_hexa.push_back (element);
599    nbr_hexas ++;
600 }
601 // ============================================================  addQuad
602 void Elements::addQuad (Quad* element)
603 {
604    tab_quad.push_back (element);
605    nbr_quads ++;
606 }
607 // ============================================================  addEdge
608 void Elements::addEdge (Edge* element)
609 {
610    tab_edge.push_back (element);
611    nbr_edges ++;
612 }
613 // ============================================================  addVertex
614 void Elements::addVertex (Vertex* element)
615 {
616    tab_vertex.push_back (element);
617    nbr_vertex ++;
618 }
619 // ============================================================  findHexa
620 int Elements::findHexa (Hexa* element)
621 {
622    int nbre = tab_hexa.size();
623    for (int nro=0 ; nro<nbre ; nro++)
624        if (tab_hexa [nro] == element)
625           return nro;
626    return NOTHING;
627 }
628 // ============================================================  findQuad
629 int Elements::findQuad (Quad* element)
630 {
631    int nbre = tab_quad.size();
632    for (int nro=0 ; nro<nbre ; nro++)
633        if (tab_quad [nro] == element)
634           return nro;
635    return NOTHING;
636 }
637 // ============================================================  findEdge
638 int Elements::findEdge (Edge* element)
639 {
640    int nbre = tab_edge.size();
641    for (int nro=0 ; nro<nbre ; nro++)
642        if (tab_edge [nro] == element)
643           return nro;
644    return NOTHING;
645 }
646 // ============================================================  findVertex
647 int Elements::findVertex (Vertex* element)
648 {
649    int nbre = tab_vertex.size();
650    for (int nro=0 ; nro<nbre ; nro++)
651        if (tab_vertex [nro] == element)
652           return nro;
653    return NOTHING;
654 }
655 // ========================================================= saveVtk (avec nro)
656 int Elements::saveVtk  (cpchar radical, int &nro)
657 {
658    char num[8];
659    sprintf (num, "%d", nro);
660    nro ++;
661
662    string filename = radical;
663    filename += num;
664    filename += ".vtk";
665    int ier = saveVtk (filename.c_str());
666    return ier;
667 }
668
669 END_NAMESPACE_HEXA