diff --git a/astest/cont001a.comm b/astest/cont001a.comm index a71f2926832..f77608cc873 100644 --- a/astest/cont001a.comm +++ b/astest/cont001a.comm @@ -31,23 +31,24 @@ DEBUT( test = CA.TestCase() -Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED") +mesh = LIRE_MAILLAGE(UNITE=20, FORMAT="MED", INFO=2) -Mail = MODI_MAILLAGE( - reuse=Mail, - MAILLAGE=Mail, +mesh = MODI_MAILLAGE( + reuse=mesh, + MAILLAGE=mesh, ORIE_PEAU=_F(GROUP_MA_PEAU=("Group_2", "Group_1", "Group_3", "Group_4")), + INFO=2, ) MODI = AFFE_MODELE( - MAILLAGE=Mail, AFFE=_F(GROUP_MA=("Haut", "Bas"), PHENOMENE="MECANIQUE", MODELISATION="DKT") + MAILLAGE=mesh, AFFE=_F(GROUP_MA=("Haut", "Bas"), PHENOMENE="MECANIQUE", MODELISATION="DKT") ) CARAMECA = AFFE_CARA_ELEM(MODELE=MODI, COQUE=_F(GROUP_MA=("Haut", "Bas"), EPAIS=0.01)) MAT = DEFI_MATERIAU(ELAS=_F(E=20000, NU=0.3, ALPHA=0.01)) -CHMAT = AFFE_MATERIAU(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", MATER=MAT)) +CHMAT = AFFE_MATERIAU(MAILLAGE=mesh, AFFE=_F(TOUT="OUI", MATER=MAT)) DF1 = DEFI_FONCTION( NOM_PARA="INST", @@ -108,41 +109,57 @@ DEFICO = DEFI_CONT( ), ) -# some checks for the first zone : -zone = DEFICO.getContactZone(0) -test.assertEqual(zone.getMasterCellsFromNode(19), [12, 13]) -test.assertEqual(zone.getSlaveCellsFromNode(64), [61, 62]) -test.assertEqual(zone.getMasterCellNeighbors(14), [13, 15]) -test.assertEqual(zone.getSlaveCellNeighbors(54), [55, 53]) - +# Global checks test.assertEqual(DEFICO.getNumberOfContactZones(), 2) test.assertEqual(DEFICO.getVerbosity(), 2) test.assertEqual(DEFICO.getModel(), MODI) -test.assertEqual(DEFICO.getMesh(), Mail) +test.assertEqual(DEFICO.getMesh(), mesh) test.assertFalse(DEFICO.hasFriction) test.assertFalse(DEFICO.hasSmoothing) -# Pairing checks - +# Some checks for the first zone +zone = DEFICO.getContactZone(0) +test.assertEqual(zone.getVerbosity(), 2) +test.assertEqual(zone.getMesh(), mesh) + +# Some checks for geometric pairing +pairGeom = zone.getMeshPairing() +test.assertEqual(pairGeom.getVerbosity(), 2) +test.assertEqual(pairGeom.getMesh(), mesh) +test.assertEqual(pairGeom.getMasterCellsFromNode(19), [12, 13]) +test.assertEqual(pairGeom.getSlaveCellsFromNode(64), [61, 62]) +test.assertEqual(pairGeom.getMasterCellNeighbors(14), [13, 15]) +test.assertEqual(pairGeom.getSlaveCellNeighbors(54), [55, 53]) + +# Create a displacement field study = CA.PhysicalProblem(MODI, CHMAT, CARAMECA) study.computeDOFNumbering() dofNumbering = study.getDOFNumbering() - disp = CA.FieldOnNodesReal(dofNumbering) disp.setValues(4) -pair = CA.ContactPairing(DEFICO) -pair.updateCoordinates(disp) + +# Contact pairing +contPair = CA.ContactPairing(DEFICO) +zone = DEFICO.getContactZone(0) +test.assertEqual(zone.getVerbosity(), 2) +test.assertEqual(zone.getMesh(), mesh) +contPair.updateCoordinates(disp) test.assertEqual( - pair.getCoordinates().getValues()[:10], [54.0, 54.0, 4.0, 54.0, 4.0, 4.0, 4.0, 54.0, 4.0, 4.0] + contPair.getCoordinates().getValues()[:10], + [54.0, 54.0, 4.0, 54.0, 4.0, 4.0, 4.0, 54.0, 4.0, 4.0], ) +# Checks on all zones nb_zones = DEFICO.getNumberOfContactZones() -for i in range(nb_zones): - pair.computeZone(i) - +for iZone in range(nb_zones): + contPair.compute(iZone) + zone = DEFICO.getContactZone(iZone) + test.assertEqual(zone.getMesh(), mesh) + test.assertEqual(DEFICO.getVerbosity(), 2) +# Some checks for the second zone test.assertEqual( - pair.getListOfPairsOfZone(1), + contPair.getListOfPairs(1), [ (77, 30), (78, 31), @@ -157,19 +174,10 @@ test.assertEqual( ], ) -test.assertEqual([pair.getNumberOfPairsOfZone(i) for i in range(nb_zones)], [26, 10]) - -nbPairs = pair.getNumberOfPairs() -test.assertEqual(nbPairs, sum(pair.getNumberOfPairsOfZone(i) for i in range(nb_zones))) - - -# Testing AsterErrorMessage -pair.clear() -try: - pair.getListOfPairsOfZone(0) -except Exception as e: - test.assertIn("List of pairs is empty or has an odd size", e.message) +test.assertEqual([contPair.getNumberOfPairs(i) for i in range(nb_zones)], [26, 10]) +nbPairs = contPair.getNumberOfPairs() +test.assertEqual(nbPairs, sum(contPair.getNumberOfPairs(i) for i in range(nb_zones))) algo_cont = [CA.ContactAlgo.Lagrangian, CA.ContactAlgo.Nitsche] vari_cont = [CA.ContactVariant.Empty, CA.ContactVariant.Fast] @@ -185,7 +193,7 @@ for i in range(DEFICO.getNumberOfContactZones()): test.assertFalse(zone.checkNormals) test.assertEqual(zone.getModel(), MODI) - test.assertEqual(zone.getMesh(), Mail) + test.assertEqual(zone.getMesh(), mesh) contParam = zone.getContactParameter() test.assertEqual(contParam.getAlgorithm(), algo_cont[i]) @@ -207,9 +215,6 @@ for i in range(DEFICO.getNumberOfContactZones()): zone.setSlaveGroupOfCells("Group_4") zone.setMasterGroupOfCells("Group_3") -# zone1 = DEFICO.getContactZone(0) -# test.assertEqual(zone1.getExcludedSlaveGroupOfCells(), ['Group_0']) - DEFICO.hasFriction = True test.assertTrue(DEFICO.hasFriction) DEFICO.hasSmoothing = False diff --git a/astest/cont001b.py b/astest/cont001b.py index 68f2e67a55b..f94e7555391 100644 --- a/astest/cont001b.py +++ b/astest/cont001b.py @@ -111,7 +111,7 @@ except CA.AsterError as err: print(fmt_raison % str(err)) # on verifie que l'erreur fatale est bien celle que l'on attendait : - if err.id_message == "CONTACT1_3": + if err.id_message == "CONTACT1_1": is_ok = 1 test.assertEqual(is_ok, 1) diff --git a/astest/cont001d.py b/astest/cont001d.py index 2c28a229aff..06e0d4aa771 100644 --- a/astest/cont001d.py +++ b/astest/cont001d.py @@ -109,7 +109,7 @@ except CA.AsterError as err: print(fmt_raison % str(err)) # on verifie que l'erreur fatale est bien celle que l'on attendait : - if err.id_message == "CONTACT1_3": + if err.id_message == "CONTACT1_1": is_ok = 1 test.assertEqual(is_ok, 1) diff --git a/astest/cont001g.py b/astest/cont001g.py index dea068c87b5..f07341767fc 100644 --- a/astest/cont001g.py +++ b/astest/cont001g.py @@ -22,7 +22,7 @@ from code_aster.Commands import * from code_aster import CA from code_aster.MacroCommands.defi_cont import DEFI_CONT -from libaster import ContactPairing, ContactComputation +from libaster import ContactPairing, ContactComputation, CoordinatesSpace import numpy @@ -32,18 +32,19 @@ test = CA.TestCase() -Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED") +meshLine = LIRE_MAILLAGE(UNITE=20, FORMAT="MED") -Mail = MODI_MAILLAGE( - reuse=Mail, MAILLAGE=Mail, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) +meshLine = MODI_MAILLAGE( + reuse=meshLine, MAILLAGE=meshLine, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) ) - -MODI = AFFE_MODELE(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="D_PLAN")) +modelLine = AFFE_MODELE( + MAILLAGE=meshLine, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="D_PLAN") +) # Slave side - CONT_BAS -DEFICO_BAS = DEFI_CONT( - MODELE=MODI, +contactLine = DEFI_CONT( + MODELE=modelLine, INFO=2, ZONE=( _F( @@ -57,101 +58,49 @@ ) # Pairing checks - -pair = ContactPairing(DEFICO_BAS) +pair = ContactPairing(contactLine) pair.compute() -test.assertSequenceEqual(pair.getListOfPairsOfZone(0), [(18, 3), (18, 4), (19, 4), (19, 5)]) -ref = [ - [ - 0.5999999999999999, - -0.7333333333333334, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], - [ - -0.7333333333333334, - -1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], - [ - 1.0, - -0.06666666666666687, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], - [ - -0.06666666666666687, - -1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], -] - -test.assertEqual(len(pair.getSlaveIntersectionPoints(0)), 4) -print(pair.getSlaveIntersectionPoints(0)) -test.assertSequenceEqual(pair.getSlaveIntersectionPoints(0), ref) - - -MailQ = CREA_MAILLAGE(MAILLAGE=Mail, LINE_QUAD=_F(TOUT="OUI")) - - -MODIQ = AFFE_MODELE( - MAILLAGE=MailQ, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="D_PLAN") +# One zone +test.assertEqual(pair.getNumberOfZones(), 1) +indexZone = 0 + +# Get number of pairs on first zone +test.assertEqual(pair.getNumberOfPairs(indexZone), 4) + +# Get list of pairs on first zone +test.assertSequenceEqual(pair.getListOfPairs(indexZone), [(18, 3), (18, 4), (19, 4), (19, 5)]) + +# Get intersection points: 4 paires de points d'intersection +test.assertEqual(len(pair.getNumberOfIntersectionPoints(indexZone)), 4) + +# For each pair: two points of intersections +iPair = 0 +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair], 2) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 1], 2) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 2], 2) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 3], 2) + +# Values of intersections +iPair = 0 +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair], + (0.5999999999999999, 0.0, -0.7333333333333334, 0.0), +) +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair + 1], + (-0.7333333333333334, 0.0, -1.0, 0.0), +) + +meshQuad = CREA_MAILLAGE(MAILLAGE=meshLine, LINE_QUAD=_F(TOUT="OUI")) + +modelQuad = AFFE_MODELE( + MAILLAGE=meshQuad, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="D_PLAN") ) # Slave side - CONT_BAS -DEFICOQ_BAS = DEFI_CONT( - MODELE=MODIQ, +contactQuad = DEFI_CONT( + MODELE=modelQuad, INFO=2, ZONE=( _F( @@ -165,90 +114,39 @@ ) # Pairing checks - -pair = ContactPairing(DEFICOQ_BAS) +pair = ContactPairing(contactQuad) pair.compute() +# One zone +test.assertEqual(pair.getNumberOfZones(), 1) +indexZone = 0 + +# Get number of pairs on first zone +test.assertEqual(pair.getNumberOfPairs(indexZone), 4) + +# Get list of pairs on first zone +test.assertSequenceEqual(pair.getListOfPairs(indexZone), [(18, 3), (18, 4), (19, 4), (19, 5)]) + +# Get intersection points +test.assertEqual(len(pair.getNumberOfIntersectionPoints(indexZone)), 4) + +# For each pair: two points of intersections +iPair = 0 +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair], 2) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 1], 2) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 2], 2) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 3], 2) + +# Values of intersections +iPair = 0 +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair], + (0.5999999999999999, 0.0, -0.7333333333333334, 0.0), +) +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair + 1], + (-0.7333333333333334, 0.0, -1.0, 0.0), +) -test.assertSequenceEqual(pair.getListOfPairsOfZone(0), [(18, 3), (18, 4), (19, 4), (19, 5)]) -ref = [ - [ - 0.5999999999999999, - -0.7333333333333334, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], - [ - -0.7333333333333334, - -1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], - [ - 1.0, - -0.06666666666666687, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], - [ - -0.06666666666666687, - -1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - ], -] - -test.assertEqual(len(pair.getSlaveIntersectionPoints(0)), 4) -test.assertEqual(len(pair.getSlaveIntersectionPoints(0)[0]), 16) -print(pair.getSlaveIntersectionPoints(0)) -test.assertSequenceEqual(pair.getSlaveIntersectionPoints(0), ref) FIN() diff --git a/astest/cont001i.py b/astest/cont001i.py index 153e09df377..96034472deb 100644 --- a/astest/cont001i.py +++ b/astest/cont001i.py @@ -22,31 +22,29 @@ from code_aster.Commands import * from code_aster import CA from code_aster.MacroCommands.defi_cont import DEFI_CONT -from libaster import ContactPairing, ContactComputation +from libaster import ContactPairing, ContactComputation, CoordinatesSpace import numpy DEBUT( - CODE=_F(NIV_PUB_WEB="INTERNET"), - ERREUR=_F(ALARME="EXCEPTION"), - # DEBUG=_F(SDVERI='OUI',), - INFO=1, + CODE=_F(NIV_PUB_WEB="INTERNET"), ERREUR=_F(ALARME="EXCEPTION"), DEBUG=_F(SDVERI="NON"), INFO=1 ) test = CA.TestCase() -Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED") +meshLine = LIRE_MAILLAGE(UNITE=20, FORMAT="MED") -Mail = MODI_MAILLAGE( - reuse=Mail, MAILLAGE=Mail, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) +meshLine = MODI_MAILLAGE( + reuse=meshLine, MAILLAGE=meshLine, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) ) - -MODI = AFFE_MODELE(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D")) +modelLine = AFFE_MODELE( + MAILLAGE=meshLine, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D") +) # Slave side - CONT_BAS -DEFICO_BAS = DEFI_CONT( - MODELE=MODI, +contactLine = DEFI_CONT( + MODELE=modelLine, INFO=2, ZONE=( _F( @@ -60,37 +58,54 @@ ) # Pairing checks - -pair = ContactPairing(DEFICO_BAS) +pair = ContactPairing(contactLine) +pair.setVerbosity(1) pair.compute() +# One zone +test.assertEqual(pair.getNumberOfZones(), 1) +indexZone = 0 + +# Get number of pairs on first zone +test.assertEqual(pair.getNumberOfPairs(indexZone), 9) + +# Get list of pairs on first zone test.assertSequenceEqual( - pair.getListOfPairsOfZone(0), + pair.getListOfPairs(indexZone), [(68, 88), (68, 90), (70, 88), (69, 90), (69, 91), (69, 88), (69, 89), (71, 88), (71, 89)], ) -ref = [ - [1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], -] -test.assertEqual(len(pair.getSlaveIntersectionPoints(0)), 9) -print(pair.getSlaveIntersectionPoints(0)) -test.assertSequenceEqual(pair.getSlaveIntersectionPoints(0), ref) - -MailQ = CREA_MAILLAGE(MAILLAGE=Mail, LINE_QUAD=_F(TOUT="OUI")) - - -MODIQ = AFFE_MODELE(MAILLAGE=MailQ, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D")) + +# Get intersection points: 9 paires de points d'intersection +test.assertEqual(len(pair.getNumberOfIntersectionPoints(indexZone)), 9) + +# For each pair: 4 points of intersections +iPair = 0 +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair], 4) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 1], 4) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 2], 4) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 3], 4) + +# Values of intersections +iPair = 0 +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair], + (1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0), +) +iPair = 1 +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair], + (0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0), +) + +meshQuad = CREA_MAILLAGE(MAILLAGE=meshLine, LINE_QUAD=_F(TOUT="OUI")) + +modelQuad = AFFE_MODELE( + MAILLAGE=meshQuad, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D") +) # Slave side - CONT_BAS -DEFICOQ_BAS = DEFI_CONT( - MODELE=MODIQ, +contactQuad = DEFI_CONT( + MODELE=modelQuad, INFO=2, ZONE=( _F( @@ -104,29 +119,38 @@ ) # Pairing checks - -pair = ContactPairing(DEFICOQ_BAS) +pair = ContactPairing(contactQuad) +pair.setVerbosity(1) pair.compute() +# One zone +test.assertEqual(pair.getNumberOfZones(), 1) +indexZone = 0 + +# Get number of pairs on first zone +test.assertEqual(pair.getNumberOfPairs(indexZone), 9) +# Get list of pairs on first zone test.assertSequenceEqual( - pair.getListOfPairsOfZone(0), + pair.getListOfPairs(indexZone), [(88, 68), (88, 70), (88, 69), (88, 71), (90, 69), (90, 68), (89, 71), (89, 69), (91, 69)], ) -ref = [ - [1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, 0.0, 0.0, 1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], - [0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], -] -test.assertEqual(len(pair.getSlaveIntersectionPoints(0)), 9) -test.assertEqual(len(pair.getSlaveIntersectionPoints(0)[0]), 16) -print(pair.getSlaveIntersectionPoints(0)) -test.assertSequenceEqual(pair.getSlaveIntersectionPoints(0), ref) + +# Get intersection points: 4 paires de points d'intersection +test.assertEqual(len(pair.getNumberOfIntersectionPoints(indexZone)), 9) + +# For each pair: two points of intersections +iPair = 0 +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair], 4) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 1], 4) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 2], 4) +test.assertEqual(pair.getNumberOfIntersectionPoints(indexZone)[iPair + 3], 4) + +# Values of intersections +iPair = 0 +test.assertSequenceEqual( + pair.getIntersectionPoints(indexZone, CoordinatesSpace.Slave)[iPair], + (1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0), +) FIN() diff --git a/astest/cont101a.export b/astest/cont101a.export new file mode 100644 index 00000000000..20da60ed5ea --- /dev/null +++ b/astest/cont101a.export @@ -0,0 +1,9 @@ +P time_limit 30 +P memory_limit 524 +P ncpus 1 +P mpi_nbcpu 1 +P mpi_nbnoeud 1 +P testlist submit verification sequential + +F comm cont101a.py D 1 +F mmed cont101a.mmed D 20 diff --git a/astest/cont101a.mmed b/astest/cont101a.mmed new file mode 100644 index 00000000000..a44253d332d Binary files /dev/null and b/astest/cont101a.mmed differ diff --git a/astest/cont101a.py b/astest/cont101a.py new file mode 100644 index 00000000000..b422858f765 --- /dev/null +++ b/astest/cont101a.py @@ -0,0 +1,266 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +# + +from code_aster.Commands import * +from code_aster import CA +from enum import Enum +from code_aster.MacroCommands.defi_cont import DEFI_CONT +from libaster import ContactPairing, ContactComputation, PairingMethod +import numpy + + +DEBUT( + CODE=_F(NIV_PUB_WEB="INTERNET"), + ERREUR=_F(ALARME="EXCEPTION"), + # DEBUG=_F(SDVERI='OUI',), + INFO=1, +) + +test = CA.TestCase() + +Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED", INFO=2) + +Mail = MODI_MAILLAGE( + reuse=Mail, MAILLAGE=Mail, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) +) + +MODI = AFFE_MODELE(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D")) + + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(1) +meshPair.setPair("CONT_BAS", "CONT_HAUT") +meshPair.setMethod(PairingMethod.Fast) +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +# Some checks +test.assertSequenceEqual( + listPairs, + [ + (141, 260), + (141, 265), + (144, 260), + (144, 255), + (144, 250), + (142, 265), + (142, 266), + (142, 260), + (142, 267), + (142, 261), + (142, 262), + (147, 250), + (145, 250), + (145, 255), + (145, 251), + (145, 260), + (145, 256), + (145, 252), + (145, 261), + (145, 257), + (145, 262), + (143, 262), + (143, 267), + (143, 263), + (143, 268), + (148, 250), + (148, 251), + (148, 252), + (146, 262), + (146, 263), + (146, 257), + (146, 258), + (146, 252), + (146, 253), + (149, 252), + (149, 253), + ], +) + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(1) +meshPair.setPair("CONT_BAS", "CONT_HAUT") +meshPair.setMethod(PairingMethod.Legacy) +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +print("Nb pairs: ", nbPairs) +print("List pairs: ", listPairs) + +# Some checks +test.assertSequenceEqual( + listPairs, + [ + (141, 260), + (141, 265), + (144, 260), + (144, 255), + (144, 250), + (142, 265), + (142, 266), + (142, 260), + (142, 267), + (142, 261), + (142, 262), + (147, 250), + (145, 250), + (145, 255), + (145, 251), + (145, 260), + (145, 256), + (145, 252), + (145, 261), + (145, 257), + (145, 262), + (143, 262), + (143, 267), + (143, 263), + (143, 268), + (148, 250), + (148, 251), + (148, 252), + (146, 262), + (146, 263), + (146, 257), + (146, 258), + (146, 252), + (146, 253), + (149, 252), + (149, 253), + ], +) + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(1) +meshPair.setPair("CONT_BAS", "CONT_HAUT") +meshPair.setMethod(PairingMethod.BrutForce) +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +test.assertSequenceEqual( + listPairs, + [ + (141, 260), + (141, 265), + (142, 260), + (142, 261), + (142, 262), + (142, 265), + (142, 266), + (142, 267), + (143, 262), + (143, 263), + (143, 267), + (143, 268), + (144, 250), + (144, 255), + (144, 260), + (145, 250), + (145, 251), + (145, 252), + (145, 255), + (145, 256), + (145, 257), + (145, 260), + (145, 261), + (145, 262), + (146, 252), + (146, 253), + (146, 257), + (146, 258), + (146, 262), + (146, 263), + (147, 250), + (148, 250), + (148, 251), + (148, 252), + (149, 252), + (149, 253), + ], +) + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(1) +meshPair.setPair("CONT_HAUT", "CONT_BAS") +# meshPair.setMethod("NEW") +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +# Some checks +test.assertSequenceEqual( + listPairs, + [ + (250, 144), + (250, 147), + (250, 145), + (250, 148), + (255, 145), + (255, 144), + (251, 148), + (251, 145), + (260, 144), + (260, 145), + (260, 141), + (260, 142), + (256, 145), + (252, 145), + (252, 148), + (252, 146), + (252, 149), + (265, 142), + (265, 141), + (261, 142), + (261, 145), + (257, 145), + (257, 146), + (253, 149), + (253, 146), + (266, 142), + (262, 145), + (262, 146), + (262, 142), + (262, 143), + (258, 146), + (267, 142), + (267, 143), + (263, 143), + (263, 146), + (268, 143), + ], +) + +FIN() diff --git a/astest/cont101b.export b/astest/cont101b.export new file mode 100644 index 00000000000..c327d80bda6 --- /dev/null +++ b/astest/cont101b.export @@ -0,0 +1,9 @@ +P time_limit 30 +P memory_limit 524 +P ncpus 1 +P mpi_nbcpu 1 +P mpi_nbnoeud 1 +P testlist submit verification sequential + +F comm cont101b.py D 1 +F mmed cont101b.mmed D 20 diff --git a/astest/cont101b.mmed b/astest/cont101b.mmed new file mode 100644 index 00000000000..0c50bd91f29 Binary files /dev/null and b/astest/cont101b.mmed differ diff --git a/astest/cont101b.py b/astest/cont101b.py new file mode 100644 index 00000000000..9bb6a9ce7bb --- /dev/null +++ b/astest/cont101b.py @@ -0,0 +1,235 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +# + +from code_aster.Commands import * +from code_aster import CA +from code_aster.MacroCommands.defi_cont import DEFI_CONT +from libaster import ContactPairing, ContactComputation, PairingMethod +import numpy + + +DEBUT( + CODE=_F(NIV_PUB_WEB="INTERNET"), + ERREUR=_F(ALARME="EXCEPTION"), + # DEBUG=_F(SDVERI='OUI',), + INFO=1, +) + +test = CA.TestCase() + +Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED", INFO=2) + +Mail = MODI_MAILLAGE( + reuse=Mail, MAILLAGE=Mail, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) +) + +MODI = AFFE_MODELE(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D")) + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(2) +meshPair.setPair("CONT_BAS", "CONT_HAUT") +meshPair.setMethod(PairingMethod.Fast) +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +# Get quadrature points +indexPair = 4 +quadPoin = meshPair.getQuadraturePoints(indexPair) +print(" => Coordinates of quadrature points (global space):", quadPoin) + +# Some checks +test.assertSequenceEqual( + listPairs, + [ + (465, 314), + (465, 316), + (465, 332), + (465, 331), + (465, 330), + (468, 330), + (468, 313), + (468, 331), + (468, 328), + (468, 312), + (466, 330), + (466, 331), + (466, 360), + (466, 332), + (466, 362), + (466, 314), + (466, 344), + (466, 364), + (466, 316), + (466, 345), + (466, 358), + (466, 335), + (466, 357), + (471, 312), + (469, 312), + (469, 328), + (469, 313), + (469, 352), + (469, 330), + (469, 341), + (469, 356), + (469, 360), + (469, 343), + (469, 347), + (469, 362), + (469, 364), + (467, 357), + (467, 359), + (467, 358), + (467, 355), + (467, 365), + (467, 364), + (467, 354), + (467, 363), + (467, 351), + (467, 361), + (467, 353), + (472, 312), + (472, 328), + (472, 352), + (472, 341), + (472, 343), + (472, 327), + (470, 364), + (470, 362), + (470, 365), + (470, 360), + (470, 363), + (470, 356), + (470, 350), + (470, 361), + (470, 347), + (470, 348), + (470, 353), + (470, 343), + (470, 333), + (470, 349), + (470, 327), + (470, 326), + (473, 327), + (473, 343), + (473, 333), + (473, 326), + ], +) + + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(2) +meshPair.setPair("CONT_HAUT", "CONT_BAS") +meshPair.setMethod(PairingMethod.Fast) +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +# Some checks +test.assertSequenceEqual( + listPairs, + [ + (312, 468), + (312, 471), + (312, 469), + (312, 472), + (328, 472), + (328, 469), + (328, 468), + (313, 468), + (313, 469), + (352, 469), + (352, 472), + (330, 469), + (330, 468), + (330, 466), + (330, 465), + (341, 472), + (341, 469), + (356, 469), + (356, 470), + (331, 465), + (331, 468), + (331, 466), + (360, 466), + (360, 469), + (360, 470), + (343, 469), + (343, 472), + (343, 470), + (343, 473), + (347, 470), + (347, 469), + (332, 466), + (332, 465), + (362, 470), + (362, 469), + (362, 466), + (327, 473), + (327, 472), + (327, 470), + (350, 470), + (314, 465), + (314, 466), + (344, 466), + (364, 466), + (364, 469), + (364, 467), + (364, 470), + (333, 470), + (333, 473), + (363, 470), + (363, 467), + (348, 470), + (316, 466), + (316, 465), + (345, 466), + (358, 467), + (358, 466), + (365, 470), + (365, 467), + (326, 473), + (326, 470), + (361, 467), + (361, 470), + (349, 470), + (335, 466), + (357, 466), + (357, 467), + (359, 467), + (351, 467), + (353, 470), + (353, 467), + (355, 467), + (354, 467), + ], +) + + +FIN() diff --git a/astest/cont101c.export b/astest/cont101c.export new file mode 100644 index 00000000000..1b77e441637 --- /dev/null +++ b/astest/cont101c.export @@ -0,0 +1,9 @@ +P time_limit 30 +P memory_limit 524 +P ncpus 1 +P mpi_nbcpu 1 +P mpi_nbnoeud 1 +P testlist submit verification sequential + +F comm cont101c.py D 1 +F mmed cont101c.mmed D 20 diff --git a/astest/cont101c.mmed b/astest/cont101c.mmed new file mode 100644 index 00000000000..f055d62eb06 Binary files /dev/null and b/astest/cont101c.mmed differ diff --git a/astest/cont101c.py b/astest/cont101c.py new file mode 100644 index 00000000000..c366ef920e9 --- /dev/null +++ b/astest/cont101c.py @@ -0,0 +1,255 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +# -- Lines for dummy test and visualisation test +path_repo_save = ( + "/home/i48378/Documents/workspace/sandbox/sandbox-contact-mec-pairing-tests/cont101c" +) +import os.path as osp +import numpy as np + +# case - a (Slave side = CONT_BAS) +path_pairs_a = osp.join(path_repo_save, "case_a/listOfPairs.npy") +path_intepoints_a = osp.join(path_repo_save, "case_a/intersectionPoints.npy") +path_quadpoints_a = osp.join(path_repo_save, "case_a/quadraturePoints.npy") +# case - b (Slave side = CONT_HAUT) +path_pairs_b = osp.join(path_repo_save, "case_b/listOfPairs.npy") +path_intepoints_b = osp.join(path_repo_save, "case_b/intersectionPoints.npy") +path_quadpoints_b = osp.join(path_repo_save, "case_b/quadraturePoints.npy") +save_data = True + +# -- Core of the test case +from code_aster.Commands import * +from code_aster import CA +from code_aster.MacroCommands.defi_cont import DEFI_CONT +from libaster import ContactPairing, ContactComputation, PairingMethod +import numpy + + +DEBUT( + CODE=_F(NIV_PUB_WEB="INTERNET"), + ERREUR=_F(ALARME="EXCEPTION"), + # DEBUG=_F(SDVERI='OUI',), + INFO=1, +) + +test = CA.TestCase() + +Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED", INFO=2) + +Mail = MODI_MAILLAGE( + reuse=Mail, MAILLAGE=Mail, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) +) + +MODI = AFFE_MODELE(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D")) + +# # Slave side - CONT_BAS +# DEFICO_BAS = DEFI_CONT( +# MODELE=MODI, +# INFO=2, +# ZONE=( +# _F( +# APPARIEMENT="MORTAR", +# GROUP_MA_MAIT="CONT_HAUT", +# GROUP_MA_ESCL="CONT_BAS", +# ALGO_CONT="LAGRANGIEN", +# CONTACT_INIT="OUI", +# ), +# ), +# ) + +# # Pairing checks +# pair = ContactPairing(DEFICO_BAS) +# pair.compute() + +# # some checks for the zone 0: +# zone = DEFICO_BAS.getContactZone(0) +# meshPair = zone.getMeshPairing() +# listPairs_zone = meshPair.getListOfPairs() + +# Generate pairs +meshPair = CA.MeshPairing(Mail) +meshPair.setVerbosity(2) +meshPair.setPair("CONT_BAS", "CONT_HAUT") +meshPair.setMethod(PairingMethod.Fast) +meshPair.compute() + +# Get pairs +nbPairs = meshPair.getNumberOfPairs() +listPairs = meshPair.getListOfPairs() + +print("Nb pairs: ", nbPairs) +print("List pairs: ", listPairs) + + +# Some checks +test.assertSequenceEqual( + listPairs, + [ + (186, 319), + (198, 319), + (198, 314), + (198, 309), + (187, 309), + (202, 309), + (202, 314), + (202, 310), + (202, 319), + (202, 315), + (202, 320), + (202, 316), + (189, 309), + (189, 304), + (203, 316), + (203, 315), + (203, 311), + (203, 310), + (203, 306), + (203, 309), + (203, 305), + (197, 316), + (197, 315), + (197, 321), + (197, 320), + (197, 319), + (188, 304), + (201, 304), + (201, 309), + (201, 305), + (201, 310), + (201, 306), + (195, 306), + (195, 311), + (195, 316), + (195, 312), + (195, 317), + (196, 321), + (196, 322), + (196, 316), + (190, 304), + (200, 306), + (200, 305), + (200, 304), + (193, 317), + (193, 312), + (193, 311), + (193, 307), + (193, 306), + (194, 317), + (194, 316), + (194, 322), + (194, 321), + (191, 304), + (199, 306), + (199, 307), + (192, 307), + ], +) + +intePoints = meshPair.getIntersectionPoints(0) + +print("intePoints: ", intePoints) + +test.assertAlmostEqual(intePoints[0][0], 50.0) +test.assertAlmostEqual(intePoints[0][1], 183.3333333333333) +test.assertAlmostEqual(intePoints[0][2], 200.0) + + +# if save_data: +# np.save(path_pairs_a, listPairs) +# intePointsList = [] +# quadPointsList = [] +# # - Loop over the pairs +# for index_pair in range(nbPairs): +# # - Store and save intersection points +# IntePoints = meshPair.getIntersectionPoints(index_pair) +# intePts_current = [tuple(intePt) for intePt in IntePoints] +# intePointsList.append(intePts_current) +# # - Store and save integration points +# quadPoints = meshPair.getQuadraturePoints(index_pair) +# quadPts_current = [tuple(quaPt) for quaPt in quadPoints] +# quadPointsList.append(quadPts_current) +# # - Save data +# np.save(path_intepoints_a, intePointsList) +# np.save(path_quadpoints_a, quadPointsList) + +# # Slave side - CONT_BAS +# DEFICO_HAUT = DEFI_CONT( +# MODELE=MODI, +# INFO=2, +# ZONE=( +# _F( +# APPARIEMENT="MORTAR", +# GROUP_MA_MAIT="CONT_BAS", +# GROUP_MA_ESCL="CONT_HAUT", +# ALGO_CONT="LAGRANGIEN", +# CONTACT_INIT="OUI", +# ), +# ), +# ) + +# # Pairing checks +# pair = ContactPairing(DEFICO_HAUT) +# pair.compute() + +# # some checks for the zone 0: +# zone = DEFICO_HAUT.getContactZone(0) +# meshPair = zone.getMeshPairing() +# listPairs_zone = meshPair.getListOfPairs() + +# # Generate pairs +# meshPair = CA.MeshPairing(Mail) +# meshPair.setVerbosity(2) +# meshPair.setPair("CONT_HAUT", "CONT_BAS") +# meshPair.setMethod("NEW") +# meshPair.compute() + +# # Get pairs +# nbPairs = meshPair.getNumberOfPairs() +# listPairs = meshPair.getListOfPairs() + +# # Some checks +# test.assertSequenceEqual(listPairs, +# [(304, 188), (304, 190), (304, 189), (304, 191), (304, 201), (304, 200), (309, 201), (309, 189), (309, 203), \ +# (309, 187), (309, 202), (309, 198), (305, 200), (305, 201), (305, 203), (314, 198), (314, 202), (310, 202), \ +# (310, 203), (310, 201), (306, 203), (306, 201), (306, 195), (306, 200), (306, 193), (306, 199), (319, 202), \ +# (319, 198), (319, 197), (319, 186), (315, 202), (315, 203), (315, 197), (311, 203), (311, 195), (311, 193), \ +# (307, 199), (307, 192), (307, 193), (320, 197), (320, 202), (316, 197), (316, 202), (316, 196), (316, 203), \ +# (316, 194), (316, 195), (312, 193), (312, 195), (321, 197), (321, 196), (321, 194), (317, 195), (317, 193), \ +# (317, 194), (322, 194), (322, 196)]) + +# if save_data: +# intePointsList = [] +# quadPointsList = [] +# # - Loop over the pairs +# for index_pair in range(nbPairs): +# # - Store and save intersection points +# IntePoints = meshPair.getIntersectionPoints(index_pair) +# intePts_current = [tuple(intePt) for intePt in IntePoints] +# intePointsList.append(intePts_current) +# # - Store and save integration points +# quadPoints = meshPair.getQuadraturePoints(indexPair) +# quadPts_current = [tuple(quaPt) for quaPt in quadPoints] +# quadPointsList.append(quadPts_current) +# # - Save data +# np.save(path_intepoints_b, intePointsList) +# np.save(path_quadpoints_b, quadPointsList) + + +FIN() diff --git a/astest/cont103b.export b/astest/cont103b.export new file mode 100644 index 00000000000..00abc192886 --- /dev/null +++ b/astest/cont103b.export @@ -0,0 +1,9 @@ +P time_limit 30 +P memory_limit 524 +P ncpus 1 +P mpi_nbcpu 1 +P mpi_nbnoeud 1 +P testlist submit verification sequential + +F comm cont103b.py D 1 +F mmed cont103b.mmed D 20 diff --git a/astest/cont103b.mmed b/astest/cont103b.mmed new file mode 100644 index 00000000000..7492568cf1a Binary files /dev/null and b/astest/cont103b.mmed differ diff --git a/astest/cont103b.py b/astest/cont103b.py new file mode 100644 index 00000000000..6fa4f10c8e8 --- /dev/null +++ b/astest/cont103b.py @@ -0,0 +1,86 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +from code_aster.Commands import * +from code_aster import CA +from code_aster.MacroCommands.defi_cont import DEFI_CONT +from libaster import ContactPairing, ContactComputation, PairingMethod +import numpy + +import os.path as osp +import time +import numpy as np + + +# ------------------------------------- +# - Main +# ------------------------------------- +DEBUT(CODE=_F(NIV_PUB_WEB="INTERNET"), DEBUG=_F(SDVERI="OUI"), INFO=1) + +test = CA.TestCase() + +Mail = LIRE_MAILLAGE(UNITE=20, FORMAT="MED") + +Mail = MODI_MAILLAGE( + reuse=Mail, MAILLAGE=Mail, ORIE_PEAU=_F(GROUP_MA_PEAU=("CONT_HAUT", "CONT_BAS")) +) + +MAT = DEFI_MATERIAU(ELAS=_F(E=20000, NU=0.3, ALPHA=0.01)) + +CHMAT = AFFE_MATERIAU(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", MATER=MAT)) + +MODI = AFFE_MODELE(MAILLAGE=Mail, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="D_PLAN")) + +# ------------------------------------- +# - Slave side - CONT_BAS +# ------------------------------------- +## -- OLD PAIRING METHOD +# - Generate pairs +meshPair_old = CA.MeshPairing(Mail) +meshPair_old.setVerbosity(2) +meshPair_old.setPair("CONT_BAS", "CONT_HAUT") +meshPair_old.setMethod(PairingMethod.Legacy) + +t_0_old = time.time() +meshPair_old.compute() +dur_old = time.time() - t_0_old + +# - Get pairs +nbPairs_old = meshPair_old.getNumberOfPairs() +listPairs_old = meshPair_old.getListOfPairs() + +# -- FAST PAIRING METHOD +# - Generate pairs +meshPair_fast = CA.MeshPairing(Mail) +meshPair_fast.setVerbosity(2) +meshPair_fast.setPair("CONT_BAS", "CONT_HAUT") +meshPair_fast.setMethod(PairingMethod.BrutForce) + +t_0_fast = time.time() +meshPair_fast.compute() +dur_fast = time.time() - t_0_fast + +# - Get pairs +nbPairs_fast = meshPair_fast.getNumberOfPairs() +listPairs_fast = meshPair_fast.getListOfPairs() + +test.assertEqual(nbPairs_fast, nbPairs_old) + + +FIN() diff --git a/astest/vocab01a.34 b/astest/vocab01a.34 index 6827e17dcdf..981935ed34b 100644 --- a/astest/vocab01a.34 +++ b/astest/vocab01a.34 @@ -492,6 +492,7 @@ A_T_D_L A_T_D_N A_T_L A_T_N +ArrheniusIndex B B1 B2 @@ -538,6 +539,8 @@ BETA_PIC BETA_REEL BETA_ULT BETON +BETON_AGEING +BETON_AGEING_FO BETON_BURGER BETON_BURGER_FO BETON_DESORP @@ -1298,6 +1301,7 @@ C_S_VP C_TZTZ C_VOLU Cohesion +ConcreteInitTime CritStateSlope D D0 @@ -1702,6 +1706,7 @@ D_SIGM_EPSI_NORM D_VAN_A D_VAN_B D_VISC_TEMP +DessiccationModulus DilatancyAngle E E1 @@ -3427,6 +3432,7 @@ K_T_D_L K_T_D_N K_T_L K_T_N +KelvinIndex L L2 LA2_FLI @@ -4071,6 +4077,8 @@ M_T_L M_T_N M_ULT M_ZIRC +MaxwellDevModulus +MaxwellSphModulus MetaAcierEPIL_PT MetaAcierEPIL_PT_FO MinCritPress @@ -5332,6 +5340,7 @@ R_X2 R_X5 RefeConsPress ReferencePressure +ReferenceTemperature S SA SANDWICH @@ -6416,6 +6425,10 @@ VZ V_1 V_2 V_BETON_GRANGER +VoigtDevModulus +VoigtDevViscosity +VoigtSphModulus +VoigtSphViscosity W WAECKEL WEIBULL diff --git a/astest/wtnv104a.comm b/astest/wtnv104a.comm new file mode 100644 index 00000000000..1b36a0128c9 --- /dev/null +++ b/astest/wtnv104a.comm @@ -0,0 +1,334 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +DEBUT(CODE=_F(NIV_PUB_WEB="INTERNET")) + +### >>>>>>>>>>>>> +### Read the mesh +### <<<<<<<<<<<<< + +MA = LIRE_MAILLAGE(FORMAT="ASTER") + +MA = MODI_MAILLAGE( + reuse=MA, + MAILLAGE=MA, + ORIE_PEAU=_F(GROUP_MA_PEAU=("HAUT", "BAS", "DEVANT", "DERRIERE", "DROITE", "GAUCHE")), +) + +### >>>>>>>>>>>>>>>>> +### Model affectation +### <<<<<<<<<<<<<<<<< + +MO = AFFE_MODELE(MAILLAGE=MA, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D_THHM")) + +### >>>>>>>>>>>>>>>>>>> +### Material properties +### <<<<<<<<<<<<<<<<<<< + +# Concrete parameters (BETON_AGEING model) + +E = 30.0e9 +NU = 0.2 +KV_VT = 1.0e9 +KD_VT = 1.0e9 +ETAV_VT = 1.0e13 +ETAD_VT = 1.0e13 +KV_MX = 1.0e9 +KD_MX = 1.0e9 +T0 = 0.0 +EA_R = 2100.0 +M_RHOR = 18.0e-3 / (1.0e3 * 8.314) +TREF = 293.0 +K_FD = 1.0e6 + +CONCRETE = DEFI_MATERIAU( + ELAS=_F(E=E, NU=NU, ALPHA=0.0), + BETON_AGEING=_F( + YoungModulus=E, + PoissonRatio=NU, + VoigtSphModulus=KV_VT, + VoigtDevModulus=KD_VT, + VoigtSphViscosity=ETAV_VT, + VoigtDevViscosity=ETAD_VT, + MaxwellSphModulus=KV_MX, + MaxwellDevModulus=KD_MX, + ConcreteInitTime=T0, + DessiccationModulus=K_FD, + ReferenceTemperature=TREF, + ArrheniusIndex=EA_R, + KelvinIndex=M_RHOR, + ), + COMP_THM="LIQU_GAZ", + THM_LIQU=_F( + RHO=1.0e3, + UN_SUR_K=0.0, + VISC=DEFI_CONSTANTE(VALE=1.0e-3), + D_VISC_TEMP=DEFI_CONSTANTE(VALE=0.0), + ALPHA=DEFI_CONSTANTE(VALE=0.0), + CP=1.0e3, + ), + THM_GAZ=_F( + MASS_MOL=28.0e-3, + VISC=DEFI_CONSTANTE(VALE=1.0e-5), + D_VISC_TEMP=DEFI_CONSTANTE(VALE=0.0), + CP=1.0e3, + ), + THM_DIFFU=_F( + R_GAZ=8.314, + CP=1.0e3, + RHO=2.7e3, + BIOT_COEF=1.0, + PESA_X=0.0, + PESA_Y=0.0, + PESA_Z=0.0, + PERM_IN=DEFI_CONSTANTE(VALE=1.0e-20), + VG_N=1.3, + VG_PR=1.0e7, + VG_SR=0.0, + VG_SMAX=0.99, + VG_SATUR=1.0, + ), + THM_INIT=_F(TEMP=TREF, PRE1=0.0, PRE2=1.0e5, PORO=0.2), +) + +### >>>>>>>>>>>>>>>>>>>> +### Material affectation +### <<<<<<<<<<<<<<<<<<<< + +CHMAT = AFFE_MATERIAU(MAILLAGE=MA, AFFE=_F(TOUT="OUI", MATER=CONCRETE)) + +### >>>>>>>>>>>>>>>>>>> +### Boundary conditions +### <<<<<<<<<<<<<<<<<<< + +second = 1.0 +year = 365.0 * (24.0 * 3600.0) +tload = 28.0 * (24.0 * 3600.0) +pload = 30.0e6 + +CL_DEPL = AFFE_CHAR_CINE( + MODELE=MO, + MECA_IMPO=( + _F(GROUP_MA="BAS", DZ=0.0), + _F(GROUP_MA="DEVANT", DX=0.0), + _F(GROUP_MA="GAUCHE", DY=0.0), + ), +) + +CL_PRE1 = AFFE_CHAR_CINE(MODELE=MO, MECA_IMPO=_F(TOUT="OUI", PRE1=0.0)) + +CL_PRE2 = AFFE_CHAR_CINE(MODELE=MO, MECA_IMPO=_F(TOUT="OUI", PRE2=0.0)) + +CL_TEMP = AFFE_CHAR_CINE(MODELE=MO, MECA_IMPO=_F(TOUT="OUI", TEMP=0.0)) + +PRES = DEFI_FONCTION( + NOM_PARA="INST", + NOM_RESU="PRESSION", + VALE=(tload, 0.0, tload + second, pload), + PROL_DROITE="CONSTANT", +) + +CL_PRES = AFFE_CHAR_MECA_F(MODELE=MO, PRES_REP=_F(GROUP_MA=("HAUT"), PRES=PRES), VERI_NORM="OUI") + +### >>>>>>>>>> +### Time steps +### <<<<<<<<<< + +TEMPS = DEFI_LIST_REEL( + DEBUT=tload, INTERVALLE=(_F(JUSQU_A=tload + second, NOMBRE=10), _F(JUSQU_A=year, NOMBRE=1000)) +) + +DEFLIST = DEFI_LIST_INST( + DEFI_LIST=_F(LIST_INST=TEMPS), + ECHEC=_F(EVENEMENT="ERREUR", ACTION="DECOUPE", SUBD_METHODE="AUTO"), +) +### >>>>>>>> +### Solution +### <<<<<<<< + +RESU = STAT_NON_LINE( + MODELE=MO, + CHAM_MATER=CHMAT, + EXCIT=( + _F(CHARGE=CL_DEPL), + _F(CHARGE=CL_PRE1), + _F(CHARGE=CL_PRE2), + _F(CHARGE=CL_TEMP), + _F(CHARGE=CL_PRES), + ), + COMPORTEMENT=_F(RELATION="KIT_THHM", RELATION_KIT=("BETON_AGEING", "LIQU_GAZ", "HYDR_VGM")), + INCREMENT=_F(LIST_INST=DEFLIST, INST_INIT=tload, INST_FIN=year), + NEWTON=_F(MATRICE="TANGENTE", REAC_ITER=1), + CONVERGENCE=_F(ITER_GLOB_MAXI=10, RESI_GLOB_RELA=1.0e-10), +) + +### >>>>>>>>>>>>>>> +### Post-processing +### <<<<<<<<<<<<<<< + +RESU = CALC_CHAMP( + reuse=RESU, + RESULTAT=RESU, + CONTRAINTE="SIEF_NOEU", + DEFORMATION="EPSI_NOEU", + VARI_INTERNE="VARI_NOEU", +) + +### >>>>> +### Tests +### <<<<< + +import numpy as np + +### Computation of the reversible part of the creep strain +def EXX_FP_R(t, ti, sig): + return ( + sig + / 3.0 + * ( + 1.0 / (3.0 * KV_VT) * (1.0 - np.exp(-KV_VT * (t - ti) / ETAV_VT)) + - 1.0 / (2.0 * KD_VT) * (1.0 - np.exp(-KD_VT * (t - ti) / ETAD_VT)) + ) + ) + + +def EZZ_FP_R(t, ti, sig): + return ( + sig + / 3.0 + * ( + 1.0 / (3.0 * KV_VT) * (1.0 - np.exp(-KV_VT * (t - ti) / ETAV_VT)) + + 1.0 / KD_VT * (1.0 - np.exp(-KD_VT * (t - ti) / ETAD_VT)) + ) + ) + + +### Computation of the irreversible part of the creep strain +def EXX_FP_I(t, t0, ti, sig): + return sig / 3.0 * (1.0 / (3.0 * KV_MX) - 1.0 / (2.0 * KD_MX)) * np.log((t - t0) / (ti - t0)) + + +def EZZ_FP_I(t, t0, ti, sig): + return sig / 3.0 * (1.0 / (3.0 * KV_MX) + 1.0 / KD_MX) * np.log((t - t0) / (ti - t0)) + + +### Computation of the total strain +def EXX(t, t0, ti, sig): + EXX_EL = -NU * sig / E + return EXX_EL + EXX_FP_R(t, ti, sig) + EXX_FP_I(t, t0, ti, sig) + + +def EZZ(t, t0, ti, sig): + EZZ_EL = sig / E + return EZZ_EL + EZZ_FP_R(t, ti, sig) + EZZ_FP_I(t, t0, ti, sig) + + +EXX_end = EXX(year, T0, tload + second, -pload) +EZZ_end = EZZ(year, T0, tload + second, -pload) +EXX_FP_R_end = EXX_FP_R(year, tload + second, -pload) +EZZ_FP_R_end = EZZ_FP_R(year, tload + second, -pload) +EXX_FP_I_end = EXX_FP_I(year, T0, tload + second, -pload) +EZZ_FP_I_end = EZZ_FP_I(year, T0, tload + second, -pload) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="EPSI_NOEU", + NOM_CMP="EPXX", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EXX_end, + VALE_CALC=0.006146144428842571, + ) +) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="EPSI_NOEU", + NOM_CMP="EPZZ", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EZZ_end, + VALE_CALC=-0.048569155430740474, + ) +) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="VARI_NOEU", + NOM_CMP="V1", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EXX_FP_R_end, + VALE_CALC=0.0016666666666666722, + ) +) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="VARI_NOEU", + NOM_CMP="V3", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EZZ_FP_R_end, + VALE_CALC=-0.013333333333333315, + ) +) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="VARI_NOEU", + NOM_CMP="V7", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EXX_FP_I_end, + VALE_CALC=0.004279477762175899, + ) +) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="VARI_NOEU", + NOM_CMP="V9", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EZZ_FP_I_end, + VALE_CALC=-0.03423582209740715, + ) +) + + +FIN() diff --git a/astest/wtnv104a.export b/astest/wtnv104a.export new file mode 100644 index 00000000000..0f07b60e7e9 --- /dev/null +++ b/astest/wtnv104a.export @@ -0,0 +1,9 @@ +P time_limit 110 +P memory_limit 512 +P ncpus 1 +P mpi_nbcpu 1 +P mpi_nbnoeud 1 +P testlist verification sequential + +F comm wtnv104a.comm D 1 +F mmed wtnv136c.mail D 20 diff --git a/astest/wtnv104b.comm b/astest/wtnv104b.comm new file mode 100644 index 00000000000..20103b1159a --- /dev/null +++ b/astest/wtnv104b.comm @@ -0,0 +1,230 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +DEBUT(CODE=_F(NIV_PUB_WEB="INTERNET")) + +### >>>>>>>>>>>>> +### Read the mesh +### <<<<<<<<<<<<< + +MA = LIRE_MAILLAGE(FORMAT="ASTER") + +MA = MODI_MAILLAGE( + reuse=MA, + MAILLAGE=MA, + ORIE_PEAU=_F(GROUP_MA_PEAU=("HAUT", "BAS", "DEVANT", "DERRIERE", "DROITE", "GAUCHE")), +) + +### >>>>>>>>>>>>>>>>> +### Model affectation +### <<<<<<<<<<<<<<<<< + +MO = AFFE_MODELE(MAILLAGE=MA, AFFE=_F(TOUT="OUI", PHENOMENE="MECANIQUE", MODELISATION="3D_THHM")) + +### >>>>>>>>>>>>>>>>>>> +### Material properties +### <<<<<<<<<<<<<<<<<<< + +# Concrete parameters (BETON_AGEING model) + +E = 30.0e9 +NU = 0.2 +KV_VT = 1.0e9 +KD_VT = 1.0e9 +ETAV_VT = 1.0e13 +ETAD_VT = 1.0e13 +KV_MX = 1.0e9 +KD_MX = 1.0e9 +T0 = 0.0 +EA_R = 2100.0 +M_RHOR = 18.0e-3 / (1.0e3 * 8.314) +TREF = 293.0 +K_FD = 1.0e9 + +# Some THM parameters to compute an analytical solution (see the post-process section) + +VG_N = 1.3 +VG_PR = 1.0e7 +BIOT = 1.0 + +CONCRETE = DEFI_MATERIAU( + ELAS=_F(E=E, NU=NU, ALPHA=0.0), + BETON_AGEING=_F( + YoungModulus=E, + PoissonRatio=NU, + VoigtSphModulus=KV_VT, + VoigtDevModulus=KD_VT, + VoigtSphViscosity=ETAV_VT, + VoigtDevViscosity=ETAD_VT, + MaxwellSphModulus=KV_MX, + MaxwellDevModulus=KD_MX, + ConcreteInitTime=T0, + DessiccationModulus=K_FD, + ReferenceTemperature=TREF, + ArrheniusIndex=EA_R, + KelvinIndex=M_RHOR, + ), + COMP_THM="LIQU_GAZ", + THM_LIQU=_F( + RHO=1.0e3, + UN_SUR_K=0.0, + VISC=DEFI_CONSTANTE(VALE=1.0e-3), + D_VISC_TEMP=DEFI_CONSTANTE(VALE=0.0), + ALPHA=DEFI_CONSTANTE(VALE=0.0), + CP=1.0e3, + ), + THM_GAZ=_F( + MASS_MOL=28.0e-3, + VISC=DEFI_CONSTANTE(VALE=1.0e-5), + D_VISC_TEMP=DEFI_CONSTANTE(VALE=0.0), + CP=1.0e3, + ), + THM_DIFFU=_F( + R_GAZ=8.314, + CP=1.0e3, + RHO=2.7e3, + BIOT_COEF=BIOT, + PESA_X=0.0, + PESA_Y=0.0, + PESA_Z=0.0, + PERM_IN=DEFI_CONSTANTE(VALE=1.0e-20), + VG_N=VG_N, + VG_PR=VG_PR, + VG_SR=0.0, + VG_SMAX=0.99, + VG_SATUR=1.0, + ), + THM_INIT=_F(TEMP=TREF, PRE1=0.0, PRE2=1.0e5, PORO=0.2), +) + +### >>>>>>>>>>>>>>>>>>>> +### Material affectation +### <<<<<<<<<<<<<<<<<<<< + +CHMAT = AFFE_MATERIAU(MAILLAGE=MA, AFFE=_F(TOUT="OUI", MATER=CONCRETE)) + +### >>>>>>>>>>>>>>>>>>> +### Boundary conditions +### <<<<<<<<<<<<<<<<<<< + +tload = 28.0 * (24.0 * 3600.0) +year = 365.0 * (24.0 * 3600.0) +pcap_load = 100.0e6 + +CL_DEPL = AFFE_CHAR_CINE( + MODELE=MO, + MECA_IMPO=( + _F(GROUP_MA="BAS", DZ=0.0), + _F(GROUP_MA="DEVANT", DX=0.0), + _F(GROUP_MA="GAUCHE", DY=0.0), + ), +) + +CL_PRE1 = AFFE_CHAR_CINE(MODELE=MO, MECA_IMPO=_F(TOUT="OUI", PRE1=1.0)) + +CL_PRE2 = AFFE_CHAR_CINE(MODELE=MO, MECA_IMPO=_F(TOUT="OUI", PRE2=0.0)) + +CL_TEMP = AFFE_CHAR_CINE(MODELE=MO, MECA_IMPO=_F(TOUT="OUI", TEMP=0.0)) + +CO_PRE1 = DEFI_FONCTION(NOM_PARA="INST", VALE=(tload, 0.0, year, pcap_load), PROL_DROITE="CONSTANT") + +### >>>>>>>>>> +### Time steps +### <<<<<<<<<< + +TEMPS = DEFI_LIST_REEL(DEBUT=tload, INTERVALLE=(_F(JUSQU_A=year, NOMBRE=1000))) + + +DEFLIST = DEFI_LIST_INST( + DEFI_LIST=_F(LIST_INST=TEMPS), + ECHEC=_F(EVENEMENT="ERREUR", ACTION="DECOUPE", SUBD_METHODE="AUTO"), +) +### >>>>>>>> +### Solution +### <<<<<<<< + +RESU = STAT_NON_LINE( + MODELE=MO, + CHAM_MATER=CHMAT, + EXCIT=( + _F(CHARGE=CL_DEPL), + _F(CHARGE=CL_PRE1, FONC_MULT=CO_PRE1), + _F(CHARGE=CL_PRE2), + _F(CHARGE=CL_TEMP), + ), + COMPORTEMENT=_F(RELATION="KIT_THHM", RELATION_KIT=("BETON_AGEING", "LIQU_GAZ", "HYDR_VGM")), + INCREMENT=_F(LIST_INST=DEFLIST, INST_INIT=tload, INST_FIN=year), + NEWTON=_F(MATRICE="TANGENTE", REAC_ITER=1), + CONVERGENCE=_F(ITER_GLOB_MAXI=10, RESI_GLOB_RELA=1.0e-8), +) + +### >>>>>>>>>>>>>>> +### Post-processing +### <<<<<<<<<<<<<<< + +RESU = CALC_CHAMP( + reuse=RESU, + RESULTAT=RESU, + CONTRAINTE="SIEF_NOEU", + DEFORMATION="EPSI_NOEU", + VARI_INTERNE="VARI_NOEU", +) + +### >>>>> +### Tests +### <<<<< + +import numpy as np +from scipy.integrate import quad + + +def sigp(pc): + return BIOT * quad(lambda x: (1.0 + (x / VG_PR) ** VG_N) ** (1.0 / VG_N - 1.0), 0, pc)[0] + + +def hr(pc): + return np.exp(-M_RHOR * pc / TREF) + + +def dhr(pc): + return -M_RHOR / TREF * hr(pc) + + +def eps_dessic(pc): + sig = 0.0 # zero total stress applied in the test + return quad(lambda x: abs(dhr(x)) * (sig - sigp(x)) / K_FD, 0, pc)[0] + + +EXX_FDESS_end = eps_dessic(pcap_load) + +TEST_RESU( + RESU=_F( + INST=year, + RESULTAT=RESU, + REFERENCE="ANALYTIQUE", + NOM_CHAM="VARI_NOEU", + NOM_CMP="V13", + GROUP_NO="NO8", + PRECISION=0.01, + VALE_REFE=EXX_FDESS_end, + VALE_CALC=-0.016621556339224738, + ) +) + +FIN() diff --git a/astest/wtnv104b.export b/astest/wtnv104b.export new file mode 100644 index 00000000000..eb7b0fa877a --- /dev/null +++ b/astest/wtnv104b.export @@ -0,0 +1,9 @@ +P time_limit 110 +P memory_limit 512 +P ncpus 1 +P mpi_nbcpu 1 +P mpi_nbnoeud 1 +P testlist verification sequential + +F comm wtnv104b.comm D 1 +F mmed wtnv136c.mail D 20 diff --git a/astest/zzzz131a.comm b/astest/zzzz131a.comm index 7688e2eabb8..6cf7e66bdaa 100644 --- a/astest/zzzz131a.comm +++ b/astest/zzzz131a.comm @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2022 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -606,16 +606,6 @@ RESU11 = EXTR_RESU(RESULTAT=RESU1, ARCHIVAGE=_F(LIST_INST=LINST11)) RESU11 = CALC_CHAMP(reuse=RESU11, DEFORMATION=("DEGE_ELNO"), RESULTAT=RESU11) -# IMPR_RESU(FORMAT="RESULTAT",RESU=_F(RESULTAT=RESU11)) - -# POUR COMPLETER LA VALIDATION INFORMATIQUE DE EXTR_RESU : EXTRACTION EN PLACE - -RESU12 = EXTR_RESU(RESULTAT=RESU1, ARCHIVAGE=_F(LIST_INST=LINST11)) -RESU12 = EXTR_RESU(reuse=RESU12, RESULTAT=RESU12, ARCHIVAGE=_F(LIST_INST=LINST11)) - -DETRUIRE(NOM=RESU12) - - DETRUIRE(NOM=RESU1) CALC_CHAMP(reuse=RESU11, RESULTAT=RESU11, CONTRAINTE="EFGE_NOEU") diff --git a/astest/zzzz163b.comm b/astest/zzzz163b.comm index 0b84725b6b4..47d96db7897 100644 --- a/astest/zzzz163b.comm +++ b/astest/zzzz163b.comm @@ -159,10 +159,17 @@ ACIER_CS = DEFI_MATERIAU( CM_CS = AFFE_MATERIAU(MAILLAGE=M, AFFE=_F(TOUT="OUI", MATER=ACIER_CS)) -RESU.setMaterialField(CM_CS) +RESU_CS = STAT_NON_LINE( + MODELE=MO, + CHAM_MATER=CM_CS, + EXCIT=(_F(CHARGE=CHARG), _F(CHARGE=ZERO)), + COMPORTEMENT=_F(RELATION="MFRONT", RESI_INTE=1e-14, COMPOR_MFRONT=BEHAVIOUR), + INCREMENT=_F(LIST_INST=L_INST, NUME_INST_FIN=10), + CONVERGENCE=_F(RESI_GLOB_RELA=1.0e-10), +) PBSMNOMT = POST_BEREMIN( - RESULTAT=RESU, + RESULTAT=RESU_CS, COEF_MULT=1, DEFORMATION="PETIT", GROUP_MA="s_tout", @@ -172,7 +179,7 @@ PBSMNOMT = POST_BEREMIN( ) PBSMMT = POST_BEREMIN( - RESULTAT=RESU, + RESULTAT=RESU_CS, COEF_MULT=1, DEFORMATION="PETIT", GROUP_MA="s_tout", diff --git a/astest/zzzz223a.comm b/astest/zzzz223a.comm index 7d3755d2074..523ba35af48 100644 --- a/astest/zzzz223a.comm +++ b/astest/zzzz223a.comm @@ -217,8 +217,8 @@ IMPR_TABLE( ) -# validation de la commande EXTR_RESU / ARCHIVAGE (+reuse) : -# ----------------------------------------------------------- +# validation de la commande EXTR_RESU / ARCHIVAGE +# ----------------------------------------------- U = CALC_CHAMP(reuse=U, RESULTAT=U, CONTRAINTE=("SIEF_ELGA")) U2 = EXTR_RESU(RESULTAT=U, ARCHIVAGE=_F(NUME_ORDRE=(3, 5, 7, 9))) # on appelle 3 fois CALC_CHAMP + MAILLE pour forcer la creation de 3 LIGREL differents @@ -228,7 +228,6 @@ U2 = CALC_CHAMP(reuse=U2, RESULTAT=U2, CONTRAINTE=("SIGM_ELNO"), NUME_ORDRE=7, G U2 = CALC_CHAMP(reuse=U2, RESULTAT=U2, CONTRAINTE=("SIGM_ELNO"), NUME_ORDRE=9, GROUP_MA="M1") U2 = CALC_CHAMP(reuse=U2, RESULTAT=U2, CONTRAINTE="SIGM_NOEU", NUME_ORDRE=(5, 7, 9)) -U3 = EXTR_RESU(RESULTAT=U2, ARCHIVAGE=_F(NUME_ORDRE=(5, 9), CHAM_EXCLU=("SIGM_NOEU"))) -U2 = EXTR_RESU(reuse=U2, RESULTAT=U2, ARCHIVAGE=_F(NUME_ORDRE=(5, 9), CHAM_EXCLU=("SIGM_NOEU"))) +U2 = EXTR_RESU(RESULTAT=U2, ARCHIVAGE=_F(NUME_ORDRE=(5, 9), CHAM_EXCLU=("SIGM_NOEU"))) FIN() diff --git a/astest/zzzz503d.py b/astest/zzzz503d.py index 837d1f0ea1f..f3a88355eaa 100644 --- a/astest/zzzz503d.py +++ b/astest/zzzz503d.py @@ -78,8 +78,17 @@ affectMat2.addMaterialOnMesh(acier) affectMat2.build() -resu.setMaterialField(affectMat2) -test.assertEqual(affectMat2, resu.getMaterialField()) +with test.assertRaisesRegex(CA.AsterError, "MaterialField already assigned"): + resu.setMaterialField(affectMat2) + +# unchanged +test.assertEqual(affectMat, resu.getMaterialField()) + +# does nothing, silently +resu.setMaterialField(affectMat2, exists_ok=True) + +# unchanged +test.assertEqual(affectMat, resu.getMaterialField()) test.printSummary() diff --git a/bibc/include/aster_fort_mesh.h b/bibc/include/aster_fort_mesh.h index da4d8fb1ae0..83290154504 100644 --- a/bibc/include/aster_fort_mesh.h +++ b/bibc/include/aster_fort_mesh.h @@ -1,5 +1,5 @@ /* -------------------------------------------------------------------- */ -/* Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org */ +/* Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org */ /* This file is part of code_aster. */ /* */ /* code_aster is free software: you can redistribute it and/or modify */ @@ -117,6 +117,31 @@ extern void DEFSSPSSSSPS( AJELLT, ajellt, const char *, STRING_SIZE, const char STRING_SIZE, const char *, STRING_SIZE, const char *, STRING_SIZE, const ASTERINTEGER *, const char *, STRING_SIZE ); +#define CALLO_PAIRWRAP( a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q ) \ + CALLPOOOOOPPPPPPPPPPO( PAIRWRAP, pairwrap, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q ) +extern void DEFPSSSSSPPPPPPPPPPS( PAIRWRAP, pairwrap, ASTERINTEGER *, const char *, STRING_SIZE, + const char *, STRING_SIZE, const char *, STRING_SIZE, + const char *, STRING_SIZE, const char *, STRING_SIZE, + ASTERDOUBLE *, ASTERDOUBLE *, ASTERINTEGER *, ASTERINTEGER *, + ASTERINTEGER *, ASTERINTEGER *, ASTERINTEGER *, ASTERINTEGER *, + ASTERINTEGER *, ASTERINTEGER *, const char *, STRING_SIZE ); + +#define CALLO_INTECELLAREAWRAP( a, b, c, d ) \ + CALLOPPP( INTECELLAREAWRAP, intecellareawrap, a, b, c, d ) +extern void DEFSPPP( INTECELLAREAWRAP, intecellareawrap, const char *, STRING_SIZE, ASTERINTEGER *, + ASTERDOUBLE *, ASTERDOUBLE * ); + +#define CALLO_INTEPOINCOORWRAP( a, b, c, d, e ) \ + CALLOOOPP( INTEPOINCOORWRAP, intepoincoorwrap, a, b, c, d, e ) +extern void DEFSSSPP( INTEPOINCOORWRAP, intepoincoorwrap, const char *, STRING_SIZE, const char *, + STRING_SIZE, const char *, STRING_SIZE, const ASTERINTEGER *, ASTERDOUBLE * ); + +#define CALLO_QUADPOINCOORWRAP( a, b, c, d, e, f ) \ + CALLOOOPPP( QUADPOINCOORWRAP, quadpoincoorwrap, a, b, c, d, e, f ) +extern void DEFSSSPPP( QUADPOINCOORWRAP, quadpoincoorwrap, const char *, STRING_SIZE, const char *, + STRING_SIZE, const char *, STRING_SIZE, const ASTERINTEGER *, ASTERINTEGER *, + ASTERDOUBLE * ); + #ifdef __cplusplus } #endif diff --git a/bibc/include/definition.h b/bibc/include/definition.h index 07cbe0bbccf..6520d96419a 100644 --- a/bibc/include/definition.h +++ b/bibc/include/definition.h @@ -171,6 +171,9 @@ #define DEFSSPPS(UN,LN,a,la,b,lb,c,d,e,le) STDCALL(UN,LN)(a,b,c,d,e,la,lb,le) #define CALLSSPPS(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)(a,b,c,d,e,strlen(a),strlen(b),strlen(e)) #define CALLOOPPO(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),c,d,(e).c_str(),(a).size(),(b).size(),(e).size()) +#define DEFSSSPP(UN,LN,a,la,b,lb,c,lc,d,e) STDCALL(UN,LN)(a,b,c,d,e,la,lb,lc) +#define CALLSSSPP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)(a,b,c,d,e,strlen(a),strlen(b),strlen(c)) +#define CALLOOOPP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),(c).c_str(),d,e,(a).size(),(b).size(),(c).size()) #define DEFSSSSP(UN,LN,a,la,b,lb,c,lc,d,ld,e) STDCALL(UN,LN)(a,b,c,d,e,la,lb,lc,ld) #define CALLSSSSP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)(a,b,c,d,e,strlen(a),strlen(b),strlen(c),strlen(d)) #define CALLOOOOP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),(c).c_str(),(d).c_str(),e,(a).size(),(b).size(),(c).size(),(d).size()) @@ -198,6 +201,9 @@ #define DEFSSPSSP(UN,LN,a,la,b,lb,c,d,ld,e,le,f) STDCALL(UN,LN)(a,b,c,d,e,f,la,lb,ld,le) #define CALLSSPSSP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)(a,b,c,d,e,f,strlen(a),strlen(b),strlen(d),strlen(e)) #define CALLOOPOOP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),c,(d).c_str(),(e).c_str(),f,(a).size(),(b).size(),(d).size(),(e).size()) +#define DEFSSSPPP(UN,LN,a,la,b,lb,c,lc,d,e,f) STDCALL(UN,LN)(a,b,c,d,e,f,la,lb,lc) +#define CALLSSSPPP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)(a,b,c,d,e,f,strlen(a),strlen(b),strlen(c)) +#define CALLOOOPPP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),(c).c_str(),d,e,f,(a).size(),(b).size(),(c).size()) #define DEFSSSPSS(UN,LN,a,la,b,lb,c,lc,d,e,le,f,lf) STDCALL(UN,LN)(a,b,c,d,e,f,la,lb,lc,le,lf) #define CALLSSSPSS(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)(a,b,c,d,e,f,strlen(a),strlen(b),strlen(c),strlen(e),strlen(f)) #define CALLOOOPOO(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),(c).c_str(),d,(e).c_str(),(f).c_str(),(a).size(),(b).size(),(c).size(),(e).size(),(f).size()) @@ -333,6 +339,9 @@ #define DEFSSSSPPPPPPPPPSSS(UN,LN,a,la,b,lb,c,lc,d,ld,e,f,g,h,i,j,k,l,m,n,ln,o,lo,p,lp) STDCALL(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,la,lb,lc,ld,ln,lo,lp) #define CALLSSSSPPPPPPPPPSSS(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) F_FUNC(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,strlen(a),strlen(b),strlen(c),strlen(d),strlen(n),strlen(o),strlen(p)) #define CALLOOOOPPPPPPPPPOOO(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) F_FUNC(UN,LN)((a).c_str(),(b).c_str(),(c).c_str(),(d).c_str(),e,f,g,h,i,j,k,l,m,(n).c_str(),(o).c_str(),(p).c_str(),(a).size(),(b).size(),(c).size(),(d).size(),(n).size(),(o).size(),(p).size()) +#define DEFPSSSSSPPPPPPPPPPS(UN,LN,a,b,lb,c,lc,d,ld,e,le,f,lf,g,h,i,j,k,l,m,n,o,p,q,lq) STDCALL(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,lb,lc,ld,le,lf,lq) +#define CALLPSSSSSPPPPPPPPPPS(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) F_FUNC(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,strlen(b),strlen(c),strlen(d),strlen(e),strlen(f),strlen(q)) +#define CALLPOOOOOPPPPPPPPPPO(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) F_FUNC(UN,LN)(a,(b).c_str(),(c).c_str(),(d).c_str(),(e).c_str(),(f).c_str(),g,h,i,j,k,l,m,n,o,p,(q).c_str(),(b).size(),(c).size(),(d).size(),(e).size(),(f).size(),(q).size()) #define DEFPPPPPPPPPPPPPPPPPPPSPPPPPPPPPPPPPPPPPP(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,lt,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) STDCALL(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,lt) #define CALLPPPPPPPPPPPPPPPPPPPSPPPPPPPPPPPPPPPPPP(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) F_FUNC(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,strlen(t)) #define CALLPPPPPPPPPPPPPPPPPPPOPPPPPPPPPPPPPPPPPP(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) F_FUNC(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,(t).c_str(),u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,(t).size()) @@ -433,6 +442,9 @@ #define DEFSSPPS(UN,LN,a,la,b,lb,c,d,e,le) STDCALL(UN,LN)(a,la,b,lb,c,d,e,le) #define CALLSSPPS(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,d,e,strlen(e)) #define CALLOOPPO(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),c,d,(e).c_str(),(e).size()) +#define DEFSSSPP(UN,LN,a,la,b,lb,c,lc,d,e) STDCALL(UN,LN)(a,la,b,lb,c,lc,d,e) +#define CALLSSSPP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,strlen(c),d,e) +#define CALLOOOPP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),(c).c_str(),(c).size(),d,e) #define DEFSSSSP(UN,LN,a,la,b,lb,c,lc,d,ld,e) STDCALL(UN,LN)(a,la,b,lb,c,lc,d,ld,e) #define CALLSSSSP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,strlen(c),d,strlen(d),e) #define CALLOOOOP(UN,LN,a,b,c,d,e) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),(c).c_str(),(c).size(),(d).c_str(),(d).size(),e) @@ -460,6 +472,9 @@ #define DEFSSPSSP(UN,LN,a,la,b,lb,c,d,ld,e,le,f) STDCALL(UN,LN)(a,la,b,lb,c,d,ld,e,le,f) #define CALLSSPSSP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,d,strlen(d),e,strlen(e),f) #define CALLOOPOOP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),c,(d).c_str(),(d).size(),(e).c_str(),(e).size(),f) +#define DEFSSSPPP(UN,LN,a,la,b,lb,c,lc,d,e,f) STDCALL(UN,LN)(a,la,b,lb,c,lc,d,e,f) +#define CALLSSSPPP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,strlen(c),d,e,f) +#define CALLOOOPPP(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),(c).c_str(),(c).size(),d,e,f) #define DEFSSSPSS(UN,LN,a,la,b,lb,c,lc,d,e,le,f,lf) STDCALL(UN,LN)(a,la,b,lb,c,lc,d,e,le,f,lf) #define CALLSSSPSS(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,strlen(c),d,e,strlen(e),f,strlen(f)) #define CALLOOOPOO(UN,LN,a,b,c,d,e,f) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),(c).c_str(),(c).size(),d,(e).c_str(),(e).size(),(f).c_str(),(f).size()) @@ -595,6 +610,9 @@ #define DEFSSSSPPPPPPPPPSSS(UN,LN,a,la,b,lb,c,lc,d,ld,e,f,g,h,i,j,k,l,m,n,ln,o,lo,p,lp) STDCALL(UN,LN)(a,la,b,lb,c,lc,d,ld,e,f,g,h,i,j,k,l,m,n,ln,o,lo,p,lp) #define CALLSSSSPPPPPPPPPSSS(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) F_FUNC(UN,LN)(a,strlen(a),b,strlen(b),c,strlen(c),d,strlen(d),e,f,g,h,i,j,k,l,m,n,strlen(n),o,strlen(o),p,strlen(p)) #define CALLOOOOPPPPPPPPPOOO(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) F_FUNC(UN,LN)((a).c_str(),(a).size(),(b).c_str(),(b).size(),(c).c_str(),(c).size(),(d).c_str(),(d).size(),e,f,g,h,i,j,k,l,m,(n).c_str(),(n).size(),(o).c_str(),(o).size(),(p).c_str(),(p).size()) +#define DEFPSSSSSPPPPPPPPPPS(UN,LN,a,b,lb,c,lc,d,ld,e,le,f,lf,g,h,i,j,k,l,m,n,o,p,q,lq) STDCALL(UN,LN)(a,b,lb,c,lc,d,ld,e,le,f,lf,g,h,i,j,k,l,m,n,o,p,q,lq) +#define CALLPSSSSSPPPPPPPPPPS(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) F_FUNC(UN,LN)(a,b,strlen(b),c,strlen(c),d,strlen(d),e,strlen(e),f,strlen(f),g,h,i,j,k,l,m,n,o,p,q,strlen(q)) +#define CALLPOOOOOPPPPPPPPPPO(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) F_FUNC(UN,LN)(a,(b).c_str(),(b).size(),(c).c_str(),(c).size(),(d).c_str(),(d).size(),(e).c_str(),(e).size(),(f).c_str(),(f).size(),g,h,i,j,k,l,m,n,o,p,(q).c_str(),(q).size()) #define DEFPPPPPPPPPPPPPPPPPPPSPPPPPPPPPPPPPPPPPP(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,lt,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) STDCALL(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,lt,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) #define CALLPPPPPPPPPPPPPPPPPPPSPPPPPPPPPPPPPPPPPP(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) F_FUNC(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,strlen(t),u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) #define CALLPPPPPPPPPPPPPPPPPPPOPPPPPPPPPPPPPPPPPP(UN,LN,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) F_FUNC(UN,LN)(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,(t).c_str(),(t).size(),u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L) diff --git a/bibcxx/Contact/ContactComputation.cxx b/bibcxx/Contact/ContactComputation.cxx index e6327b3ce5f..91a3ab2bd1d 100644 --- a/bibcxx/Contact/ContactComputation.cxx +++ b/bibcxx/Contact/ContactComputation.cxx @@ -29,36 +29,34 @@ #include "Numbering/DOFNumbering.h" #include "Utilities/Tools.h" -/** - * @brief Compute contact mortar matrix - */ -FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr pairing, +FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr contPairing, const MaterialFieldPtr mater, const bool &initial_contact ) const { CALL_JEMARQ(); - auto fed = pairing->getFiniteElementDescriptor(); + // Get finite element descriptor + auto fed = contPairing->getFiniteElementDescriptor(); // Field for intersection points and other thing ... auto data = FieldOnCellsPtrBuilder< ASTERDOUBLE >( fed, "CHAR_MECA_CONT", "PCONFR" ); - ASTERINTEGER nbContPair = pairing->getNumberOfPairs(); - auto nbInter = concatenate( pairing->getNumberOfIntersectionPoints() ); - auto inter = concatenate( pairing->getSlaveIntersectionPoints() ); - auto listPairs = pairing->getListOfPairs(); - AS_ASSERT( nbContPair == nbInter.size() ); - AS_ASSERT( 16 * nbContPair == inter.size() ); + // Get pairing + ASTERINTEGER nbContPair = contPairing->getNumberOfPairs(); + VectorLong nbInter = contPairing->getNumberOfIntersectionPoints(); + std::vector< VectorOfVectorsReal > inter = + contPairing->getIntersectionPoints( CoordinatesSpace::Slave ); + VectorPairLong listPairs = contPairing->getListOfPairs(); + MapLong globPairToLocaPair = contPairing->globPairToLocaPair(); - auto pair2Zone = pairing->pairsToZones(); + AS_ASSERT( nbContPair == nbInter.size() ); + // Acces to list of cells + const JeveuxCollectionLong meshConnex = contPairing->getMesh()->getConnectivity(); + MapLong pair2Zone = contPairing->pairsToZones(); auto grel = fed->getListOfGroupsOfElements(); auto nbGrel = data->getNumberOfGroupOfElements(); - auto meshConnectivty = pairing->getMesh()->getConnectivity(); - - ASTERINTEGER nbPair = 0; - - // create local mapping + // Create local mapping (for Nitsche) auto mapping = []( const VectorLong &surf_nodes, const VectorLong &volu_nodes ) { VectorLong mapping; mapping.reserve( surf_nodes.size() ); @@ -77,34 +75,44 @@ FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr pai return mapping; }; - // get Material + // Get material (for Nitsche) auto listMaterial = mater->getVectorOfMaterial(); - // Loop on Grel + // Loop on groups of elements + ASTERINTEGER nbPair = 0; for ( ASTERINTEGER iGrel = 0; iGrel < nbGrel; iGrel++ ) { auto nbElem = data->getNumberOfElements( iGrel ); - // size from catalogue AS_ASSERT( data->getSizeOfFieldOfElement( iGrel ) == 60 ); auto liel = ( *grel )[iGrel + 1]; liel->updateValuePointer(); + // Loop on elements for ( ASTERINTEGER iElem = 0; iElem < nbElem; iElem++ ) { + // Get mesh cell index auto iPair = -( *liel )[iElem]; if ( iPair <= nbContPair ) { + // Current contact zone auto iZone = pair2Zone[iPair - 1]; auto zone = _contact->getContactZone( iZone ); + // Adress in field auto shift = data->getShifting( iGrel, iElem ); - // Number of intersection points + // Set number of intersection points ( *data )[shift + 0] = nbInter[iPair - 1]; - // Parametric coordinates - for ( ASTERINTEGER i = 0; i < 16; i++ ) { - ( *data )[shift + 1 + i] = inter[16 * ( iPair - 1 ) + i]; + AS_ASSERT( nbInter[iPair - 1] <= 8 ); + + // Set coordinates of slave intersection points + for ( ASTERINTEGER iInter = 0; iInter < 8; iInter++ ) { + if ( iInter < nbInter[iPair - 1] ) { + auto iLocaPair = iPair - 1 - globPairToLocaPair[iZone]; + ( *data )[shift + 1 + iInter] = inter[iZone][iLocaPair][2 * iInter]; + ( *data )[shift + 9 + iInter] = inter[iZone][iLocaPair][2 * iInter + 1]; + } } - - /// Contact parameter + // Contact parameter auto cont = zone->getContactParameter(); + // Value for ALGO_CONT ( *data )[shift + 23] = double( cont->getAlgorithm() ); // Value for TYPE_CONT @@ -131,8 +139,10 @@ FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr pai /// Other auto pair = zone->getPairingParameter(); + // Value for projection tolerancetolerance ( *data )[shift + 40] = 1.e-8; + // Status to impose to contact if ( initial_contact ) { ( *data )[shift + 41] = double( pair->getInitialState() ); @@ -140,15 +150,17 @@ FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr pai ( *data )[shift + 41] = double( InitialState::Interpenetrated ); } - /// Nitsche + // Nitsche if ( cont->getAlgorithm() == ContactAlgo::Nitsche ) { auto [slavCellNume, mastCellNume] = listPairs[iPair - 1]; - auto slav_surf_con = ( *meshConnectivty )[slavCellNume + 1]->toVector(); + auto slav_surf_con = ( *meshConnex )[slavCellNume + 1]->toVector(); auto slavVoluNume = zone->getSlaveCellSurfToVolu( slavCellNume ); - auto slav_volu_con = ( *meshConnectivty )[slavVoluNume + 1]->toVector(); + auto slav_volu_con = ( *meshConnex )[slavVoluNume + 1]->toVector(); + auto mapLoc = mapping( slav_surf_con, slav_volu_con ); // Number of nodes ( *data )[shift + 50] = double( mapLoc.size() ); + // Mapping auto i = 0; for ( auto &nodeId : mapLoc ) { @@ -159,7 +171,7 @@ FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr pai AS_ASSERT( listMaterial.size() == 1 ); // Young modulus ( *data )[shift + 45] = listMaterial[0]->getValueReal( "ELAS", "E" ); - // Poisson ration + // Poisson ratio ( *data )[shift + 46] = listMaterial[0]->getValueReal( "ELAS", "NU" ); } @@ -174,22 +186,19 @@ FieldOnCellsRealPtr ContactComputation::contactData( const ContactPairingPtr pai return data; }; -/** - * @brief Compute contact mortar matrix - */ std::pair< FieldOnNodesRealPtr, FieldOnNodesRealPtr > ContactComputation::contactCoefficient() const { // Create FieldOnNodes - auto ccont = + auto fieldCont = std::make_shared< FieldOnNodesReal >( _contact->getFiniteElementDescriptor(), "ECCONT" ); - ccont->updateValuePointers(); + fieldCont->updateValuePointers(); - auto cfrot = + auto fieldFric = std::make_shared< FieldOnNodesReal >( _contact->getFiniteElementDescriptor(), "ECFROT" ); - cfrot->updateValuePointers(); + fieldFric->updateValuePointers(); - auto dof2nodes = ccont->getDescription()->getNodeAndComponentIdFromDOF(); + auto dof2nodes = fieldCont->getDescription()->getNodeAndComponentIdFromDOF(); MapLong nodes2dof; for ( ASTERINTEGER i_eq = 0; i_eq < dof2nodes.size(); i_eq++ ) { auto [node, cmp] = dof2nodes[i_eq]; @@ -201,14 +210,13 @@ ContactComputation::contactCoefficient() const { for ( auto &zone : zones ) { auto coef_cont = zone->getContactParameter()->getCoefficient(); - auto coef_frot = zone->getFrictionParameter()->getCoefficient(); auto nodes = zone->getSlaveNodes(); for ( auto &node : nodes ) { - ( *ccont )[nodes2dof[node]] = coef_cont; - ( *cfrot )[nodes2dof[node]] = coef_frot; + ( *fieldCont )[nodes2dof[node]] = coef_cont; + ( *fieldFric )[nodes2dof[node]] = coef_frot; } } - return std::make_pair( ccont, cfrot ); + return std::make_pair( fieldCont, fieldFric ); }; diff --git a/bibcxx/Contact/ContactComputation.h b/bibcxx/Contact/ContactComputation.h index 442b1300a22..3b0168a910f 100644 --- a/bibcxx/Contact/ContactComputation.h +++ b/bibcxx/Contact/ContactComputation.h @@ -33,35 +33,39 @@ class ContactComputation { // Contact Definition ContactNewPtr _contact; - /** - * @brief Convert ELNO -> NOEU for virtual nodes - */ + /** @brief Convert ELNO -> NOEU for virtual nodes */ FieldOnNodesRealPtr convertVirtualField( const FieldOnCellsRealPtr field ) const; + /** @brief Level of verbosity */ + ASTERINTEGER _verbosity; + public: + /** @brief Main constructor */ ContactComputation( const ContactNewPtr contact ) : _contact( contact ) {}; - /** @brief restricted constructor (Set) and method (Get) to support pickling */ + /** @brief Restricted constructor (Set) to support pickling */ ContactComputation( const py::tuple &tup ) : ContactComputation( tup[0].cast< ContactNewPtr >() ) {}; + + /** @brief Method (Get) to support pickling */ py::tuple _getState() const { return py::make_tuple( _contact ); }; - /** - * @brief Compute contact mortar matrix - */ + /** @brief Compute contact mortar matrix */ ElementaryMatrixDisplacementRealPtr contactMortarMatrix() const; - FieldOnCellsRealPtr contactData( const ContactPairingPtr pairing, const MaterialFieldPtr mater, + /** @brief Compute field for input data in elementary computations of contact */ + FieldOnCellsRealPtr contactData( const ContactPairingPtr contPairing, + const MaterialFieldPtr mater, const bool &initial_contact ) const; - /** - * @brief Compute contact coefficient field (COEF_CONT) - */ + /** @brief Compute contact coefficient field (COEF_CONT) */ std::pair< FieldOnNodesRealPtr, FieldOnNodesRealPtr > contactCoefficient() const; + + /** @brief Set verbosity */ + void setVerbosity( const ASTERINTEGER &level ) { _verbosity = level; } + + /** @brief Get verbosity */ + ASTERINTEGER getVerbosity() const { return _verbosity; } }; -/** - * @typedef ContactComputationPtr - * @brief Pointeur intelligent vers un ContactComputation - */ -typedef std::shared_ptr< ContactComputation > ContactComputationPtr; +using ContactComputationPtr = std::shared_ptr< ContactComputation >; diff --git a/bibcxx/Contact/ContactNew.cxx b/bibcxx/Contact/ContactNew.cxx index ddb0bcd744e..36e19868094 100644 --- a/bibcxx/Contact/ContactNew.cxx +++ b/bibcxx/Contact/ContactNew.cxx @@ -44,30 +44,41 @@ ContactNew::ContactNew( const std::string name, const ModelPtr model, const std: UTMESS( "F", "CONTACT1_2" ); }; -bool ContactNew::build() { - CALL_JEMARQ(); +void ContactNew::appendContactZone( const ContactZonePtr zone ) { + _zones.push_back( zone ); + _zones.back()->setVerbosity( getVerbosity() ); +} - auto mesh = getMesh(); +ASTERINTEGER ContactNew::getSpaceDime() const { - // calico - ASTERINTEGER nb_dim = 0; - ASTERINTEGER nb_dim_ = getModel()->getGeometricDimension(); - if ( nb_dim_ > 3 ) { // general ? dans model ? + ASTERINTEGER spaceDime = 0; + ASTERINTEGER spaceDime_ = getModel()->getGeometricDimension(); + if ( spaceDime_ > 3 ) { UTMESS( "A", "CONTACT_84" ); - if ( nb_dim_ == 1003 ) { - nb_dim = 3; - } else if ( nb_dim_ == 1002 ) { - nb_dim = 2; - } else if ( nb_dim_ == 23 ) { - nb_dim = 2; + if ( spaceDime_ == 1003 ) { + spaceDime = 3; + } else if ( spaceDime_ == 1002 ) { + spaceDime = 2; + } else if ( spaceDime_ == 23 ) { + spaceDime = 2; } else { UTMESS( "F", "CONTACT1_4" ); } } else { - nb_dim = nb_dim_; + spaceDime = spaceDime_; } + return spaceDime; +} - // define name of catalogue +bool ContactNew::build() { + CALL_JEMARQ(); + + auto mesh = getMesh(); + + // Space dimension + ASTERINTEGER spaceDime = this->getSpaceDime(); + + // Define name of catalogue std::map< std::tuple< ASTERINTEGER, ContactAlgo, bool >, std::string > cata; cata[std::make_tuple( 2, ContactAlgo::Lagrangian, false )] = "CONT_LAG_SL_2D"; @@ -88,8 +99,10 @@ bool ContactNew::build() { ASTERINTEGER nb_slave_cells = 0; - // sdcont_defi.CONTACT.MAILCO/NOEUCO/ssnoco + // List of all contact cells std::vector< std::pair< VectorLong, std::string > > mailco; + + // List of all contact nodes std::vector< VectorLong > noeuco; for ( auto &zone_i : _zones ) { @@ -101,12 +114,12 @@ bool ContactNew::build() { nb_slave_cells += l_slave_cells.size(); mailco.push_back( std::make_pair( l_slave_cells, - cata[std::make_tuple( nb_dim, zone_i->getContactParameter()->getAlgorithm(), + cata[std::make_tuple( spaceDime, zone_i->getContactParameter()->getAlgorithm(), zone_i->hasFriction() )] ) ); noeuco.push_back( l_slave_nodes ); } - // check the common slave nodes between zones (or cells ?) + // Check the common slave nodes between zones (or cells ?) VectorLong doublNodes; for ( auto it = noeuco.begin(); it != noeuco.end(); ++it ) { VectorLong l_a = *it; @@ -130,12 +143,12 @@ bool ContactNew::build() { } #endif if ( nb_doublNodes > 0 ) { - UTMESS( "F", "CONTACT1_3" ); + UTMESS( "F", "CONTACT1_1" ); } } } - // create slave elements in model : routine mmprel + // Sreate slave elements in model : routine mmprel std::string ligret = ljust( "&&OP0030.LIGRET", 19, ' ' ); std::string phenom = ljust( "MECANIQUE", 16, ' ' ); std::string modeli; @@ -211,7 +224,6 @@ VectorLong ContactNew::getSlaveCells() const { cells.insert( l_slave_cells.begin(), l_slave_cells.end() ); } - return VectorLong( cells.begin(), cells.end() ); }; @@ -227,7 +239,6 @@ bool ContactNew::hasFriction() const { return true; } } - return false; }; @@ -243,6 +254,24 @@ bool ContactNew::hasSmoothing() const { return true; } } - return false; }; + +void ContactNew::setVerbosity( const ASTERINTEGER &level ) { + _verbosity = level; + for ( auto &zone : _zones ) { + zone->setVerbosity( level ); + } +} + +VectorLong ContactNew::getNumberOfIntersectionPoints() const { + VectorLong returnValue; + + return returnValue; +} + +VectorLong ContactNew::getNumberOfIntersectionPoints( const ASTERINTEGER &indexZone ) const { + VectorLong returnValue; + + return returnValue; +} diff --git a/bibcxx/Contact/ContactNew.h b/bibcxx/Contact/ContactNew.h index 60db251dcb8..c887911fb98 100644 --- a/bibcxx/Contact/ContactNew.h +++ b/bibcxx/Contact/ContactNew.h @@ -1,8 +1,8 @@ /** * @file ContactNew.h - * @brief Fichier entete de la class ContactNew + * @brief Header of class ContactNew * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -33,126 +33,142 @@ class ContactNew : public DataStructure { protected: - /** @brief Modele */ + /** @brief Model */ ModelPtr _model; - /** @brief Ligel ".CHME.LIGRE" */ + + /** @brief Ligrel ".CHME.LIGRE" */ FiniteElementDescriptorPtr _FEDesc; - /** @brief List of contact zone */ + + /** @brief List of contact zones */ std::vector< ContactZonePtr > _zones; + /** @brief Level of verbosity */ ASTERINTEGER _verbosity; - /** - * @brief Constructeur - */ + protected: + /** @brief Main constructor */ ContactNew( const std::string name, const ModelPtr model, const std::string type ); - public: - typedef std::vector< std::pair< ASTERINTEGER, ASTERINTEGER > > VectorLongPairs; + private: + /** @brief Get global dimension of space */ + ASTERINTEGER getSpaceDime() const; - /** - * @typedef ContactNewPtr - * @brief Pointeur intelligent vers un ContactNew - */ - typedef std::shared_ptr< ContactNew > ContactNewPtr; + public: + using ContactNewPtr = std::shared_ptr< ContactNew >; - /** - * @brief Constructeur - */ + /** @brief No default constructor */ ContactNew() = delete; - /** - * @brief Constructeur - */ + /** @brief Constructor with given name */ ContactNew( const std::string name, const ModelPtr model ) : ContactNew( name, model, "CHAR_CONT" ) {}; - /** - * @brief Constructeur - */ + /** @brief Constructor with automatic name */ ContactNew( const ModelPtr model ) : ContactNew( ResultNaming::getNewResultName(), model ) {}; - /** - * @brief Get Model - */ + /** @brief Get mesh */ + BaseMeshPtr getMesh() const { return _model->getMesh(); } + + /** @brief Get model */ ModelPtr getModel() const { return _model; } - /** - * @brief Get FiniteElementDescriptor - */ + /** @brief Get Finite Element Descriptor */ FiniteElementDescriptorPtr getFiniteElementDescriptor() const { return _FEDesc; } - BaseMeshPtr getMesh() const { return _model->getMesh(); } + /** @brief Set verbosity */ + void setVerbosity( const ASTERINTEGER &level ); - void appendContactZone( const ContactZonePtr zone ) { _zones.push_back( zone ); } + /** @brief Get verbosity */ + ASTERINTEGER getVerbosity() const { return _verbosity; } + + /** @brief Append contact zone */ + void appendContactZone( const ContactZonePtr zone ); + /** @brief Get number of contact zones */ ASTERINTEGER getNumberOfContactZones() const { return _zones.size(); } + /** @brief Get contact zone */ ContactZonePtr getContactZone( const ASTERINTEGER &zone_id ) const { return _zones.at( zone_id ); } - std::vector< ContactZonePtr > getContactZones() const { return _zones; } + /** @brief Get pair geometry of zone */ + MeshPairingPtr getMeshPairing( const ASTERINTEGER &zone_id ) { + return _zones.at( zone_id )->getMeshPairing(); + }; - void setVerbosity( const ASTERINTEGER &level ) { _verbosity = level; } + /** @brief Clear pairing result of zone */ + void clearPairing( const ASTERINTEGER &zone_id ) { + _zones.at( zone_id )->getMeshPairing()->clearResult(); + }; - ASTERINTEGER getVerbosity() const { return _verbosity; } + /** @brief Update coordinates */ + void updateCoordinates( const FieldOnNodesRealPtr &disp ) { + for ( auto &zone : _zones ) { + zone->updateCoordinates( disp ); + } + }; - bool build(); + /** @brief Set coordinates */ + void setCoordinates( const MeshCoordinatesFieldPtr &coor ) { + for ( auto &zone : _zones ) { + zone->setCoordinates( coor ); + } + }; + + /** @brief Get all contact zones */ + std::vector< ContactZonePtr > getContactZones() const { return _zones; } + + /** @brief Get all slaves nodes */ + VectorLong getSlaveNodes() const; + /** @brief Get all slaves cells */ + VectorLong getSlaveCells() const; + + /** @brief Set/unset friction flag everywhere */ void enableFriction( const bool &friction ); + /** @brief Detect if friction on one of the contact zone */ bool hasFriction() const; + /** @brief Set/unset smoothing of normals flag everywhere */ void enableSmoothing( const bool &smoothing ); + /** @brief Detect if smoothing of normals on one of the contact zone */ bool hasSmoothing() const; - VectorLong getSlaveNodes() const; + /** @brief Get number of intersection points on all zones */ + VectorLong getNumberOfIntersectionPoints() const; - VectorLong getSlaveCells() const; + /** @brief Get number of intersection points on a contact zone */ + VectorLong getNumberOfIntersectionPoints( const ASTERINTEGER &indexZone ) const; + + /** @brief Builder from Fortran part */ + bool build(); }; -/** - * @typedef ContactNewPtr - * @brief Pointeur intelligent vers un ContactNew - */ using ContactNewPtr = std::shared_ptr< ContactNew >; class FrictionNew : public ContactNew { public: - /** - * @typedef FrictionNewPtr - * @brief Pointeur intelligent vers un FrictionNew - */ - typedef std::shared_ptr< FrictionNew > FrictionNewPtr; - - /** - * @brief Constructeur - */ + using FrictionNewPtr = std::shared_ptr< FrictionNew >; + + /** @brief No default constructor */ FrictionNew() = delete; - /** - * @brief Constructeur - */ + /** @brief Constructor with given name */ FrictionNew( const std::string name, const ModelPtr model ) : ContactNew( name, model, "CHAR_FROT" ) {}; - /** - * @brief Constructeur - */ + /** @brief Constructor with automatic name */ FrictionNew( const ModelPtr model ) : FrictionNew( ResultNaming::getNewResultName(), model ) {}; + /** @brief Builder from Fortran part */ bool build() { AS_ASSERT( hasFriction() ); - return ContactNew::build(); }; }; -/** - * @typedef FrictionNewPtr - * @brief Pointeur intelligent vers un FrictionNew - */ using FrictionNewPtr = std::shared_ptr< FrictionNew >; diff --git a/bibcxx/Contact/ContactPairing.cxx b/bibcxx/Contact/ContactPairing.cxx index 60fa5ead89e..eaaec2d7c4d 100644 --- a/bibcxx/Contact/ContactPairing.cxx +++ b/bibcxx/Contact/ContactPairing.cxx @@ -24,62 +24,47 @@ #include "Messages/Messages.h" -void ContactPairing::resizePairing( const int nbZoneCont ) { - if ( nbZoneCont == 0 ) - raiseAsterError( "ContactZone vector is empty " ); - _nbPairs.resize( nbZoneCont ); - _listOfPairs.resize( nbZoneCont ); - _nbIntersectionPoints.resize( nbZoneCont ); - _slaveIntersectionPoints.resize( nbZoneCont ); -} - -ContactPairing::ContactPairing( const std::string name, const ContactNewPtr cont ) - : DataStructure( name, 8, "PAIRING_SD" ), _contDefi( cont ), _mesh( cont->getMesh() ) { +ContactPairing::ContactPairing( const std::string name, const ContactNewPtr contDefi ) + : DataStructure( name, 8, "PAIRING_SD" ), + _contDefi( contDefi ), + _mesh( contDefi->getMesh() ), + _verbosity( 1 ) { if ( !_mesh || _mesh->isParallel() ) raiseAsterError( "Mesh is empty or is parallel " ); + // Set verbosity + setVerbosity( contDefi->getVerbosity() ); + + // Create object for mesh coordinates _currentCoordinates = std::make_shared< MeshCoordinatesField >( *( _mesh->getCoordinates() ) ); - // be sure that zones is not empty and get size of zones and resize + // Be sure that zones is not empty and get size of zones int nbZoneCont = _contDefi->getNumberOfContactZones(); if ( nbZoneCont == 0 ) raiseAsterError( "ContactZone vector is empty " ); - - // Resize pairing quantities - resizePairing( nbZoneCont ); }; -ASTERBOOL ContactPairing::computeZone( ASTERINTEGER indexZone ) { +void ContactPairing::setVerbosity( const ASTERINTEGER &level ) { + _verbosity = level; + _contDefi->setVerbosity( getVerbosity() ); +} + +ASTERBOOL ContactPairing::compute( ASTERINTEGER &indexZone ) { if ( indexZone < 0 || indexZone >= _contDefi->getNumberOfContactZones() ) { throw std::out_of_range( "The zone index should be between 0 and " + std::to_string( _contDefi->getNumberOfContactZones() - 1 ) ); } - CALL_JEMARQ(); + ASTERBOOL returnValue; + // Get current zone auto zone = _contDefi->getContactZone( indexZone ); AS_ASSERT( !zone->hasSmoothing() ); - // Get and define some input parameters - VectorLong masterCells = zone->getMasterCells(); - VectorLong masterNodes = zone->getMasterNodes(); - VectorLong slaveCells = zone->getSlaveCells(); - ASTERINTEGER nbCellMaster = masterCells.size(); - ASTERINTEGER nbNodeMaster = masterNodes.size(); - ASTERINTEGER nbCellSlave = slaveCells.size(); - std::string pair_method; - - // Update the numbering for fortran - std::for_each( masterCells.begin(), masterCells.end(), []( ASTERINTEGER &d ) { d += 1; } ); - std::for_each( masterNodes.begin(), masterNodes.end(), []( ASTERINTEGER &d ) { d += 1; } ); - std::for_each( slaveCells.begin(), slaveCells.end(), []( ASTERINTEGER &d ) { d += 1; } ); - // Get pairing method auto variant = zone->getPairingParameter()->getAlgorithm(); - if ( variant == PairingAlgo::Mortar ) { - pair_method = ljust( "RAPIDE", 24, ' ' ); - } else { + if ( variant != PairingAlgo::Mortar ) { AS_ABORT( "Not expected" ); } @@ -89,43 +74,18 @@ ASTERBOOL ContactPairing::computeZone( ASTERINTEGER indexZone ) { // Tolerance for pairing ASTERDOUBLE pair_tole = 1e-8; - // Set pairs numbers to 0 - ASTERINTEGER nb_pairs = 0; - - // Main routine for pairing - auto pairs = JeveuxVectorLong( "&&LISTPAIRS" ); - auto nbInterPoints = JeveuxVectorLong( "&&NBPAIRS" ); - auto interSlavePoints = JeveuxVectorReal( "&&INTERSLPTS" ); - - CALLO_APLCPGN( _mesh->getName(), _currentCoordinates->getName(), zone->getName(), pair_method, - &pair_tole, &dist_pairing, &nbCellMaster, masterCells.data(), &nbCellSlave, - slaveCells.data(), masterNodes.data(), &nbNodeMaster, &nb_pairs, - ljust( pairs->getName(), 19, ' ' ), ljust( nbInterPoints->getName(), 19, ' ' ), - ljust( interSlavePoints->getName(), 19, ' ' ) ); - - // clearZone - this->clearZone( indexZone ); - - // fill the pairing quantities - _nbPairs[indexZone] = nb_pairs; - _listOfPairs[indexZone] = pairs->toVector(); - _nbIntersectionPoints[indexZone] = nbInterPoints->toVector(); - _slaveIntersectionPoints[indexZone] = interSlavePoints->toVector(); - - // update numerotation - std::transform( _listOfPairs[indexZone].begin(), _listOfPairs[indexZone].end(), - _listOfPairs[indexZone].begin(), - []( ASTERINTEGER &indexZone ) -> ASTERINTEGER { return --indexZone; } ); - - CALL_JEDEMA(); + // Pairing + zone->setVerbosity( getVerbosity() ); + returnValue = zone->pairing( dist_pairing, pair_tole ); - return true; + return returnValue; } ASTERBOOL ContactPairing::compute() { + // Pairing - for ( int i = 0; i < _contDefi->getNumberOfContactZones(); i++ ) { - computeZone( i ); + for ( ASTERINTEGER i = 0; i < _contDefi->getNumberOfContactZones(); i++ ) { + AS_ASSERT( compute( i ) ); } // Build FED @@ -134,60 +94,118 @@ ASTERBOOL ContactPairing::compute() { return true; } -void ContactPairing::clearZone( ASTERINTEGER indexZone ) { +void ContactPairing::clearPairing( const ASTERINTEGER &indexZone ) { + if ( indexZone < 0 || indexZone >= _contDefi->getNumberOfContactZones() ) { + throw std::out_of_range( "The zone index should be between 0 and " + + std::to_string( _contDefi->getNumberOfContactZones() - 1 ) ); + } - _listOfPairs[indexZone].clear(); - _nbIntersectionPoints[indexZone].clear(); - _slaveIntersectionPoints[indexZone].clear(); - _nbPairs.at( indexZone ) = 0; + _contDefi->clearPairing( indexZone ); } -std::vector< std::pair< ASTERINTEGER, ASTERINTEGER > > -ContactPairing::getListOfPairsOfZone( ASTERINTEGER indexZone ) const { +VectorPairLong ContactPairing::getListOfPairs( const ASTERINTEGER &indexZone ) const { - std::vector< std::pair< ASTERINTEGER, ASTERINTEGER > > tmp; - ASTERINTEGER nbPairs = getNumberOfPairsOfZone( indexZone ); - tmp.reserve( nbPairs ); + if ( indexZone < 0 || indexZone >= _contDefi->getNumberOfContactZones() ) { + throw std::out_of_range( "The zone index should be between 0 and " + + std::to_string( _contDefi->getNumberOfContactZones() - 1 ) ); + } - for ( auto iPair = 0; iPair < nbPairs; iPair++ ) { - tmp.push_back( std::make_pair( _listOfPairs[indexZone][2 * iPair], - _listOfPairs[indexZone][2 * iPair + 1] ) ); + auto zone = _contDefi->getContactZone( indexZone ); + + return ( zone->getMeshPairing()->getListOfPairs() ); +} + +ASTERINTEGER ContactPairing::getNumberOfPairs( const ASTERINTEGER &indexZone ) const { + if ( indexZone < 0 || indexZone >= _contDefi->getNumberOfContactZones() ) { + throw std::out_of_range( "The zone index should be between 0 and " + + std::to_string( _contDefi->getNumberOfContactZones() - 1 ) ); } + return ( _contDefi->getContactZone( indexZone )->getMeshPairing()->getNumberOfPairs() ); +} - return tmp; +ASTERINTEGER ContactPairing::getNumberOfPairs() const { + ASTERINTEGER returnValue; + returnValue = 0; + for ( auto indexZone = 0; indexZone < _contDefi->getNumberOfContactZones(); indexZone++ ) { + returnValue += _contDefi->getMeshPairing( indexZone )->getNumberOfPairs(); + } + + return returnValue; +}; + +ASTERINTEGER ContactPairing::getNumberOfZones() const { + return _contDefi->getNumberOfContactZones(); } -std::vector< std::pair< ASTERINTEGER, ASTERINTEGER > > ContactPairing::getListOfPairs() const { +VectorPairLong ContactPairing::getListOfPairs() const { - std::vector< std::pair< ASTERINTEGER, ASTERINTEGER > > tmp; + VectorPairLong returnValue; ASTERINTEGER nbPairs = getNumberOfPairs(); - tmp.reserve( nbPairs ); - for ( int indexZone = 0; indexZone < _contDefi->getNumberOfContactZones(); indexZone++ ) { - auto nbPairs = getNumberOfPairsOfZone( indexZone ); + if ( nbPairs == 0 ) { + raiseAsterError( "No contact pairs: was the pairing performed correctly? " ); + } + + returnValue.reserve( nbPairs ); - for ( auto iPair = 0; iPair < nbPairs; iPair++ ) { - tmp.push_back( std::make_pair( _listOfPairs[indexZone][2 * iPair], - _listOfPairs[indexZone][2 * iPair + 1] ) ); - } + for ( ASTERINTEGER indexZone = 0; indexZone < _contDefi->getNumberOfContactZones(); + indexZone++ ) { + VectorPairLong pairsOnZone = getListOfPairs( indexZone ); + auto nbPairsZone = pairsOnZone.size(); + + for ( auto iPairZone = 0; iPairZone < nbPairsZone; iPairZone++ ) { + returnValue.push_back( pairsOnZone[iPairZone] ); + }; } - return tmp; + return returnValue; } -std::vector< VectorReal > -ContactPairing::getSlaveIntersectionPoints( ASTERINTEGER indexZone ) const { +VectorOfVectorsReal +ContactPairing::getIntersectionPoints( ASTERINTEGER &indexZone, + const CoordinatesSpace coorSpace ) const { - std::vector< VectorReal > ret; - ASTERINTEGER nbPairs = getNumberOfPairsOfZone( indexZone ); - ret.reserve( nbPairs ); - - auto iter = _slaveIntersectionPoints[indexZone].begin(); - for ( auto i = 0; i < nbPairs; i++ ) { - ret.push_back( VectorReal( iter + 16 * i, iter + 16 * ( i + 1 ) ) ); + VectorOfVectorsReal returnValue; + ASTERINTEGER nbPairs = getNumberOfPairs( indexZone ); + if ( nbPairs == 0 ) { + raiseAsterError( "No contact pairs: was the pairing performed correctly? " ); } + returnValue.reserve( nbPairs ); + for ( auto iPair = 0; iPair < nbPairs; iPair++ ) { + VectorOfVectorsReal interOnZone = _contDefi->getContactZone( indexZone ) + ->getMeshPairing() + ->getIntersectionPoints( iPair, coorSpace ); + ASTERINTEGER nbInter = _contDefi->getContactZone( indexZone ) + ->getMeshPairing() + ->getNumberOfIntersectionPoints( iPair ); + if ( nbInter != 0 ) { + VectorReal vectVale; + for ( auto iInter = 0; iInter < nbInter; iInter++ ) { + vectVale.insert( vectVale.end(), interOnZone[iInter].begin(), + interOnZone[iInter].end() ); + }; + returnValue.push_back( vectVale ); + vectVale.clear(); + } + } + return returnValue; +} - return ret; +std::vector< VectorOfVectorsReal > +ContactPairing::getIntersectionPoints( const CoordinatesSpace coorSpace ) const { + + std::vector< VectorOfVectorsReal > returnValue; + const ASTERINTEGER nbZoneCont = _contDefi->getNumberOfContactZones(); + if ( nbZoneCont == 0 ) + raiseAsterError( "ContactZone vector is empty " ); + returnValue.reserve( nbZoneCont ); + + for ( ASTERINTEGER iZone = 0; iZone < nbZoneCont; iZone++ ) { + VectorOfVectorsReal interSlave; + interSlave = ContactPairing::getIntersectionPoints( iZone, coorSpace ); + returnValue.push_back( interSlave ); + } + return returnValue; } ASTERINTEGER ContactPairing::getContCellIndx( const ContactAlgo contAlgo, @@ -279,18 +297,17 @@ void ContactPairing::createVirtualElemForContact( const ASTERLOGICAL lAxis, cons // Get pairing for this zone auto surf2Volu = zone->getSlaveCellsSurfToVolu(); - auto iZonePairing = this->getListOfPairsOfZone( iZone ); - auto nbContPairZone = this->getNumberOfPairsOfZone( iZone ); + auto listOfPairsZone = this->getListOfPairs( iZone ); + auto nbPairsZone = this->getNumberOfPairs( iZone ); // Create vector of (virtual) contact cells for this zone VectorPairLong listContTypeZone; - listContTypeZone.reserve( nbContPairZone ); + listContTypeZone.reserve( nbPairsZone ); // Loop on pairs in zone - for ( int iPair = 0; iPair < nbContPairZone; iPair++ ) { - + for ( int iPair = 0; iPair < nbPairsZone; iPair++ ) { // Get pairing of current zone - auto [slavCellNume, mastCellNume] = iZonePairing[iPair]; + auto [slavCellNume, mastCellNume] = listOfPairsZone[iPair]; // Get cell slave to construct (is volumic cell for Nitsche) auto slavCellUsedNume = slavCellNume; @@ -374,8 +391,8 @@ void ContactPairing::createVirtualElemForOrphelanNodes( auto lFric = zone->getFrictionParameter()->hasFriction(); // Get pairing for this zone - auto iZonePairing = this->getListOfPairsOfZone( iZone ); - auto nbContPairZone = this->getNumberOfPairsOfZone( iZone ); + auto listOfPairsZone = this->getListOfPairs( iZone ); + auto nbPairsZone = this->getNumberOfPairs( iZone ); // Get slave cells on this zone auto slaveCells = zone->getSlaveCells(); @@ -493,9 +510,6 @@ void ContactPairing::buildFiniteElementDescriptor() { const ASTERINTEGER nbZoneCont = _contDefi->getNumberOfContactZones(); const ASTERINTEGER nbContPairTot = this->getNumberOfPairs(); - // Number of cells for each type of contact cell - MapLong contactElemType; - // Create objets for nodes and cells VectorOfVectorsLong listContElem; listContElem.reserve( nbContPairTot ); @@ -509,6 +523,9 @@ void ContactPairing::buildFiniteElementDescriptor() { // Index of current contact pair ASTERINTEGER iContPair = 0; + // Object for number of cells for each type of contact cell + MapLong contactElemType; + // Create virtual elements for contact createVirtualElemForContact( lAxis, nbZoneCont, contactElemType, meshConnectivity, listContElem, listContType, iContPair, slaveNodePaired, slaveCellPaired ); @@ -544,6 +561,9 @@ void ContactPairing::buildFiniteElementDescriptor() { // Clear map between zone and contact elements _pair2Zone.clear(); + // Clear map between index of global pair and index of local pair in zone + _globPairToLocaPair.clear(); + // Add virtual element for ( auto &[type, size] : contactElemType ) { VectorLong contactElemZone; @@ -564,6 +584,16 @@ void ContactPairing::buildFiniteElementDescriptor() { ContactResFEDLiel->push_back( contactElemZone ); } + for ( ASTERINTEGER indexZone = 0; indexZone < nbZoneCont; indexZone++ ) { + if ( indexZone == 0 ) { + _globPairToLocaPair[indexZone] = 0; + } else { + auto zone = _contDefi->getContactZone( indexZone - 1 ); + ASTERINTEGER nbPairs = zone->getMeshPairing()->getNumberOfPairs(); + _globPairToLocaPair[indexZone] = _globPairToLocaPair[indexZone - 1] + nbPairs; + } + } + // Get parameters from standard model auto paramToCopy = model->getFiniteElementDescriptor()->getParameters(); paramToCopy->updateValuePointer(); @@ -592,3 +622,23 @@ void ContactPairing::buildFiniteElementDescriptor() { CALL_JEDEMA(); }; + +VectorLong ContactPairing::getNumberOfIntersectionPoints() const { + VectorLong returnValue; + const ASTERINTEGER nbZoneCont = _contDefi->getNumberOfContactZones(); + for ( ASTERINTEGER iZone = 0; iZone < nbZoneCont; iZone++ ) { + VectorLong nbInter; + nbInter = ContactPairing::getNumberOfIntersectionPoints( iZone ); + returnValue.insert( returnValue.end(), nbInter.begin(), nbInter.end() ); + } + return returnValue; +} + +VectorLong ContactPairing::getNumberOfIntersectionPoints( ASTERINTEGER &indexZone ) const { + + VectorLong returnValue; + + returnValue = _contDefi->getMeshPairing( indexZone )->getNumberOfIntersectionPoints(); + + return returnValue; +} diff --git a/bibcxx/Contact/ContactPairing.h b/bibcxx/Contact/ContactPairing.h index 766f89c6493..72151eed472 100644 --- a/bibcxx/Contact/ContactPairing.h +++ b/bibcxx/Contact/ContactPairing.h @@ -26,6 +26,7 @@ #include "Contact/ContactZone.h" #include "DataFields/FieldOnNodes.h" #include "DataStructures/DataStructure.h" +#include "Meshes/MeshEnum.h" // Description of a virtual contact cell struct contCellType { @@ -93,32 +94,26 @@ const struct contCellType contCellNits[contNitsType] = { class ContactPairing : public DataStructure { /** Datastructure for pairing */ private: + /** @brief Mesh */ + BaseMeshPtr _mesh; + /** @brief Current coordinates of nodes */ MeshCoordinatesFieldPtr _currentCoordinates; /** @brief Contact definition */ ContactNewPtr _contDefi; - /** @brief Mesh */ - BaseMeshPtr _mesh; - - /** @brief Vector of number of pairs */ - VectorLong _nbPairs; - - /** @brief Vector of pairs */ - std::vector< VectorLong > _listOfPairs; - - /** @brief Vector of number of intersection points */ - std::vector< VectorLong > _nbIntersectionPoints; + /** @brief Finite element descriptor for virtual elements of contact */ + FiniteElementDescriptorPtr _fed; - /** @brief Vector of coordinates for intersection points */ - std::vector< VectorReal > _slaveIntersectionPoints; + /** @brief Level of verbosity */ + ASTERINTEGER _verbosity; /** @brief Map between pair and zone */ MapLong _pair2Zone; - /** @brief Finite element descriptor for virtual elements of contact */ - FiniteElementDescriptorPtr _fed; + /** @brief Map between index of global pair and index of local pair in zone */ + MapLong _globPairToLocaPair; private: /** @brief Resize pairing quantities */ @@ -151,14 +146,15 @@ class ContactPairing : public DataStructure { const bool lAxis, const bool lFric ); public: - using VectorLongPairs = std::vector< std::pair< ASTERINTEGER, ASTERINTEGER > >; + /** @brief No default constructor */ + ContactPairing() = delete; /** @brief Constructor with given name */ - ContactPairing( const std::string name, const ContactNewPtr cont ); + ContactPairing( const std::string name, const ContactNewPtr contDefi ); /** @brief Constructor with automatic name */ - ContactPairing( const ContactNewPtr cont ) - : ContactPairing( ResultNaming::getNewResultName(), cont ) {}; + ContactPairing( const ContactNewPtr contDefi ) + : ContactPairing( ResultNaming::getNewResultName(), contDefi ) {}; /** @brief Get coordinates */ MeshCoordinatesFieldPtr getCoordinates() const { return _currentCoordinates; } @@ -167,57 +163,66 @@ class ContactPairing : public DataStructure { BaseMeshPtr getMesh() const { return _mesh; }; /** @brief Update coordinates */ - void updateCoordinates( FieldOnNodesRealPtr &disp ) { + void updateCoordinates( const FieldOnNodesRealPtr disp ) { *_currentCoordinates = *( _mesh->getCoordinates() ) + *disp; + for ( auto indexZone = 0; indexZone < _contDefi->getNumberOfContactZones(); indexZone++ ) { + _contDefi->updateCoordinates( disp ); + } }; /** @brief Set coordinates */ - void setCoordinates( MeshCoordinatesFieldPtr &coor ) { _currentCoordinates = coor; }; + void setCoordinates( const MeshCoordinatesFieldPtr coor ) { + _currentCoordinates = coor; + for ( auto indexZone = 0; indexZone < _contDefi->getNumberOfContactZones(); indexZone++ ) { + _contDefi->setCoordinates( coor ); + } + }; /** @brief Compute pairing quantities of zone */ - ASTERBOOL computeZone( ASTERINTEGER indexZone ); + ASTERBOOL compute( ASTERINTEGER &indexZone ); /** @brief Compute pairing quantities of all zones */ ASTERBOOL compute(); /** @brief Clear pairing quantities of zone */ - void clearZone( ASTERINTEGER indexZone ); + void clearPairing( const ASTERINTEGER &indexZone ); /** @brief Clear pairing quantities for all zones */ - void clear() { + void clearPairing() { for ( auto indexZone = 0; indexZone < _contDefi->getNumberOfContactZones(); indexZone++ ) { - clearZone( indexZone ); + clearPairing( indexZone ); } }; - /** @brief Get number of all pairs */ - ASTERINTEGER getNumberOfPairs() const { - return std::accumulate( _nbPairs.begin(), _nbPairs.end(), 0 ); - }; + /** @brief Get number of zones */ + ASTERINTEGER getNumberOfZones() const; /** @brief Get number of pairs of zone */ - ASTERINTEGER getNumberOfPairsOfZone( ASTERINTEGER indexZone ) const { - return _nbPairs[indexZone]; - } + ASTERINTEGER getNumberOfPairs( const ASTERINTEGER &indexZone ) const; - /** @brief Get all list of pairs */ - VectorLongPairs getListOfPairs() const; + /** @brief Get number of pairs of all zones */ + ASTERINTEGER getNumberOfPairs() const; /** @brief Get list of pairs of zone */ - VectorLongPairs getListOfPairsOfZone( ASTERINTEGER indexZone ) const; + VectorPairLong getListOfPairs( const ASTERINTEGER &indexZone ) const; - /** @brief Get slave intersection points of zone */ - std::vector< VectorReal > getSlaveIntersectionPoints( ASTERINTEGER indexZone ) const; + /** @brief Get list of pairs of all zones */ + VectorPairLong getListOfPairs() const; - /** @brief Get vector of number of intersection points on all zones */ - std::vector< VectorLong > getNumberOfIntersectionPoints() const { - return _nbIntersectionPoints; - }; + /** @brief Get slave intersection points on all zones */ + std::vector< VectorOfVectorsReal > + getIntersectionPoints( const CoordinatesSpace = CoordinatesSpace::Global ) const; - /** @brief Get vector of slave intersection points on all zones */ - std::vector< VectorReal > getSlaveIntersectionPoints() const { - return _slaveIntersectionPoints; - }; + /** @brief Get slave intersection points on contact zone */ + VectorOfVectorsReal + getIntersectionPoints( ASTERINTEGER &indexZone, + const CoordinatesSpace = CoordinatesSpace::Global ) const; + + /** @brief Get number of intersection points on all zones */ + VectorLong getNumberOfIntersectionPoints() const; + + /** @brief Get number of intersection points on contact zone */ + VectorLong getNumberOfIntersectionPoints( ASTERINTEGER &indexZone ) const; /** @brief Build Finite Element Descriptor from pairing */ void buildFiniteElementDescriptor(); @@ -227,6 +232,15 @@ class ContactPairing : public DataStructure { /** @brief Get map between pair and zone */ MapLong pairsToZones() const { return _pair2Zone; }; + + /** @brief Get map between index of global pair and index of local pair in zone */ + MapLong globPairToLocaPair() const { return _globPairToLocaPair; }; + + /** @brief Set verbosity */ + void setVerbosity( const ASTERINTEGER &level ); + + /** @brief Get verbosity */ + ASTERINTEGER getVerbosity() const { return _verbosity; } }; using ContactPairingPtr = std::shared_ptr< ContactPairing >; diff --git a/bibcxx/Contact/ContactZone.cxx b/bibcxx/Contact/ContactZone.cxx index 4b5508863a8..7918a4d5496 100644 --- a/bibcxx/Contact/ContactZone.cxx +++ b/bibcxx/Contact/ContactZone.cxx @@ -24,6 +24,7 @@ #include "aster_fort_mesh.h" +#include "Meshes/MeshPairing.h" #include "Messages/Messages.h" #include "ParallelUtilities/AsterMPI.h" #include "Utilities/Tools.h" @@ -36,289 +37,35 @@ ContactZone::ContactZone( const std::string name, const ModelPtr model ) _smoothing( false ), _contParam( std::make_shared< ContactParameter >() ), _fricParam( std::make_shared< FrictionParameter >() ), - _pairParam( std::make_shared< PairingParameter >() ), - _masterInverseConnectivity( JeveuxCollectionLong( getName() + ".CM" ) ), - _slaveInverseConnectivity( JeveuxCollectionLong( getName() + ".CS" ) ), - _masterNeighbors( JeveuxCollectionLong( getName() + ".MN" ) ), - _slaveNeighbors( JeveuxCollectionLong( getName() + ".SN" ) ) { - // model has to be mechanics + _pairParam( std::make_shared< PairingParameter >() ) { if ( !_model->isMechanical() ) UTMESS( "F", "CONTACT1_2" ); -}; - -void ContactZone::setSlaveGroupOfCells( const std::string &slave ) { - if ( getMesh()->hasGroupOfCells( slave ) ) { - _slaveNodes = getMesh()->getNodesFromCells( slave, false, true ); - _slaveCells = getMesh()->getCells( slave ); - _slaveGrp = slave; - } else { - throw std::runtime_error( "The given group " + slave + " doesn't exist in mesh" ); - } -}; - -void ContactZone::setMasterGroupOfCells( const std::string &master ) { - if ( getMesh()->hasGroupOfCells( master ) ) { - _masterNodes = getMesh()->getNodesFromCells( master, false, true ); - _masterCells = getMesh()->getCells( master ); - _masterGrp = master; - } else { - throw std::runtime_error( "The given group " + master + " doesn't exist in mesh" ); - } -}; - -void ContactZone::setExcludedSlaveGroupOfCells( const VectorString &excluded_slave ) { - auto mesh = getMesh(); - for ( auto &name : excluded_slave ) { - if ( !( getMesh()->hasGroupOfCells( name ) ) ) { - throw std::runtime_error( "The group " + name + " doesn't exist in mesh" ); - } - - VectorLong sans_gr_i = mesh->getCells( name ); - auto it = _slaveCellsExcluded.end(); - _slaveCellsExcluded.insert( it, sans_gr_i.begin(), sans_gr_i.end() ); - } - _slaveCells = set_difference( _slaveCells, _slaveCellsExcluded ); - AS_ASSERT( _slaveCells.size() > 0 ); - _slaveNodes = getMesh()->getNodesFromCells( _slaveCells ); + _meshPairing = std::make_shared< MeshPairing >( getName(), model->getMesh() ); }; -void ContactZone::setExcludedSlaveGroupOfNodes( const VectorString &excluded_slave ) { - auto mesh = getMesh(); - // build inverse connvectivity - buildInverseConnectivity(); - - for ( auto &name : excluded_slave ) { - if ( !( getMesh()->hasGroupOfNodes( name ) ) ) { - throw std::runtime_error( "The group " + name + " doesn't exist in mesh" ); - } - - VectorLong sans_gr_i = mesh->getNodes( name ); - for ( auto &node : sans_gr_i ) { - auto cellsToExclude = this->getSlaveCellsFromNode( node ); - auto it = _slaveCellsExcluded.end(); - _slaveCellsExcluded.insert( it, cellsToExclude.begin(), cellsToExclude.end() ); - } - } +void ContactZone::setVerbosity( const ASTERINTEGER &level ) { + _verbosity = level; + _meshPairing->setVerbosity( getVerbosity() ); +} - _slaveCells = set_difference( _slaveCells, _slaveCellsExcluded ); - AS_ASSERT( _slaveCells.size() > 0 ); - _slaveNodes = getMesh()->getNodesFromCells( _slaveCells ); -}; +bool ContactZone::pairing( ASTERDOUBLE &dist_pairing, ASTERDOUBLE &pair_tole ) { + return _meshPairing->compute( dist_pairing, pair_tole ); +} bool ContactZone::build() { - auto mesh = getMesh(); - - // check that there is no nodes in common - VectorLong commonNodes; - - if ( mesh->isParallel() ) { -#ifdef ASTER_HAVE_MPI - VectorLong slaveNodes_gl; - AsterMPI::all_gather( _slaveNodes, slaveNodes_gl ); - commonNodes = set_intersection( slaveNodes_gl, _masterNodes ); -#endif - } else { - commonNodes = set_intersection( _slaveNodes, _masterNodes ); - } - ASTERINTEGER size_inter_gl = commonNodes.size(); + _meshPairing->initObjects(); - // share error -#ifdef ASTER_HAVE_MPI - if ( mesh->isParallel() ) { - ASTERINTEGER size_inter_lc = size_inter_gl; - size_inter_gl = AsterMPI::sum( size_inter_lc ); - } -#endif - - if ( size_inter_gl > 0 ) { + auto hasCommonNodes = _meshPairing->hasCommonNodes(); + if ( hasCommonNodes ) { UTMESS( "F", "CONTACT1_1" ); } // check mesh orientation (normals) if ( checkNormals() ) { - CALL_CHECKNORMALS( _model->getName().c_str(), ljust( _slaveGrp, 24, ' ' ).c_str(), - ljust( _masterGrp, 24, ' ' ).c_str() ); + _meshPairing->checkNormals( _model ); } - // build inverse connvectivity - AS_ASSERT( buildInverseConnectivity() ); - - // build master and slave Cells Neighbors - AS_ASSERT( buildCellsNeighbors() ); - - // build surface to volume slave cell - buildSlaveCellsVolu(); - - return true; -} - -ASTERBOOL ContactZone::buildInverseConnectivity() { - // create master inverse connectivity - ASTERINTEGER nbMaster = getMasterCells().size(); - std::string base( "G" ); - - VectorLong masterCells; - masterCells.reserve( _masterCells.size() ); - - // shifting for fortran - for ( auto cell : _masterCells ) - masterCells.push_back( cell + 1 ); - - _masterInverseConnectivity->deallocate(); - CALL_CNCINV( getMesh()->getName().c_str(), masterCells.data(), &nbMaster, base.c_str(), - _masterInverseConnectivity->getName().c_str() ); - _masterInverseConnectivity->build(); - - // create slave inverse connectivity - ASTERINTEGER nbSlave = _slaveCells.size(); - - VectorLong slaveCells; - slaveCells.reserve( _slaveCells.size() ); - for ( auto cell : _slaveCells ) - slaveCells.push_back( cell + 1 ); - - _slaveInverseConnectivity->deallocate(); - CALL_CNCINV( getMesh()->getName().c_str(), slaveCells.data(), &nbSlave, base.c_str(), - _slaveInverseConnectivity->getName().c_str() ); - _slaveInverseConnectivity->build(); - return true; } - -ASTERBOOL ContactZone::buildCellsNeighbors() { - - ASTERINTEGER ind_max, ind_min; - // get master neighbors - ASTERINTEGER nbMaster = getMasterCells().size(); - if ( nbMaster > 0 ) { - ind_max = *std::max_element( _masterCells.begin(), _masterCells.end() ) + 1; - ind_min = *std::min_element( _masterCells.begin(), _masterCells.end() ) + 1; - - std::string invmcn_name = ljust( _masterInverseConnectivity->getName(), 24, ' ' ); - std::string mn_name = ljust( _masterNeighbors->getName(), 24, ' ' ); - - VectorLong masterCells; - masterCells.reserve( _masterCells.size() ); - for ( auto cell : _masterCells ) - masterCells.push_back( cell + 1 ); - - _masterNeighbors->deallocate(); - CALL_CNVOIS( getMesh()->getName(), masterCells.data(), invmcn_name, &nbMaster, &ind_min, - &ind_max, mn_name ); - - _masterNeighbors->build(); - } - - // get slave neighbors - - ASTERINTEGER nbSlave = _slaveCells.size(); - if ( nbSlave > 0 ) { - ind_max = *std::max_element( _slaveCells.begin(), _slaveCells.end() ) + 1; - ind_min = *std::min_element( _slaveCells.begin(), _slaveCells.end() ) + 1; - - std::string invscn_name = ljust( _slaveInverseConnectivity->getName(), 24, ' ' ); - std::string sn_name = ljust( _slaveNeighbors->getName(), 24, ' ' ); - - VectorLong slaveCells; - slaveCells.reserve( _slaveCells.size() ); - for ( auto cell : _slaveCells ) - slaveCells.push_back( cell + 1 ); - CALL_CNVOIS( getMesh()->getName(), slaveCells.data(), invscn_name, &nbSlave, &ind_min, - &ind_max, sn_name ); - - _slaveNeighbors->build(); - } - - return true; -} - -void ContactZone::buildSlaveCellsVolu() { - auto mesh = getMesh(); - auto nbCells = mesh->getNumberOfCells(); - - auto invCon = mesh->getInverseConnectivity(); - invCon->build(); - - auto exp = mesh->getConnectivityExplorer(); - - for ( auto &cellId : _slaveCells ) { - const auto cell = exp[cellId]; - VectorLong candidat; - for ( const auto nodeId : cell ) { - auto listCells = ( *invCon )[nodeId + 1]->toVector(); - - std::for_each( listCells.begin(), listCells.end(), []( ASTERINTEGER &d ) { d -= 1; } ); - - if ( candidat.empty() ) { - candidat = listCells; - } else { - auto tmp = set_intersection( candidat, listCells ); - AS_ASSERT( !tmp.empty() ); - candidat = tmp; - } - } - - AS_ASSERT( candidat.size() == 2 ); - ASTERINTEGER cellVolu; - if ( candidat[0] == cellId ) { - cellVolu = candidat[1]; - } else { - cellVolu = candidat[0]; - } - - _slavSurf2Volu[cellId] = cellVolu; - } -}; - -VectorLong ContactZone::getMasterCellsFromNode( const ASTERINTEGER &i ) const { - auto vct = ( *_masterInverseConnectivity )[i + 1]->toVector(); - std::transform( vct.begin(), vct.end(), vct.begin(), [this]( ASTERINTEGER k ) -> ASTERINTEGER { - return k > 0 ? _masterCells[k - 1] : 0; - } ); - return vct; -} - -VectorLong ContactZone::getSlaveCellsFromNode( const ASTERINTEGER &i ) const { - auto vct = ( *_slaveInverseConnectivity )[i + 1]->toVector(); - std::transform( vct.begin(), vct.end(), vct.begin(), [this]( ASTERINTEGER k ) -> ASTERINTEGER { - return k > 0 ? _slaveCells[k - 1] : 0; - } ); - return vct; -} - -VectorLong ContactZone::getMasterCellNeighbors( const ASTERINTEGER &i ) const { - ASTERINTEGER ind_min = *std::min_element( _masterCells.begin(), _masterCells.end() ); - ASTERINTEGER ind_max = *std::max_element( _masterCells.begin(), _masterCells.end() ); - - if ( i < ind_min || i > ind_max ) - throw std::out_of_range( " the master cell's number should be" - " between " + - std::to_string( ind_min ) + " and " + std::to_string( ind_max ) ); - - auto vct = ( *_masterNeighbors )[i - ind_min + 1]->toVector(); - vct.erase( std::remove_if( vct.begin(), vct.end(), []( ASTERINTEGER &i ) { return i == 0; } ), - vct.end() ); - std::transform( vct.begin(), vct.end(), vct.begin(), - []( ASTERINTEGER k ) -> ASTERINTEGER { return k - 1; } ); - return vct; -} - -VectorLong ContactZone::getSlaveCellNeighbors( const ASTERINTEGER &i ) const { - - ASTERINTEGER ind_min = *std::min_element( _slaveCells.begin(), _slaveCells.end() ); - ASTERINTEGER ind_max = *std::max_element( _slaveCells.begin(), _slaveCells.end() ); - - if ( i < ind_min || i > ind_max ) - throw std::out_of_range( " the slave cell's number should be" - " between " + - std::to_string( ind_min ) + " and " + std::to_string( ind_max ) ); - - auto vct = ( *_slaveNeighbors )[i - ind_min + 1]->toVector(); - vct.erase( std::remove_if( vct.begin(), vct.end(), []( ASTERINTEGER &i ) { return i == 0; } ), - vct.end() ); - std::transform( vct.begin(), vct.end(), vct.begin(), - []( ASTERINTEGER k ) -> ASTERINTEGER { return k - 1; } ); - return vct; -} diff --git a/bibcxx/Contact/ContactZone.h b/bibcxx/Contact/ContactZone.h index 12115de8ae4..f68aacae2ef 100644 --- a/bibcxx/Contact/ContactZone.h +++ b/bibcxx/Contact/ContactZone.h @@ -3,9 +3,9 @@ /** * @file ContactZone.h - * @brief Fichier entete de la class ContactZone + * @brief Header of class ContactZone * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -29,191 +29,150 @@ #include "Contact/ContactParameter.h" #include "DataStructures/DataStructure.h" #include "MemoryManager/JeveuxVector.h" +#include "Meshes/MeshPairing.h" #include "Modeling/Model.h" #include "Supervis/ResultNaming.h" class ContactZone : public DataStructure { private: - /** @brief Modele */ + /** @brief Model */ ModelPtr _model; /** @brief Level of verbosity */ ASTERINTEGER _verbosity; - /** @brief Parameter for contact only */ + /** @brief Parameters for contact */ ContactParameterPtr _contParam; - /** @brief Parameter for friction only */ + /** @brief Parameters for friction */ FrictionParameterPtr _fricParam; - /** @brief Parameter for pairing only */ + /** @brief Parameters for pairing */ PairingParameterPtr _pairParam; - /** @brief Check direction of normal */ + /** @brief Definition of pairing of two surfaces */ + MeshPairingPtr _meshPairing; + /** @brief Check direction of normal */ bool _checkNormal; /** @brief Smoothing of normal */ bool _smoothing; - /** @brief List of master Cells */ - VectorLong _masterCells; - /** @brief List of slave cells */ - VectorLong _slaveCells; - /** @brief List of master nodes */ - VectorLong _masterNodes; - /** @brief List of slave nodes */ - VectorLong _slaveNodes; - /** @brief excluded elements of slave side for LAGRANGIEN */ - VectorLong _slaveCellsExcluded; - /** @brief Master inverse connectivity */ - JeveuxCollectionLong _masterInverseConnectivity; - /** @brief Slave inverse connectivity */ - JeveuxCollectionLong _slaveInverseConnectivity; - /** @brief Master cells neighbors */ - JeveuxCollectionLong _masterNeighbors; - /** @brief slave cells neighbors */ - JeveuxCollectionLong _slaveNeighbors; - /** @brief Map between slave surfaciv and volumic cell */ - MapLong _slavSurf2Volu; - /** @brief name of slave side */ - std::string _slaveGrp; - /** @brief name of master side */ - std::string _masterGrp; - - /** - * @brief Construct the inverse connectivity - */ - ASTERBOOL buildInverseConnectivity(); - /** - * @brief construct master/slave cells neighbors - */ - ASTERBOOL buildCellsNeighbors(); - - /** - * @brief construct surface->volume slave cell - */ - void buildSlaveCellsVolu(); public: - /** - * @typedef ContactZonePt - * @brief Pointeur intelligent vers un ContactZone - */ - typedef std::shared_ptr< ContactZone > ContactZonePtr; - /** - * @brief Constructeur - */ + using ContactZonePtr = std::shared_ptr< ContactZone >; + + /** @brief No default constructor */ ContactZone() = delete; - /** - * @brief Constructeur - */ + /** @brief Constructor with given name */ ContactZone( const std::string name, const ModelPtr model ); - /** - * @brief Constructeur - */ + /** @brief Constructor with automatic name */ ContactZone( const ModelPtr model ) : ContactZone( ResultNaming::getNewResultName(), model ) {}; + /** @brief Get model */ ModelPtr getModel() const { return _model; } + /** @brief Get mesh */ BaseMeshPtr getMesh() const { return _model->getMesh(); } - void setVerbosity( const ASTERINTEGER &level ) { _verbosity = level; } + /** @brief Set verbosity */ + void setVerbosity( const ASTERINTEGER &level ); + /** @brief Get verbosity */ ASTERINTEGER getVerbosity() const { return _verbosity; } - bool build(); - + /** @brief Get parameters for contact */ ContactParameterPtr getContactParameter() const { return _contParam; }; + /** @brief Get parameters for friction */ FrictionParameterPtr getFrictionParameter() const { return _fricParam; }; + /** @brief Get parameters for pairing */ PairingParameterPtr getPairingParameter() const { return _pairParam; }; + /** @brief Set parameters for contact */ void setContactParameter( const ContactParameterPtr contParam ) { _contParam = contParam; }; + /** @brief Set parameters for friction */ void setFrictionParameter( const FrictionParameterPtr fricParam ) { _fricParam = fricParam; }; + /** @brief Set parameters for pairing */ void setPairingParameter( const PairingParameterPtr pairParam ) { _pairParam = pairParam; }; - void setSlaveGroupOfCells( const std::string &slave ); - - void setMasterGroupOfCells( const std::string &master ); - - void setExcludedSlaveGroupOfCells( const VectorString &excluded_slave ); - - void setExcludedSlaveGroupOfNodes( const VectorString &excluded_slave ); - - VectorLong getExcludedSlaveCells() const { return _slaveCellsExcluded; }; - - void checkNormals( const bool &checkNormal ) { _checkNormal = checkNormal; } - - bool checkNormals() const { return _checkNormal; } - - /** - * @brief get master nodes - */ - const VectorLong &getMasterNodes() const { return _masterNodes; }; - - VectorLong &getMasterNodes() { - return const_cast< VectorLong & >( std::as_const( *this ).getMasterNodes() ); + /** @brief Set group of slave cells */ + void setSlaveGroupOfCells( const std::string &groupName ) { + _meshPairing->setSlaveGroupOfCells( groupName ); } - VectorLong getSlaveNodes() const { return _slaveNodes; } - - /** - * @brief get master cells - */ - const VectorLong &getMasterCells() const { return _masterCells; }; + /** @brief Set group of master cells */ + void setMasterGroupOfCells( const std::string &groupName ) { + _meshPairing->setMasterGroupOfCells( groupName ); + } + /** @brief Get master cells */ + const VectorLong &getMasterCells() const { return _meshPairing->getMasterCells(); }; VectorLong &getMasterCells() { return const_cast< VectorLong & >( std::as_const( *this ).getMasterCells() ); } - /** - * @brief get slave cells - */ - VectorLong getSlaveCells() const { return _slaveCells; } + /** @brief Get slave cells */ + VectorLong getSlaveCells() const { return _meshPairing->getSlaveCells(); } - VectorLong getMasterCellsFromNode( const ASTERINTEGER &i ) const; + /** @brief Set excluded groups of slave cells */ + void setExcludedSlaveGroupOfCells( const VectorString &groupsName ) { + _meshPairing->setExcludedSlaveGroupOfCells( groupsName ); + } - VectorLong getSlaveCellsFromNode( const ASTERINTEGER &i ) const; + /** @brief Set excluded groups of slave nodes */ + void setExcludedSlaveGroupOfNodes( const VectorString &groupsName ) { + _meshPairing->setExcludedSlaveGroupOfNodes( groupsName ); + } - VectorLong getMasterCellNeighbors( const ASTERINTEGER &i ) const; + /** @brief Set/get check normals */ + void checkNormals( const bool &checkNormal ) { _checkNormal = checkNormal; } + bool checkNormals() const { return _checkNormal; } - VectorLong getSlaveCellNeighbors( const ASTERINTEGER &i ) const; + /** @brief Get master nodes */ + VectorLong getMasterNodes() const { return _meshPairing->getMasterNodes(); }; - auto getSlaveCellsSurfToVolu() const { return _slavSurf2Volu; }; + /** @brief Get slave nodes */ + VectorLong getSlaveNodes() const { return _meshPairing->getSlaveNodes(); }; + + /** @brief Get volume slave cells linked to all surfacic slave cells */ + MapLong getSlaveCellsSurfToVolu() const { return _meshPairing->getSlaveCellsSurfToVolu(); }; + + /** @brief Get volume slave cell linked to a surfacic slave cells */ + ASTERINTEGER getSlaveCellSurfToVolu( const ASTERINTEGER &cellIndex ) const { + return _meshPairing->getSlaveCellSurfToVolu( cellIndex ); + }; - ASTERINTEGER getSlaveCellSurfToVolu( const ASTERINTEGER &i ) const { - return _slavSurf2Volu.at( i ); + /** @brief Set coordinates */ + void setCoordinates( const MeshCoordinatesFieldPtr &coor ) { + _meshPairing->setCoordinates( coor ); }; - /** - * @brief get master inverse connectivity as JeVeuxCollection - */ - JeveuxCollectionLong getMasterInverseConnectivity() const { return _masterInverseConnectivity; } - /** - * @brief get slave inverse connectivity as JeVeuxCollection - */ - JeveuxCollectionLong getSlaveInverseConnectivity() const { return _slaveInverseConnectivity; } - - /** - * @brief get master neighbors - */ - JeveuxCollectionLong getMasterNeighbors() const { return _masterNeighbors; } - /** - * @brief get slave neighbors - */ - JeveuxCollectionLong getSlaveNeighbors() const { return _slaveNeighbors; } + /** @brief Update coordinates */ + void updateCoordinates( const FieldOnNodesRealPtr &disp ) { + _meshPairing->updateCoordinates( disp ); + }; + /** @brief Set/unset friction for this zone */ void enableFriction( const bool &friction ) { _fricParam->enableFriction( friction ); }; + /** @brief Detect if friction for this zone */ bool hasFriction() const { return _fricParam->hasFriction(); }; + /** @brief Set/unset normal smoothing for this zone */ void enableSmoothing( const bool &smoothing ) { _smoothing = smoothing; }; + /** @brief Detect if normal smoothing for this zone */ bool hasSmoothing() const { return _smoothing; }; + + /** @brief Compute pairing of zone */ + bool pairing( ASTERDOUBLE &dist_pairing, ASTERDOUBLE &pair_tole ); + + /** @brief Get pairing of surface meshes */ + MeshPairingPtr getMeshPairing() { return _meshPairing; }; + + /** @brief Builder from Fortran part */ + bool build(); }; -/** - * @typedef ContactZonePtr - * @brief Pointeur intelligent vers un ContactZone - */ -typedef std::shared_ptr< ContactZone > ContactZonePtr; +using ContactZonePtr = std::shared_ptr< ContactZone >; #endif /* CONTACT_ZONE_H_ */ diff --git a/bibcxx/DataFields/FieldBuilder.h b/bibcxx/DataFields/FieldBuilder.h index db31ebe8e53..e98e1d230d9 100644 --- a/bibcxx/DataFields/FieldBuilder.h +++ b/bibcxx/DataFields/FieldBuilder.h @@ -6,7 +6,7 @@ * @brief Header of class FieldBuilder * @author Nicolas Sellenet * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -40,176 +40,174 @@ * @author Nicolas Sellenet */ class FieldBuilder { -private: - std::map _mapGlobNume; - std::map _mapLigrel; - - // I use them to debug easily mutiple creation - // I don't use map directly to avoid to keep in memory unnecessary objects - static std::set _setGlobNume; - static std::set _setLigrel; - - /** - * @brief Add a existing FiniteElementDescriptor in FieldBuilder - */ - FiniteElementDescriptorPtr - newFiniteElementDescriptor(const std::string &name, const BaseMeshPtr mesh) { - if (_setLigrel.count(strip(name)) > 0) { - raiseAsterError("LIGREL already exists: " + name); - } - - auto curDesc = std::make_shared(name, mesh); - - addFiniteElementDescriptor(curDesc); - - return curDesc; - }; - - /** - * @brief Add a existing EquationNumbering in FieldBuilder - */ - EquationNumberingPtr newEquationNumbering(const std::string &name, - const BaseMeshPtr mesh) { - if (_setGlobNume.count(strip(name)) > 0) { - raiseAsterError("NUME_EQUA already exists: " + name); - } - - auto curDesc = std::make_shared(name); - curDesc->setMesh(mesh); - - addEquationNumbering(curDesc); - - return curDesc; - }; - - /** - * @brief Add a existing generalizedEquationNumbering in FieldBuilder - */ - GeneralizedEquationNumberingPtr - newGeneralizedEquationNumbering(const std::string &name) { - AS_ABORT(name); - if (_setGlobNume.count(strip(name)) > 0) { - raiseAsterError("nume_equa_gene already exists: " + name); - } - - auto curDesc = std::make_shared(name); - - return curDesc; - }; - -public: - /** - * @brief Constructor - */ - FieldBuilder(){}; - - /** - * @brief Add a existing EquationNumbering in FieldBuilder - */ - void addEquationNumbering(const EquationNumberingPtr &fond) { - AS_ASSERT(fond); - - _mapGlobNume[strip(fond->getName())] = fond; - _setGlobNume.insert(strip(fond->getName())); - }; - - /** - * @brief Add a existing FiniteElementDescriptor in FieldBuilder - */ - void addFiniteElementDescriptor(const FiniteElementDescriptorPtr &fed) { - AS_ASSERT(fed); - - _mapLigrel[strip(fed->getName())] = fed; - _setLigrel.insert(strip(fed->getName())); - }; - - void clear() { - _mapGlobNume.clear(); - _mapLigrel.clear(); - }; - - /** - * @brief Build a FieldOnCells with a FiniteElementDescriptor - */ - template - std::shared_ptr> - buildFieldOnCells(const std::string &name, const BaseMeshPtr mesh) { - std::shared_ptr> field = - std::make_shared>(name); - field->updateValuePointers(); - - const std::string ligrel = strip((*(*field)._reference)[0].toString()); - - if (!ligrel.empty()) { - auto curIter = _mapLigrel.find(ligrel); - FiniteElementDescriptorPtr curDesc; - if (curIter != _mapLigrel.end()) { - curDesc = curIter->second; - } else { - curDesc = newFiniteElementDescriptor(ligrel, mesh); - } - - field->setDescription(curDesc); - } - return field; - }; - - /** - * @brief Build a ConstantFieldOnCells with a FiniteElementDescriptor - */ - template - std::shared_ptr> - buildConstantFieldOnCells(const std::string &name, const BaseMeshPtr mesh) { - - std::shared_ptr> field = - std::make_shared>(name, mesh); - field->updateValuePointers(); - - return field; - }; - - /** - * @brief Build a FieldOnNodes with a EquationNumbering - */ - template - std::shared_ptr> - buildFieldOnNodes(std::string name, const BaseMeshPtr mesh) { - std::shared_ptr> field = - std::make_shared>(name); - field->updateValuePointers(); - - const std::string globNume = strip((*(*field)._reference)[1].toString()); - AS_ASSERT(!globNume.empty()); - - auto curIter = _mapGlobNume.find(globNume); - EquationNumberingPtr curDesc; - if (curIter != _mapGlobNume.end()) - curDesc = curIter->second; - else { - curDesc = newEquationNumbering(globNume, mesh); - } - field->setDescription(curDesc); - - return field; - }; - - std::vector getFiniteElementDescriptors() const { - std::vector ret; - - for (auto &[name, fed] : _mapLigrel) - ret.push_back(fed); - - return ret; - }; - - std::vector getEquationNumberings() const { - std::vector ret; - - for (auto &[name, fnd] : _mapGlobNume) - ret.push_back(fnd); - - return ret; - }; + private: + std::map< std::string, EquationNumberingPtr > _mapGlobNume; + std::map< std::string, FiniteElementDescriptorPtr > _mapLigrel; + + // I use them to debug easily mutiple creation + // I don't use map directly to avoid to keep in memory unnecessary objects + static std::set< std::string > _setGlobNume; + static std::set< std::string > _setLigrel; + + /** + * @brief Add a existing FiniteElementDescriptor in FieldBuilder + */ + FiniteElementDescriptorPtr newFiniteElementDescriptor( const std::string &name, + const BaseMeshPtr mesh ) { + if ( _setLigrel.count( strip( name ) ) > 0 ) { + raiseAsterError( "LIGREL already exists: " + name ); + } + + auto curDesc = std::make_shared< FiniteElementDescriptor >( name, mesh ); + + addFiniteElementDescriptor( curDesc ); + + return curDesc; + }; + + /** + * @brief Add a existing EquationNumbering in FieldBuilder + */ + EquationNumberingPtr newEquationNumbering( const std::string &name, const BaseMeshPtr mesh ) { + if ( _setGlobNume.count( strip( name ) ) > 0 ) { + raiseAsterError( "NUME_EQUA already exists: " + name ); + } + + auto curDesc = std::make_shared< EquationNumbering >( name ); + curDesc->setMesh( mesh ); + + addEquationNumbering( curDesc ); + + return curDesc; + }; + + /** + * @brief Add a existing generalizedEquationNumbering in FieldBuilder + */ + GeneralizedEquationNumberingPtr newGeneralizedEquationNumbering( const std::string &name ) { + AS_ABORT( name ); + if ( _setGlobNume.count( strip( name ) ) > 0 ) { + raiseAsterError( "NUME_EQUA_GENE already exists: " + name ); + } + + auto curDesc = std::make_shared< GeneralizedEquationNumbering >( name ); + + return curDesc; + }; + + public: + /** + * @brief Constructor + */ + FieldBuilder() {}; + + /** + * @brief Add a existing EquationNumbering in FieldBuilder + */ + void addEquationNumbering( const EquationNumberingPtr &fond ) { + AS_ASSERT( fond ); + + _mapGlobNume[strip( fond->getName() )] = fond; + _setGlobNume.insert( strip( fond->getName() ) ); + }; + + /** + * @brief Add a existing FiniteElementDescriptor in FieldBuilder + */ + void addFiniteElementDescriptor( const FiniteElementDescriptorPtr &fed ) { + AS_ASSERT( fed ); + + _mapLigrel[strip( fed->getName() )] = fed; + _setLigrel.insert( strip( fed->getName() ) ); + }; + + void clear() { + _mapGlobNume.clear(); + _mapLigrel.clear(); + }; + + /** + * @brief Build a FieldOnCells with a FiniteElementDescriptor + */ + template < typename ValueType > + std::shared_ptr< FieldOnCells< ValueType > > buildFieldOnCells( const std::string &name, + const BaseMeshPtr mesh ) { + std::shared_ptr< FieldOnCells< ValueType > > field = + std::make_shared< FieldOnCells< ValueType > >( name ); + field->updateValuePointers(); + + const std::string ligrel = strip( ( *( *field )._reference )[0].toString() ); + + if ( !ligrel.empty() ) { + auto curIter = _mapLigrel.find( ligrel ); + FiniteElementDescriptorPtr curDesc; + if ( curIter != _mapLigrel.end() ) { + curDesc = curIter->second; + } else { + curDesc = newFiniteElementDescriptor( ligrel, mesh ); + } + + field->setDescription( curDesc ); + } + return field; + }; + + /** + * @brief Build a ConstantFieldOnCells with a FiniteElementDescriptor + */ + template < typename ValueType > + std::shared_ptr< ConstantFieldOnCells< ValueType > > + buildConstantFieldOnCells( const std::string &name, const BaseMeshPtr mesh ) { + + std::shared_ptr< ConstantFieldOnCells< ValueType > > field = + std::make_shared< ConstantFieldOnCells< ValueType > >( name, mesh ); + field->updateValuePointers(); + + return field; + }; + + /** + * @brief Build a FieldOnNodes with a EquationNumbering + */ + template < typename ValueType > + std::shared_ptr< FieldOnNodes< ValueType > > buildFieldOnNodes( std::string name, + const BaseMeshPtr mesh ) { + std::shared_ptr< FieldOnNodes< ValueType > > field = + std::make_shared< FieldOnNodes< ValueType > >( name ); + field->updateValuePointers(); + + const std::string globNume = strip( ( *( *field )._reference )[1].toString() ); + AS_ASSERT( !globNume.empty() ); + + auto curIter = _mapGlobNume.find( globNume ); + EquationNumberingPtr curDesc; + if ( curIter != _mapGlobNume.end() ) + curDesc = curIter->second; + else { + curDesc = newEquationNumbering( globNume, mesh ); + } + field->setDescription( curDesc ); + + return field; + }; + + std::vector< FiniteElementDescriptorPtr > getFiniteElementDescriptors() const { + std::vector< FiniteElementDescriptorPtr > ret; + + for ( auto &[name, fed] : _mapLigrel ) + ret.push_back( fed ); + + return ret; + }; + + std::vector< EquationNumberingPtr > getEquationNumberings() const { + std::vector< EquationNumberingPtr > ret; + + for ( auto &[name, fnd] : _mapGlobNume ) + ret.push_back( fnd ); + + return ret; + }; }; #endif /* FIELDBUILDER_H_ */ diff --git a/bibcxx/Meshes/BaseMesh.cxx b/bibcxx/Meshes/BaseMesh.cxx index 12b7171f323..b208e845b65 100644 --- a/bibcxx/Meshes/BaseMesh.cxx +++ b/bibcxx/Meshes/BaseMesh.cxx @@ -283,6 +283,18 @@ JeveuxVectorLong BaseMesh::getCellsType() const { return _cellsType; }; +ASTERINTEGER BaseMesh::getCellDime( const ASTERINTEGER &index ) const { + ASTERINTEGER returnValue; + + auto cellType = getCellType( index ); + const std::string cata = "&CATA.TM.TMDIM"; + JeveuxChar32 objName, charName; + CALLO_JEXNUM( objName, cata, &cellType ); + CALLO_JENONU( objName, &returnValue ); + + return returnValue; +}; + std::string BaseMesh::getCellTypeName( const ASTERINTEGER &index ) const { auto cellType = getCellType( index ); const std::string cata = "&CATA.TM.NOMTM"; @@ -317,6 +329,34 @@ bool BaseMesh::hasCellsOfType( const std::string typma ) const { return false; } +bool BaseMesh::isSkin( const std::string groupName ) const { + + if ( isParallel() ) { + auto meshDime = getDimension(); + std::cout << "PARALLEL Mesh dime: " << meshDime << std::endl; + return true; + } else { + auto meshDime = getDimension(); + std::cout << "Mesh dime: " << meshDime << std::endl; + if ( hasGroupOfCells( groupName ) ) { + const VectorLong cells = getCells( groupName ); + const auto cellsType = getCellsType(); + for ( auto &cellId : cells ) { + auto cellType = ( *cellsType )[cellId]; + auto cellDime = getCellDime( cellType ); + std::cout << "Cell dime: " << cellDime << std::endl; + if ( cellDime != ( meshDime - 1 ) ) { + return false; + } + } + + } else { + throw std::runtime_error( "The given group " + groupName + " doesn't exist in mesh" ); + } + } + return true; +} + bool BaseMesh::build() { _groupsOfNodes->build(); _groupsOfCells->build(); diff --git a/bibcxx/Meshes/BaseMesh.h b/bibcxx/Meshes/BaseMesh.h index 805ff8a6dfa..aa3ab3863d3 100644 --- a/bibcxx/Meshes/BaseMesh.h +++ b/bibcxx/Meshes/BaseMesh.h @@ -213,10 +213,14 @@ class BaseMesh : public DataStructure, public ListOfTables { JeveuxVectorLong getCellsType() const; + ASTERINTEGER getCellDime( const ASTERINTEGER &index ) const; + std::string getCellTypeName( const ASTERINTEGER &index ) const; bool hasCellsOfType( const std::string ) const; + bool isSkin( const std::string groupName ) const; + /** * @brief Recuperation de la dimension du maillage */ diff --git a/bibcxx/Meshes/Mesh.h b/bibcxx/Meshes/Mesh.h index 16cce4dba8d..5d498a22455 100644 --- a/bibcxx/Meshes/Mesh.h +++ b/bibcxx/Meshes/Mesh.h @@ -138,6 +138,9 @@ class Mesh : public BaseMesh { bool isQuadratic() const; + /** @brief Test if all cells in group are skin cells */ + bool isSkin( const std::string groupName ) const; + /** * @brief Read a Aster Mesh file * @return retourne true si tout est ok diff --git a/bibcxx/Meshes/MeshEnum.h b/bibcxx/Meshes/MeshEnum.h new file mode 100644 index 00000000000..2bc476ded1b --- /dev/null +++ b/bibcxx/Meshes/MeshEnum.h @@ -0,0 +1,37 @@ +#ifndef MESH_ENUM_H_ +#define MESH_ENUM_H_ + +/** + * @file MeshEnum.h + * @brief Header of class MeshEnum + * @section LICENCE + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org + * + * This file is part of Code_Aster. + * + * Code_Aster is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Code_Aster is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Code_Aster. If not, see . + */ + +#include "astercxx.h" + +/* Define here Enum for mesh + * + * Thinkd to bind enum in python + */ + +enum class PairingMethod { Fast, Legacy, BrutForce }; + +enum class CoordinatesSpace { Slave, Global }; + +#endif /* MESH_ENUM_H_ */ diff --git a/bibcxx/Meshes/MeshPairing.cxx b/bibcxx/Meshes/MeshPairing.cxx new file mode 100644 index 00000000000..3e7c5a31fc0 --- /dev/null +++ b/bibcxx/Meshes/MeshPairing.cxx @@ -0,0 +1,676 @@ +/** + * @file MeshPairing.cxx + * @brief Implementation of MeshPairing class + * @section LICENCE + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org + * + * This file is part of Code_Aster. + * + * Code_Aster is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Code_Aster is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Code_Aster. If not, see . + */ + +#include "Meshes/MeshPairing.h" + +#include "aster_fort_ds.h" +#include "aster_fort_mesh.h" + +#include "Messages/Messages.h" +#include "Utilities/Tools.h" + +MeshPairing::MeshPairing( const std::string name, const BaseMeshPtr mesh ) + : DataStructure( name, 8, "MESH_PAIRING" ), + _mesh( mesh ), + _masterInverseConnectivity( JeveuxCollectionLong( getName() + ".CM" ) ), + _slaveInverseConnectivity( JeveuxCollectionLong( getName() + ".CS" ) ), + _masterNeighbors( JeveuxCollectionLong( getName() + ".MN" ) ), + _slaveNeighbors( JeveuxCollectionLong( getName() + ".SN" ) ), + _verbosity( 1 ), + _slaveCellsGroup( " " ), + _masterCellsGroup( " " ), + _zoneHaveBeenDefined( false ), + _nbPairs( 0 ), + _method( PairingMethod::Fast ) { + + _currentCoordinates = std::make_shared< MeshCoordinatesField >( *( _mesh->getCoordinates() ) ); +}; + +// void MeshPairing::initPair() { +// if ( !surfacesHasBeenDefined() ) { +// throw std::runtime_error( "Surfaces are not defined." ); +// } +// setPair( _slaveCellsGroup, _masterCellsGroup ); +// }; + +void MeshPairing::setSlaveGroupOfCells( const std::string &groupName ) { + if ( getMesh()->hasGroupOfCells( groupName ) ) { + _slaveCellsGroup = groupName; + _slaveNodes = getMesh()->getNodesFromCells( groupName, false, true ); + _slaveCells = getMesh()->getCells( groupName ); + } else { + throw std::runtime_error( "The given group " + groupName + " doesn't exist in mesh" ); + } +}; + +void MeshPairing::setMasterGroupOfCells( const std::string &groupName ) { + if ( getMesh()->hasGroupOfCells( groupName ) ) { + _masterCellsGroup = groupName; + _masterNodes = getMesh()->getNodesFromCells( groupName, false, true ); + _masterCells = getMesh()->getCells( groupName ); + } else { + throw std::runtime_error( "The given group " + groupName + " doesn't exist in mesh" ); + } +}; + +void MeshPairing::setPair( const std::string &groupNameSlav, const std::string &groupNameMast ) { + + MeshPairing::setMasterGroupOfCells( groupNameMast ); + MeshPairing::setSlaveGroupOfCells( groupNameSlav ); + + this->initObjects(); +}; + +ASTERBOOL +MeshPairing::buildInverseConnectivity() { + // Create master inverse connectivity + ASTERINTEGER nbMaster = getMasterCells().size(); + std::string base( "G" ); + + VectorLong masterCells; + masterCells.reserve( _masterCells.size() ); + + // Shifting for fortran + for ( auto cell : _masterCells ) + masterCells.push_back( cell + 1 ); + + _masterInverseConnectivity->deallocate(); + CALL_CNCINV( getMesh()->getName().c_str(), masterCells.data(), &nbMaster, base.c_str(), + _masterInverseConnectivity->getName().c_str() ); + _masterInverseConnectivity->build(); + + // create slave inverse connectivity + ASTERINTEGER nbSlave = _slaveCells.size(); + + VectorLong slaveCells; + slaveCells.reserve( _slaveCells.size() ); + + // Shifting for fortran + for ( auto cell : _slaveCells ) + slaveCells.push_back( cell + 1 ); + + _slaveInverseConnectivity->deallocate(); + CALL_CNCINV( getMesh()->getName().c_str(), slaveCells.data(), &nbSlave, base.c_str(), + _slaveInverseConnectivity->getName().c_str() ); + _slaveInverseConnectivity->build(); + + return true; +} + +ASTERBOOL MeshPairing::buildCellsNeighbors() { + + ASTERINTEGER ind_max, ind_min; + + // Get master neighbors + ASTERINTEGER nbMaster = getMasterCells().size(); + if ( nbMaster > 0 ) { + ind_max = *std::max_element( _masterCells.begin(), _masterCells.end() ) + 1; + ind_min = *std::min_element( _masterCells.begin(), _masterCells.end() ) + 1; + + std::string invmcn_name = ljust( _masterInverseConnectivity->getName(), 24, ' ' ); + std::string mn_name = ljust( _masterNeighbors->getName(), 24, ' ' ); + + VectorLong masterCells; + masterCells.reserve( _masterCells.size() ); + for ( auto cell : _masterCells ) + masterCells.push_back( cell + 1 ); + + _masterNeighbors->deallocate(); + CALL_CNVOIS( getMesh()->getName(), masterCells.data(), invmcn_name, &nbMaster, &ind_min, + &ind_max, mn_name ); + + _masterNeighbors->build(); + } + + // Get slave neighbors + ASTERINTEGER nbSlave = getSlaveCells().size(); + if ( nbSlave > 0 ) { + ind_max = *std::max_element( _slaveCells.begin(), _slaveCells.end() ) + 1; + ind_min = *std::min_element( _slaveCells.begin(), _slaveCells.end() ) + 1; + + std::string invscn_name = ljust( _slaveInverseConnectivity->getName(), 24, ' ' ); + std::string sn_name = ljust( _slaveNeighbors->getName(), 24, ' ' ); + + VectorLong slaveCells; + slaveCells.reserve( _slaveCells.size() ); + for ( auto cell : _slaveCells ) + slaveCells.push_back( cell + 1 ); + CALL_CNVOIS( getMesh()->getName(), slaveCells.data(), invscn_name, &nbSlave, &ind_min, + &ind_max, sn_name ); + + _slaveNeighbors->build(); + } + + return true; +} + +void MeshPairing::clearResult() { + _nbPairs = 0; + _pairs.clear(); + _nbPoinInte.clear(); + _poinInteSlav.clear(); +} + +ASTERBOOL MeshPairing::surfacesHasBeenDefined() { + ASTERBOOL returnValue; + returnValue = ( _slaveCellsGroup.size() != 0 && _masterCellsGroup.size() != 0 ); + return returnValue; +} + +ASTERBOOL MeshPairing::compute( ASTERDOUBLE &dist_pairing, ASTERDOUBLE &pair_tole ) { + + CALL_JEMARQ(); + + // Get and define some input parameters + VectorLong masterCells = getMasterCells(); + VectorLong masterNodes = getMasterNodes(); + VectorLong slaveCells = getSlaveCells(); + ASTERINTEGER nbCellMaster = masterCells.size(); + ASTERINTEGER nbNodeMaster = masterNodes.size(); + ASTERINTEGER nbCellSlave = slaveCells.size(); + ASTERINTEGER verbosity = getVerbosity(); + std::string mastConnexInveName = getMasterInverseConnectivityName(); + std::string mastNeighName = getMasterNeighName(); + std::string slavNeighName = getSlaveNeighName(); + + // Update the numbering for fortran + std::for_each( masterCells.begin(), masterCells.end(), []( ASTERINTEGER &d ) { d += 1; } ); + std::for_each( masterNodes.begin(), masterNodes.end(), []( ASTERINTEGER &d ) { d += 1; } ); + std::for_each( slaveCells.begin(), slaveCells.end(), []( ASTERINTEGER &d ) { d += 1; } ); + + // Set pairs numbers to 0 + ASTERINTEGER nb_pairs = 0; + + // Clear pairing results + this->clearResult(); + + // Method + ASTERINTEGER method; + if ( _method == PairingMethod::Fast ) { + method = 1; + } else if ( _method == PairingMethod::Legacy ) { + method = 2; + } else if ( _method == PairingMethod::BrutForce ) { + method = 3; + } else { + raiseAsterError( "Unknown method of pairing " ); + } + + // Main routine for pairing + CALLO_PAIRWRAP( &method, _mesh->getName(), _currentCoordinates->getName(), mastConnexInveName, + mastNeighName, slavNeighName, &pair_tole, &dist_pairing, &verbosity, + &nbCellMaster, masterCells.data(), &nbCellSlave, slaveCells.data(), + &nbNodeMaster, masterNodes.data(), &nb_pairs, getBasename() ); + + // Output JEVEUX objects + if ( !_jvPairs.exists() ) { + _jvPairs = JeveuxVectorLong( getPairsName() ); + } + if ( !_jvNbInterPoints.exists() ) { + _jvNbInterPoints = JeveuxVectorLong( getNbInterName() ); + } + if ( !_jvInterSlavePoints.exists() ) { + _jvInterSlavePoints = JeveuxVectorReal( getCoorInterName() ); + } + _jvPairs->updateValuePointer(); + _jvNbInterPoints->updateValuePointer(); + _jvInterSlavePoints->updateValuePointer(); + + // Set output values + _nbPairs = nb_pairs; + _pairs = _jvPairs->toVector(); + std::transform( _pairs.begin(), _pairs.end(), _pairs.begin(), + []( ASTERINTEGER &indexCell ) -> ASTERINTEGER { return --indexCell; } ); + _nbPoinInte = _jvNbInterPoints->toVector(); + _poinInteSlav = _jvInterSlavePoints->toVector(); + + CALL_JEDEMA(); + + return true; +} + +VectorPairLong MeshPairing::getListOfPairs() const { + + VectorPairLong returnValue; + ASTERINTEGER nbPairs = getNumberOfPairs(); + + if ( nbPairs == 0 ) { + throw std::runtime_error( "No pairs !" ); + } + + if ( _pairs.size() == 0 ) { + throw std::runtime_error( "No pairs from Fortran!" ); + } + + returnValue.reserve( nbPairs ); + + for ( auto iPair = 0; iPair < nbPairs; iPair++ ) { + returnValue.push_back( std::make_pair( _pairs[2 * iPair], _pairs[2 * iPair + 1] ) ); + } + + return returnValue; +} + +// VectorOfVectorsReal MeshPairing::getIntersectionPoints( const ASTERINTEGER &indexPair, +// const CoordinatesSpace coorSpace ) const +// { + +// ASTERINTEGER nbPairs = getNumberOfPairs(); +// VectorOfVectorsReal returnValue; + +// if ( indexPair < 0 || indexPair >= nbPairs ) { +// throw std::out_of_range( "The pair index should be between 0 and " + +// std::to_string( nbPairs ) ); +// } + +// ASTERINTEGER nbInter = getNumberOfIntersectionPoints( indexPair ); +// VectorReal coorParaPoint; +// coorParaPoint.reserve( 2 ); +// coorParaPoint.push_back( 0.0 ); +// coorParaPoint.push_back( 0.0 ); + +// if ( nbInter != 0 ) { +// returnValue.reserve( nbInter ); +// for ( auto iInter = 0; iInter < nbInter; iInter++ ) { +// coorParaPoint[0] = _poinInteSlav[16 * ( indexPair ) + iInter]; +// coorParaPoint[1] = _poinInteSlav[16 * ( indexPair ) + iInter + 8]; +// returnValue.push_back( coorParaPoint ); +// } +// } + +// return returnValue; +// } + +ASTERINTEGER MeshPairing::getNumberOfIntersectionPoints( const ASTERINTEGER &indexPair ) const { + + ASTERINTEGER nbPairs = getNumberOfPairs(); + + if ( indexPair < 0 || indexPair >= nbPairs ) { + throw std::out_of_range( "The pair index should be between 0 and " + + std::to_string( nbPairs ) ); + } + + return _nbPoinInte[indexPair]; +} + +VectorLong MeshPairing::getNumberOfIntersectionPoints() const { + + ASTERINTEGER nbPairs = getNumberOfPairs(); + + VectorLong returnValue; + + for ( auto indexPair = 0; indexPair < nbPairs; indexPair++ ) { + ASTERINTEGER nbInter = getNumberOfIntersectionPoints( indexPair ); + returnValue.push_back( nbInter ); + } + return returnValue; +} + +VectorOfVectorsReal MeshPairing::getIntersectionPoints( const ASTERINTEGER &indexPair, + const CoordinatesSpace coorSpace ) const { + + ASTERINTEGER nbPairs = getNumberOfPairs(); + + if ( indexPair < 0 || indexPair >= nbPairs ) { + throw std::out_of_range( "The pair index should be between 0 and " + + std::to_string( nbPairs ) ); + } + + ASTERINTEGER nbInter = getNumberOfIntersectionPoints( indexPair ); + + VectorOfVectorsReal returnValue; + + if ( coorSpace == CoordinatesSpace::Global ) { + VectorReal coorGlobPoint; + coorGlobPoint.reserve( 3 ); + coorGlobPoint.push_back( 0.0 ); + coorGlobPoint.push_back( 0.0 ); + coorGlobPoint.push_back( 0.0 ); + + // Objects for output + VectorReal poinInteReal; + poinInteReal.reserve( 3 * 8 ); + CALLO_INTEPOINCOORWRAP( _mesh->getName(), _currentCoordinates->getName(), getBasename(), + &indexPair, poinInteReal.data() ); + + if ( nbInter == 0 ) { + throw std::out_of_range( "No intersection in pair " + std::to_string( indexPair ) ); + } else { + returnValue.reserve( 3 * nbInter ); + for ( auto iInter = 0; iInter < nbInter; iInter++ ) { + coorGlobPoint[0] = poinInteReal[3 * iInter]; + coorGlobPoint[1] = poinInteReal[3 * iInter + 1]; + coorGlobPoint[2] = poinInteReal[3 * iInter + 2]; + returnValue.push_back( coorGlobPoint ); + } + } + } else if ( coorSpace == CoordinatesSpace::Slave ) { + + VectorReal coorParaPoint; + coorParaPoint.reserve( 2 ); + coorParaPoint.push_back( 0.0 ); + coorParaPoint.push_back( 0.0 ); + + if ( nbInter != 0 ) { + returnValue.reserve( nbInter ); + for ( auto iInter = 0; iInter < nbInter; iInter++ ) { + coorParaPoint[0] = _poinInteSlav[16 * ( indexPair ) + iInter]; + coorParaPoint[1] = _poinInteSlav[16 * ( indexPair ) + iInter + 8]; + returnValue.push_back( coorParaPoint ); + } + } + } + return returnValue; +} + +ASTERDOUBLE MeshPairing::getIntersectionArea( const ASTERINTEGER &indexPair ) const { + + ASTERINTEGER nbPairs = getNumberOfPairs(); + + if ( indexPair < 0 || indexPair >= nbPairs ) { + throw std::out_of_range( "The pair index should be between 0 and " + + std::to_string( nbPairs ) ); + } + + double coorPoint; + VectorReal poinInte; + ASTERDOUBLE inteArea = 0.0; + + ASTERINTEGER nbInter = getNumberOfIntersectionPoints( indexPair ); + if ( nbInter != 0 ) { + for ( auto iInter = 0; iInter < nbInter; iInter++ ) { + coorPoint = _poinInteSlav[16 * indexPair + iInter]; + poinInte.push_back( coorPoint ); + coorPoint = _poinInteSlav[16 * indexPair + 8 + iInter]; + poinInte.push_back( coorPoint ); + } + CALLO_INTECELLAREAWRAP( _mesh->getName(), &nbInter, poinInte.data(), &inteArea ); + } + return inteArea; +} + +std::vector< VectorReal > MeshPairing::getQuadraturePoints( const ASTERINTEGER &indexPair ) const { + + std::vector< VectorReal > returnValue; + + ASTERINTEGER nbPairs = getNumberOfPairs(); + if ( indexPair < 0 || indexPair >= nbPairs ) { + throw std::out_of_range( "The pair index should be between 0 and " + + std::to_string( nbPairs ) ); + } + + VectorReal coorPoint; + coorPoint.reserve( 3 ); + coorPoint.push_back( 0.0 ); + coorPoint.push_back( 0.0 ); + coorPoint.push_back( 0.0 ); + + ASTERINTEGER nbPoinQuad = 0; + VectorReal poinQuadReal; + poinQuadReal.reserve( 3 * 48 ); + CALLO_QUADPOINCOORWRAP( _mesh->getName(), _currentCoordinates->getName(), getBasename(), + &indexPair, &nbPoinQuad, poinQuadReal.data() ); + + if ( nbPoinQuad != 0 ) { + returnValue.reserve( nbPoinQuad ); + for ( long int iPoinQuad = 0; iPoinQuad < nbPoinQuad; iPoinQuad++ ) { + coorPoint[0] = poinQuadReal[3 * iPoinQuad]; + coorPoint[1] = poinQuadReal[3 * iPoinQuad + 1]; + coorPoint[2] = poinQuadReal[3 * iPoinQuad + 2]; + returnValue.push_back( coorPoint ); + } + } + + return returnValue; +} + +/** @brief Check for common nodes between slave and master side */ +ASTERBOOL MeshPairing::hasCommonNodes() const { + + ASTERBOOL returnValue; + auto mesh = getMesh(); + + VectorLong commonNodes; + VectorLong masterNodes = _masterNodes; + VectorLong slaveNodes = _slaveNodes; + std::cout << "Master SIze<" << masterNodes.size() << ">" << std::endl; + for ( long int iNode = 0; iNode < masterNodes.size(); iNode++ ) { + std::cout << "Master node: " << masterNodes[iNode] << std::endl; + } + std::cout << "Slave SIze<" << slaveNodes.size() << ">" << std::endl; + for ( long int iNode = 0; iNode < slaveNodes.size(); iNode++ ) { + std::cout << "Slave node: " << slaveNodes[iNode] << std::endl; + } + + if ( mesh->isParallel() ) { +#ifdef ASTER_HAVE_MPI + VectorLong slaveNodes_gl; + AsterMPI::all_gather( _slaveNodes, slaveNodes_gl ); + commonNodes = set_intersection( slaveNodes_gl, masterNodes ); +#endif + } else { + commonNodes = set_intersection( slaveNodes, masterNodes ); + } + + ASTERINTEGER size_inter_gl = commonNodes.size(); + + // share error +#ifdef ASTER_HAVE_MPI + if ( mesh->isParallel() ) { + ASTERINTEGER size_inter_lc = size_inter_gl; + size_inter_gl = AsterMPI::sum( size_inter_lc ); + } +#endif + returnValue = false; + if ( size_inter_gl > 0 ) { + returnValue = true; + } + + return returnValue; +} + +VectorLong MeshPairing::getMasterCellsFromNode( const ASTERINTEGER &nodeIndex ) const { + auto vct = ( *_masterInverseConnectivity )[nodeIndex + 1]->toVector(); + std::transform( vct.begin(), vct.end(), vct.begin(), [this]( ASTERINTEGER k ) -> ASTERINTEGER { + return k > 0 ? _masterCells[k - 1] : 0; + } ); + return vct; +} + +VectorLong MeshPairing::getSlaveCellsFromNode( const ASTERINTEGER &nodeIndex ) const { + auto vct = ( *_slaveInverseConnectivity )[nodeIndex + 1]->toVector(); + std::transform( vct.begin(), vct.end(), vct.begin(), [this]( ASTERINTEGER k ) -> ASTERINTEGER { + return k > 0 ? _slaveCells[k - 1] : 0; + } ); + return vct; +} + +VectorLong MeshPairing::getMasterCellNeighbors( const ASTERINTEGER &cellIndex ) const { + ASTERINTEGER ind_min = *std::min_element( _masterCells.begin(), _masterCells.end() ); + ASTERINTEGER ind_max = *std::max_element( _masterCells.begin(), _masterCells.end() ); + + if ( cellIndex < ind_min || cellIndex > ind_max ) + throw std::out_of_range( " the master cell's number should be" + " between " + + std::to_string( ind_min ) + " and " + std::to_string( ind_max ) ); + + auto vct = ( *_masterNeighbors )[cellIndex - ind_min + 1]->toVector(); + vct.erase( std::remove_if( vct.begin(), vct.end(), + []( ASTERINTEGER &cellIndex ) { return cellIndex == 0; } ), + vct.end() ); + std::transform( vct.begin(), vct.end(), vct.begin(), + []( ASTERINTEGER k ) -> ASTERINTEGER { return k - 1; } ); + return vct; +} + +VectorLong MeshPairing::getSlaveCellNeighbors( const ASTERINTEGER &cellIndex ) const { + + ASTERINTEGER ind_min = *std::min_element( _slaveCells.begin(), _slaveCells.end() ); + ASTERINTEGER ind_max = *std::max_element( _slaveCells.begin(), _slaveCells.end() ); + + if ( cellIndex < ind_min || cellIndex > ind_max ) + throw std::out_of_range( " the slave cell's number should be" + " between " + + std::to_string( ind_min ) + " and " + std::to_string( ind_max ) ); + + auto vct = ( *_slaveNeighbors )[cellIndex - ind_min + 1]->toVector(); + vct.erase( std::remove_if( vct.begin(), vct.end(), + []( ASTERINTEGER &cellIndex ) { return cellIndex == 0; } ), + vct.end() ); + std::transform( vct.begin(), vct.end(), vct.begin(), + []( ASTERINTEGER k ) -> ASTERINTEGER { return k - 1; } ); + return vct; +} + +ASTERBOOL MeshPairing::buildSlaveCellsVolu() { + auto mesh = getMesh(); + auto nbCells = mesh->getNumberOfCells(); + + auto invCon = mesh->getInverseConnectivity(); + invCon->build(); + + auto exp = mesh->getConnectivityExplorer(); + + for ( auto &cellId : _slaveCells ) { + const auto cell = exp[cellId]; + VectorLong candidat; + for ( const auto nodeId : cell ) { + auto listCells = ( *invCon )[nodeId + 1]->toVector(); + + std::for_each( listCells.begin(), listCells.end(), []( ASTERINTEGER &d ) { d -= 1; } ); + + if ( candidat.empty() ) { + candidat = listCells; + } else { + auto tmp = set_intersection( candidat, listCells ); + AS_ASSERT( !tmp.empty() ); + candidat = tmp; + } + } + + AS_ASSERT( candidat.size() == 2 ); + ASTERINTEGER cellVolu; + if ( candidat[0] == cellId ) { + cellVolu = candidat[1]; + } else { + cellVolu = candidat[0]; + } + + _slavSurf2Volu[cellId] = cellVolu; + } + + return true; +}; + +void MeshPairing::setExcludedSlaveGroupOfCells( const VectorString &groupsName ) { + auto mesh = getMesh(); + for ( auto &groupName : groupsName ) { + if ( !( getMesh()->hasGroupOfCells( groupName ) ) ) { + throw std::runtime_error( "The group " + groupName + " doesn't exist in mesh" ); + } + + VectorLong sans_gr_i = mesh->getCells( groupName ); + auto it = _slaveCellsExcluded.end(); + _slaveCellsExcluded.insert( it, sans_gr_i.begin(), sans_gr_i.end() ); + } + + _slaveCells = set_difference( _slaveCells, _slaveCellsExcluded ); + AS_ASSERT( _slaveCells.size() > 0 ); + _slaveNodes = getMesh()->getNodesFromCells( _slaveCells ); +}; + +void MeshPairing::setExcludedSlaveGroupOfNodes( const VectorString &groupsName ) { + auto mesh = getMesh(); + + std::cout << "MESH - setExcludedSlaveGroupOfNodes <" << groupsName[0] << ">" << std::endl; + + // Build inverse connectivity + AS_ASSERT( buildInverseConnectivity() ); + std::cout << "MESH/nodes - Avant <" << _slaveNodes.size() << ">" << std::endl; + std::cout << "MESH - Avant <" << _slaveCells.size() << ">" << std::endl; + + for ( auto &groupName : groupsName ) { + if ( !( getMesh()->hasGroupOfNodes( groupName ) ) ) { + throw std::runtime_error( "The group " + groupName + " doesn't exist in mesh" ); + } + + VectorLong sans_gr_i = mesh->getNodes( groupName ); + std::cout << "Nombre de noeuds à exclure: " << sans_gr_i.size() << std::endl; + for ( auto &node : sans_gr_i ) { + auto cellsToExclude = this->getSlaveCellsFromNode( node ); + std::cout << " Noeud: " << node << std::endl; + std::cout << " Cells : " << cellsToExclude.size() << std::endl; + auto it = _slaveCellsExcluded.end(); + _slaveCellsExcluded.insert( it, cellsToExclude.begin(), cellsToExclude.end() ); + } + } + + std::cout << "MESH - Exclus <" << _slaveCellsExcluded.size() << ">" << std::endl; + std::cout << "MESH - Exclus <" << _slaveCellsExcluded[0] << ">" << std::endl; + _slaveCells = set_difference( _slaveCells, _slaveCellsExcluded ); + std::cout << "MESH - Après <" << _slaveCells.size() << ">" << std::endl; + AS_ASSERT( _slaveCells.size() > 0 ); + _slaveNodes = getMesh()->getNodesFromCells( _slaveCells ); + std::cout << "MESH/nodes - Après <" << _slaveNodes.size() << ">" << std::endl; +}; + +ASTERBOOL MeshPairing::initObjects() { + + _zoneHaveBeenDefined = true; + + // // Désactivation verif (voir issue34073) + // // bool returnValue; + // // returnValue = getMesh()->isSkin( groupNameMast ); + // // if ( !returnValue ) { + // // UTMESS( "F", "MESH4_2" ); + // // } + // // returnValue = getMesh()->isSkin( groupNameSlav ); + // // if ( !returnValue ) { + // // UTMESS( "F", "MESH4_2" ); + // // } + + // Build inverse connectivity + AS_ASSERT( buildInverseConnectivity() ); + + // Build master and slave cells neighbors + AS_ASSERT( buildCellsNeighbors() ); + + // Build surface to volume slave cell mapping + AS_ASSERT( buildSlaveCellsVolu() ); + + return true; +} + +void MeshPairing::checkNormals( const ModelPtr _model ) const { + if ( _zoneHaveBeenDefined ) { + if ( _model->getMesh() == getMesh() ) { + CALL_CHECKNORMALS( _model->getName().c_str(), + ljust( getSlaveGroupOfCells(), 24, ' ' ).c_str(), + ljust( getMasterGroupOfCells(), 24, ' ' ).c_str() ); + } else { + throw std::runtime_error( "Mesh is different in model" ); + } + + } else { + throw std::runtime_error( "Zone is undefined" ); + } +} diff --git a/bibcxx/Meshes/MeshPairing.h b/bibcxx/Meshes/MeshPairing.h new file mode 100644 index 00000000000..51bb978254c --- /dev/null +++ b/bibcxx/Meshes/MeshPairing.h @@ -0,0 +1,284 @@ +#ifndef MESH_PAIRING_H_ +#define MESH_PAIRING_H_ + +/** + * @file MeshPairing.h + * @brief Header of MeshPairing class + * @section LICENCE + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org + * + * This file is part of Code_Aster. + * + * Code_Aster is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Code_Aster is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Code_Aster. If not, see . + */ + +#include "astercxx.h" + +#include "DataFields/FieldOnNodes.h" +#include "DataFields/MeshCoordinatesField.h" +#include "DataStructures/DataStructure.h" +#include "MemoryManager/JeveuxVector.h" +#include "Meshes/Mesh.h" +#include "Meshes/MeshEnum.h" +#include "Supervis/ResultNaming.h" + +class MeshPairing : public DataStructure { + private: + /** @brief Mesh */ + BaseMeshPtr _mesh; + /** @brief Current coordinates of nodes */ + MeshCoordinatesFieldPtr _currentCoordinates; + + /** @brief Flag when zone is defined */ + bool _zoneHaveBeenDefined; + /** @brief Name of group for slave side */ + std::string _slaveCellsGroup; + /** @brief Name of group for master side */ + std::string _masterCellsGroup; + /** @brief List of master cells */ + VectorLong _masterCells; + /** @brief List of slave cells */ + VectorLong _slaveCells; + /** @brief List of master nodes */ + VectorLong _masterNodes; + /** @brief List of slave nodes */ + VectorLong _slaveNodes; + /** @brief List of excluded slave cells */ + VectorLong _slaveCellsExcluded; + + /** @brief Master inverse connectivity */ + JeveuxCollectionLong _masterInverseConnectivity; + /** @brief Slave inverse connectivity */ + JeveuxCollectionLong _slaveInverseConnectivity; + /** @brief Master cells neighbors */ + JeveuxCollectionLong _masterNeighbors; + /** @brief Slave cells neighbors */ + JeveuxCollectionLong _slaveNeighbors; + + /** @brief Output JEVEUX objects from FORTRAN pairing */ + JeveuxVectorLong _jvPairs; + JeveuxVectorLong _jvNbInterPoints; + JeveuxVectorReal _jvInterSlavePoints; + + /** @brief Map between slave surfacic and volumic cell */ + MapLong _slavSurf2Volu; + + /** @brief Method of pairing */ + PairingMethod _method; + + /** @brief Level of verbosity */ + ASTERINTEGER _verbosity; + + /** @brief Number of pairs */ + ASTERINTEGER _nbPairs; + + /** @brief Vector of pairs */ + VectorLong _pairs; + + /** @brief Vector of number of intersection points */ + VectorLong _nbPoinInte; + + /** @brief Vector of coordinates for intersection points in slave parameteric space*/ + VectorReal _poinInteSlav; + + private: + /** @brief Get name of JEVEUX object for master inverse connectivity */ + std::string getMasterInverseConnectivityName() const { + return ljust( getName() + ".CM", 24, ' ' ); + } + + /** @brief Get name of JEVEUX object for slave inverse connectivity */ + std::string getSlaveInverseConnectivityName() const { + return ljust( getName() + ".CS", 24, ' ' ); + } + + /** @brief Get name of JEVEUX object for master neighbors */ + std::string getMasterNeighName() const { return ljust( getName() + ".MN", 24, ' ' ); } + + /** @brief Get name of JEVEUX object for slave neighbors */ + std::string getSlaveNeighName() const { return ljust( getName() + ".SN", 24, ' ' ); } + + /** @brief Get name of JEVEUX object for outputs*/ + std::string getBasename() const { return ljust( getName(), 8, ' ' ); } + + /** @brief Get name of JEVEUX object for pairs */ + std::string getPairsName() const { return ljust( getBasename() + ".LISTPAIRS", 24, ' ' ); } + + /** @brief Get name of JEVEUX object for number of intersection points */ + std::string getNbInterName() const { return ljust( getBasename() + ".NBPOIN", 24, ' ' ); } + + /** @brief Get name of JEVEUX object for coordinates of intersection points */ + std::string getCoorInterName() const { return ljust( getBasename() + ".INTERSLPTS", 24, ' ' ); } + + /** @brief Construct the inverse connectivity */ + ASTERBOOL buildInverseConnectivity(); + + /** @brief Construct master/slave cells neighbors */ + ASTERBOOL buildCellsNeighbors(); + + /** @brief Construct surface to volume slave cell mapping */ + ASTERBOOL buildSlaveCellsVolu(); + + /** @brief Surface defined */ + ASTERBOOL surfacesHasBeenDefined(); + + public: + using MeshPairingPtr = std::shared_ptr< MeshPairing >; + + /** @brief No default constructor */ + MeshPairing() = delete; + + /** @brief Constructor with given name */ + MeshPairing( const std::string name, const BaseMeshPtr mesh ); + + /** @brief Constructor with automatic name */ + MeshPairing( const BaseMeshPtr mesh ) + : MeshPairing( ResultNaming::getNewResultName(), mesh ) {}; + + /** @brief Initializations of datastructures defining pairing */ + bool initObjects(); + + /** @brief Get mesh */ + BaseMeshPtr getMesh() const { return _mesh; }; + + /** @brief Set verbosity */ + void setVerbosity( const ASTERINTEGER &level ) { _verbosity = level; } + + /** @brief Get verbosity */ + ASTERINTEGER getVerbosity() const { return _verbosity; } + + /** @brief Get coordinates */ + MeshCoordinatesFieldPtr getCoordinates() const { return _currentCoordinates; } + + /** @brief Update coordinates */ + void updateCoordinates( const FieldOnNodesRealPtr &disp ) { + *_currentCoordinates = *( _mesh->getCoordinates() ) + *disp; + }; + + /** @brief Set coordinates */ + void setCoordinates( const MeshCoordinatesFieldPtr &coor ) { _currentCoordinates = coor; }; + + /** @brief Set pair */ + void setPair( const std::string &groupNameSlav, const std::string &groupNameMast ); + + /** @brief Init pair */ + void initPair(); + + /** @brief Set slave cells */ + void setSlaveGroupOfCells( const std::string &groupName ); + + /** @brief Set master cells */ + void setMasterGroupOfCells( const std::string &groupName ); + + /** @brief Set excluded groups of slave cells */ + void setExcludedSlaveGroupOfCells( const VectorString &groupsName ); + + /** @brief Set excluded groups of slave nodes */ + void setExcludedSlaveGroupOfNodes( const VectorString &groupsName ); + + /** @brief Get name of group for slave cells */ + std::string getSlaveGroupOfCells() const { return _slaveCellsGroup; } + + /** @brief Get name of group for master cells */ + std::string getMasterGroupOfCells() const { return _masterCellsGroup; } + + /** @brief Get master cells*/ + const VectorLong &getMasterCells() const { return _masterCells; }; + + /** @brief Get slave cells */ + const VectorLong &getSlaveCells() const { return _slaveCells; }; + + /** @brief Get master nodes*/ + const VectorLong &getMasterNodes() const { return _masterNodes; }; + VectorLong &getMasterNodes() { + return const_cast< VectorLong & >( std::as_const( *this ).getMasterNodes() ); + }; + + /** @brief Get slave nodes*/ + const VectorLong &getSlaveNodes() const { return _slaveNodes; }; + VectorLong &getSlaveNodes() { + return const_cast< VectorLong & >( std::as_const( *this ).getSlaveNodes() ); + }; + + /** @brief Get master cells from a node (inverse connectivity) */ + VectorLong getMasterCellsFromNode( const ASTERINTEGER &nodeIndex ) const; + + /** @brief Get slave cells from a node (inverse connectivity) */ + VectorLong getSlaveCellsFromNode( const ASTERINTEGER &nodeIndex ) const; + + /** @brief Get neighbors of master cell */ + VectorLong getMasterCellNeighbors( const ASTERINTEGER &cellIndex ) const; + + /** @brief Get neighbors of slave cell */ + VectorLong getSlaveCellNeighbors( const ASTERINTEGER &cellIndex ) const; + + /** @brief Get volume slave cells linked to all surfacic slave cells */ + MapLong getSlaveCellsSurfToVolu() const { return _slavSurf2Volu; }; + + /** @brief Get volume slave cells linked to one surfacic slave cells */ + ASTERINTEGER getSlaveCellSurfToVolu( const ASTERINTEGER &cellIndex ) const { + return _slavSurf2Volu.at( cellIndex ); + }; + + /** @brief Main subroutine for pairing */ + ASTERBOOL compute( ASTERDOUBLE &dist_pairing, ASTERDOUBLE &pair_tole ); + + /** @brief Clear pairing result */ + void clearResult(); + + /** @brief Get number of pairs */ + ASTERBOOL hasPairs() const { return ( _nbPairs > 0 ); }; + + /** @brief Get number of pairs */ + ASTERINTEGER getNumberOfPairs() const { return _nbPairs; }; + + /** @brief Get all list of pairs */ + VectorPairLong getListOfPairs() const; + + /** @brief Get pair */ + MapLong getPair( const ASTERINTEGER &iPair ); + + /** @brief Get number of intersection points on all pairs */ + VectorLong getNumberOfIntersectionPoints() const; + + /** @brief Get number of intersection points of given pair */ + ASTERINTEGER getNumberOfIntersectionPoints( const ASTERINTEGER &indexPair ) const; + + /** @brief Get intersection points of given pair */ + VectorOfVectorsReal + getIntersectionPoints( const ASTERINTEGER &indexPair, + const CoordinatesSpace = CoordinatesSpace::Global ) const; + + /** @brief Get area of intersection of given pair */ + ASTERDOUBLE getIntersectionArea( const ASTERINTEGER &indexPair ) const; + + /** @brief Get number of quadrature points of given pair */ + ASTERINTEGER getNumberOfQuadraturePoints( const ASTERINTEGER &indexPair ) const; + + /** @brief Get quadrature points of given pair */ + VectorOfVectorsReal getQuadraturePoints( const ASTERINTEGER &indexPair ) const; + + /** @brief Check for common nodes between slave and master side */ + ASTERBOOL hasCommonNodes() const; + + /** @brief Check orientation of normals */ + void checkNormals( const ModelPtr _model ) const; + + /** @brief Set method */ + void setMethod( const PairingMethod &method ) { _method = method; }; +}; + +using MeshPairingPtr = std::shared_ptr< MeshPairing >; + +#endif diff --git a/bibcxx/Messages/Messages.cxx b/bibcxx/Messages/Messages.cxx index c9cf00748b4..18cff3a14d1 100644 --- a/bibcxx/Messages/Messages.cxx +++ b/bibcxx/Messages/Messages.cxx @@ -2,7 +2,7 @@ * @file Message.cxx * @brief Fichier entete de la class Messages * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -24,10 +24,13 @@ #include "aster_fort_utils.h" -void UTMESS( char *error, char *message ) { CALL_UTMESS( error, message ); } - -void UTMESS( const char *error, const char *message ) { UTMESS( (char *)error, (char *)message ); } - -void UTMESS( const std::string &error, const std::string &message ) { - UTMESS( &error[0], &message[0] ); +void UTMESS( const std::string &typm, const std::string &idmess ) { + if ( typm == "A" || typm == "I" ) { + CALL_UTMESS( (char *)typm.c_str(), (char *)idmess.c_str() ); + } else { + raiseAsterError( idmess ); + } } +void UTMESS( char *typm, char *idmess ) { UTMESS( std::string( typm ), std::string( idmess ) ); } + +void UTMESS( const char *typm, const char *idmess ) { UTMESS( (char *)typm, (char *)idmess ); } diff --git a/bibcxx/Messages/Messages.h b/bibcxx/Messages/Messages.h index 3753fbbd179..386c6afee53 100644 --- a/bibcxx/Messages/Messages.h +++ b/bibcxx/Messages/Messages.h @@ -5,7 +5,7 @@ * @file Message.h * @brief Fichier entete de la class Messages * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -25,12 +25,14 @@ #include "astercxx.h" +#include "Supervis/Exceptions.h" + /* Encapsulation of utmess */ -void UTMESS( char *error, char *message ); +void UTMESS( char *typm, char *idmess ); -void UTMESS( const char *error, const char *message ); +void UTMESS( const char *typm, const char *idmess ); -void UTMESS( const std::string &error, const std::string &message ); +void UTMESS( const std::string &typm, const std::string &idmess ); #endif /* MESSAGES_H_ */ diff --git a/bibcxx/PythonBindings/ContactComputationInterface.cxx b/bibcxx/PythonBindings/ContactComputationInterface.cxx index 443faa490e7..355764a8f0d 100644 --- a/bibcxx/PythonBindings/ContactComputationInterface.cxx +++ b/bibcxx/PythonBindings/ContactComputationInterface.cxx @@ -32,7 +32,7 @@ void exportContactComputationToPython( py::module_ &mod ) { .def( py::init( &initFactoryPtr< ContactComputation, ContactNewPtr > ) ) .def( define_pickling< ContactComputation >() ) .def( "contactData", &ContactComputation::contactData, R"( -Compute contact data (cf. MMCHML) as input to compute contact forces and matrices. +Compute contact data as input to compute contact forces and matrices. Arguments: pairing (ContactPairing): pairing object @@ -43,12 +43,30 @@ Compute contact data (cf. MMCHML) as input to compute contact forces and matrice FieldOnCellsReal: contact data )", py::arg( "pairing" ), py::arg( "material" ), py::arg( "initial_contact" ) ) + .def( "setVerbosity", &ContactComputation::setVerbosity, R"( +Set level of verbosity +0- without +1- normal (default) +2- detailled + +Arguments: + level (int) : level of verbosity +)", + py::arg( "level" ) ) + .def( "getVerbosity", &ContactComputation::getVerbosity, R"( +Get level of verbosity +0- without +1- normal +2- detailled + +Returns: + int: level of verbosity +)" ) .def( "contactCoefficient", &ContactComputation::contactCoefficient, R"( -Compute contact coefficient at the nodes of the slave surface based on values of COEF_CONT +Compute contact coefficients at the nodes of the slave surface based on values of COEF_CONT and COEF_FROT Returns: - FieldOnNodesReal: contact coefficient (= COEF_CONT) - FieldOnNodesReal: friction coefficient (= COEF_FROT) + list[FieldOnNodesReal]: coefficients (COEF_CONT and COEF_FROT) )" ); }; diff --git a/bibcxx/PythonBindings/ContactNewInterface.cxx b/bibcxx/PythonBindings/ContactNewInterface.cxx index b81e5cf8eeb..4526bd29ebf 100644 --- a/bibcxx/PythonBindings/ContactNewInterface.cxx +++ b/bibcxx/PythonBindings/ContactNewInterface.cxx @@ -2,7 +2,7 @@ * @file ContactNewInterface.cxx * @brief Interface python de ContactNew * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -33,25 +33,25 @@ void exportContactNewToPython( py::module_ &mod ) { Return the model used in the contact definition Returns: - Model: model. + Model: model )" ) .def( "getMesh", &ContactNew::getMesh, R"( Return the mesh used in the contact definition Returns: - Mesh: mesh. + BaseMesh: mesh. )" ) .def( "getFiniteElementDescriptor", &ContactNew::getFiniteElementDescriptor, R"( Return the finite element descriptor to define virtual cells for Lagrange multipliers Returns: - FiniteElementDescriptor: fed. + FiniteElementDescriptor: finite element descriptor )" ) .def( "getNumberOfContactZones", &ContactNew::getNumberOfContactZones, R"( Return the number of contact zones used Returns: - inter: number of contact zones. + int: number of contact zones. )" ) .def( "getContactZone", &ContactNew::getContactZone, R"( Return the specified contact zone diff --git a/bibcxx/PythonBindings/ContactPairingInterface.cxx b/bibcxx/PythonBindings/ContactPairingInterface.cxx index 88218c48448..d1535c317a0 100644 --- a/bibcxx/PythonBindings/ContactPairingInterface.cxx +++ b/bibcxx/PythonBindings/ContactPairingInterface.cxx @@ -3,7 +3,7 @@ * @brief Interface python de ContactPairing * @author Nicolas Sellenet * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -24,92 +24,170 @@ #include "PythonBindings/ContactPairingInterface.h" #include "aster_pybind.h" +// aslint: disable=C3006 void exportContactPairingToPython( py::module_ &mod ) { - py::class_< ContactPairing, ContactPairingPtr, DataStructure >( mod, "ContactPairing" ) - .def( py::init( &initFactoryPtr< ContactPairing, std::string, ContactNewPtr > ) ) - .def( py::init( &initFactoryPtr< ContactPairing, ContactNewPtr > ) ) - .def( "getCoordinates", &ContactPairing::getCoordinates, R"( + py::class_< ContactPairing, ContactPairingPtr, DataStructure > class_( mod, "ContactPairing", + R"( +Object to create contact pairing.)" ); + class_.def( py::init( &initFactoryPtr< ContactPairing, std::string, ContactNewPtr > ) ); + class_.def( py::init( &initFactoryPtr< ContactPairing, ContactNewPtr > ) ); + class_.def( "getMesh", &ContactPairing::getMesh, R"( +Mesh + +Returns: + BaseMesh: the mesh +)" ); + class_.def( "getCoordinates", &ContactPairing::getCoordinates, R"( Coordinates of nodes used for pairing (almost always different from the intial mesh). Returns: - MeshCoordinatesFieldPtr: the coordinates field -)" ) - .def( "updateCoordinates", &ContactPairing::updateCoordinates, R"( + MeshCoordinatesField: the coordinates field +)" ); + class_.def( "updateCoordinates", &ContactPairing::updateCoordinates, R"( Update the mesh coordinates given a displacement field + +Arguments: + disp (FieldOnNodes) : field for displacement + )", - ( py::arg( "disp" ) ) ) - .def( "setCoordinates", &ContactPairing::setCoordinates, R"( + ( py::arg( "disp" ) ) ); + class_.def( "setCoordinates", &ContactPairing::setCoordinates, R"( Set the mesh coordinates field Arguments: coordinates (MeshCoordinatesField) : coordinates to use for pairing )", - ( py::arg( "coordinates" ) ) ) - .def( "compute", &ContactPairing::compute, R"( -Compute the pairing quantities associated with the zones + ( py::arg( "coordinates" ) ) ); + class_.def( "compute", py::overload_cast<>( &ContactPairing::compute ), + R"( +Compute the pairing quantities on all zones Returns: bool: True if the pairing quantities are updated appropriately -)" ) - .def( "computeZone", &ContactPairing::computeZone, R"( -Compute the pairing quantities associated with the zone zone_index +)" ); + class_.def( "compute", py::overload_cast< long int & >( &ContactPairing::compute ), + R"( +Compute the pairing quantities on a zone + Arguments: zone_index(int) + Returns: bool: True if the pairing quantities are updated appropriately )", - ( py::arg( "zone_index" ) ) ) - .def( "getListOfPairsOfZone", &ContactPairing::getListOfPairsOfZone, R"( -return list of pairs associated with the zone izone + ( py::arg( "zone_index" ) ) ); + class_.def( "getNumberOfZones", &ContactPairing::getNumberOfZones, R"( +Return the number of zones + +Returns: + int: number of zones +)" ); + class_.def( "getNumberOfPairs", + py::overload_cast<>( &ContactPairing::getNumberOfPairs, py::const_ ), R"( +Return number of pairs on all zones + +Returns: + int: number of pairs +)" ); + class_.def( + "getNumberOfPairs", + py::overload_cast< const long int & >( &ContactPairing::getNumberOfPairs, py::const_ ), + R"( +Return the number of pairs on a zone + Arguments: zone_index(int) Returns: - List[List[int]]: List of pairs + int: number of pairs )", - ( py::arg( "zone_index" ) ) ) - .def( "getNumberOfPairsOfZone", &ContactPairing::getNumberOfPairsOfZone, R"( -return number of pairs associated with the zone zone_index + ( py::arg( "zone_index" ) ) ); + class_.def( + "getListOfPairs", + py::overload_cast< const long int & >( &ContactPairing::getListOfPairs, py::const_ ), + R"( +Get list of contact pairs for a contact zone + Arguments: zone_index(int) + Returns: - int: number of pairs + list[tuple[int, int]]: list of contact pairs )", - ( py::arg( "zone_index" ) ) ) - .def( "getNumberOfPairs", &ContactPairing::getNumberOfPairs, R"( -return the total number of pairs + ( py::arg( "zone_index" ) ) ); + class_.def( "getListOfPairs", + py::overload_cast<>( &ContactPairing::getListOfPairs, py::const_ ), + R"( +Get list of contact pairs on all zones + Returns: - int: Total number of pairs -)" ) - .def( "clearZone", &ContactPairing::clearZone, R"( -clean all the paring quantities of zone zonde_index + list[tuple[int, int]]: list of contact pairs +)" ); + class_.def( "getIntersectionPoints", + py::overload_cast< ASTERINTEGER &, CoordinatesSpace >( + &ContactPairing::getIntersectionPoints, py::const_ ), + R"( +Get the intersection points between master and slave cells + Arguments: - zone_index(int) + zone_index(int) : index of zone + CoordinatesSpace (CoordinatesSpace): space to describe coordinates + Returns: - bool: true if the pairing quantities are cleared + list[pair]: list of pair of coordinates of intersection points )", - ( py::arg( "zone_index" ) ) ) - .def( "getSlaveIntersectionPoints", - py::overload_cast< ASTERINTEGER >( &ContactPairing::getSlaveIntersectionPoints, - py::const_ ), - R"( -Get the intersection points beetween a master and slave cells in the parametric -slave space. The maximum number of points is 8. + ( py::arg( "zone_index" ) ), + py::arg( "CoordinatesSpace" ) = CoordinatesSpace::Global ); + class_.def( "getNumberOfIntersectionPoints", + py::overload_cast< ASTERINTEGER & >( &ContactPairing::getNumberOfIntersectionPoints, + py::const_ ), + R"( +Get list of the number of intersection points beetween a master and slave cells. Arguments: zone_index(int) : index of zone Returns: - list[list]: list of list of intersection points (each intersection is of size 16) + list: list of number of intersection points )", - ( py::arg( "zone_index" ) ) ) - .def( "clear", &ContactPairing::clear, R"( -clean all the paring quantities of all zones + ( py::arg( "zone_index" ) ) ); + class_.def( "clearPairing", py::overload_cast<>( &ContactPairing::clearPairing ), + R"( +Clean pairing for all zones + Returns: bool: true if the pairing quantities are cleared -)" ) - .def( "getFiniteElementDescriptor", &ContactPairing::getFiniteElementDescriptor, R"( +)" ); + class_.def( "clearPairing", + py::overload_cast< const ASTERINTEGER & >( &ContactPairing::clearPairing ), + R"( +Clean pairing for a zone + +Arguments: + zone_index(int) : index of zone + +Returns: + bool: true if the pairing quantities are cleared +)", + ( py::arg( "zone_index" ) ) ); + class_.def( "setVerbosity", &ContactPairing::setVerbosity, R"( +Set level of verbosity + 0 - without + 1 - normal (default) + 2 - detailled (text) + +Arguments: + level (integer): level of verbosity + )", + py::arg( "verbosity" ) ); + class_.def( "getVerbosity", &ContactPairing::getVerbosity, R"( +Get level of verbosity + +Returns: + integer: level of verbosity + )" ); + class_.def( "getFiniteElementDescriptor", &ContactPairing::getFiniteElementDescriptor, R"( Return Finite Element Descriptor for virtual cells from pairing. Returns: diff --git a/bibcxx/PythonBindings/ContactZoneInterface.cxx b/bibcxx/PythonBindings/ContactZoneInterface.cxx index 93a7d6f6776..eeb809a25c3 100644 --- a/bibcxx/PythonBindings/ContactZoneInterface.cxx +++ b/bibcxx/PythonBindings/ContactZoneInterface.cxx @@ -2,7 +2,7 @@ * @file ContactZoneInterface.cxx * @brief Interface python de ContactZone * @section LICENCE - * Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org * * This file is part of Code_Aster. * @@ -26,166 +26,150 @@ void exportContactZoneToPython( py::module_ &mod ) { - py::class_< ContactZone, ContactZone::ContactZonePtr, DataStructure >( mod, "ContactZone" ) + py::class_< ContactZone, ContactZone::ContactZonePtr, DataStructure >( mod, "ContactZone", R"( +Object to define a zone of contact.)" ) .def( py::init( &initFactoryPtr< ContactZone, std::string, ModelPtr > ) ) .def( py::init( &initFactoryPtr< ContactZone, ModelPtr > ) ) .def( "getModel", &ContactZone::getModel, R"( Return the model used in the contact zone definition Returns: - Model: model. - )" ) + Model: model +)" ) .def( "getMesh", &ContactZone::getMesh, R"( Return the mesh used in the contact zone definition Returns: - BaseMesh: mesh. - )" ) + BaseMesh: mesh +)" ) .def( "setVerbosity", &ContactZone::setVerbosity, R"( -Set level of verbosity: - 0- without - 1- normal (default) - 2- detailled +Set level of verbosity +0- without +1- normal (default) +2- detailled Arguments: - integer: level of verbosity - )", + level (int) : level of verbosity +)", py::arg( "level" ) ) .def( "getVerbosity", &ContactZone::getVerbosity, R"( -Get level of verbosity: - 0- without - 1- normal - 2- detailled +Get level of verbosity +0- without +1- normal +2- detailled Returns: - integer: level of verbosity - )" ) - .def_property( "hasFriction", &ContactZone::hasFriction, &ContactZone::enableFriction, R"( -bool: enable or disable the use of friction. + int: level of verbosity +)" ) + .def_property( "hasFriction", &ContactZone::hasFriction, &ContactZone::enableFriction, + R"( +Get status of friction + +Returns: + bool: friction or not )" ) .def_property( "hasSmoothing", &ContactZone::hasSmoothing, &ContactZone::enableSmoothing, R"( -bool: enable or disable the use of smoothing. - )" ) +Smoothing of normals + +Returns: + bool: smoothing or not + )" ) .def( "build", &ContactZone::build, R"( Build and check internal objects - )" ) + +Returns: + bool: success or failure + )" ) .def( "setContactParameter", &ContactZone::setContactParameter, R"( Set contact parameters defining method, coefficient... Arguments: - ContactParameter: contact parameters - )", - py::arg( "contact" ) ) + contParam (ContactParameter) : contact parameters +)", + py::arg( "contParam" ) ) .def( "getContactParameter", &ContactZone::getContactParameter, R"( Get contact parameters defining method, coefficient... Returns: ContactParameter: contact parameters - )" ) +)" ) .def( "setFrictionParameter", &ContactZone::setFrictionParameter, R"( Set friction parameters defining method, coefficient... Arguments: - FrictionParameter: friction parameters - )", - py::arg( "friction" ) ) + fricParam (FrictionParameter) : friction parameters +)", + py::arg( "fricParam" ) ) .def( "getFrictionParameter", &ContactZone::getFrictionParameter, R"( Get friction parameters defining method, coefficient... Returns: FrictionParameter: friction parameters - )" ) +)" ) .def( "setPairingParameter", &ContactZone::setPairingParameter, R"( Set pairing parameters defining algorithm, distance... Arguments: - PairingParameter: pairing parameters - )", - py::arg( "pairing" ) ) + pairParam (PairingParameter) : pairing parameters +)", + py::arg( "pairParam" ) ) .def( "getPairingParameter", &ContactZone::getPairingParameter, R"( Get pairing parameters defining algorithm, distance... Returns: PairingParameter: pairing parameters - )" ) +)" ) .def( "getSlaveNodes", &ContactZone::getSlaveNodes, R"( Get slave's nodes index Returns: list[int]: slave's nodes index - )" ) +)" ) .def( "getSlaveCells", &ContactZone::getSlaveCells, R"( Get slave's cells index Returns: list[int]: slave's cells index - )" ) +)" ) .def( "setSlaveGroupOfCells", &ContactZone::setSlaveGroupOfCells, R"( Set slave's name of group of cells Arguments: - str: slave's name - )", + slave_name (str) : name of group for slave cells +)", py::arg( "slave_name" ) ) .def( "setMasterGroupOfCells", &ContactZone::setMasterGroupOfCells, R"( Set master's name of group of cells Arguments: - str: master's name - )", + master_name (str) : name of group for master cells +)", py::arg( "master_name" ) ) - .def( "setExcludedSlaveGroupOfNodes", &ContactZone::setExcludedSlaveGroupOfNodes, R"( + .def( "setExcludedSlaveGroupOfNodes", &ContactZone::setExcludedSlaveGroupOfNodes, + R"( Set excluded groups of nodes on slave side Arguments: - str: excluded groups' names - )", - py::arg( "groups" ) ) + nodeGroupsName (str) : excluded groups' names + )", + py::arg( "nodeGroupsName" ) ) .def( "setExcludedSlaveGroupOfCells", &ContactZone::setExcludedSlaveGroupOfCells, R"( Set excluded groups of cells on slave side Arguments: - str: excluded groups' names - )", - py::arg( "groups" ) ) - .def( "getExcludedSlaveCells", &ContactZone::getExcludedSlaveCells, R"( -Get excluded groups of cells on slave side + cellGroupsName (str) : excluded groups' names + )", + py::arg( "cellGroupsName" ) ) + .def( "getMeshPairing", &ContactZone::getMeshPairing, R"( +Get pairing of surface meshes Returns: - str: excluded groups' names + MeshPairing: mesh pairing )" ) .def_property( "checkNormals", py::overload_cast<>( &ContactZone::checkNormals, py::const_ ), py::overload_cast< const bool & >( &ContactZone::checkNormals ), R"( - bool: Attribute that holds the checking of outwards normals. - )" ) - .def( "getMasterCellsFromNode", &ContactZone::getMasterCellsFromNode, R"( -Get the master cells associtaed with a node number - -Arguments: - int: node number - )", - py::arg( "node_number" ) ) - .def( "getSlaveCellsFromNode", &ContactZone::getSlaveCellsFromNode, R"( -Get the slave cells associtaed with a node number - -Arguments: - int: node number - )", - py::arg( "node_number" ) ) - .def( "getMasterCellNeighbors", &ContactZone::getMasterCellNeighbors, R"( -Get the master cells in the neighbor of a given master cell number - -Arguments: - int: master cell number - )", - py::arg( "cell_number" ) ) - .def( "getSlaveCellNeighbors", &ContactZone::getSlaveCellNeighbors, R"( -Get the slave cells in the neighbor of a given slave cell number - -Arguments: - int: slave cell number - )", - py::arg( "cell_number" ) ); +bool: attribute that holds the checking of outwards normals. + )" ); }; diff --git a/bibcxx/PythonBindings/LibAster.cxx b/bibcxx/PythonBindings/LibAster.cxx index 83dabfd1201..9c8aad02121 100644 --- a/bibcxx/PythonBindings/LibAster.cxx +++ b/bibcxx/PythonBindings/LibAster.cxx @@ -123,6 +123,7 @@ #include "PythonBindings/MeshCoordinatesFieldInterface.h" #include "PythonBindings/MeshEntitiesInterface.h" #include "PythonBindings/MeshInterface.h" +#include "PythonBindings/MeshPairingInterface.h" #include "PythonBindings/MeshesMappingInterface.h" #include "PythonBindings/ModalBasisInterface.h" #include "PythonBindings/ModeResultInterface.h" @@ -234,6 +235,7 @@ PYBIND11_MODULE( libaster, mod ) { exportContactParameterToPython( mod ); exportContactNewToPython( mod ); exportContactZoneToPython( mod ); + exportMeshPairingToPython( mod ); exportContactPairingToPython( mod ); exportContactComputationToPython( mod ); exportBaseAssemblyMatrixToPython( mod ); diff --git a/bibcxx/PythonBindings/MeshPairingInterface.cxx b/bibcxx/PythonBindings/MeshPairingInterface.cxx new file mode 100644 index 00000000000..0338467f4d7 --- /dev/null +++ b/bibcxx/PythonBindings/MeshPairingInterface.cxx @@ -0,0 +1,250 @@ +/** + * @file ContactZoneInterface.cxx + * @brief Interface python de ContactZone + * @section LICENCE + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org + * + * This file is part of Code_Aster. + * + * Code_Aster is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Code_Aster is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Code_Aster. If not, see . + */ + +#include "PythonBindings/MeshPairingInterface.h" + +#include "aster_pybind.h" +// aslint: disable=C3006 + +void exportMeshPairingToPython( py::module_ &mod ) { + + py::class_< MeshPairing, MeshPairingPtr, DataStructure > class_( mod, "MeshPairing", R"( +Object to create a pairing operator between two meshed surfaces.)" ); + py::enum_< CoordinatesSpace >( mod, "CoordinatesSpace", R"( +Type of coordinates: Slave or Global.)" ) + .value( "Slave", CoordinatesSpace::Slave ) + .value( "Global", CoordinatesSpace::Global ) + .export_values(); + class_.def( py::init( &initFactoryPtr< MeshPairing, std::string, BaseMeshPtr > ) ); + class_.def( py::init( &initFactoryPtr< MeshPairing, BaseMeshPtr > ) ); + class_.def( "getNumberOfPairs", &MeshPairing::getNumberOfPairs, R"( +Get number of pairs + +Returns: + integer: number of pairs + )" ); + class_.def( "getListOfPairs", &MeshPairing::getListOfPairs, R"( +Get pairs + +Returns: + list: pairs (slave-master) + )" ); + class_.def( "getNumberOfIntersectionPoints", + py::overload_cast< const ASTERINTEGER & >( + &MeshPairing::getNumberOfIntersectionPoints, py::const_ ), + R"( +Get number of intersection points + +Arguments: + indexPair (integer): index of pair + +Returns: + integer: number of intersection points + )", + py::arg( "indexPair" ) ); + class_.def( + "getIntersectionArea", + py::overload_cast< const ASTERINTEGER & >( &MeshPairing::getIntersectionArea, py::const_ ), + R"( +Compute intersection of area + +Arguments: + indexPair (integer): index of pair + +Returns: + double: area of intersection + )", + py::arg( "indexPair" ) ); + class_.def( "getNumberOfIntersectionPoints", + py::overload_cast<>( &MeshPairing::getNumberOfIntersectionPoints, py::const_ ), + R"( + Get number of intersection points of all pairs + + Returns: + list: number of intersection points + )" ); + class_.def( "setPair", &MeshPairing::setPair, R"( + Set pair of meshed surfaces + + Arguments: + groupNameSlav (str): slave's name + groupNameMast (str): master's name + )", + py::arg( "groupNameSlav" ), py::arg( "groupNameMast" ) ); + class_.def( "compute", &MeshPairing::compute, R"( +Compute pairing + +Arguments: + dist_pairing (real): tolerance from DIST_RATIO (projection outside cell) + pair_tole (real): tolerance for pairing + )", + py::arg( "dist_pairing" ) = -1.0, py::arg( "pair_tole" ) = 1.E-8 ); + class_.def( "updateCoordinates", &MeshPairing::updateCoordinates, R"( +Update coordinates of nodes + +Arguments: + disp (FieldOnNodesReal): nodal field of displacement + )", + py::arg( "disp" ) ); + class_.def( "setVerbosity", &MeshPairing::setVerbosity, R"( +Set level of verbosity + 0 - without + 1 - normal (default) + 2 - detailled (text) + +Arguments: + level (integer): level of verbosity + )", + py::arg( "level" ) ); + class_.def( "getIntersectionPoints", &MeshPairing::getIntersectionPoints, R"( +Get coordinates of intersection points for a given pair + +Arguments: + indexPair (integer): index of pair + CoordinatesSpace (CoordinatesSpace): space to describe coordinates + +Returns: + list[list]: coordinates in given space + )", + py::arg( "indexPair" ), py::arg( "CoordinatesSpace" ) = CoordinatesSpace::Global ); + class_.def( "getIntersectionArea", &MeshPairing::getIntersectionArea, R"( +Get area of intersection for a given pair + +Arguments: + indexPair (integer): index of pair + +Returns: + real: area of intersection + )", + py::arg( "indexPair" ) ); + + // class_.def( "getIntersectionPoints", &MeshPairing::getIntersectionPoints, R"( + // Get coordinates of intersection points for a given pair in global space + + // Arguments: + // indexPair (integer): index of pair + + // Returns: + // list: intersection points + // )", + // py::arg( "indexPair" ) ); + class_.def( "getQuadraturePoints", &MeshPairing::getQuadraturePoints, R"( +Get coordinates of quadrature points for a given pair in global space + +Arguments: + indexPair (integer): index of pair + +Returns: + list: quadrature points + )", + py::arg( "indexPair" ) ); + class_.def( "getVerbosity", &MeshPairing::getVerbosity, R"( +Get level of verbosity + +Returns: + integer: level of verbosity + )" ); + class_.def( "getMesh", &MeshPairing::getMesh, R"( +Return the mesh + +Returns: + Mesh: mesh. + )" ); + class_.def( "getMasterCellsFromNode", &MeshPairing::getMasterCellsFromNode, R"( +Get the master cells associated with a node number + +Arguments: + int: node number + +Returns: + list: master cells associated + )", + py::arg( "node_number" ) ); + class_.def( "getSlaveCellsFromNode", &MeshPairing::getSlaveCellsFromNode, R"( +Get the slave cells associated with a node number + +Arguments: + int: node number + +Returns: + list: slave cells associated + )", + py::arg( "node_number" ) ); + class_.def( "getMasterCellNeighbors", &MeshPairing::getMasterCellNeighbors, R"( +Get the master cells in the neighbor of a given master cell number + +Arguments: + int: master cell number + +Returns: + list: master neighbors cells + )", + py::arg( "cell_number" ) ); + class_.def( "setExcludedSlaveGroupOfNodes", &MeshPairing::setExcludedSlaveGroupOfNodes, + R"( +Set excluded groups of nodes on slave side + +Arguments: + str: excluded groups' names + )", + py::arg( "groups" ) ); + class_.def( "setExcludedSlaveGroupOfCells", &MeshPairing::setExcludedSlaveGroupOfCells, R"( +Set excluded groups of cells on slave side + +Arguments: + str: excluded groups' names + )", + py::arg( "groups" ) ); + class_.def( "getSlaveCellNeighbors", &MeshPairing::getSlaveCellNeighbors, R"( +Get the slave cells in the neighbor of a given slave cell number + +Arguments: + int: slave cell number + +Returns: + list: slave neighbors cells + )", + py::arg( "cell_number" ) ); + class_.def( "checkNormals", &MeshPairing::checkNormals, R"( +Check orientation of normals + +Arguments: + ModelPtr: a pointer to the model + +Returns: + nothing + )", + py::arg( "model" ) ); + class_.def( "setMethod", &MeshPairing::setMethod, R"( +Set method of pairing + +Arguments: + method (PairingMethod): method ("OLD", "Fast", "Robust) + )", + py::arg( "method" ) ); + py::enum_< PairingMethod >( mod, "PairingMethod", R"( +Type of pairing: Fast, BrutForce and Legacy.)" ) + .value( "Fast", PairingMethod::Fast ) + .value( "Legacy", PairingMethod::Legacy ) + .value( "BrutForce", PairingMethod::BrutForce ) + .export_values(); +}; diff --git a/bibcxx/PythonBindings/MeshPairingInterface.h b/bibcxx/PythonBindings/MeshPairingInterface.h new file mode 100644 index 00000000000..0a0d027accd --- /dev/null +++ b/bibcxx/PythonBindings/MeshPairingInterface.h @@ -0,0 +1,34 @@ +#ifndef PAIRGEOMINTERFACE_H_ +#define PAIRGEOMINTERFACE_H_ + +/** + * @file PairGeomInterface.h + * @brief Header of class PairGeomInterface + * @section LICENCE + * Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org + * + * This file is part of Code_Aster. + * + * Code_Aster is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Code_Aster is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Code_Aster. If not, see . + */ + +#include "astercxx.h" + +#include "aster_pybind.h" + +#include "Meshes/MeshPairing.h" + +void exportMeshPairingToPython( py::module_ &mod ); + +#endif diff --git a/bibcxx/PythonBindings/ResultInterface.cxx b/bibcxx/PythonBindings/ResultInterface.cxx index a8a0b561bdc..45724dbf705 100644 --- a/bibcxx/PythonBindings/ResultInterface.cxx +++ b/bibcxx/PythonBindings/ResultInterface.cxx @@ -100,13 +100,14 @@ Returns py::arg( "index" ) ) .def( "addEquationNumbering", &Result::addEquationNumbering ) .def( "setMaterialField", - py::overload_cast< const MaterialFieldPtr & >( &Result::setMaterialField ), R"( + py::overload_cast< const MaterialFieldPtr &, bool >( &Result::setMaterialField ), R"( Set material field on all indexs Arguments: mater (MaterialField): material field to set. + exists_ok (bool): If *True*, pass silently if a Model is already defined. *False* by default. )", - py::arg( "mater" ) ) + py::arg( "mater" ), py::arg( "exists_ok" ) = false ) .def( "setMaterialField", py::overload_cast< const MaterialFieldPtr &, ASTERINTEGER >( &Result::setMaterialField ), @@ -126,13 +127,14 @@ Set list of loads on the specified index index (int): index to set )", py::arg( "load" ), py::arg( "index" ) ) - .def( "setModel", py::overload_cast< const ModelPtr & >( &Result::setModel ), R"( + .def( "setModel", py::overload_cast< const ModelPtr &, bool >( &Result::setModel ), R"( Set model on all indexs Arguments: - model (Model): model to set. + model (Model): Model to be assigned. + exists_ok (bool): If *True*, pass silently if a Model is already defined. *False* by default. )", - py::arg( "model" ) ) + py::arg( "model" ), py::arg( "exists_ok" ) = false ) .def( "setModel", py::overload_cast< const ModelPtr &, ASTERINTEGER >( &Result::setModel ), R"( Set model on the specified index @@ -143,15 +145,16 @@ Set model on the specified index )", py::arg( "model" ), py::arg( "index" ) ) .def( "setElementaryCharacteristics", - py::overload_cast< const ElementaryCharacteristicsPtr & >( + py::overload_cast< const ElementaryCharacteristicsPtr &, bool >( &Result::setElementaryCharacteristics ), R"( Set elementary characterictics on all indexs Arguments: cara_elem (ElementaryCharacteristics): elementary characterictics to set. + exists_ok (bool): If *True*, pass silently if a Model is already defined. *False* by default. )", - py::arg( "cara_elem" ) ) + py::arg( "cara_elem" ), py::arg( "exists_ok" ) = false ) .def( "setElementaryCharacteristics", py::overload_cast< const ElementaryCharacteristicsPtr &, ASTERINTEGER >( &Result::setElementaryCharacteristics ), diff --git a/bibcxx/Results/Result.cxx b/bibcxx/Results/Result.cxx index 7ec964efe2c..81dd2c54274 100644 --- a/bibcxx/Results/Result.cxx +++ b/bibcxx/Results/Result.cxx @@ -138,9 +138,15 @@ void Result::setMesh( const BaseMeshPtr &mesh ) { }; void Result::setElementaryCharacteristics( const ElementaryCharacteristicsPtr &cara, - ASTERINTEGER storageIndex ) { + ASTERINTEGER storageIndex, bool exists_ok ) { if ( !cara ) raiseAsterError( "ValueError: ElementaryCharacteristics is empty" ); + if ( _mapElemCara.count( storageIndex ) != 0 ) { + if ( exists_ok || _mapElemCara[storageIndex] == cara ) + return; + raiseAsterError( "ValueError: ElementaryCharacteristics already assigned at index " + + std::to_string( storageIndex ) ); + } _mapElemCara[storageIndex] = cara; std::string type( "CARAELEM" ); @@ -152,6 +158,12 @@ void Result::setElementaryCharacteristics( const ElementaryCharacteristicsPtr &c void Result::setListOfLoads( const ListOfLoadsPtr &load, ASTERINTEGER storageIndex ) { if ( !load ) raiseAsterError( "ValueError: Load is empty" ); + if ( _mapLoads.count( storageIndex ) != 0 ) { + if ( _mapLoads[storageIndex] == load ) + return; + raiseAsterError( "ValueError: Load already assigned at index " + + std::to_string( storageIndex ) ); + } _mapLoads[storageIndex] = load; std::string type( "EXCIT" ); @@ -159,9 +171,16 @@ void Result::setListOfLoads( const ListOfLoadsPtr &load, ASTERINTEGER storageInd CALLO_RSADPA_ZK24_WRAP( getName(), &storageIndex, load->getName(), type, cel ); }; -void Result::setMaterialField( const MaterialFieldPtr &mater, ASTERINTEGER storageIndex ) { +void Result::setMaterialField( const MaterialFieldPtr &mater, ASTERINTEGER storageIndex, + bool exists_ok ) { if ( !mater ) raiseAsterError( "ValueError: MaterialField is empty" ); + if ( _mapMaterial.count( storageIndex ) != 0 ) { + if ( exists_ok || _mapMaterial[storageIndex] == mater ) + return; + raiseAsterError( "ValueError: MaterialField already assigned at index " + + std::to_string( storageIndex ) ); + } _mapMaterial[storageIndex] = mater; std::string type( "CHAMPMAT" ); @@ -170,9 +189,15 @@ void Result::setMaterialField( const MaterialFieldPtr &mater, ASTERINTEGER stora setMesh( mater->getMesh() ); }; -void Result::setModel( const ModelPtr &model, ASTERINTEGER storageIndex ) { +void Result::setModel( const ModelPtr &model, ASTERINTEGER storageIndex, bool exists_ok ) { if ( !model ) raiseAsterError( "ValueError: Model is empty" ); + if ( _mapModel.count( storageIndex ) != 0 ) { + if ( exists_ok || _mapModel[storageIndex] == model ) + return; + raiseAsterError( "ValueError: Model already assigned at index " + + std::to_string( storageIndex ) ); + } _mapModel[storageIndex] = model; std::string type( "MODELE" ); @@ -280,24 +305,25 @@ void Result::_listOfParameters() { } } -void Result::setElementaryCharacteristics( const ElementaryCharacteristicsPtr &cara ) { +void Result::setElementaryCharacteristics( const ElementaryCharacteristicsPtr &cara, + bool exists_ok ) { auto allStorageIndexes = getIndexes(); for ( auto &storageIndex : allStorageIndexes ) { - setElementaryCharacteristics( cara, storageIndex ); + setElementaryCharacteristics( cara, storageIndex, exists_ok ); } }; -void Result::setMaterialField( const MaterialFieldPtr &mater ) { +void Result::setMaterialField( const MaterialFieldPtr &mater, bool exists_ok ) { auto allStorageIndexes = getIndexes(); for ( auto &storageIndex : allStorageIndexes ) { - setMaterialField( mater, storageIndex ); + setMaterialField( mater, storageIndex, exists_ok ); } }; -void Result::setModel( const ModelPtr &model ) { +void Result::setModel( const ModelPtr &model, bool exists_ok ) { auto allStorageIndexes = getIndexes(); for ( auto &storageIndex : allStorageIndexes ) { - setModel( model, storageIndex ); + setModel( model, storageIndex, exists_ok ); } }; @@ -307,7 +333,9 @@ std::vector< ElementaryCharacteristicsPtr > Result::getAllElementaryCharacterist ElementaryCharacteristicsPtr Result::getElementaryCharacteristics() const { const auto cara = getAllElementaryCharacteristics(); - AS_ASSERT( cara.size() <= 1 ); + if ( cara.size() > 1 ) { + UTMESS( "F", "RESULT2_8" ); + } if ( cara.size() == 1 ) return cara[0]; @@ -342,7 +370,9 @@ std::vector< MaterialFieldPtr > Result::getMaterialFields() const { MaterialFieldPtr Result::getMaterialField() const { const auto mate = getMaterialFields(); - AS_ASSERT( mate.size() <= 1 ); + if ( mate.size() > 1 ) { + UTMESS( "F", "RESULT2_7" ); + }; if ( mate.size() == 1 ) return mate[0]; @@ -387,7 +417,7 @@ std::vector< ModelPtr > Result::getModels() const { return unique( _mapModel ); ModelPtr Result::getModel() const { if ( hasMultipleModel() ) { - raiseAsterError( "Error: multiple models" ); + UTMESS( "F", "RESULT2_6" ); } const auto models = getModels(); diff --git a/bibcxx/Results/Result.h b/bibcxx/Results/Result.h index 0037722a599..346d2decef6 100644 --- a/bibcxx/Results/Result.h +++ b/bibcxx/Results/Result.h @@ -214,7 +214,11 @@ class Result : public DataStructure, public ListOfTables { * @param storageIndex */ void setElementaryCharacteristics( const ElementaryCharacteristicsPtr &elemCara, - ASTERINTEGER storageIndex ); + ASTERINTEGER storageIndex, bool exists_ok ); + void setElementaryCharacteristics( const ElementaryCharacteristicsPtr &elemCara, + ASTERINTEGER storageIndex ) { + return setElementaryCharacteristics( elemCara, storageIndex, false ); + }; /** * @brief Add a existing EquationNumbering in _fieldBuilder @@ -233,13 +237,20 @@ class Result : public DataStructure, public ListOfTables { * @brief Add material definition * @param storageIndex */ - void setMaterialField( const MaterialFieldPtr &mate, ASTERINTEGER storageIndex ); + void setMaterialField( const MaterialFieldPtr &mate, ASTERINTEGER storageIndex, + bool exists_ok ); + void setMaterialField( const MaterialFieldPtr &mate, ASTERINTEGER storageIndex ) { + return setMaterialField( mate, storageIndex, false ); + } /** * @brief Add model * @param storageIndex */ - void setModel( const ModelPtr &model, ASTERINTEGER storageIndex ); + void setModel( const ModelPtr &model, ASTERINTEGER storageIndex, bool exists_ok ); + void setModel( const ModelPtr &model, ASTERINTEGER storageIndex ) { + return setModel( model, storageIndex, false ); + }; /** * @brief Set model @@ -282,19 +293,20 @@ class Result : public DataStructure, public ListOfTables { * @brief Append a elementary characteristics on all index of Result * @param ElementaryCharacteristicsPtr */ - void setElementaryCharacteristics( const ElementaryCharacteristicsPtr &cara ); + void setElementaryCharacteristics( const ElementaryCharacteristicsPtr &cara, + bool exists_ok = false ); /** * @brief Append a material on all index of Result * @param MaterialFieldPtr */ - void setMaterialField( const MaterialFieldPtr &mate ); + void setMaterialField( const MaterialFieldPtr &mate, bool exists_ok = false ); /** * @brief Append a model on all index of Result * @param ModelPtr */ - void setModel( const ModelPtr &model ); + void setModel( const ModelPtr &model, bool exists_ok = false ); /** * @brief Get list of loads at index diff --git a/bibcxx/include/astercxx.h b/bibcxx/include/astercxx.h index 6da21f26011..902b78c3ed4 100644 --- a/bibcxx/include/astercxx.h +++ b/bibcxx/include/astercxx.h @@ -50,6 +50,7 @@ using VectorComplex = std::vector< ASTERCOMPLEX >; using VectorString = std::vector< std::string >; using VectorOfVectorsLong = std::vector< VectorLong >; +using VectorOfVectorsReal = std::vector< VectorReal >; using SetInt = std::set< ASTERINTEGER4 >; using SetLong = std::set< ASTERINTEGER >; diff --git a/bibfor/cont_elem/getInterCont.F90 b/bibfor/cont_elem/getInterCont.F90 new file mode 100644 index 00000000000..00209861110 --- /dev/null +++ b/bibfor/cont_elem/getInterCont.F90 @@ -0,0 +1,58 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +subroutine getInterCont(nbPoinInte, poinInteSlav) +! + implicit none +! +#include "asterf_types.h" +#include "asterfort/assert.h" +#include "asterfort/jevech.h" +#include "asterfort/mesh_pairing_type.h" +#include "jeveux.h" +! + integer, intent(out) :: nbPoinInte + real(kind=8), intent(out) :: poinInteSlav(2, MAX_NB_INTE) +! +! -------------------------------------------------------------------------------------------------- +! +! Contact - Quadrature +! +! Get intersection points +! +! -------------------------------------------------------------------------------------------------- +! +! Out nbPoinInte : number of intersection points +! Out poinInteSlav : coordinates of intersection points (in slave parametric space) +! +! -------------------------------------------------------------------------------------------------- +! + integer :: jcont, iPoinInte +! +! -------------------------------------------------------------------------------------------------- +! + call jevech('PCONFR', 'L', jcont) + nbPoinInte = int(zr(jcont-1+1)) + ASSERT(nbPoinInte .le. MAX_NB_INTE) + poinInteSlav = 0.d0 + do iPoinInte = 1, nbPoinInte + poinInteSlav(1, iPoinInte) = zr(jcont-1+1+iPoinInte) + poinInteSlav(2, iPoinInte) = zr(jcont-1+9+iPoinInte) + end do +! +end subroutine diff --git a/bibfor/cont_elem/getQuadCont.F90 b/bibfor/cont_elem/getQuadCont.F90 index f8dd4e6751e..4dda7f65765 100644 --- a/bibfor/cont_elem/getQuadCont.F90 +++ b/bibfor/cont_elem/getQuadCont.F90 @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -16,29 +16,35 @@ ! along with code_aster. If not, see . ! -------------------------------------------------------------------- ! -subroutine getQuadCont(elem_dime, l_axis, nb_node_slav, & - elem_slav_code, elem_slav_coor, & - elem_mast_code, & - nb_qp, coor_qp, weight_qp) +subroutine getQuadCont(elem_dime, & + elem_slav_code, elem_mast_code, & + nbPoinInte, poinInteSlav, & + nb_qp, coor_qp, & + l_axis_, nb_node_slav_, elem_slav_coor_, & + weight_qp_) ! implicit none ! #include "asterf_types.h" #include "asterfort/assert.h" -#include "asterfort/lcptga.h" #include "asterfort/latrco.h" -#include "asterfort/jevech.h" +#include "asterfort/lcptga.h" +#include "asterfort/mesh_pairing_type.h" +#include "asterfort/mmdonf.h" #include "asterfort/mmmjac.h" #include "asterfort/mmnonf.h" -#include "asterfort/mmdonf.h" #include "jeveux.h" ! - integer, intent(in) :: elem_dime, nb_node_slav - aster_logical, intent(in) :: l_axis + integer, intent(in) :: elem_dime character(len=8), intent(in) :: elem_slav_code, elem_mast_code - real(kind=8), intent(in) :: elem_slav_coor(3, 9) - real(kind=8), intent(out) :: coor_qp(2, 48), weight_qp(48) + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInteSlav(2, MAX_NB_INTE) + real(kind=8), intent(out) :: coor_qp(2, MAX_NB_QUAD) integer, intent(out) :: nb_qp + integer, optional, intent(in) :: nb_node_slav_ + real(kind=8), optional, intent(in) :: elem_slav_coor_(3, 9) + aster_logical, optional, intent(in) :: l_axis_ + real(kind=8), optional, intent(out) :: weight_qp_(MAX_NB_QUAD) ! ! -------------------------------------------------------------------------------------------------- ! @@ -48,20 +54,22 @@ subroutine getQuadCont(elem_dime, l_axis, nb_node_slav, & ! ! -------------------------------------------------------------------------------------------------- ! -! In elem_dime : dimension of elements +! In modelDime : dimension of model ! In elem_slav_code : code element for slave side from contact element ! In elem_slav_coor : coordinates from slave side of contact element -! Out nb_qp : number of quadrature points -! Out coor_qp : coordinates of quadrature points (parametric slave space) -! Out weight_qp : weight of quadrature points +! In nbPoinInte : number of intersection points +! In poinInteSlav : coordinates of intersection points (in slave parametric space) +! Out nb_qp : number of quadrature points +! Out coor_qp : coordinates of quadrature points (parametric slave space) +! Out weight_qp : weight of quadrature points ! ! -------------------------------------------------------------------------------------------------- ! aster_logical :: l_slav_line, l_mast_line - integer :: i_node, i_dime, i_tria, i_gauss, jcont - integer :: nb_tria, nb_poin_inte, nb_gauss - real(kind=8) :: tria_coot_sl(2, 3), tria_coor_sl(16), poin_inte_sl(16) - real(kind=8) :: gauss_weight_sl(12), gauss_coor_sl(2, 12) + integer :: iTria, iGauss + integer :: nbTria, nbGauss + real(kind=8) :: triaCoorSlav(2, 3) + real(kind=8) :: gausWeightSlav(12), gausCoorSlav(2, 12) real(kind=8) :: shape_func(9), shape_dfunc(2, 9), jacobian_sl character(len=8) :: elga_fami ! @@ -69,25 +77,19 @@ subroutine getQuadCont(elem_dime, l_axis, nb_node_slav, & ! nb_qp = 0 coor_qp = 0 - weight_qp = 0 -! -! - Get intersection point -! - call jevech('PCONFR', 'L', jcont) - nb_poin_inte = int(zr(jcont-1+1)) - poin_inte_sl = zr(jcont-1+2:jcont-1+17) -! + if (present(weight_qp_)) then + weight_qp_ = 0.d0 + end if l_slav_line = elem_slav_code == "SE2" .or. elem_slav_code == "TR3" .or. elem_slav_code == "QU4" l_mast_line = elem_mast_code == "SE2" .or. elem_mast_code == "TR3" .or. elem_mast_code == "QU4" -! + ! - Triangulation of convex polygon defined by intersection points if (elem_dime .eq. 3) then - if (nb_poin_inte == 3) then - nb_tria = 1 + if (nbPoinInte == 3) then + nbTria = 1 else - nb_tria = nb_poin_inte + nbTria = nbPoinInte end if -! if (l_slav_line .and. l_mast_line) then ! order 3 by triangle elga_fami = 'FPG4' @@ -96,7 +98,7 @@ subroutine getQuadCont(elem_dime, l_axis, nb_node_slav, & elga_fami = 'FPG7' end if elseif (elem_dime .eq. 2) then - nb_tria = 1 + nbTria = 1 if (l_slav_line .and. l_mast_line) then ! order 5 elga_fami = 'FPG3' @@ -107,56 +109,47 @@ subroutine getQuadCont(elem_dime, l_axis, nb_node_slav, & else ASSERT(ASTER_FALSE) end if + ! - Loop on triangles - do i_tria = 1, nb_tria + do iTria = 1, nbTria ! ----- Coordinates of current triangle (slave) - tria_coor_sl(:) = 0.d0 + triaCoorSlav = 0.d0 if (elem_dime .eq. 3) then - call latrco(i_tria, nb_poin_inte, poin_inte_sl, tria_coor_sl) + call latrco(iTria, nbPoinInte, poinInteSlav, triaCoorSlav) elseif (elem_dime .eq. 2) then - tria_coor_sl(1:16) = poin_inte_sl(1:16) - end if -! ----- Change shape of vector (slave) - tria_coot_sl(1:2, 1:3) = 0.d0 - if (elem_dime .eq. 3) then - do i_node = 1, 3 - do i_dime = 1, (elem_dime-1) - tria_coot_sl(i_dime, i_node) = & - tria_coor_sl((i_node-1)*(elem_dime-1)+i_dime) - end do - end do - else - tria_coot_sl(1, 1) = tria_coor_sl(1) - tria_coot_sl(2, 1) = 0.d0 - tria_coot_sl(1, 2) = tria_coor_sl(2) - tria_coot_sl(2, 2) = 0.d0 + ASSERT(nbPoinInte .eq. 2) + triaCoorSlav(1:2, 1:2) = poinInteSlav(1:2, 1:2) end if + ! ----- Get integration points for slave element - call lcptga(elem_dime, tria_coot_sl, elga_fami, & - nb_gauss, gauss_coor_sl, gauss_weight_sl) + call lcptga(elem_dime, triaCoorSlav, elga_fami, & + nbGauss, gausCoorSlav, gausWeightSlav) + ! ----- Loop on integration points - do i_gauss = 1, nb_gauss + do iGauss = 1, nbGauss nb_qp = nb_qp+1 - ASSERT(nb_qp <= 48) + ASSERT(nb_qp <= MAX_NB_QUAD) + ! --------- Get current integration point (slave) - do i_dime = 1, elem_dime-1 - coor_qp(i_dime, nb_qp) = gauss_coor_sl(i_dime, i_gauss) - end do -! -! - Get shape functions and first derivative only (for perf) -! - call mmnonf(elem_dime, nb_node_slav, elem_slav_code, & - gauss_coor_sl(1, i_gauss), gauss_coor_sl(2, i_gauss), & - shape_func) - call mmdonf(elem_dime, nb_node_slav, elem_slav_code, & - gauss_coor_sl(1, i_gauss), gauss_coor_sl(2, i_gauss), & - shape_dfunc) -! --------- Compute jacobian - call mmmjac(l_axis, nb_node_slav, elem_dime, & - elem_slav_code, elem_slav_coor, & - shape_func, shape_dfunc, jacobian_sl) + coor_qp(1:2, nb_qp) = gausCoorSlav(1:2, iGauss) + ! WRITE (6, *) "coor_qp: ", coor_qp(:, nb_qp) + + if (present(weight_qp_)) then +! ------------- Get shape functions and first derivative only (for perf) + call mmnonf(elem_dime, nb_node_slav_, elem_slav_code, & + gausCoorSlav(1, iGauss), gausCoorSlav(2, iGauss), & + shape_func) + call mmdonf(elem_dime, nb_node_slav_, elem_slav_code, & + gausCoorSlav(1, iGauss), gausCoorSlav(2, iGauss), & + shape_dfunc) + +! ------------- Compute jacobian + call mmmjac(l_axis_, nb_node_slav_, elem_dime, & + elem_slav_code, elem_slav_coor_, & + shape_func, shape_dfunc, jacobian_sl) - weight_qp(nb_qp) = jacobian_sl*gauss_weight_sl(i_gauss) + weight_qp_(nb_qp) = jacobian_sl*gausWeightSlav(iGauss) + end if end do end do ! diff --git a/bibfor/cont_elem/laMatr.F90 b/bibfor/cont_elem/laMatr.F90 index 23ca4a88bd9..2a6975d735b 100644 --- a/bibfor/cont_elem/laMatr.F90 +++ b/bibfor/cont_elem/laMatr.F90 @@ -18,13 +18,14 @@ ! subroutine laMatr(parameters, geom, matr_cont, matr_fric) ! - use contact_type use contact_module + use contact_type ! implicit none ! #include "asterf_types.h" #include "asterfort/assert.h" +#include "asterfort/getInterCont.h" #include "asterfort/getQuadCont.h" #include "asterfort/laElemCont.h" #include "blas/dgemm.h" @@ -54,12 +55,12 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) ! In elem_slav_code : code element for slave side from contact element ! In nb_node_mast : number of nodes of for master side from contact element ! In elem_mast_code : code element for master side from contact element -! IO matr_cont : matrix (only upper part) +! IO matr_cont : matrix (only upper part) ! ! -------------------------------------------------------------------------------------------------- ! aster_logical :: l_cont_qp, l_fric_qp - integer :: i_qp, nb_qp + integer :: i_qp, nb_qp real(kind=8) :: weight_sl_qp, coeff, hF real(kind=8) :: coor_qp_sl(2) real(kind=8) :: coor_qp(2, 48), weight_qp(48) @@ -67,6 +68,8 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) real(kind=8) :: lagr_f(2), vT(2), gamma_f, projBsVal(2) real(kind=8) :: dGap(MAX_LAGA_DOFS), mu_c(MAX_LAGA_DOFS), d2Gap(MAX_LAGA_DOFS, MAX_LAGA_DOFS) real(kind=8) :: mu_f(MAX_LAGA_DOFS, 2) + integer :: nbPoinInte + real(kind=8) :: poinInteSlav(2, MAX_NB_INTE) blas_int :: b_k, b_lda, b_ldb, b_ldc, b_m, b_n blas_int :: b_incx, b_incy ! @@ -74,9 +77,8 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) ! matr_cont = 0.d0 matr_fric = 0.d0 -! + ! - Slave node is not paired -> Special treatment -! if (geom%elem_slav_code == "PO1") then if (geom%elem_mast_code == "LAGR") then matr_cont(geom%elem_dime+1, geom%elem_dime+1) = 1.d0 @@ -94,39 +96,39 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) ! go to 999 end if -! + +! - Get intersection points + call getInterCont(nbPoinInte, poinInteSlav) + ! - Get quadrature (slave side) -! - call getQuadCont(geom%elem_dime, geom%l_axis, geom%nb_node_slav, geom%elem_slav_code, & - geom%coor_slav_init, geom%elem_mast_code, nb_qp, coor_qp, weight_qp) -! + call getQuadCont(geom%elem_dime, & + geom%elem_slav_code, geom%elem_mast_code, & + nbPoinInte, poinInteSlav, & + nb_qp, coor_qp, & + geom%l_axis, geom%nb_node_slav, geom%coor_slav_init, & + weight_qp) + ! - Diameter of slave side -! hF = diameter(geom%nb_node_slav, geom%coor_slav_init) -! + ! - Loop on quadrature points -! do i_qp = 1, nb_qp ! ! ----- Get current quadrature point (slave side) ! coor_qp_sl(1:2) = coor_qp(1:2, i_qp) weight_sl_qp = weight_qp(i_qp) -! + ! ----- Compute contact quantities -! - call laElemCont(parameters, geom, coor_qp_sl, hF, lagr_c, & - gap, gamma_c, projRmVal, l_cont_qp, lagr_f, & - vT, gamma_f, projBsVal, l_fric_qp, dGap=dGap, & - d2Gap=d2Gap, mu_c=mu_c, mu_f=mu_f) -! + call laElemCont(parameters, geom, coor_qp_sl, hF, & + lagr_c, gap, gamma_c, projRmVal, l_cont_qp, & + lagr_f, vT, gamma_f, projBsVal, l_fric_qp, & + dGap=dGap, d2Gap=d2Gap, mu_c=mu_c, mu_f=mu_f) + ! ------ CONTACT PART (always computed) -! if (l_cont_qp) then -! ! ------ Compute displacement / displacement (slave and master side) ! term: (gamma_c*H*D(gap(u))[v], D(gap(u))[du]) -! coeff = weight_sl_qp*gamma_c b_lda = to_blas_int(MAX_LAGA_DOFS) b_m = to_blas_int(geom%nb_dofs) @@ -138,15 +140,13 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) ! ! ------ Compute displacement / displacement (slave and master side) ! term: (H*[lagr_c + gamma_c * gap(u)]_R-, D2(gap(u))[v, du]) -! coeff = weight_sl_qp*projRmVal - matr_cont(1:geom%nb_dofs, 1:geom%nb_dofs) = matr_cont(1:geom%nb_dofs, 1:geom%nb_dofs)& - &+coeff*d2Gap(1:geom%nb_dofs, 1:geom%nb_d& - &ofs) -! + matr_cont(1:geom%nb_dofs, 1:geom%nb_dofs) = & + matr_cont(1:geom%nb_dofs, 1:geom%nb_dofs)+ & + coeff*d2Gap(1:geom%nb_dofs, 1:geom%nb_dofs) + ! ------ Compute displacement / Lagrange and Lagrange / displacement ! term: (H * D(gap(u))[v], dlagr_c) + (H * mu_c, D(gap(u))[du]) -! coeff = weight_sl_qp b_lda = to_blas_int(MAX_LAGA_DOFS) b_m = to_blas_int(geom%nb_dofs) @@ -163,10 +163,9 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) call dger(b_m, b_n, coeff, mu_c, b_incx, & dGap, b_incy, matr_cont, b_lda) else -! + ! ------ Compute Lagrange / Lagrange (slave side) ! term: ((H-1) / gamma_c * mu_c, dlagr_c) = (- mu_c / gamma_c, dlagr_c) since H = 0 -! coeff = -weight_sl_qp/gamma_c b_lda = to_blas_int(MAX_LAGA_DOFS) b_m = to_blas_int(geom%nb_dofs) @@ -177,17 +176,15 @@ subroutine laMatr(parameters, geom, matr_cont, matr_fric) mu_c, b_incy, matr_cont, b_lda) ! end if -! + ! ------ FRICTION PART (computed only if friction) -! if (parameters%l_fric) then if (l_fric_qp) then ASSERT(ASTER_FALSE) else -! + ! ------ Compute Lagrange / Lagrange (slave side) ! term: (-1/ gamma_f * mu_f, dlagr_f) - Without friction -! coeff = -weight_sl_qp/gamma_f b_ldc = to_blas_int(MAX_LAGA_DOFS) b_ldb = to_blas_int(MAX_LAGA_DOFS) diff --git a/bibfor/cont_elem/laVect.F90 b/bibfor/cont_elem/laVect.F90 index abb3ff331e9..257f4422865 100644 --- a/bibfor/cont_elem/laVect.F90 +++ b/bibfor/cont_elem/laVect.F90 @@ -25,6 +25,7 @@ subroutine laVect(parameters, geom, vect_cont, vect_fric) ! #include "asterf_types.h" #include "asterfort/assert.h" +#include "asterfort/getInterCont.h" #include "asterfort/getQuadCont.h" #include "asterfort/laElemCont.h" #include "blas/daxpy.h" @@ -59,7 +60,7 @@ subroutine laVect(parameters, geom, vect_cont, vect_fric) ! -------------------------------------------------------------------------------------------------- ! aster_logical :: l_cont_qp, l_fric_qp - integer :: i_qp, nb_qp + integer :: i_qp, nb_qp real(kind=8) :: weight_sl_qp, coeff, hF real(kind=8) :: coor_qp_sl(2) real(kind=8) :: coor_qp(2, 48), weight_qp(48) @@ -67,6 +68,8 @@ subroutine laVect(parameters, geom, vect_cont, vect_fric) real(kind=8) :: lagr_f(2), vT(2), gamma_f, projBsVal(2), term_f(2) real(kind=8) :: dGap(MAX_LAGA_DOFS), mu_c(MAX_LAGA_DOFS) real(kind=8) :: mu_f(MAX_LAGA_DOFS, 2), jump_t(MAX_LAGA_DOFS, 3) + integer :: nbPoinInte + real(kind=8) :: poinInteSlav(2, MAX_NB_INTE) blas_int :: b_incx, b_incy, b_n blas_int :: b_lda, b_m ! @@ -94,11 +97,17 @@ subroutine laVect(parameters, geom, vect_cont, vect_fric) ! go to 999 end if -! + +! - Get intersection points + call getInterCont(nbPoinInte, poinInteSlav) + ! - Get quadrature (slave side) -! - call getQuadCont(geom%elem_dime, geom%l_axis, geom%nb_node_slav, geom%elem_slav_code, & - geom%coor_slav_init, geom%elem_mast_code, nb_qp, coor_qp, weight_qp) + call getQuadCont(geom%elem_dime, & + geom%elem_slav_code, geom%elem_mast_code, & + nbPoinInte, poinInteSlav, & + nb_qp, coor_qp, & + geom%l_axis, geom%nb_node_slav, geom%coor_slav_init, & + weight_qp) ! ! - Diameter of slave side ! @@ -115,10 +124,10 @@ subroutine laVect(parameters, geom, vect_cont, vect_fric) ! ! ----- Compute contact quantities ! - call laElemCont(parameters, geom, coor_qp_sl, hF, lagr_c, & - gap, gamma_c, projRmVal, l_cont_qp, lagr_f, & - vT, gamma_f, projBsVal, l_fric_qp, dGap=dGap, & - mu_c=mu_c, mu_f=mu_f, jump_t=jump_t) + call laElemCont(parameters, geom, coor_qp_sl, hF, & + lagr_c, gap, gamma_c, projRmVal, l_cont_qp, & + lagr_f, vT, gamma_f, projBsVal, l_fric_qp, & + dGap=dGap, mu_c=mu_c, mu_f=mu_f, jump_t=jump_t) ! ! ------ CONTACT PART (always computed) ! diff --git a/bibfor/cont_elem/latrco.F90 b/bibfor/cont_elem/latrco.F90 index 039a92136e3..9c8ce0d71ab 100644 --- a/bibfor/cont_elem/latrco.F90 +++ b/bibfor/cont_elem/latrco.F90 @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,18 +15,18 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- - -subroutine latrco(i_tria, nb_poin_inte, poin_inte, tria_coor) +! +subroutine latrco(iTria, nbPoinInte, poinInte, triaCoorPara) ! implicit none ! #include "asterfort/assert.h" +#include "asterfort/mesh_pairing_type.h" ! -! - integer, intent(in) :: i_tria - integer, intent(in) :: nb_poin_inte - real(kind=8), intent(in) :: poin_inte(2, 8) - real(kind=8), intent(out) :: tria_coor(2, 3) + integer, intent(in) :: iTria + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInte(2, MAX_NB_INTE) + real(kind=8), intent(out) :: triaCoorPara(2, 3) ! ! -------------------------------------------------------------------------------------------------- ! @@ -36,34 +36,34 @@ subroutine latrco(i_tria, nb_poin_inte, poin_inte, tria_coor) ! ! -------------------------------------------------------------------------------------------------- ! -! In i_tria : index of current triangle -! In tria_node : list of triangles (defined by index of intersection points) -! In poin_inte : list (sorted) of intersection points -! Out tria_coor : coordinates of current triangle +! In iTria : index of current triangle +! In nbPoinInte : number of intersection points +! In poinInte : coordinates of intersection points (in cell parametric space) +! Out triaCoorPara : coordinates of current triangle (in cell parametric space) ! ! -------------------------------------------------------------------------------------------------- ! - integer :: i_node, i_node1, i_node2 + integer :: iPoinInte, iPoinInte1, iPoinInte2 real(kind=8) :: barycenter(2) ! ! -------------------------------------------------------------------------------------------------- ! - if (nb_poin_inte == 3) then - tria_coor(1:2, 1:3) = poin_inte(1:2, 1:3) + if (nbPoinInte == 3) then + triaCoorPara(1:2, 1:3) = poinInte(1:2, 1:3) else barycenter = 0.d0 - do i_node = 1, nb_poin_inte - barycenter(1:2) = barycenter(1:2)+poin_inte(1:2, i_node) + do iPoinInte = 1, nbPoinInte + barycenter(1:2) = barycenter(1:2)+poinInte(1:2, iPoinInte) end do - barycenter = barycenter/real(nb_poin_inte, kind=8) -! - i_node1 = i_tria - i_node2 = i_tria+1 - if (i_tria == nb_poin_inte) i_node2 = 1 - - tria_coor(1:2, 1) = poin_inte(1:2, i_node1) - tria_coor(1:2, 2) = poin_inte(1:2, i_node2) - tria_coor(1:2, 3) = barycenter + barycenter = barycenter/real(nbPoinInte, kind=8) + iPoinInte1 = iTria + iPoinInte2 = iTria+1 + if (iTria == nbPoinInte) then + iPoinInte2 = 1 + end if + triaCoorPara(1:2, 1) = poinInte(1:2, iPoinInte1) + triaCoorPara(1:2, 2) = poinInte(1:2, iPoinInte2) + triaCoorPara(1:2, 3) = barycenter end if ! end subroutine diff --git a/bibfor/cont_elem/niMatr.F90 b/bibfor/cont_elem/niMatr.F90 index ed1e8353857..7b7cfa79f2e 100644 --- a/bibfor/cont_elem/niMatr.F90 +++ b/bibfor/cont_elem/niMatr.F90 @@ -18,14 +18,15 @@ ! subroutine niMatr(parameters, geom, matr_cont, matr_fric) ! + use contact_module use contact_nitsche_module use contact_type - use contact_module ! implicit none ! #include "asterf_types.h" #include "asterfort/assert.h" +#include "asterfort/getInterCont.h" #include "asterfort/getQuadCont.h" #include "asterfort/niElemCont.h" #include "blas/dgemm.h" @@ -51,7 +52,7 @@ subroutine niMatr(parameters, geom, matr_cont, matr_fric) ! type(ContactNitsche) :: nits aster_logical :: l_cont_qp, l_fric_qp - integer :: i_qp, nb_qp, total_dofs, face_dofs, slav_dofs + integer :: i_qp, nb_qp, total_dofs, face_dofs, slav_dofs real(kind=8) :: weight_sl_qp, coeff, hF real(kind=8) :: coor_qp_sl(2) real(kind=8) :: coor_qp(2, 48), weight_qp(48) @@ -61,6 +62,8 @@ subroutine niMatr(parameters, geom, matr_cont, matr_fric) real(kind=8) :: dStress_nn(MAX_NITS_DOFS), dGapRenum(MAX_NITS_DOFS) real(kind=8) :: matr_tmp(MAX_LAGA_DOFS, MAX_LAGA_DOFS) integer :: dofsMap(54) + integer :: nbPoinInte + real(kind=8) :: poinInteSlav(2, MAX_NB_INTE) blas_int :: b_incx, b_incy, b_lda, b_m, b_n ! ! -------------------------------------------------------------------------------------------------- @@ -70,17 +73,22 @@ subroutine niMatr(parameters, geom, matr_cont, matr_fric) dGapRenum = 0.d0 ! ! - Mapping of dofs -! dofsMap = dofsMapping(geom) -! + +! - Get intersection points + call getInterCont(nbPoinInte, poinInteSlav) + ! - Get quadrature (slave side) -! - call getQuadCont(geom%elem_dime, geom%l_axis, geom%nb_node_slav, geom%elem_slav_code, & - geom%coor_slav_init, geom%elem_mast_code, nb_qp, coor_qp, weight_qp) -! + call getQuadCont(geom%elem_dime, & + geom%elem_slav_code, geom%elem_mast_code, & + nbPoinInte, poinInteSlav, & + nb_qp, coor_qp, & + geom%l_axis, geom%nb_node_slav, geom%coor_slav_init, & + weight_qp) + ! - Diameter of slave side -! hF = diameter(geom%nb_node_slav, geom%coor_slav_init) + ! call nbDofsNitsche(geom, total_dofs, face_dofs, slav_dofs) ! @@ -163,7 +171,7 @@ subroutine niMatr(parameters, geom, matr_cont, matr_fric) call dger(b_m, b_n, coeff, dStress_nn, b_incx, & dGapRenum, b_incy, matr_cont, b_lda) end if -! + else if (parameters%vari_cont .ne. CONT_VARI_RAPI) then ! diff --git a/bibfor/cont_elem/niVect.F90 b/bibfor/cont_elem/niVect.F90 index 1bf6a6b6db1..0abe3a02cef 100644 --- a/bibfor/cont_elem/niVect.F90 +++ b/bibfor/cont_elem/niVect.F90 @@ -19,13 +19,14 @@ subroutine niVect(parameters, geom, vect_cont, vect_fric) ! use contact_module - use contact_type use contact_nitsche_module + use contact_type ! implicit none ! #include "asterf_types.h" #include "asterfort/assert.h" +#include "asterfort/getInterCont.h" #include "asterfort/getQuadCont.h" #include "asterfort/niElemCont.h" #include "blas/daxpy.h" @@ -51,7 +52,7 @@ subroutine niVect(parameters, geom, vect_cont, vect_fric) ! type(ContactNitsche) :: nits aster_logical :: l_cont_qp, l_fric_qp - integer :: i_qp, nb_qp, total_dofs, face_dofs, slav_dofs + integer :: i_qp, nb_qp, total_dofs, face_dofs, slav_dofs real(kind=8) :: weight_sl_qp, coeff, hF real(kind=8) :: coor_qp_sl(2) real(kind=8) :: coor_qp(2, 48), weight_qp(48) @@ -60,6 +61,8 @@ subroutine niVect(parameters, geom, vect_cont, vect_fric) real(kind=8) :: dGap(MAX_LAGA_DOFS), dStress_nn(MAX_NITS_DOFS) real(kind=8) :: jump_t(MAX_LAGA_DOFS, 3) integer :: dofsMap(54) + integer :: nbPoinInte + real(kind=8) :: poinInteSlav(2, MAX_NB_INTE) blas_int :: b_incx, b_incy, b_n blas_int :: b_lda, b_m ! @@ -67,18 +70,22 @@ subroutine niVect(parameters, geom, vect_cont, vect_fric) ! vect_cont = 0.d0 vect_fric = 0.d0 -! + ! - Mapping of dofs -! dofsMap = dofsMapping(geom) -! + +! - Get intersection points + call getInterCont(nbPoinInte, poinInteSlav) + ! - Get quadrature (slave side) -! - call getQuadCont(geom%elem_dime, geom%l_axis, geom%nb_node_slav, geom%elem_slav_code, & - geom%coor_slav_init, geom%elem_mast_code, nb_qp, coor_qp, weight_qp) -! + call getQuadCont(geom%elem_dime, & + geom%elem_slav_code, geom%elem_mast_code, & + nbPoinInte, poinInteSlav, & + nb_qp, coor_qp, & + geom%l_axis, geom%nb_node_slav, geom%coor_slav_init, & + weight_qp) + ! - Diameter of slave side -! hF = diameter(geom%nb_node_slav, geom%coor_slav_init) ! call nbDofsNitsche(geom, total_dofs, face_dofs, slav_dofs) diff --git a/bibfor/cont_pair/aplcpgn.F90 b/bibfor/cont_pair/aplcpgn.F90 index b60ebbe6d80..56fe690bda9 100644 --- a/bibfor/cont_pair/aplcpgn.F90 +++ b/bibfor/cont_pair/aplcpgn.F90 @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,15 +15,19 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- - ! -subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & +subroutine aplcpgn(mesh, newgeo, & + mastConxInvName, mastNeighName, slavNeighName, & + pair_tole, dist_ratio, & nb_elem_mast, list_elem_mast, nb_elem_slav, list_elem_slav, list_node_mast, & - nb_node_mast, nb_pair_zone, list_pair_zone, list_nbptit_zone, list_ptitsl_zone) + nb_node_mast, meshPairing) +! + use mesh_type + use mesh_cell_module + use MeshPairing_module ! implicit none ! -!#include "asterfort/ap_infast.h" #include "asterc/r8nnem.h" #include "asterf_types.h" #include "asterfort/ap_infast_n.h" @@ -51,11 +55,11 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & #include "asterfort/wkvect.h" #include "jeveux.h" #include "Contact_type.h" -! ! character(len=8), intent(in) :: mesh character(len=19), intent(in) :: newgeo - character(len=19), intent(in) :: zone + character(len=24), intent(in) :: mastConxInvName + character(len=24), intent(in) :: mastNeighName, slavNeighName real(kind=8), intent(in) :: pair_tole, dist_ratio integer, intent(in) :: nb_elem_slav integer, intent(in) :: nb_elem_mast @@ -63,10 +67,7 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & integer, intent(in) :: list_elem_mast(nb_elem_mast) integer, intent(in) :: list_elem_slav(nb_elem_slav) integer, intent(in) :: list_node_mast(nb_node_mast) - integer, intent(out) :: nb_pair_zone - character(len=19), intent(in) :: list_pair_zone, list_nbptit_zone - character(len=19), intent(in) :: list_ptitsl_zone - character(len=24), intent(in) :: pair_method + type(MESH_PAIRING), intent(inout) :: meshPairing ! ! -------------------------------------------------------------------------------------------------- ! @@ -74,11 +75,13 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & ! ! Pairing by PANG method ! +! NO OUTPUT (only for verbose debug) +! ! -------------------------------------------------------------------------------------------------- ! ! In mesh : name of mesh ! In newgeo : name of field for geometry update from initial coordinates of nodes -! In zone : name of contactzone sd +! In zone : name of contact zone sd ! In pair_tole : tolerance for pairing ! In nb_elem_mast : number of master elements on current zone ! In nb_elem_slav : number of slave elements on current zone @@ -106,13 +109,12 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & real(kind=8) :: poin_inte_ma(SIZE_MAX_INTE_SL) character(len=8) :: elem_slav_name, elem_name integer :: nb_slav_start, nb_find_mast, nb_mast_start - integer :: elem_start, elem_nume, jtab + integer :: elem_start, elem_nume integer :: slav_indx_mini, mast_indx_mini, slav_indx_maxi, mast_indx_maxi integer :: elem_neigh_indx, mast_find_indx, elem_slav_neigh, elem_mast_neigh aster_logical :: l_recup, debug, pair_exist integer, pointer :: mast_find_flag(:) => null() integer, pointer :: elem_slav_flag(:) => null() - character(len=24) :: sdappa_slne, sdappa_mane integer, pointer :: v_sdappa_slne(:) => null() integer, pointer :: v_sdappa_mane(:) => null() integer :: list_slav_master(4) @@ -132,8 +134,6 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & integer, pointer :: elem_mast_start(:) => null() ! ! -------------------------------------------------------------------------------------------------- -! -! -------------------------------------------------------------------------------------------------- ! call jemarq() ! @@ -173,27 +173,26 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & AS_ALLOCATE(vi=elem_slav_start, size=nb_elem_slav) AS_ALLOCATE(vi=elem_mast_start, size=nb_elem_slav) list_find_mast = 0 -! + ! - Object for neighbours (inverse connectivity) -! - sdappa_mane = zone(1:8)//'.MN' - sdappa_slne = zone(1:8)//'.SN' - call jeveuo(sdappa_mane, 'L', vi=v_sdappa_mane) - call jeveuo(sdappa_slne, 'L', vi=v_sdappa_slne) -! + call jeveuo(mastNeighName, 'L', vi=v_sdappa_mane) + call jeveuo(slavNeighName, 'L', vi=v_sdappa_slne) + ! - while loop on the existence of a pair slave-master -! do while (pair_exist) - if (pair_method == "RAPIDE") then - ! - Search by computing the minimum distance between the barycenters - call ap_infast_n(mesh, newgeo, pair_tole, dist_ratio, nb_elem_mast, & - list_elem_mast, nb_elem_slav, list_elem_slav, elem_slav_flag, & - nb_mast_start, elem_mast_start, nb_slav_start, elem_slav_start, & - zone, list_node_mast, nb_node_mast) - elseif (pair_method == "ROBUSTE") then - call apprin_n(mesh, newgeo, pair_tole, dist_ratio, nb_elem_mast, & - list_elem_mast, nb_elem_slav, list_elem_slav, elem_slav_flag, & - nb_mast_start, elem_mast_start, nb_slav_start, elem_slav_start) + if (debug) then + WRITE (6, *) "Get cells for starting search" + WRITE (6, *) "=============================" + end if + +! ----- Search by computing the minimum distance between the barycenters + call ap_infast_n(mesh, newgeo, pair_tole, dist_ratio, nb_elem_mast, & + list_elem_mast, nb_elem_slav, list_elem_slav, elem_slav_flag, & + nb_mast_start, elem_mast_start, nb_slav_start, elem_slav_start, & + mastConxInvName, list_node_mast, nb_node_mast) + if (debug) then + WRITE (6, *) " Starting points (Master): ", nb_mast_start, elem_mast_start + WRITE (6, *) " Starting points (Slave) : ", nb_slav_start, elem_slav_start end if if (nb_slav_start == 0) then @@ -229,9 +228,9 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & if (debug) then call jenuno(jexnum(mesh//'.NOMMAI', elem_slav_nume), elem_slav_name) - write (*, *) "Current slave element: ", elem_slav_nume, elem_slav_name, & - '(type : ', elem_slav_code, ')' - write (*, *) elem_slav_coor(1:3*elem_slav_nbnode) + write (*, *) "Current slave element : ", elem_slav_nume + write (6, *) " Coordinates (global frame): ", & + elem_slav_coor(1:3*elem_slav_nbnode) end if ! ! ----- Number of neighbours @@ -251,6 +250,7 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & end if ! if (debug) then + write (6, *) "Potential number of neighbours: ", nb_slav_neigh do i_slav_neigh = 1, nb_slav_neigh elem_nume = v_sdappa_slne((elem_slav_indx-1)*4+i_slav_neigh) if (elem_nume .ne. 0) then @@ -258,7 +258,7 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & else elem_name = 'None' end if - write (*, *) "Current slave element neighbours: ", elem_name + write (6, *) "Neighbour (", i_slav_neigh, "): ", elem_nume end do end if ! @@ -269,19 +269,30 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & ! elem_start = elem_mast_start(1) mast_find_indx = elem_start+1-mast_indx_mini -! + if (debug) then + WRITE (6, *) "Avant décalage" + WRITE (6, *) " => ", nb_mast_start, elem_mast_start(1:nb_mast_start) + end if + ! ----- Shift list of master element start ! do i_mast_start = 1, nb_mast_start-1 elem_mast_start(i_mast_start) = elem_mast_start(i_mast_start+1) end do nb_mast_start = nb_mast_start-1 + if (debug) then + WRITE (6, *) "Après décalage" + WRITE (6, *) " => ", nb_mast_start, elem_mast_start(1:nb_mast_start) + end if ! ! ----- Management of list of master elements: first element to seek ! list_find_mast(1) = elem_start nb_find_mast = 1 mast_find_flag(mast_find_indx) = 1 + if (debug) then + write (6, *) "Master cell to start: ", elem_start + end if ! ! ----- Initialization list of contact pairs ! @@ -304,8 +315,8 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & ! if (debug) then call jenuno(jexnum(mesh//'.NOMMAI', elem_mast_nume), elem_name) - write (*, *) ". Current master element: ", elem_mast_nume, elem_name, & - '(type : ', elem_mast_type, ')' + write (*, *) "Current master element: ", elem_mast_nume + write (6, *) " Coordinates (global frame): " end if ! ! ------------- Shift list of master elements (on supprime de la liste) @@ -352,6 +363,13 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & ! if (inte_weight > pair_tole .and. iret == 0) then nb_pair = nb_pair+1 + if (debug) then + WRITE (6, *) "Add pair: ", nb_pair, & + "(", elem_slav_nume, "-", elem_mast_nume, ")" + WRITE (6, *) " Nb points integrations : ", nb_poin_inte + WRITE (6, *) " Coef. points integrations : ", poin_inte_sl + end if + ASSERT(nb_pair .le. nb_elem_slav*nb_elem_mast) list_pair(2*(nb_pair-1)+1) = elem_slav_nume list_pair(2*(nb_pair-1)+2) = elem_mast_nume @@ -363,12 +381,15 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & (nb_pair-1)*SIZE_MAX_INTE_SL+SIZE_MAX_INTE_SL) = poin_inte_ma !print*,"LIPTMA_APLC", li_pt_inte_ma((nb_pair-1)*SIZE_MAX_INTE_SL+1:& ! (nb_pair-1)*SIZE_MAX_INTE_SL+2) + + call pairAdd(elem_slav_nume, elem_mast_nume, & + nb_poin_inte, li_pt_inte_sl, & + meshPairing) end if if (debug) then write (*, *) ". Contact pair: ", elem_slav_nume, elem_mast_nume, & " (weight: ", inte_weight, ", nb point inter: ", nb_poin_inte, ")" - end if ! ! --------- Find neighbour of current master element @@ -393,6 +414,7 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & ! ! ------------- Prepare next master element ! + ! WRITE (6, *) "Prepare next master element" do i_mast_neigh = 1, nb_mast_neigh elem_mast_neigh = v_sdappa_mane((elem_mast_indx-1)*4+i_mast_neigh) elem_neigh_indx = elem_mast_neigh+1-mast_indx_mini @@ -400,15 +422,30 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & mast_find_flag(elem_neigh_indx) == 0) then list_find_mast(nb_find_mast+1) = elem_mast_neigh nb_find_mast = nb_find_mast+1 + if (debug) then + WRITE (6, *) " => added: ", nb_find_mast, & + list_find_mast(nb_find_mast) + end if mast_find_flag(elem_neigh_indx) = 1 end if end do + ! ! ------------- Prepare next slave element: higher weight ! + if (debug) then + WRITE (6, *) "Prepare next slave element" + end if do i_slav_neigh = 1, nb_slav_neigh elem_slav_neigh = v_sdappa_slne((elem_slav_indx-1)*4+i_slav_neigh) elem_neigh_indx = elem_slav_neigh+1-slav_indx_mini + if (debug) then + WRITE (6, *) " < Index:", i_slav_neigh + WRITE (6, *) " < cellNeighNume:", elem_slav_neigh + WRITE (6, *) " < cellNeighIndx: ", elem_neigh_indx + WRITE (6, *) " < cellSlavFlag: ", elem_slav_flag(elem_neigh_indx) + WRITE (6, *) " < inteNeigh: ", inte_neigh(i_slav_neigh) + end if if (elem_slav_neigh .ne. 0 .and. & inte_neigh(i_slav_neigh) == 1 & .and. elem_slav_flag(elem_neigh_indx) .ne. 1 & @@ -422,6 +459,9 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & !if (weight_test > list_slav_weight(i_slav_neigh).and.& ! weight_test > pair_tole) then list_slav_master(i_slav_neigh) = elem_mast_nume + if (debug) then + WRITE (6, *) " => added: ", elem_mast_nume + end if ! list_slav_weight(i_slav_neigh) = weight_test !end if end if @@ -434,7 +474,7 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & ! ----- Next elements ! if (debug) then - write (*, *) 'Next elements - Nb: ', nb_slav_neigh + write (*, *) 'Prepare next elements - Nb: ', nb_slav_neigh end if do i_slav_neigh = 1, nb_slav_neigh elem_slav_neigh = v_sdappa_slne((elem_slav_indx-1)*4+i_slav_neigh) @@ -459,21 +499,8 @@ subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & !pair_exist = ASTER_FALSE end do -! -!----- save results -! - nb_pair_zone = nb_pair - if (nb_pair_zone > 0) then - call wkvect(list_pair_zone, 'G V I', 2*nb_pair_zone, jtab) - zi(jtab-1+1:jtab-1+2*nb_pair_zone) = list_pair(1:2*nb_pair_zone) - call wkvect(list_nbptit_zone, 'G V I', nb_pair_zone, jtab) - zi(jtab-1+1:jtab-1+nb_pair_zone) = li_nb_pt_inte_sl(1:nb_pair_zone) - call wkvect(list_ptitsl_zone, 'G V R', 16*nb_pair_zone, jtab) - zr(jtab-1+1:jtab-1+16*nb_pair_zone) = li_pt_inte_sl(1:16*nb_pair_zone) - end if -! -!--- DEALLOCATE -! + +! - DEALLOCATE AS_DEALLOCATE(vi=mast_find_flag) AS_DEALLOCATE(vi=elem_slav_flag) AS_DEALLOCATE(vr=li_pt_inte_sl) diff --git a/bibfor/cont_pair/lcptga.F90 b/bibfor/cont_pair/lcptga.F90 index 3a56633f95c..f4a623d1334 100644 --- a/bibfor/cont_pair/lcptga.F90 +++ b/bibfor/cont_pair/lcptga.F90 @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -60,10 +60,8 @@ subroutine lcptga(elem_dime, tria_coor, gauss_family, & ! model_ndim = elem_dime-1 nb_gauss = 0 - do i_dime = 1, model_ndim - gauss_coor(i_dime, 1:12) = 0.d0 - end do - gauss_weight(1:12) = 0.d0 + gauss_coor = 0.d0 + gauss_weight = 0.d0 ! ! - Select reference geometry for auxiliary parametric space ! diff --git a/bibfor/include/Contact_type.h b/bibfor/include/Contact_type.h index ec1d2446092..50fa8253cd2 100644 --- a/bibfor/include/Contact_type.h +++ b/bibfor/include/Contact_type.h @@ -16,21 +16,14 @@ ! along with code_aster. If not, see . ! -------------------------------------------------------------------- ! -! Contact data structure : Parameters <-> integer definitions -! ------------------------------------------------------------------------- +! ================================================================================================== ! +! Algorithm +! +! ================================================================================================== #define ALGO_FIXE 0 #define ALGO_NEWT 1 #define NB_DATA_CYCL 75 +! Total number of coordinates for intersection points (old one, to suppress) #define SIZE_MAX_INTE_SL 16 - -! Projection type -! ------------------------------------------------------------------------- -#define PROJ_TYPE_NODE 0 -#define PROJ_TYPE_FIXE 1 - -! Projection algo parameters -! ------------------------------------------------------------------------- -#define PROJ_ALGO_NONE 0 -#define PROJ_ALGO_GAPI 1 diff --git a/bibfor/include/asterfort/aplcpgn.h b/bibfor/include/asterfort/aplcpgn.h index 492700a4531..eca01fb5382 100644 --- a/bibfor/include/asterfort/aplcpgn.h +++ b/bibfor/include/asterfort/aplcpgn.h @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2022 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,19 +15,19 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- - -! -! #include "asterf_types.h" ! interface - subroutine aplcpgn(mesh, newgeo, zone, pair_method, pair_tole, dist_ratio, & - nb_elem_mast, list_elem_mast, nb_elem_slav, list_elem_slav, list_node_mast,& - nb_node_mast , nb_pair_zone, list_pair_zone, list_nbptit_zone,& - list_ptitsl_zone) + subroutine aplcpgn(mesh, newgeo, & + mastConxInvName, mastNeighName, slavNeighName, & + pair_tole, dist_ratio, & + nb_elem_mast, list_elem_mast, nb_elem_slav, list_elem_slav, list_node_mast, & + nb_node_mast, meshPairing) + use MeshPairing_module character(len=8), intent(in) :: mesh character(len=19), intent(in) :: newgeo - character(len=19), intent(in) :: zone + character(len=24), intent(in) :: mastConxInvName + character(len=24), intent(in) :: mastNeighName, slavNeighName real(kind=8), intent(in) :: pair_tole, dist_ratio integer, intent(in) :: nb_elem_slav integer, intent(in) :: nb_elem_mast @@ -35,9 +35,6 @@ interface integer, intent(in) :: list_elem_mast(nb_elem_mast) integer, intent(in) :: list_elem_slav(nb_elem_slav) integer, intent(in) :: list_node_mast(nb_node_mast) - integer, intent(out) :: nb_pair_zone - character(len=19), intent(in) :: list_pair_zone, list_nbptit_zone - character(len=19), intent(in) :: list_ptitsl_zone - character(len=24), intent(in) :: pair_method + type(MESH_PAIRING), intent(inout) :: meshPairing end subroutine aplcpgn end interface diff --git a/bibfor/include/asterfort/getInterCont.h b/bibfor/include/asterfort/getInterCont.h new file mode 100644 index 00000000000..51b0049716c --- /dev/null +++ b/bibfor/include/asterfort/getInterCont.h @@ -0,0 +1,25 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +#include "asterfort/mesh_pairing_type.h" +! +interface + subroutine getInterCont(nbPoinInte, poinInteSlav) + integer, intent(out) :: nbPoinInte + real(kind=8), intent(out) :: poinInteSlav(2, MAX_NB_INTE) + end subroutine getInterCont +end interface diff --git a/bibfor/include/asterfort/getQuadCont.h b/bibfor/include/asterfort/getQuadCont.h index 8421093fde1..fab9359fbd2 100644 --- a/bibfor/include/asterfort/getQuadCont.h +++ b/bibfor/include/asterfort/getQuadCont.h @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2022 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,19 +15,25 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- -! #include "asterf_types.h" +#include "asterfort/mesh_pairing_type.h" ! interface - subroutine getQuadCont(elem_dime, l_axis, & - nb_node_slav, elem_slav_code, elem_slav_coor,& - elem_mast_code, & - nb_qp, coor_qp , weight_qp ) - integer, intent(in) :: elem_dime, nb_node_slav - aster_logical, intent(in) :: l_axis + subroutine getQuadCont(elem_dime, & + elem_slav_code, elem_mast_code, & + nbPoinInte, poinInteSlav, & + nb_qp, coor_qp, & + l_axis_, nb_node_slav_, elem_slav_coor_, & + weight_qp_) + integer, intent(in) :: elem_dime character(len=8), intent(in) :: elem_slav_code, elem_mast_code - real(kind=8), intent(in) :: elem_slav_coor(3, 9) - real(kind=8), intent(out) :: coor_qp(2, 48), weight_qp(48) + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInteSlav(2, MAX_NB_INTE) + real(kind=8), intent(out) :: coor_qp(2, 48) integer, intent(out) :: nb_qp + integer, optional, intent(in) :: nb_node_slav_ + real(kind=8), optional, intent(in) :: elem_slav_coor_(3, 9) + aster_logical, optional, intent(in) :: l_axis_ + real(kind=8), optional, intent(out) :: weight_qp_(48) end subroutine getQuadCont end interface diff --git a/bibfor/include/asterfort/extrs1.h b/bibfor/include/asterfort/inteCellAreaWrap.h similarity index 62% rename from bibfor/include/asterfort/extrs1.h rename to bibfor/include/asterfort/inteCellAreaWrap.h index bcd6d15686a..06c378def71 100644 --- a/bibfor/include/asterfort/extrs1.h +++ b/bibfor/include/asterfort/inteCellAreaWrap.h @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2017 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,21 +15,13 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- - -! +#include "asterfort/mesh_pairing_type.h" ! interface - subroutine extrs1(resu0, nbrang, nuordr, nbpara, nompar,& - nbarch, nuarch, nbexcl, chexcl, nbnosy) - character(len=*) :: resu0 - integer :: nbrang - integer :: nuordr(*) - integer :: nbpara - character(len=16) :: nompar(*) - integer :: nbarch - integer :: nuarch(*) - integer :: nbexcl - character(len=16) :: chexcl(*) - integer :: nbnosy - end subroutine extrs1 + subroutine inteCellAreaWrap(spaceDime, nbPoinInte, poinInteSlav, & + inteArea) + integer, intent(in) :: spaceDime, nbPoinInte + real(kind=8), intent(in) :: poinInteSlav(2, MAX_NB_INTE) + real(kind=8), intent(out) :: inteArea + end subroutine inteCellAreaWrap end interface diff --git a/bibfor/include/asterfort/intePoinCoorWrap.h b/bibfor/include/asterfort/intePoinCoorWrap.h new file mode 100644 index 00000000000..db9dafbc7bb --- /dev/null +++ b/bibfor/include/asterfort/intePoinCoorWrap.h @@ -0,0 +1,27 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +#include "asterfort/mesh_pairing_type.h" +! +interface + subroutine intePoinCoorWrap(mesh, baseName, iPair, poinInteReal) + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: baseName + integer, intent(in) :: iPair + real(kind=8), intent(out) :: poinInteReal(3, MAX_NB_INTE) + end subroutine intePoinCoorWrap +end interface diff --git a/bibfor/include/asterfort/latrco.h b/bibfor/include/asterfort/latrco.h index 6a3b3e9018e..1cabc7f46af 100644 --- a/bibfor/include/asterfort/latrco.h +++ b/bibfor/include/asterfort/latrco.h @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2022 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,14 +15,13 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- - -! +#include "mesh_pairing_type.h" ! interface - subroutine latrco(i_tria, nb_poin_inte, poin_inte, tria_coor) - integer, intent(in) :: i_tria - integer, intent(in) :: nb_poin_inte - real(kind=8), intent(in) :: poin_inte(2,8) - real(kind=8), intent(out) :: tria_coor(2,3) + subroutine latrco(iTria, nbPoinInte, poinInte, triaCoorPara) + integer, intent(in) :: iTria + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInte(2, MAX_NB_INTE) + real(kind=8), intent(out) :: triaCoorPara(2, 3) end subroutine latrco end interface diff --git a/bibfor/include/asterfort/mesh_pairing_type.h b/bibfor/include/asterfort/mesh_pairing_type.h new file mode 100644 index 00000000000..ccc37ea3111 --- /dev/null +++ b/bibfor/include/asterfort/mesh_pairing_type.h @@ -0,0 +1,58 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- + +! ================================================================================================== +! +! Pairing/intersection +! +! ================================================================================================== +! Method of pairing +#define PAIR_FAST 1 +#define PAIR_OLD 2 +#define PAIR_ROBUST 3 + +! Maximum number of neighbours of a cell +#define MAX_NB_NEIGH 4 + +! Maximum number of intersection points +#define MAX_NB_INTE 8 + +! Maximum number of quadrature points +#define MAX_NB_QUAD 48 + +! ================================================================================================== +! +! Error code for pairing +! +! ERR_CELL_ORTH: cells are orthognal +! ERR_CELL_OOR : out of range (greater than DIST_RATIO) +! ERR_PAIR_PROJ: error during projection +! ERR_INTE_VOID: intersection is not correct +! ERR_PAIR_SLAV: projected slave nodes are not inside master cell +! ERR_PAIR_MAST: master nodes are not inside projected slave cell +! ERR_CELL_DEGE: cell is degenerated +! +! ================================================================================================== +#define ERR_PAIR_NONE 0 +#define ERR_CELL_ORTH 1 +#define ERR_CELL_OOR 2 +#define ERR_PAIR_PROJ 3 +#define ERR_INTE_VOID 4 +#define ERR_PAIR_SLAV 5 +#define ERR_PAIR_MAST 6 +#define ERR_CELL_DEGE 7 diff --git a/bibfor/include/asterfort/pairWrap.h b/bibfor/include/asterfort/pairWrap.h new file mode 100644 index 00000000000..2da628b541b --- /dev/null +++ b/bibfor/include/asterfort/pairWrap.h @@ -0,0 +1,40 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +interface + subroutine pairWrap(method, & + mesh, newgeo, mastConxInvName, & + mastNeighName, slavNeighName, & + pairTole, distRatio, verbosity, & + nbCellMast, listCellMast, & + nbCellSlav, listCellSlav, & + nbNodeMast, listNodeMast, & + nbPairZone, baseName) + integer, intent(in) :: method + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: newgeo, mastConxInvName + character(len=24), intent(in) :: mastNeighName, slavNeighName + real(kind=8), intent(in) :: pairTole, distRatio + integer, intent(in) :: verbosity + integer, intent(in) :: nbCellMast, listCellMast(nbCellMast) + integer, intent(in) :: nbCellSlav, listCellSlav(nbCellSlav) + integer, intent(in) :: nbNodeMast, listNodeMast(nbNodeMast) + integer, intent(out) :: nbPairZone + character(len=8), intent(in) :: baseName + end subroutine pairWrap +end interface diff --git a/bibfor/include/asterfort/quadPoinCoorWrap.h b/bibfor/include/asterfort/quadPoinCoorWrap.h new file mode 100644 index 00000000000..81488ddff03 --- /dev/null +++ b/bibfor/include/asterfort/quadPoinCoorWrap.h @@ -0,0 +1,29 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +#include "asterfort/mesh_pairing_type.h" +! +interface + subroutine quadPoinCoorWrap(mesh, baseName, iPair, & + nbPoinQuad, poinQuad) + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: baseName + integer, intent(in) :: iPair + integer, intent(out) :: nbPoinQuad + real(kind=8), intent(out) :: poinQuad(3, MAX_NB_QUAD) + end subroutine quadPoinCoorWrap +end interface diff --git a/bibfor/load/load_neum_prep.F90 b/bibfor/load/load_neum_prep.F90 index 537787bb0e1..4a503d31fea 100644 --- a/bibfor/load/load_neum_prep.F90 +++ b/bibfor/load/load_neum_prep.F90 @@ -89,7 +89,7 @@ subroutine load_neum_prep(model, cara_elem, mate, mateco, load_type, inst_prev, ! ! -------------------------------------------------------------------------------------------------- ! - character(len=24) :: chgeom, chcara(18), chharm, chtime, chinst_curr, chinst_prev + character(len=24) :: chgeom, chcara(18), chharm, chtime character(len=19) :: ligrel_model character(len=8) :: nomcmp(3), mesh real(kind=8) :: time(3) @@ -112,30 +112,19 @@ subroutine load_neum_prep(model, cara_elem, mate, mateco, load_type, inst_prev, ! - Elementary characteristics fields ! call mecara(cara_elem, chcara) -! + ! - Times field -! - if (load_type .ne. 'Dead') then - nomcmp(1) = 'INST' - chinst_curr = '&&VECHME.CH_INST_R' - call mecact('V', chinst_curr, 'LIGREL', ligrel_model, 'INST_R ', & - ncmp=1, nomcmp=nomcmp(1), sr=inst_curr) - chinst_prev = '&&VECHME.CH_INST_M' - call mecact('V', chinst_prev, 'LIGREL', ligrel_model, 'INST_R ', & - ncmp=1, nomcmp=nomcmp(1), sr=inst_prev) - nomcmp(1) = 'INST' - nomcmp(2) = 'DELTAT' - nomcmp(3) = 'THETA' - time(1) = inst_curr + nomcmp(1) = 'INST' + nomcmp(2) = 'DELTAT' + nomcmp(3) = 'THETA' + if (load_type .eq. 'Dead') then + time(1) = inst_prev time(2) = inst_curr-inst_prev time(3) = inst_theta call mecact('V', chtime, 'LIGREL', ligrel_model, 'INST_R ', & ncmp=3, lnomcmp=nomcmp, vr=time) else - nomcmp(1) = 'INST' - nomcmp(2) = 'DELTAT' - nomcmp(3) = 'THETA' - time(1) = inst_prev + time(1) = inst_curr time(2) = inst_curr-inst_prev time(3) = inst_theta call mecact('V', chtime, 'LIGREL', ligrel_model, 'INST_R ', & @@ -211,12 +200,6 @@ subroutine load_neum_prep(model, cara_elem, mate, mateco, load_type, inst_prev, nb_in_prep = nb_in_prep+1 lpain(nb_in_prep) = 'PDEPLPR' lchin(nb_in_prep) = disp_cumu_inst(1:19) - nb_in_prep = nb_in_prep+1 - lpain(nb_in_prep) = 'PINSTMR' - lchin(nb_in_prep) = chinst_prev(1:19) - nb_in_prep = nb_in_prep+1 - lpain(nb_in_prep) = 'PINSTPR' - lchin(nb_in_prep) = chinst_curr(1:19) end if if (load_type .eq. 'Suiv') then nb_in_prep = nb_in_prep+1 @@ -226,12 +209,6 @@ subroutine load_neum_prep(model, cara_elem, mate, mateco, load_type, inst_prev, lpain(nb_in_prep) = 'PDEPLPR' lchin(nb_in_prep) = disp_cumu_inst(1:19) nb_in_prep = nb_in_prep+1 - lpain(nb_in_prep) = 'PINSTMR' - lchin(nb_in_prep) = chinst_prev(1:19) - nb_in_prep = nb_in_prep+1 - lpain(nb_in_prep) = 'PINSTPR' - lchin(nb_in_prep) = chinst_curr(1:19) - nb_in_prep = nb_in_prep+1 lpain(nb_in_prep) = 'PCOMPOR' lchin(nb_in_prep) = compor(1:19) if (present(vite_curr_)) then diff --git a/bibfor/mesh/inteCellAreaWrap.F90 b/bibfor/mesh/inteCellAreaWrap.F90 new file mode 100644 index 00000000000..231e1657cc9 --- /dev/null +++ b/bibfor/mesh/inteCellAreaWrap.F90 @@ -0,0 +1,64 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +subroutine inteCellAreaWrap(mesh, nbPoinInte, poinInteSlav, & + inteArea) +! + use MeshPairing_module +! + implicit none +! +#include "asterf_types.h" +#include "asterfort/assert.h" +#include "asterfort/dismoi.h" +#include "asterfort/mesh_pairing_type.h" +! + character(len=8), intent(in) :: mesh + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInteSlav(2, MAX_NB_INTE) + real(kind=8), intent(out) :: inteArea +! +! -------------------------------------------------------------------------------------------------- +! +! Pairing segment to segment +! +! Compute area of intersection +! +! -------------------------------------------------------------------------------------------------- +! +! In mesh : mesh +! In nbPoinInte : number of intersection points +! In poinInte : list of intersection points +! Out inteArea : area of intersection +! +! -------------------------------------------------------------------------------------------------- +! + integer :: spaceDime +! +! -------------------------------------------------------------------------------------------------- +! + call dismoi('DIM_GEOM', mesh, 'MAILLAGE', repi=spaceDime) + if (spaceDime .eq. 2) then + spaceDime = 2 + else + spaceDime = 3 + end if + inteArea = 0.d0 + call inteCellArea(spaceDime, nbPoinInte, poinInteSlav, inteArea) +! +end subroutine diff --git a/bibfor/mesh/intePoinCoorWrap.F90 b/bibfor/mesh/intePoinCoorWrap.F90 new file mode 100644 index 00000000000..dba253c6a0a --- /dev/null +++ b/bibfor/mesh/intePoinCoorWrap.F90 @@ -0,0 +1,77 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +subroutine intePoinCoorWrap(mesh, nodeCoorName, baseName, iPair, & + poinInteReal) +! + use MeshPairing_module + use mesh_type + use mesh_cell_module +! + implicit none +! +#include "asterf_types.h" +#include "asterfort/assert.h" +#include "asterfort/jeveuo.h" +#include "asterfort/mesh_pairing_type.h" +#include "jeveux.h" +! + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: nodeCoorName + character(len=24), intent(in) :: baseName + integer, intent(in) :: iPair + real(kind=8), intent(out) :: poinInteReal(3, MAX_NB_INTE) +! +! -------------------------------------------------------------------------------------------------- +! +! Pairing segment to segment +! +! Compute point of intersection in global space +! +! -------------------------------------------------------------------------------------------------- +! +! In mesh : mesh +! In baseName : JEVEUX base name for output objects +! In nodeCoorName : JEVEUX name for coordinates of nodes +! In iPair : index of pair +! Out poinInteReal : coordinates of intersection points en global space +! +! -------------------------------------------------------------------------------------------------- +! + type(CELL_GEOM) :: cellSlav + integer :: nbPoinInte + real(kind=8) :: poinInteSlav(2, MAX_NB_INTE) + real(kind=8), pointer :: nodeCoor(:) => null() +! +! -------------------------------------------------------------------------------------------------- +! + poinInteReal = 0.d0 + +! - Access to updated geometry + call jeveuo(nodeCoorName(1:19)//'.VALE', 'L', vr=nodeCoor) + +! - Access to pair objects + call getPairJV(mesh, baseName, nodeCoor, iPair+1, cellSlav_=cellSlav) + +! - Get coordinates of intersection points in slave parametric space + call getInteJV(baseName, iPair+1, nbPoinInte, poinInteSlav) + +! - Project coordinates + call intePoinCoor(cellSlav, nbPoinInte, poinInteSlav, poinInteReal) +! +end subroutine diff --git a/bibfor/mesh/mesh_cell_module.F90 b/bibfor/mesh/mesh_cell_module.F90 new file mode 100644 index 00000000000..ebdd54e859a --- /dev/null +++ b/bibfor/mesh/mesh_cell_module.F90 @@ -0,0 +1,1120 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +! ================================================================================================== +! +! Module for cells in mesh +! +! ================================================================================================== +! +module mesh_cell_module +! ================================================================================================== + use mesh_type +! ================================================================================================== + implicit none +! ================================================================================================== + public :: cellCreate + public :: cellCompTang, cellCompNorm, cellCompBaseAtPoint, cellCompNormAtBary + public :: cellCompDiam, cellCompBary, cellCompCenterGlob + public :: cellDebug, cellCopyType, cellPoinParaToGlob + public :: cellPoinInside, cellPoinAdjust + public :: cellSetType + private :: cellSetCoorGlob, cellSetLine, cellSetUndef + private :: cellCompCenterPara, cellSetNbNeigh + private :: cellPoinAdjustSeg, cellPoinAdjustTria, cellPoinAdjustQuad +! ================================================================================================== + private +#include "asterc/r8nnem.h" +#include "asterf_types.h" +#include "asterfort/assert.h" +#include "asterfort/elrfdf.h" +#include "asterfort/elrfno.h" +#include "asterfort/elrfvf.h" +#include "asterfort/jenuno.h" +#include "asterfort/jexnum.h" +#include "asterfort/normev.h" +#include "asterfort/provec.h" +#include "jeveux.h" +#include "MeshTypes_type.h" +! ================================================================================================== +contains +! -------------------------------------------------------------------------------------------------- +! +! cellCreate +! +! Create a cell +! +! In cellNume : index of cell in mesh +! Ptr nodeCoor : pointer to coordinates of nodes +! Ptr meshTypeGeom : pointer to type of cells in mesh +! Ptr meshConx : pointers to connectivity of mesh +! meshConxCumu +! Out cellGeom : general geometric properties of cell +! Out cellGeomLine : general geometric properties of cell after linearization +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCreate(cellNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellGeom, cellGeomLine_) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: cellNume + real(kind=8), pointer :: nodeCoor(:) + integer, pointer :: meshTypeGeom(:), meshConx(:), meshConxCumu(:) + type(CELL_GEOM), intent(out) :: cellGeom + type(CELL_GEOM), optional, intent(out) :: cellGeomLine_ +! ------------------------------------------------------------------------------------------------ +! + +! ----- Set type of cell from mesh + call cellSetType(meshTypeGeom, cellNume, cellGeom) + +! ----- Set coordinates of cell (in global space) + call cellSetCoorGlob(cellNume, nodeCoor, & + meshConx, meshConxCumu, & + cellGeom) + +! ----- Compute barycenters + call cellCompBary(cellGeom) + +! ----- Compute diameter + call cellCompDiam(cellGeom) + +! ----- Linearize cell + if (present(cellGeomLine_)) then + call cellSetLine(cellGeom, cellGeomLine_) + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellSetType +! +! Get type of cell +! +! Ptr meshTypeGeom : geometric type of cells +! In cellNume : index of cell in mesh +! IO cellGeom : geometric properties of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellSetType(meshTypeGeom, cellNume, cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, pointer :: meshTypeGeom(:) + integer, intent(in) :: cellNume + type(CELL_GEOM), intent(inout) :: cellGeom +! ----- Local + integer :: cellTypeNume, nbNode, nbNodeS, cellDime + character(len=8) :: cellTypeName +! ------------------------------------------------------------------------------------------------ +! + cellTypeNume = meshTypeGeom(cellNume) + call jenuno(jexnum('&CATA.TM.NOMTM', cellTypeNume), cellTypeName) + select case (cellTypeName) + case ('SEG2') + cellGeom%cellCode = 'SE2' + case ('SEG3') + cellGeom%cellCode = 'SE3' + case ('TRIA3') + cellGeom%cellCode = 'TR3' + case ('TRIA6') + cellGeom%cellCode = 'TR6' + case ('QUAD4') + cellGeom%cellCode = 'QU4' + case ('QUAD8') + cellGeom%cellCode = 'QU8' + case ('QUAD9') + cellGeom%cellCode = 'QU9' + case default + ASSERT(ASTER_FALSE) + end select + +! ----- Prov: all cells are skin's ones + cellGeom%isSkin = ASTER_TRUE + +! ----- For standard cells + call elrfno(cellGeom%cellCode, nbNode, nbNodeS, cellDime, nodeCoor=cellGeom%coorNodePara) + cellGeom%nbNode = nbNode + cellGeom%cellDime = cellDime + cellGeom%isLinear = (nbNode .eq. nbNodeS) + if (cellGeom%isSkin) then + call cellSetNbNeigh(cellGeom) + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellSetCoorGlob +! +! Set coordinates of cell (in global reference frame) +! +! In cellNume : index of cell in mesh +! Ptr nodeCoor : pointer to coordinates of nodes for this cell +! Ptr meshConnex : pointer to connectivity of mesh +! Ptr meshConnexCumu : pointer to connectivity of mesh +! IO cellGeom : geometric properties of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellSetCoorGlob(cellNume, nodeCoor, & + meshConnex, meshConnexCumu, & + cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: cellNume + real(kind=8), pointer :: nodeCoor(:) + integer, pointer :: meshConnex(:), meshConnexCumu(:) + type(CELL_GEOM), intent(inout) :: cellGeom +! ----- Local + integer :: iNode, iDime, nodeNume +! ------------------------------------------------------------------------------------------------ +! + cellGeom%coorNodeGlob = 0.d0 + do iNode = 1, cellGeom%nbNode + nodeNume = meshConnex(meshConnexCumu(cellNume)-1+iNode) + do iDime = 1, 3 + cellGeom%coorNodeGlob(iDime, iNode) = & + nodeCoor(3*(nodeNume-1)+iDime) + end do + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellSetLine +! +! Linearization of cell +! +! In cellGeom : geometric properties of cell +! Out cellGeomLine : geometry of cell after linearization +! +! -------------------------------------------------------------------------------------------------- + subroutine cellSetLine(cellGeom, cellGeomLine) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + type(CELL_GEOM), intent(out) :: cellGeomLine +! ------------------------------------------------------------------------------------------------ +! + cellGeomLine = cellGeom + +! ----- Change support + if (cellGeom%cellCode .eq. 'SE2' .or. cellGeom%cellCode .eq. 'SE3') then + cellGeomLine%cellCode = 'SE2' + cellGeomLine%nbNode = 2 + elseif (cellGeom%cellCode .eq. 'TR3' .or. cellGeom%cellCode .eq. 'TR6') then + cellGeomLine%cellCode = 'TR3' + cellGeomLine%nbNode = 3 + else if (cellGeom%cellCode .eq. 'QU4' .or. & + cellGeom%cellCode .eq. 'QU8' .or. & + cellGeom%cellCode .eq. 'QU9') then + cellGeomLine%cellCode = 'QU4' + cellGeomLine%nbNode = 4 + else + WRITE (6, *) "cellGeom%cellCode: ", cellGeom%cellCode + ASSERT(ASTER_FALSE) + end if + cellGeomLine%isLinear = ASTER_TRUE + +! ----- Change coordinates + cellGeomLine%coorNodeGlob(:, cellGeomLine%nbNode+1:MT_NNOMAX3D) = 0.d0 + cellGeomLine%coorNodePara(:, cellGeomLine%nbNode+1:MT_NNOMAX3D) = 0.d0 + +! ----- Update barycenter + call cellCompBary(cellGeomLine) + +! ----- Update diameter + call cellCompDiam(cellGeomLine) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellSetUndef +! +! Set undefined values for cell +! +! IO cellGeom : geometric properties of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellSetUndef(cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(inout) :: cellGeom +! ------------------------------------------------------------------------------------------------ +! + cellGeom%diameter = r8nnem() + cellGeom%baryGlob = r8nnem() + cellGeom%baryPara = r8nnem() + cellGeom%coorNodeGlob = r8nnem() + cellGeom%coorNodePara = r8nnem() +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompTang +! +! Compute tangents on cell at current point +! +! In cellGeom : geometric properties of cell +! In spaceDime : dimension of space (2 or 3) +! In dShapeFunc : values of derivatives of shape functions at current point +! Out tau1 : first tangent at current point +! Out tau2 : second tangent at current point +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompTang(cellGeom, spaceDime, dShapeFunc, tau1, tau2) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + integer, intent(in) :: spaceDime + real(kind=8), intent(in) :: dShapeFunc(3, MT_NNOMAX3D) + real(kind=8), intent(out) :: tau1(3), tau2(3) +! ----- Local + real(kind=8), parameter :: zero = 0.d0 + integer :: iNode, iDime +! ------------------------------------------------------------------------------------------------ +! + ASSERT(cellGeom%nbNode .le. MT_NNOMAX3D) + tau1 = zero + tau2 = zero + do iDime = 1, spaceDime + do iNode = 1, cellGeom%nbNode + tau1(iDime) = cellGeom%coorNodeGlob(iDime, iNode)*dShapeFunc(1, iNode)+tau1(iDime) + if (spaceDime .eq. 3) then + tau2(iDime) = cellGeom%coorNodeGlob(iDime, iNode)*dShapeFunc(2, iNode)+ & + tau2(iDime) + end if + end do + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompBaseAtPoint +! +! Compute base at point (outward normal) +! +! In cellGeom : geometric properties of cell +! In spaceDime : dimension of space (2 or 3) +! In poinCoorPara : coordinates of point in parametric space +! Out baseExte : base on point (with outward normal) +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompBaseAtPoint(cellGeom, spaceDime, poinCoorPara, baseExte) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + integer, intent(in) :: spaceDime + real(kind=8), intent(in) :: poinCoorPara(3) + type(CELL_SKIN_BASE), intent(out) :: baseExte +! ----- Local + real(kind=8) :: dShapeFunc(3, MT_NNOMAX3D), tau1(3), tau2(3), norm(3) +! ------------------------------------------------------------------------------------------------ +! + ASSERT(cellGeom%isSkin) + baseExte%spaceDime = spaceDime + baseExte%normIsExte = ASTER_TRUE + baseExte%norm = 0.d0 + baseExte%tau = 0.d0 + call elrfdf(cellGeom%cellCode, poinCoorPara, dShapeFunc) + call cellCompTang(cellGeom, spaceDime, dShapeFunc, tau1, tau2) + call cellCompNorm(spaceDime, tau1, tau2, norm) + baseExte%norm = -norm + baseExte%tau(:, 1) = tau1 + baseExte%tau(:, 2) = tau2 +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompNorm +! +! Compute norm +! +! In spaceDime : dimension of space (2 or 3) +! In tau1 : first tangent +! In tau2 : second tangent +! Out norm : norm +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompNorm(spaceDime, tau1, tau2, norm) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: spaceDime + real(kind=8), intent(in) :: tau1(3), tau2(3) + real(kind=8), intent(out) :: norm(3) +! ----- Local + real(kind=8) :: noor +! ------------------------------------------------------------------------------------------------ +! + norm = 0.d0 + noor = 0.d0 + if (spaceDime .eq. 2) then + norm(1) = -tau1(2) + norm(2) = tau1(1) + norm(3) = 0.d0 + else if (spaceDime .eq. 3) then + call provec(tau2, tau1, norm) + else + ASSERT(ASTER_FALSE) + end if + call normev(norm, noor) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellPoinParaToGlob +! +! Change coordinates of a point in cell to global reference frame +! +! In cellGeom : geometric properties of cell +! In poinCoorPara : coordinates of point in cell parametric frame +! Out poinCoorGlob : coordinates of point in global reference frame +! +! -------------------------------------------------------------------------------------------------- + subroutine cellPoinParaToGlob(cellGeom, & + poinCoorPara, poinCoorGlob) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(in) :: poinCoorPara(2) + real(kind=8), intent(out) :: poinCoorGlob(3) +! ----- Local + real(kind=8) :: shapeFunc(MT_NNOMAX3D) + integer :: iNode, iDime +! ------------------------------------------------------------------------------------------------ +! + poinCoorGlob = 0.d0 + +! ----- Get shape functions in parametric space + shapeFunc = 0.d0 + call elrfvf(cellGeom%cellCode, poinCoorPara, shapeFunc) + +! ----- Change coordinates + do iDime = 1, 3 + do iNode = 1, cellGeom%nbNode + poinCoorGlob(iDime) = poinCoorGlob(iDime)+ & + cellGeom%coorNodeGlob(iDime, iNode)*shapeFunc(iNode) + end do + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompCenterPara +! +! Compute center of cell in parametric space +! +! In cellGeom : geometric properties of cell +! Out cellCentPara : center of cell in parametric space +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompCenterPara(cellGeom, cellCentPara) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(out) :: cellCentPara(3) +! ----- Local + integer :: iNode +! ------------------------------------------------------------------------------------------------ +! + cellCentPara = 0.d0 + do iNode = 1, cellGeom%nbNode + cellCentPara = cellCentPara+cellGeom%coorNodePara(:, iNode) + end do + cellCentPara = cellCentPara/cellGeom%nbNode +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompCenterGlob +! +! Compute center of cell in global space +! +! In cellGeom : geometric properties of cell +! Out cellCentPara : center of cell in parametric space +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompCenterGlob(cellGeom, cellCentGlob) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(out) :: cellCentGlob(3) +! ----- Local + real(kind=8) :: cellCentPara(3) +! ------------------------------------------------------------------------------------------------ +! + cellCentGlob = 0.d0 + call cellCompCenterPara(cellGeom, cellCentPara) + call cellPoinParaToGlob(cellGeom, cellCentPara, cellCentGlob) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompDiam +! +! Compute diameter of cell +! +! IO cellGeom : geometry of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompDiam(cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(inout) :: cellGeom +! ----- Locals + integer :: iNode, jNode + real(kind=8) :: length +! ------------------------------------------------------------------------------------------------ +! + cellGeom%diameter = 0.d0 + do iNode = 1, cellGeom%nbNode + do jNode = iNode+1, cellGeom%nbNode + length = norm2(cellGeom%coorNodeGlob(1:3, iNode)- & + cellGeom%coorNodeGlob(1:3, jNode)) + cellGeom%diameter = max(cellGeom%diameter, length) + end do + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompBary +! +! Compute barycenters of cell +! +! In spaceDime : dimension of space (2 or 3) +! IO cellGeom : geometry of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompBary(cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(inout) :: cellGeom +! ----- Local + real(kind=8) :: cellBaryPara(3) + integer :: iNode +! ------------------------------------------------------------------------------------------------ +! + cellGeom%baryGlob = 0.d0 + do iNode = 1, cellGeom%nbNode + cellGeom%baryGlob = cellGeom%baryGlob+ & + cellGeom%coorNodeGlob(:, iNode) + end do + cellGeom%baryGlob = cellGeom%baryGlob/real(cellGeom%nbNode, kind=8) + call cellCompCenterPara(cellGeom, cellBaryPara) + cellGeom%baryPara = cellBaryPara +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCompNormAtBary +! +! Compute normal at barycenter of cell +! +! In spaceDime : dimension of space (2 or 3) +! In cellGeom : geometric properties of cell +! Out cellNormBary : normal at barycenter of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCompNormAtBary(spaceDime, cellGeom, cellNormBary) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: spaceDime + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(out) :: cellNormBary(3) +! ----- Local + real(kind=8) :: cellCentPara(3) + type(CELL_SKIN_BASE) :: baseExte +! ------------------------------------------------------------------------------------------------ +! + cellNormBary = 0.d0 + ASSERT(cellGeom%isSkin) + +! ----- Get center of cell in parametric space + cellCentPara = cellGeom%baryPara + +! ----- Compute base on point (outward normal) + call cellCompBaseAtPoint(cellGeom, spaceDime, cellCentPara, baseExte) + cellNormBary = baseExte%norm +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellSetNbNeigh +! +! Set number of neighbours of skin cell +! +! IO cellGeom : geometric properties of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellSetNbNeigh(cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(inout) :: cellGeom +! ----- Local + integer :: nbNeigh +! ------------------------------------------------------------------------------------------------ +! + nbNeigh = 0 + ASSERT(cellGeom%isSkin) + if (cellGeom%cellCode == 'SE2' .or. & + cellGeom%cellCode == 'SE3') then + nbNeigh = 2 + elseif (cellGeom%cellCode == 'TR3' .or. & + cellGeom%cellCode == 'TR6' .or. & + cellGeom%cellCode == 'TR7') then + nbNeigh = 3 + elseif (cellGeom%cellCode == 'QU4' .or. & + cellGeom%cellCode == 'QU8' .or. & + cellGeom%cellCode == 'QU9') then + nbNeigh = 4 + else + ASSERT(ASTER_FALSE) + end if + cellGeom%nbNeigh = nbNeigh +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellDebug +! +! Print debug informations about cell +! +! In cellGeom : geometric properties of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellDebug(cellGeom) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom +! ----- Locals + integer :: iNode +! ------------------------------------------------------------------------------------------------ +! + if (cellGeom%isLinear) then + WRITE (6, *) "Linéaire" + else + WRITE (6, *) "Quadratique" + end if + if (cellGeom%isSkin) then + WRITE (6, *) "Maille de bord" + else + WRITE (6, *) "Maille d'intérieur" + end if + WRITE (6, *) "Type :", cellGeom%cellCode + WRITE (6, *) "Dime :", cellGeom%cellDime + WRITE (6, *) "Nb node :", cellGeom%nbNode + do iNode = 1, cellGeom%nbNode + WRITE (6, *) "Node (", iNode, "): ", & + cellGeom%coorNodeGlob(1:3, iNode), " (global frame)" + WRITE (6, *) "Node (", iNode, "): ", & + cellGeom%coorNodePara(1:3, iNode), " (local frame)" + end do + WRITE (6, *) "Diameter :", cellGeom%diameter + WRITE (6, *) "Barycenter:", cellGeom%baryGlob, " (global frame)" + WRITE (6, *) "Barycenter:", cellGeom%baryPara, " (local frame)" +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellCopyType +! +! Create new cell with same geometric type +! +! In cellGeom : geometric properties of original cell +! Out cellCopy : geometric properties of new cell +! +! -------------------------------------------------------------------------------------------------- + subroutine cellCopyType(cellOrig, cellCopy) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellOrig + type(CELL_GEOM), intent(out) :: cellCopy +! ----- Locals + +! ------------------------------------------------------------------------------------------------ +! + cellCopy = cellOrig + call cellSetUndef(cellCopy) +! +! ------------------------------------------------------------------------------------------------ + end subroutine + +! -------------------------------------------------------------------------------------------------- +! +! cellPoinInside +! +! Detect if point is inside cell - With its own reference frame +! +! In toleInside : tolerance to detect +! In cellGeom : geometric properties of cell +! In poinCoorPara : parametric coordinates of point +! Out poinIsInside +! +! -------------------------------------------------------------------------------------------------- + function cellPoinInside(cellGeom, toleInside, poinCoorPara) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + aster_logical :: cellPoinInside + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(in) :: toleInside + real(kind=8), intent(in) :: poinCoorPara(2) +! ----- Local + character(len=8) :: cellCode +! ------------------------------------------------------------------------------------------------ +! + cellCode = cellGeom%cellCode + ASSERT(cellGeom%isSkin) + cellPoinInside = ASTER_FALSE + if (cellCode .eq. 'SE2' .or. cellCode .eq. 'SE3') then + if (poinCoorPara(1) .ge. (-1.d0-toleInside) .and. & + poinCoorPara(1) .le. (1.d0+toleInside)) then + cellPoinInside = ASTER_TRUE + end if + elseif (cellCode .eq. 'TR3' .or. cellCode .eq. 'TR6') then + if (poinCoorPara(1) .ge. -toleInside .and. & + poinCoorPara(2) .ge. -toleInside .and. & + (poinCoorPara(2)+poinCoorPara(1)) .le. (1.d0+toleInside)) then + cellPoinInside = ASTER_TRUE + end if + elseif (cellCode .eq. 'QU4' .or. cellCode .eq. 'QU8' .or. cellCode .eq. 'QU9') then + if (poinCoorPara(1) .ge. (-1.d0-toleInside) .and. & + poinCoorPara(1) .le. (1.d0+toleInside) .and. & + poinCoorPara(2) .ge. (-1.d0-toleInside) .and. & + poinCoorPara(2) .le. (1.d0+toleInside)) then + cellPoinInside = ASTER_TRUE + end if + else + ASSERT(ASTER_FALSE) + end if +! +! ------------------------------------------------------------------------------------------------ + end function +! -------------------------------------------------------------------------------------------------- +! +! cellPoinAdjust +! +! Adjust parametric coordinates to be inside cell +! +! In cellGeom : geometric properties of cell +! In projOutside : tolerance for projection outside cell +! IO poinCoorPara : coordinates of point +! Out projType : type of projection +! 0 - No projection inside cell (point is inside) +! 1 - Projection inside cell +! 2 - No projection inside cell (to far away) +! +! -------------------------------------------------------------------------------------------------- + subroutine cellPoinAdjust(cellGeom, projOutside, & + poinCoorPara, projType_) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(in) :: projOutside + real(kind=8), intent(inout) :: poinCoorPara(2) + integer, optional, intent(out) :: projType_ +! ----- Local + integer :: projType + character(len=8) :: cellCode +! ------------------------------------------------------------------------------------------------ +! + projType = 0 + cellCode = cellGeom%cellCode + ASSERT(cellGeom%isSkin) + + if (cellCode(1:2) .eq. 'SE') then + call cellPoinAdjustSeg(projOutside, & + poinCoorPara, projType) + else if (cellCode(1:2) .eq. 'TR') then + call cellPoinAdjustTria(projOutside, & + poinCoorPara, projType) + else if (cellCode(1:2) .eq. 'QU') then + call cellPoinAdjustQuad(projOutside, & + poinCoorPara, projType) + else + ASSERT(ASTER_FALSE) + end if +! + if (present(projType_)) then + projType_ = projType + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellPoinAdjustSeg +! +! Adjust parametric coordinates to be inside cell when cell is segment +! +! In projOutside : tolerance for projection outside cell +! IO poinCoorPara : coordinates of point +! Out projType : type of projection +! 0 - No projection inside cell (point is inside) +! 1 - Projection inside cell +! 2 - No projection inside cell (to far away) +! +! -------------------------------------------------------------------------------------------------- + subroutine cellPoinAdjustSeg(projOutside, & + poinCoorPara, projType) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + real(kind=8), intent(in) :: projOutside + real(kind=8), intent(inout) :: poinCoorPara(2) + integer, intent(out) :: projType +! ----- Local + aster_logical :: near + real(kind=8) :: ecart +! tolerances --- absolue et relative --- pour determiner si deux distances sont egales + real(kind=8), parameter :: atol = 1.e-12 + real(kind=8), parameter :: rtol = 1.e-12 +! ------------------------------------------------------------------------------------------------ +! + projType = 0 + ecart = -1.d0 + +! ----- Premier ajustement : on positionne le point sur le bord, s'il est à une distance +! ----- (normalisée) inférieure a atol du bord + if (abs(poinCoorPara(1)+1.d0) .le. atol) then + poinCoorPara(1) = -1.d0 + end if + if (abs(poinCoorPara(1)-1.d0) .le. atol) then + poinCoorPara(1) = +1.d0 + end if + +! ----- RABATTEMENT + if ((poinCoorPara(1) .lt. -1.d0) .or. (poinCoorPara(1) .gt. 1.d0)) then + ecart = abs(poinCoorPara(1))-1.d0 + projType = 1 + if (poinCoorPara(1) .lt. -1.d0) then + poinCoorPara(1) = -1.d0 + else if (poinCoorPara(1) .gt. 1.d0) then + poinCoorPara(1) = 1.d0 + end if + near = abs(ecart-projOutside) .le. (atol+projOutside*rtol) + if (ecart .gt. projOutside .and. .not. near) then + projType = 2 + end if + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellPoinAdjustTria +! +! Adjust parametric coordinates to be inside cell when cell is triangle +! +! In projOutside : tolerance for projection outside cell +! IO poinCoorPara : coordinates of point +! Out projType : type of projection +! 0 - No projection inside cell (point is inside) +! 1 - Projection inside cell +! 2 - No projection inside cell (to far away) +! +! -------------------------------------------------------------------------------------------------- + subroutine cellPoinAdjustTria(projOutside, & + poinCoorPara, projType) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + real(kind=8), intent(in) :: projOutside + real(kind=8), intent(inout) :: poinCoorPara(2) + integer, intent(out) :: projType +! ----- Local + integer :: izone + aster_logical :: near + real(kind=8) :: ecart, k1pk2, k2mk1, ksi1e, ksi2e +! tolerances --- absolue et relative --- pour determiner si deux distances sont egales + real(kind=8), parameter :: atol = 1.e-12 + real(kind=8), parameter :: rtol = 1.e-12 +! ------------------------------------------------------------------------------------------------ +! + projType = 0 + ecart = -1.d0 + k1pk2 = poinCoorPara(1)+poinCoorPara(2) + k2mk1 = poinCoorPara(2)-poinCoorPara(1) + +! ----- Premier ajustement : on positionne le point sur le bord, s'il est à une distance +! ----- (normalisée) inférieure a atol du bord + if (abs(poinCoorPara(1)) .le. atol) then + poinCoorPara(1) = 0.d0 + end if + if (abs(poinCoorPara(2)) .le. atol) then + poinCoorPara(2) = 0.d0 + end if + if (abs(k1pk2-1.d0) .le. atol) then + k1pk2 = +1.d0 + end if + if (abs(k2mk1+1.d0) .le. atol) then + k2mk1 = -1.d0 + end if + if (abs(k2mk1-1.d0) .le. atol) then + k2mk1 = +1.d0 + end if + if ((poinCoorPara(1) .ge. 0.d0) .and. (poinCoorPara(2) .ge. 0.d0) .and. & + (k1pk2 .le. 1.d0)) then + goto 99 + end if + +! ----- SECTEUR CONCERNE + izone = 0 + if (poinCoorPara(1) .lt. 0.d0) then + if (poinCoorPara(2) .lt. 0.d0) then + izone = 1 + else if ((poinCoorPara(2) .ge. 0.d0) .and. (poinCoorPara(2) .le. 1.d0)) then + izone = 2 + else if (poinCoorPara(2) .gt. 1.d0) then + izone = 3 + else + ASSERT(ASTER_FALSE) + end if + end if + if (poinCoorPara(2) .lt. 0.d0) then + if (poinCoorPara(1) .lt. 0.d0) then + izone = 1 + else if ((poinCoorPara(1) .ge. 0.d0) .and. (poinCoorPara(1) .le. 1.d0)) then + izone = 8 + else if (poinCoorPara(1) .gt. 1.d0) then + izone = 7 + else + ASSERT(ASTER_FALSE) + end if + end if + if (poinCoorPara(1) .ge. 0.d0) then + if (k2mk1 .gt. 1.d0) then + izone = 4 + elseif ((k1pk2 .gt. 1.d0) .and. (k2mk1 .ge. -1.d0) & + .and. (k2mk1 .le. 1.d0)) then + izone = 5 + ksi1e = 5.d-1*(1.d0+poinCoorPara(1)-poinCoorPara(2)) + ksi2e = 5.d-1*(1.d0-poinCoorPara(1)+poinCoorPara(2)) + else if ((poinCoorPara(2) .ge. 0.d0) .and. (k2mk1 .lt. -1.d0)) then + izone = 6 + end if + end if + +! ----- CALCUL DE L'ECART + if (izone .eq. 1) then + ecart = sqrt(abs(poinCoorPara(1))*abs(poinCoorPara(1))+ & + abs(poinCoorPara(2))*abs(poinCoorPara(2))) + else if (izone .eq. 2) then + ecart = sqrt(abs(poinCoorPara(1))*abs(poinCoorPara(1))) + else if (izone .eq. 3 .or. izone .eq. 4) then + ecart = sqrt(abs(poinCoorPara(1))*abs(poinCoorPara(1))+ & + (poinCoorPara(2)-1.d0)*(poinCoorPara(2)-1.d0)) + else if (izone .eq. 5) then + ecart = sqrt((poinCoorPara(1)-ksi1e)*(poinCoorPara(1)-ksi1e)+ & + (poinCoorPara(2)-ksi2e)*(poinCoorPara(2)-ksi2e)) + else if (izone .eq. 6 .or. izone .eq. 7) then + ecart = sqrt(abs(poinCoorPara(2))*abs(poinCoorPara(2))+ & + (poinCoorPara(1)-1.d0)*(poinCoorPara(1)-1.d0)) + else if (izone .eq. 8) then + ecart = sqrt(abs(poinCoorPara(2))*abs(poinCoorPara(2))) + else + ASSERT(ASTER_FALSE) + end if + +! ----- RABATTEMENT + projType = 1 + if (izone .eq. 1) then + poinCoorPara(1) = 0.d0 + poinCoorPara(2) = 0.d0 + else if (izone .eq. 2) then + poinCoorPara(1) = 0.d0 + else if (izone .eq. 3 .or. izone .eq. 4) then + poinCoorPara(1) = 0.d0 + poinCoorPara(2) = 1.d0 + else if (izone .eq. 5) then + poinCoorPara(1) = ksi1e + poinCoorPara(2) = ksi2e + else if (izone .eq. 6 .or. izone .eq. 7) then + poinCoorPara(1) = 1.d0 + poinCoorPara(2) = 0.d0 + else if (izone .eq. 8) then + poinCoorPara(2) = 0.d0 + end if + + near = abs(ecart-projOutside) .le. (atol+projOutside*rtol) + if (ecart .gt. projOutside .and. .not. near) then + projType = 2 + end if +99 continue +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellPoinAdjustQuad +! +! Adjust parametric coordinates to be inside cell when cell is quadrangle +! +! In projOutside : tolerance for projection outside cell +! IO poinCoorPara : coordinates of point +! Out projType : type of projection +! 0 - No projection inside cell (point is inside) +! 1 - Projection inside cell +! 2 - No projection inside cell (to far away) +! +! -------------------------------------------------------------------------------------------------- + subroutine cellPoinAdjustQuad(projOutside, & + poinCoorPara, projType) +! ------------------------------------------------------------------------------------------------ +! ----- Parameter + real(kind=8), intent(in) :: projOutside + real(kind=8), intent(inout) :: poinCoorPara(2) + integer, intent(out) :: projType +! ----- Local + integer :: izone + aster_logical :: near + real(kind=8) :: ecart, k1pk2, k2mk1 +! tolerances --- absolue et relative --- pour determiner si deux distances sont egales + real(kind=8), parameter :: atol = 1.e-12 + real(kind=8), parameter :: rtol = 1.e-12 +! ------------------------------------------------------------------------------------------------ +! + projType = 0 + ecart = -1.d0 + k1pk2 = poinCoorPara(1)+poinCoorPara(2) + k2mk1 = poinCoorPara(2)-poinCoorPara(1) + +! ----- Premier ajustement : on positionne le point sur le bord, s'il est à une distance +! ----- (normalisée) inférieure a atol du bord + if (abs(poinCoorPara(1)+1.d0) .le. atol) then + poinCoorPara(1) = -1.d0 + end if + if (abs(poinCoorPara(1)-1.d0) .le. atol) then + poinCoorPara(1) = +1.d0 + end if + if (abs(poinCoorPara(2)+1.d0) .le. atol) then + poinCoorPara(2) = -1.d0 + end if + if (abs(poinCoorPara(2)-1.d0) .le. atol) then + poinCoorPara(2) = +1.d0 + end if + if ((poinCoorPara(1) .ge. -1.d0) .and. (poinCoorPara(1) .le. 1.d0) .and. & + (poinCoorPara(2) .ge. -1.d0) .and. (poinCoorPara(2) .le. 1.d0)) then + goto 99 + end if + +! ----- SECTEUR CONCERNE + izone = 0 + if (poinCoorPara(1) .lt. -1.d0) then + if (poinCoorPara(2) .lt. -1.d0) then + izone = 1 + else if ((poinCoorPara(2) .ge. -1.d0) .and. (poinCoorPara(2) .le. 1.d0)) then + izone = 2 + else if (poinCoorPara(2) .gt. 1.d0) then + izone = 3 + else + ASSERT(ASTER_FALSE) + end if + end if + if (poinCoorPara(1) .gt. 1.d0) then + if (poinCoorPara(2) .lt. -1.d0) then + izone = 7 + else if ((poinCoorPara(2) .ge. -1.d0) .and. (poinCoorPara(2) .le. 1.d0)) then + izone = 6 + else if (poinCoorPara(2) .gt. 1.d0) then + izone = 5 + else + ASSERT(ASTER_FALSE) + end if + end if + if ((poinCoorPara(1) .ge. -1.d0) .and. (poinCoorPara(1) .le. 1.d0)) then + if (poinCoorPara(2) .lt. -1.d0) then + izone = 8 + else if (poinCoorPara(2) .gt. 1.d0) then + izone = 4 + end if + end if + +! ----- CALCUL DE L'ECART + if (izone .eq. 1) then + ecart = sqrt((abs(poinCoorPara(1))-1.d0)*(abs(poinCoorPara(1))-1.d0)+ & + (abs(poinCoorPara(2))-1.d0)*(abs(poinCoorPara(2))-1.d0)) + else if (izone .eq. 2) then + ecart = sqrt((abs(poinCoorPara(1))-1.d0)*(abs(poinCoorPara(1))-1.d0)) + else if (izone .eq. 3) then + ecart = sqrt((abs(poinCoorPara(1))-1.d0)*(abs(poinCoorPara(1))-1.d0)+ & + (abs(poinCoorPara(2))-1.d0)*(abs(poinCoorPara(2))-1.d0)) + else if (izone .eq. 4) then + ecart = sqrt((abs(poinCoorPara(2))-1.d0)*(abs(poinCoorPara(2))-1.d0)) + else if (izone .eq. 5) then + ecart = sqrt((abs(poinCoorPara(1))-1.d0)*(abs(poinCoorPara(1))-1.d0)+ & + (abs(poinCoorPara(2))-1.d0)*(abs(poinCoorPara(2))-1.d0)) + else if (izone .eq. 6) then + ecart = sqrt((abs(poinCoorPara(1))-1.d0)*(abs(poinCoorPara(1))-1.d0)) + else if (izone .eq. 7) then + ecart = sqrt((abs(poinCoorPara(1))-1.d0)*(abs(poinCoorPara(1))-1.d0)+ & + (abs(poinCoorPara(2))-1.d0)*(abs(poinCoorPara(2))-1.d0)) + else if (izone .eq. 8) then + ecart = sqrt((abs(poinCoorPara(2))-1.d0)*(abs(poinCoorPara(2))-1.d0)) + else + ASSERT(ASTER_FALSE) + end if + +! ----- RABATTEMENT + projType = 1 + if (izone .eq. 1) then + poinCoorPara(1) = -1.d0 + poinCoorPara(2) = -1.d0 + else if (izone .eq. 2) then + poinCoorPara(1) = -1.d0 + else if (izone .eq. 3) then + poinCoorPara(1) = -1.d0 + poinCoorPara(2) = 1.d0 + else if (izone .eq. 4) then + poinCoorPara(2) = 1.d0 + else if (izone .eq. 5) then + poinCoorPara(1) = 1.d0 + poinCoorPara(2) = 1.d0 + else if (izone .eq. 6) then + poinCoorPara(1) = 1.d0 + else if (izone .eq. 7) then + poinCoorPara(1) = 1.d0 + poinCoorPara(2) = -1.d0 + else if (izone .eq. 8) then + poinCoorPara(2) = -1.d0 + end if + + near = abs(ecart-projOutside) .le. (atol+projOutside*rtol) + if (ecart .gt. projOutside .and. .not. near) then + projType = 2 + end if +! +99 continue +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! +end module diff --git a/bibfor/mesh/mesh_operators_type.F90 b/bibfor/mesh/mesh_operators_type.F90 index ba994f8dfbb..affe4e29115 100644 --- a/bibfor/mesh/mesh_operators_type.F90 +++ b/bibfor/mesh/mesh_operators_type.F90 @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -15,45 +15,51 @@ ! You should have received a copy of the GNU General Public License ! along with code_aster. If not, see . ! -------------------------------------------------------------------- -! person_in_charge: mickael.abbas at edf.fr ! +! ================================================================================================== +! +! Module for types in MODI_MAILLAGE command +! +! ================================================================================================== module mesh_operators_type - ! +! ================================================================================================== use Behaviour_type - ! +! ================================================================================================== implicit none - ! +! ================================================================================================== + private #include "asterf_types.h" - ! ================================================================================================== -! ! Global variables -! ! ================================================================================================== - +! - Non ! ================================================================================================== -! -! Derivated types - Parameters from MODI_MAILLAGE command -! +! Define types ! ================================================================================================== - +! -------------------------------------------------------------------------------------------------- +! For MODI_MAILLAGE/ ORIE_NORM_COQUE operator +! -------------------------------------------------------------------------------------------------- type MESH_OPER_ORIE_SHELL aster_logical :: orieByVect = ASTER_FALSE real(kind=8) :: orieVect(3) = 0.d0 - integer :: nbGroupCell = 0 character(len=24), pointer :: listOfGroupOfCell(:) => null() - integer :: nodeNume = 0 - end type MESH_OPER_ORIE_SHELL - +! -------------------------------------------------------------------------------------------------- +! For MODI_MAILLAGE/ORIE_* operators +! -------------------------------------------------------------------------------------------------- type MESH_OPER_MODI_PARA integer :: orieShell = 0 type(MESH_OPER_ORIE_SHELL), pointer :: meshOperOrieShell(:) => null() integer :: orieSkin = 0 integer :: orieLine = 0 end type MESH_OPER_MODI_PARA - +!=================================================================================================== +!=================================================================================================== + public :: MESH_OPER_ORIE_SHELL, MESH_OPER_MODI_PARA +contains +!=================================================================================================== +!=================================================================================================== ! end module mesh_operators_type diff --git a/bibfor/mesh/mesh_pairing_module.F90 b/bibfor/mesh/mesh_pairing_module.F90 new file mode 100644 index 00000000000..6274c0d3c78 --- /dev/null +++ b/bibfor/mesh/mesh_pairing_module.F90 @@ -0,0 +1,2847 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! aslint: disable=W1306 +! +! ================================================================================================== +! +! Module for pairing meshes +! +! ================================================================================================== +! +module MeshPairing_module +! ================================================================================================== + use mesh_type + use mesh_cell_module +! ================================================================================================== + implicit none +! ================================================================================================== + public :: fastPair, robustPair, pairDeallocate, pairAllocate + public :: inteCellArea, intePoinCoor, quadPoinCoor + public :: getPairJV, getInteJV, pairAdd + private :: pairGetStartCells, getClosestNodesFromCell, getCellsFromNode + private :: cellInteProj, cellProjOnCell, nodeProjOnCell + private :: poinProjOnCell, poinProjByVect, poinIsInsideOtherCell + private :: inteCellChck, addPoinInte2D, addPoinInte3D, addPoinOnEdge + private :: inteCellSegm, intePoinSort, intePoinInCell + private :: isFatalError +! ================================================================================================== + private +#include "asterc/r8gaem.h" +#include "asterc/r8prem.h" +#include "asterf_types.h" +#include "asterfort/as_allocate.h" +#include "asterfort/as_deallocate.h" +#include "asterfort/assert.h" +#include "asterfort/elrfdf.h" +#include "asterfort/elrfvf.h" +#include "asterfort/jeexin.h" +#include "asterfort/jelira.h" +#include "asterfort/jeveuo.h" +#include "asterfort/jexatr.h" +#include "asterfort/mesh_pairing_type.h" +#include "asterfort/ordr8.h" +#include "asterfort/utmess.h" +#include "jeveux.h" +#include "MeshTypes_type.h" +! ================================================================================================== +! ================================================================================================== +! Global variables +! ================================================================================================== +! - Index of next nodes for segment, triangle and quadrangle + integer, parameter :: nodeNextSEG(2) = (/2, 1/) + integer, parameter :: nodeNextTRIA(3) = (/2, 3, 1/) + integer, parameter :: nodeNextQUAD(4) = (/2, 3, 4, 1/) +! - Index of previous nodes for triangle and quadrangle + integer, parameter :: nodePrevTRIA(3) = (/3, 1, 2/) + integer, parameter :: nodePrevQUAD(4) = (/4, 1, 2, 3/) +! ================================================================================================== +! Type for pairing +! ================================================================================================== + type MESH_PAIRING +! ----- Dimension of space (2 or 3) + integer :: spaceDime = 0 +! ----- Flag for debug (text) + aster_logical :: debug = ASTER_FALSE +! ----- Main tolerance for pairing + real(kind=8) :: pairTole = 0.d0 +! ----- Tolerance for extension of cell + real(kind=8) :: distRatio = 0.d0 +! ----- Number of pairs + integer :: nbPair = 0 +! ----- Pointer to pairs + integer, pointer :: pair(:) => null() +! ----- Pointer to list of intersection points + integer, pointer :: nbPoinInte(:) => null() + real(kind=8), pointer :: poinInte(:) => null() + end type MESH_PAIRING +! ================================================================================================== +! Type for parameters of projection algorithm +! ================================================================================================== + type MESH_PROJ_PARA +! ----- Parameters for algorithm + aster_logical :: debug = ASTER_FALSE + integer :: newtIterMaxi = 0 + real(kind=8) :: newtTole = 0.d0 +! ----- Coordinate of point to project (in global frame) + real(kind=8) :: coorPoinGlob(3) = 0.d0 +! ----- Dimension of space (2 or 3) + integer :: spaceDime = 0 +! ----- Vector to project + real(kind=8):: projVect(3) = 0.d0 +! ----- Coordinate of point after projection (in cell parametric space) + real(kind=8) :: coorProjPara(2) = 0.d0 +! ----- Tangents at projection of point + real(kind=8) :: tau1(3) = 0.d0, tau2(3) = 0.d0 +! ----- Return code + integer:: errorCode = 0 + end type MESH_PROJ_PARA +! ================================================================================================== + public :: MESH_PAIRING, nodeNextTRIA, nodeNextQUAD, nodePrevTRIA, nodePrevQUAD +! ================================================================================================== +contains +! -------------------------------------------------------------------------------------------------- +! +! fastPair +! +! Fast pairing on zone +! +! In mesh : mesh +! In newgeo : updated coordinates of nodes +! In mastConxInvName : name of object for inverse connectivity of master cells on current zone +! In mastNeighName : name of object for neighbours of master cells +! In slavNeighName : name of object for neighbours of slave cells +! In nbCellSlav : number of slave cells +! In nbCellMast : number of master cells +! In nbNodeMast : number of master nodes +! In listCellSlav : list of slave cells +! In listCellMast : list of master cells +! In listNodeMast : list of master nodes +! In meshPairing : main datastructure for pairing +! +! -------------------------------------------------------------------------------------------------- + subroutine fastPair(mesh, newgeo, mastConxInvName, & + mastNeighName, slavNeighName, & + nbCellSlav, nbCellMast, nbNodeMast, & + listCellSlav, listCellMast, listNodeMast, & + meshPairing) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: newgeo, mastConxInvName + character(len=24), intent(in) :: mastNeighName, slavNeighName + integer, intent(in) :: nbCellSlav, nbCellMast + integer, intent(in) :: listCellMast(nbCellMast), listCellSlav(nbCellSlav) + integer, intent(in) :: nbNodeMast + integer, intent(in) :: listNodeMast(nbNodeMast) + type(MESH_PAIRING), intent(inout) :: meshPairing +! ----- Local + aster_logical :: pair_exist, isFatal, l_recup + integer :: nbSlavStart, nbMastStart + integer, pointer :: cellSlavStart(:) => null() + integer, pointer :: cellMastStart(:) => null() + integer, pointer :: cellMastFlag(:) => null() + integer, pointer :: cellSlavFlag(:) => null(), cellMastPaired(:) => null() + integer :: slavIndxMini, slavIndxMaxi + integer :: mastIndxMini, mastIndxMaxi + integer :: iCell, iMastNeigh, iSlavNeigh + real(kind=8), pointer :: nodeCoor(:) => null() + integer, pointer :: meshTypeGeom(:) => null() + integer, pointer :: meshConx(:) => null(), meshConxCumu(:) => null() + integer, pointer :: mastConxInv(:) => null(), mastConxInvCumu(:) => null() + type(CELL_GEOM) :: cellSlav, cellMast + type(CELL_GEOM) :: cellSlavLine, cellMastLine + integer :: nbSlavNeigh, nbMastPaired, inteNeigh(MAX_NB_NEIGH), nbMastNeigh + integer :: cellNeigh(MAX_NB_NEIGH), iret + real(kind=8) :: inteArea + integer :: mastFindIndx, cellMastNume, cellMastIndx, cellSlavIndx, cellSlavNume + integer :: nbPoinInte + real(kind=8) :: poinInte(2, MAX_NB_INTE), poinInteReal(3, MAX_NB_INTE) + integer :: cellNeighNume, cellNeighIndx + integer, pointer :: meshMastNeigh(:) => null(), meshSlavNeigh(:) => null() +! ------------------------------------------------------------------------------------------------ +! + pair_exist = ASTER_TRUE + inteNeigh = 0 + cellNeigh = 0 + mastIndxMini = minval(listCellMast) + mastIndxMaxi = maxval(listCellMast) + slavIndxMaxi = maxval(listCellSlav) + slavIndxMini = minval(listCellSlav) + +! ----- Management of debug + if (meshPairing%debug) then + write (6, *) "================" + write (6, *) "= Fast pairing =" + write (6, *) "================" + write (6, *) " " + end if + +! ----- Access to updated geometry + call jeveuo(newgeo(1:19)//'.VALE', 'L', vr=nodeCoor) + +! ----- Access to mesh + call jeveuo(mesh(1:8)//'.TYPMAIL', 'L', vi=meshTypeGeom) + call jeveuo(mesh(1:8)//'.CONNEX', 'L', vi=meshConx) + call jeveuo(jexatr(mesh(1:8)//'.CONNEX', 'LONCUM'), 'L', vi=meshConxCumu) + call jeveuo(mastConxInvName, 'L', vi=mastConxInv) + call jeveuo(jexatr(mastConxInvName, 'LONCUM'), 'L', vi=mastConxInvCumu) + call jeveuo(mastNeighName, 'L', vi=meshMastNeigh) + call jeveuo(slavNeighName, 'L', vi=meshSlavNeigh) + +! ----- Protection + if (nbCellSlav .eq. 0 .or. nbCellMast .eq. 0) then + call utmess('F', 'MESH4_1') + end if + +! ----- List of starting cells + AS_ALLOCATE(vi=cellSlavStart, size=nbCellSlav) + AS_ALLOCATE(vi=cellMastStart, size=nbCellMast) + +! ----- Flag for slave cell usage status +! 0 - Never used +! 1 - Used as starting point +! 2 - Used + AS_ALLOCATE(vi=cellSlavFlag, size=slavIndxMaxi+1-slavIndxMini) + +! ----- Flag for master cell usage status +! 0 - Never used +! 1 - Used as starting point + AS_ALLOCATE(vi=cellMastFlag, size=mastIndxMaxi+1-mastIndxMini) + +! ----- Master elements paired with the current slave cell (number of master elements: nbMastPaired) + AS_ALLOCATE(vi=cellMastPaired, size=nbCellMast) + +! ----- While loop on the existence of a pair slave-master + do while (pair_exist) + if (meshPairing%debug) then + WRITE (6, *) "Get cells for starting search" + WRITE (6, *) "=============================" + end if +! --------- Get initial start cells + call pairGetStartCells(meshPairing, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + mastConxInv, mastConxInvCumu, & + nbCellSlav, listCellSlav, cellSlavFlag, & + nbCellMast, listCellMast, & + nbNodeMast, listNodeMast, & + nbMastStart, cellMastStart, & + nbSlavStart, cellSlavStart) + ASSERT(nbMastStart .le. 1) + ASSERT(nbSlavStart .le. 1) + if (meshPairing%debug) then + if (nbSlavStart .eq. 1 .and. nbMastStart .eq. 1) then + WRITE (6, *) " New starting point (M/S): ", cellMastStart(1), cellSlavStart(1) + else + WRITE (6, *) " Not new starting point (M/S)" + end if + end if + +! --------- No more slave cell + if (nbSlavStart == 0) then + pair_exist = ASTER_FALSE + end if + + do while (nbSlavStart > 0) +! ------------- Get slave element + cellSlavNume = cellSlavStart(1) + cellSlavIndx = cellSlavNume+1-slavIndxMini + +! ------------- Shift list of starting slave cells + do iCell = 1, nbSlavStart-1 + cellSlavStart(iCell) = cellSlavStart(iCell+1) + end do + nbSlavStart = nbSlavStart-1 + +! ------------- Create slave cell + call cellCreate(cellSlavNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellSlav, cellSlavLine) + + if (meshPairing%debug) then + write (6, *) "Current slave element : ", cellSlavNume + write (6, *) " Coordinates (global frame): ", & + cellSlav%coorNodeGlob(1:meshPairing%spaceDime, 1:cellSlav%nbNode) + end if + +! ------------- Get number of neighbours + nbSlavNeigh = cellSlav%nbNeigh + ASSERT(nbSlavNeigh .le. MAX_NB_NEIGH) + if (meshPairing%debug) then + write (6, *) "Potential number of neighbours: ", nbSlavNeigh + do iSlavNeigh = 1, nbSlavNeigh + cellNeighNume = meshSlavNeigh(4*(cellSlavIndx-1)+iSlavNeigh) + if (cellNeighNume .eq. 0) then + write (6, *) "Neighbour (", iSlavNeigh, "): " + else + write (6, *) "Neighbour (", iSlavNeigh, "): ", cellNeighNume + end if + end do + end if + cellNeigh = 0 + +! ------------- Get master element to start (don't use this starting cell for pairing) + cellMastNume = cellMastStart(1) + mastFindIndx = cellMastNume+1-mastIndxMini + cellMastFlag(mastFindIndx) = 1 + if (meshPairing%debug) then + WRITE (6, *) "Avant décalage" + WRITE (6, *) " => ", nbMastStart, cellMastStart(1:nbMastStart) + end if + +! ------------- Delete cell in the list of master element start + do iCell = 1, nbMastStart-1 + cellMastStart(iCell) = cellMastStart(iCell+1) + end do + nbMastStart = nbMastStart-1 + if (meshPairing%debug) then + WRITE (6, *) "Après décalage" + WRITE (6, *) " => ", nbMastStart, cellMastStart(1:nbMastStart) + end if + +! ------------- Management of list of master elements: first element to seek + cellMastPaired(1) = cellMastNume + nbMastPaired = 1 + if (meshPairing%debug) then + write (6, *) "Master cell to start: ", cellMastNume + end if + +! ------------- Initialization list of pairs + l_recup = ASTER_TRUE + +! ------------- Loop on master elements => Look for the master elements + do while (nbMastPaired > 0) + inteArea = 0.d0 + nbPoinInte = 0 + poinInte = 0.d0 + poinInteReal = 0.d0 + +! ----------------- Get master element + cellMastNume = cellMastPaired(1) + cellMastIndx = cellMastNume+1-mastIndxMini + +! ----------------- Shift list of master element to pair + do iCell = 1, nbMastPaired-1 + cellMastPaired(iCell) = cellMastPaired(iCell+1) + end do + nbMastPaired = nbMastPaired-1 + +! ----------------- Create master cell + call cellCreate(cellMastNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellMast, cellMastLine) + if (meshPairing%debug) then + write (6, *) "Current master element: ", cellMastNume + write (6, *) " Coordinates (global frame): ", & + cellMast%coorNodeGlob(1:meshPairing%spaceDime, 1:cellMast%nbNode) + end if + +! ----------------- Get number of neighbours + nbMastNeigh = cellMast%nbNeigh + ASSERT(nbMastNeigh .le. MAX_NB_NEIGH) + if (meshPairing%debug) then + write (6, *) "Potential number of neighbours: ", nbMastNeigh + end if + +! ----------------- Compute intersection of the two cells + if (meshPairing%debug) then + WRITE (6, *) "Compute intersection and projection in master space" + end if + call cellInteProj(meshPairing, & + cellSlav, cellSlavLine, cellMastLine, & + iret, & + nbPoinInte, poinInte, & + inteArea, inteNeigh) + isFatal = isFatalError(iret) + if (.not. isFatal .and. iret .ne. ERR_PAIR_NONE) then + call utmess('A', 'MESH4_3') + inteArea = 0.d0 + nbPoinInte = 0 + end if + ASSERT(nbPoinInte .le. MAX_NB_INTE) + if (meshPairing%debug) then + WRITE (6, *) "Intersection area: ", inteArea + end if + +! ----------------- Add pair + if (inteArea > meshPairing%pairTole .and. iret == ERR_PAIR_NONE) then + +! --------------------- Debug + if (meshPairing%debug) then +! ------------------------- Compute coordinates in global space for intersection points + call intePoinCoor(cellSlav, nbPoinInte, poinInte, poinInteReal) + WRITE (6, *) "Add pair: ", meshPairing%nbPair+1, & + "(", cellSlavNume, "-", cellMastNume, ")" + WRITE (6, *) "Nb points integrations : ", & + nbPoinInte + WRITE (6, *) "Coor. points integrations (parametric): ", & + poinInte(:, 1:nbPoinInte) + WRITE (6, *) "Coef. points integrations (global) : ", & + poinInteReal(:, 1:nbPoinInte) + WRITE (6, *) "Area of intersection : ", & + inteArea + end if +! --------------------- Add pair + call pairAdd(cellSlavNume, cellMastNume, & + nbPoinInte, poinInte, & + meshPairing) + end if + +! ----------------- Find neighbour of current master element + if (inteArea > meshPairing%pairTole .or. l_recup) then +! --------------------- Prepare next master element + if (meshPairing%debug) then + WRITE (6, *) "Prepare next master element" + end if + do iMastNeigh = 1, nbMastNeigh + cellNeighNume = meshMastNeigh(MAX_NB_NEIGH*(cellMastIndx-1)+iMastNeigh) + cellNeighIndx = cellNeighNume+1-mastIndxMini + if (cellNeighNume .ne. 0 .and. & + cellMastFlag(cellNeighIndx) .ne. 1) then + nbMastPaired = nbMastPaired+1 + cellMastPaired(nbMastPaired) = cellNeighNume + cellMastFlag(cellNeighIndx) = 1 + if (meshPairing%debug) then + WRITE (6, *) " => added: ", nbMastPaired, & + cellMastPaired(nbMastPaired) + end if + end if + end do + +! --------------------- Prepare next slave element + if (meshPairing%debug) then + WRITE (6, *) "Prepare next slave element" + end if + do iSlavNeigh = 1, nbSlavNeigh + cellNeighNume = meshSlavNeigh(MAX_NB_NEIGH*(cellSlavIndx-1)+iSlavNeigh) + cellNeighIndx = cellNeighNume+1-slavIndxMini + if (meshPairing%debug) then + WRITE (6, *) " < Index:", iSlavNeigh + WRITE (6, *) " < cellNeighNume:", cellNeighNume + WRITE (6, *) " < cellNeighIndx: ", cellNeighIndx + WRITE (6, *) " < cellSlavFlag: ", cellSlavFlag(cellNeighIndx) + WRITE (6, *) " < inteNeigh: ", inteNeigh(iSlavNeigh) + end if + if (cellNeighNume .ne. 0 .and. & + cellSlavFlag(cellNeighIndx) .ne. 1 .and. & + inteNeigh(iSlavNeigh) == 1) then + cellNeigh(iSlavNeigh) = cellMastNume + if (meshPairing%debug) then + WRITE (6, *) " => added: ", cellMastNume + end if + end if + end do + l_recup = ASTER_FALSE + end if + end do + +! ------------- Next elements + if (meshPairing%debug) then + WRITE (6, *) "Prepare next elements - Nb: ", nbSlavNeigh + end if + do iSlavNeigh = 1, nbSlavNeigh + cellNeighNume = meshSlavNeigh(MAX_NB_NEIGH*(cellSlavIndx-1)+iSlavNeigh) + cellNeighIndx = cellNeighNume+1-slavIndxMini + if (meshPairing%debug) then + write (*, *) 'Next elements - Current: ', iSlavNeigh, cellNeighNume, & + cellNeigh(iSlavNeigh), cellSlavFlag(cellNeighIndx) + end if + if (cellNeighNume .ne. 0 .and. & + cellNeigh(iSlavNeigh) .ne. 0 .and. & + cellSlavFlag(cellNeighIndx) .ne. 1) then + nbSlavStart = nbSlavStart+1 + cellSlavStart(nbSlavStart) = cellNeighNume + cellSlavFlag(cellNeighIndx) = 1 + nbMastStart = nbMastStart+1 + cellMastStart(nbMastStart) = cellNeigh(iSlavNeigh) + end if + end do + +! ------------- All master cells are candidates for pairing + cellMastFlag(1:mastIndxMaxi+1-mastIndxMini) = 0 + end do + !pair_exist = ASTER_FALSE + end do + +! ----- Clean memory + AS_DEALLOCATE(vi=cellSlavStart) + AS_DEALLOCATE(vi=cellMastStart) + AS_DEALLOCATE(vi=cellSlavFlag) + AS_DEALLOCATE(vi=cellMastFlag) + AS_DEALLOCATE(vi=cellMastPaired) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! nodeProjOnCell +! +! Project nodes of cell (origin) on another cell (target) in target parametric space using +! raytracing +! +! In meshPairing : main datastructure for pairing +! In cellOrig : geometric properties of cell to project +! In cellOrigLine : geometric properties of cell to project (linearized) +! In cellTargLine : geometric properties of cell where to project (linearized) +! IO cellProj : geometric properties of projected cell +! Out nbNodeProj : number of projected nodes +! Out iret : return code error +! +! -------------------------------------------------------------------------------------------------- + subroutine nodeProjOnCell(meshPairing, & + cellOrig, cellOrigLine, cellTargLine, & + cellProj, nbNodeProj, iret) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellOrig, cellOrigLine, cellTargLine + type(CELL_GEOM), intent(inout) :: cellProj + integer, intent(out) :: nbNodeProj, iret +! ----- Local + integer :: iNode, nbNode + real(kind=8) :: coorNodeGlob(3), coorNodePara(3), projNodePara(3), projNodeGlob(3) + type(CELL_SKIN_BASE) :: base + aster_logical :: errorProj +! ------------------------------------------------------------------------------------------------ +! + iret = ERR_PAIR_NONE + nbNodeProj = 0 + ASSERT(cellOrigLine%isLinear) + ASSERT(cellTargLine%isLinear) + + if (meshPairing%debug) then + WRITE (6, *) " Project nodes of cell on another cell using raytracing" + WRITE (6, *) " ======================================================" + end if + +! ----- Projected cell: same type as original one + call cellCopyType(cellOrigLine, cellProj) + cellProj%coorNodePara = 0.d0 + cellProj%coorNodeGlob = 0.d0 + +! ----- Project only vertices of original cell (linearized cell) + nbNode = cellOrigLine%nbNode + nbNodeProj = nbNode + if (meshPairing%debug) then + WRITE (6, *) " Number of nodes on original cell: ", nbNode + end if + do iNode = 1, nbNode + if (meshPairing%debug) then + WRITE (6, *) " Current node: ", iNode + end if + +! --------- Get coordinates of current node (real space and parametric space) + coorNodeGlob = cellOrigLine%coorNodeGlob(:, iNode) + coorNodePara = cellOrigLine%coorNodePara(:, iNode) + if (meshPairing%debug) then + WRITE (6, *) " Coordinate of node to project (local frame): ", & + coorNodePara + WRITE (6, *) " Coordinate of node to project (global frame): ", & + coorNodeGlob + end if + +! --------- Compute base on this node (outward normal) + call cellCompBaseAtPoint(cellOrig, meshPairing%spaceDime, coorNodePara, base) + if (meshPairing%debug) then + WRITE (6, *) " Normal at node to project: ", base%norm + end if + +! --------- Project node on target cell + call poinProjOnCell(meshPairing%spaceDime, meshPairing%pairTole, & + coorNodeGlob, base%norm, & + cellTargLine, & + projNodePara, errorProj) + +! --------- Careful ! projNodePara can be outside of reference frame ! + +! --------- Failure + if (errorProj) then + if (meshPairing%debug) then + WRITE (6, *) " Failure of projection of node" + end if + nbNodeProj = 0 + cellProj%coorNodePara = 0.d0 + cellProj%coorNodeGlob = 0.d0 + iret = ERR_PAIR_PROJ + exit + end if + +! --------- Transform coordinates of the projection in global space + call cellPoinParaToGlob(cellTargLine, projNodePara, projNodeGlob) + if (meshPairing%debug) then + WRITE (6, *) " Success of projection of node" + WRITE (6, *) " Coordinates of the projection of the node (local frame): ", & + projNodePara(1:2) + WRITE (6, *) " Coordinates of the projection of the node(global frame): ", & + projNodeGlob + end if + +! --------- Save projection of node for this cell + cellProj%coorNodePara(1:2, iNode) = projNodePara(1:2) + cellProj%coorNodeGlob(:, iNode) = projNodeGlob + + end do + +! ----- Update parameters for projected cell + call cellCompBary(cellProj) + call cellCompDiam(cellProj) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! poinProjOnCell +! +! Project a point on cell - Cell is linear +! +! In coorPoinGlob : coordinates of point in global frame +! In projTole : tolerance for projection +! In normPoint : normal at point +! In cellGeomTarget : cell where to project +! Out coorProjPara : coordinates of point in reference frame of target cell +! Out errorProj : error code +! +! -------------------------------------------------------------------------------------------------- + subroutine poinProjOnCell(spaceDime, projTole, & + coorPoinGlob, normPoint, & + cellGeomTarget, & + coorProjPara, errorProj) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: spaceDime + real(kind=8), intent(in) :: projTole + real(kind=8), intent(in) :: coorPoinGlob(3), normPoint(3) + type(CELL_GEOM), intent(in) :: cellGeomTarget + real(kind=8), intent(out) :: coorProjPara(3) + aster_logical, intent(out) :: errorProj +! ----- Local + aster_logical, parameter :: debug = ASTER_FALSE + type(MESH_PROJ_PARA) :: projPara +! ------------------------------------------------------------------------------------------------ +! + coorProjPara = 0.d0 + errorProj = ASTER_FALSE + ASSERT(cellGeomTarget%isLinear) + ASSERT(cellGeomTarget%isSkin) + +! ----- Set parameters of Newton algorithm for projection + projPara%debug = debug + projPara%newtIterMaxi = 75 + projPara%newtTole = projTole + +! ----- Prepare object for projection on target cell + projPara%spaceDime = spaceDime + projPara%coorPoinGlob = coorPoinGlob + projPara%projVect = normPoint + +! ----- Projection by given vector + call poinProjByVect(projPara, cellGeomTarget) + +! ----- Copy to output results + coorProjPara(1:2) = projPara%coorProjPara + errorProj = projPara%errorCode .ne. 0 +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! poinProjByVect +! +! Projection of a point on _skin_ cell by given vector +! +! IO projPara : parameters of projection +! In cellTarget : target cell +! +! -------------------------------------------------------------------------------------------------- + subroutine poinProjByVect(projPara, cellTarget) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PROJ_PARA), intent(inout) :: projPara + type(CELL_GEOM), intent(in) :: cellTarget +! ----- Local + real(kind=8), parameter :: zero = 0.d0, one = 1.d0 + integer :: iNode, iDime, spaceDime + real(kind=8) :: shapeFunc(MT_NNOMAX3D), dShapeFunc(3, MT_NNOMAX3D) + real(kind=8) :: vect_posi(3), dist + real(kind=8) :: residu(3), matrix(3, 3), det + real(kind=8) :: dksi(2), dbeta, beta + integer :: iterNewt + real(kind=8) :: toleAbso, toleRela, toleNewt + real(kind=8) :: distMini, ksiMini(2), betaMini + real(kind=8) :: refe, test +! ------------------------------------------------------------------------------------------------ +! + ASSERT(cellTarget%isSkin) + spaceDime = projPara%spaceDime + projPara%errorCode = 0 + projPara%coorProjPara = zero + beta = one + iterNewt = 0 + toleAbso = projPara%newtTole/100.d0 + toleRela = projPara%newtTole + distMini = r8gaem() + +! ----- Newton loop +20 continue + vect_posi = zero + projPara%tau1 = zero + projPara%tau2 = zero + matrix = zero + residu = zero + dksi = zero + dbeta = zero + +! ----- Get shape functions and derivated shape functions + call elrfvf(cellTarget%cellCode, projPara%coorProjPara, shapeFunc) + call elrfdf(cellTarget%cellCode, projPara%coorProjPara, dShapeFunc) + +! ----- Position vector of current point + do iDime = 1, 3 + do iNode = 1, cellTarget%nbNode + vect_posi(iDime) = & + cellTarget%coorNodeGlob(iDime, iNode)*shapeFunc(iNode)+vect_posi(iDime) + end do + end do + +! ----- Compute local base + call cellCompTang(cellTarget, spaceDime, dShapeFunc, projPara%tau1, projPara%tau2) + +! ----- Quantity to minimize + do iDime = 1, 3 + vect_posi(iDime) = projPara%coorPoinGlob(iDime)-vect_posi(iDime) + end do + dist = sqrt(vect_posi(1)*vect_posi(1)+vect_posi(2)*vect_posi(2)+vect_posi(3)*vect_posi(3)) + +! ----- Newton residual + do iDime = 1, 3 + residu(iDime) = vect_posi(iDime)-beta*projPara%projVect(iDime) + end do + +! ----- Tangent matrix (Newton) + do iDime = 1, 3 + matrix(iDime, 1) = projPara%tau1(iDime) + if (spaceDime .eq. 2) then + matrix(iDime, 2) = projPara%projVect(iDime) + elseif (spaceDime .eq. 3) then + matrix(iDime, 2) = projPara%tau2(iDime) + matrix(iDime, 3) = projPara%projVect(iDime) + else + ASSERT(ASTER_FALSE) + end if + end do + +! ----- System determinant + if (spaceDime .eq. 2) then + det = matrix(1, 1)*matrix(2, 2)-matrix(1, 2)*matrix(2, 1) + else if (spaceDime .eq. 3) then + det = matrix(1, 1)*(matrix(2, 2)*matrix(3, 3)-matrix(3, 2)*matrix(2, 3))- & + matrix(2, 1)*(matrix(1, 2)*matrix(3, 3)-matrix(3, 2)*matrix(1, 3))+ & + matrix(3, 1)*(matrix(1, 2)*matrix(2, 3)-matrix(2, 2)*matrix(1, 3)) + else + ASSERT(ASTER_FALSE) + end if +! + if (abs(det) .le. r8prem()) then + projPara%errorCode = 1 + goto 99 + end if + +! ----- Solve system + if (spaceDime .eq. 2) then + dksi(1) = (residu(1)*matrix(2, 2)-residu(2)*matrix(1, 2))/det + dksi(2) = 0.d0 + dbeta = (residu(2)*matrix(1, 1)-residu(1)*matrix(2, 1))/det + else if (spaceDime .eq. 3) then + dksi(1) = (residu(1)*(matrix(2, 2)*matrix(3, 3)-matrix(3, 2)*matrix(2, 3))+ & + residu(2)*(matrix(3, 2)*matrix(1, 3)-matrix(1, 2)*matrix(3, 3))+ & + residu(3)*(matrix(1, 2)*matrix(2, 3)-matrix(2, 2)*matrix(1, 3)))/det + dksi(2) = (residu(1)*(matrix(3, 1)*matrix(2, 3)-matrix(2, 1)*matrix(3, 3))+ & + residu(2)*(matrix(1, 1)*matrix(3, 3)-matrix(3, 1)*matrix(1, 3))+ & + residu(3)*(matrix(2, 1)*matrix(1, 3)-matrix(2, 3)*matrix(1, 1)))/det + dbeta = (residu(1)*(matrix(2, 1)*matrix(3, 2)-matrix(3, 1)*matrix(2, 2))+ & + residu(2)*(matrix(3, 1)*matrix(1, 2)-matrix(1, 1)*matrix(3, 2))+ & + residu(3)*(matrix(1, 1)*matrix(2, 2)-matrix(2, 1)*matrix(1, 2)))/det + else + ASSERT(ASTER_FALSE) + end if + +! ----- Update + projPara%coorProjPara = projPara%coorProjPara+dksi + beta = beta+dbeta + +! ----- Save values if Newton avoids + if (dist .le. distMini) then + distMini = dist + ksiMini = projPara%coorProjPara + betaMini = beta + end if + +! ----- Convergence + refe = (projPara%coorProjPara(1)*projPara%coorProjPara(1)+ & + projPara%coorProjPara(2)*projPara%coorProjPara(2)+beta*beta) + if (refe .le. toleRela) then + toleNewt = toleAbso + test = sqrt(dksi(1)*dksi(1)+dksi(2)*dksi(2)+dbeta*dbeta) + else + toleNewt = toleRela + test = sqrt(dksi(1)*dksi(1)+dksi(2)*dksi(2)+dbeta*dbeta)/sqrt(refe) + end if + +! ----- Continue or not ? + if ((test .gt. toleNewt) .and. (iterNewt .lt. projPara%newtIterMaxi)) then + iterNewt = iterNewt+1 + goto 20 + else if ((iterNewt .ge. projPara%newtIterMaxi) .and. (test .gt. toleNewt)) then + projPara%coorProjPara = ksiMini + call elrfvf(cellTarget%cellCode, projPara%coorProjPara, shapeFunc) + call elrfdf(cellTarget%cellCode, projPara%coorProjPara, dShapeFunc) + call cellCompTang(cellTarget, spaceDime, dShapeFunc, projPara%tau1, projPara%tau2) + projPara%errorCode = 1 + end if + +! ----- End of loop +99 continue +! + if (projPara%errorCode .eq. 1) then + WRITE (6, *) "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + WRITE (6, *) "Newton algorithm for projection" + WRITE (6, *) " => failure " + WRITE (6, *) "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + write (6, *) "Dimension de l'espace: ", spaceDime + write (6, *) "Coordonnées du point à projeter: ", & + projPara%coorPoinGlob(1), & + projPara%coorPoinGlob(2), & + projPara%coorPoinGlob(3) + write (6, *) "Direction de projection: ", & + projPara%projVect(1), & + projPara%projVect(2), & + projPara%projVect(3) + write (6, *) 'Maille cible de la projection: ', & + cellTarget%cellCode, & + cellTarget%nbNode + do iNode = 1, cellTarget%nbNode + write (6, *) ' Noeud ', iNode + write (6, *) ' (X,Y,Z)', & + cellTarget%coorNodeGlob(1, iNode), & + cellTarget%coorNodeGlob(2, iNode), & + cellTarget%coorNodeGlob(3, iNode) + end do + write (6, *) 'KSI : ', projPara%coorProjPara(1), projPara%coorProjPara(2) + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! inteCellChck +! +! Check intersection of cells (linearized) +! +! In meshPairing : main datastructure for pairing +! In cellProj : geometric properties of projected cell +! In nbNodeProj : number of projected nodes +! In cellOrigLine : geometric properties of projected cell in origin reference frame +! In cellTargLine : geometric properties of cell where cell has been projected +! In normOrig : normal to origin cell +! In normTarg : normal to target cell +! Out inteIsEmpty : flag for empty intersection +! +! -------------------------------------------------------------------------------------------------- + subroutine inteCellChck(meshPairing, & + cellProj, nbNodeProj, & + cellOrigLine, cellTargLine, & + normOrig, normTarg, & + inteIsEmpty) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellProj + integer, intent(in) :: nbNodeProj + type(CELL_GEOM), intent(in) :: cellOrigLine, cellTargLine + real(kind=8), intent(in) :: normOrig(3), normTarg(3) + aster_logical, intent(out) :: inteIsEmpty +! ----- Local + integer :: iNodeProj + integer :: listNodeNext(4) + real(kind=8) :: edgeOrig(3), edgeProj(3), vectProjOrig(3) + real(kind=8) :: sig, sp_ns_vsp, sp_np_vsp +! ------------------------------------------------------------------------------------------------ +! + inteIsEmpty = ASTER_FALSE + ASSERT(cellProj%isLinear) + ASSERT(cellOrigLine%isLinear) + ASSERT(cellTargLine%isLinear) + ASSERT(cellProj%cellCode .eq. cellOrigLine%cellCode) + + if (meshPairing%debug) then + WRITE (6, *) " Check intersection of cells" + WRITE (6, *) " ===========================" + end if + +! ----- Set index of next nodes + ASSERT(nbNodeProj .le. 4) + listNodeNext = 0 + if (cellOrigLine%cellCode .eq. "SE2") then + listNodeNext(1:2) = nodeNextSEG + elseif (cellOrigLine%cellCode .eq. "TR3") then + listNodeNext(1:3) = nodeNextTRIA + elseif (cellOrigLine%cellCode .eq. "QU4") then + listNodeNext(1:4) = nodeNextQUAD + else + ASSERT(ASTER_FALSE) + end if + + do iNodeProj = 1, nbNodeProj +! --------- Original edge + edgeOrig = 0.d0 + edgeOrig = & + cellOrigLine%coorNodeGlob(:, listNodeNext(iNodeProj))- & + cellOrigLine%coorNodeGlob(:, iNodeProj) + +! --------- Projected edge + edgeProj = 0.d0 + edgeProj = & + cellProj%coorNodeGlob(:, listNodeNext(iNodeProj))- & + cellProj%coorNodeGlob(:, iNodeProj) + +! --------- Compute vector start side to projected side + vectProjOrig = 0.d0 + vectProjOrig = & + cellProj%coorNodeGlob(:, iNodeProj)- & + cellOrigLine%coorNodeGlob(:, iNodeProj) + +! --------- Sign of colinear product edgeProj . edgeOrig + sig = 0.d0 + if (meshPairing%spaceDime .eq. 3) then + sig = edgeProj(1)*edgeOrig(1)+ & + edgeProj(2)*edgeOrig(2)+ & + edgeProj(3)*edgeOrig(3) + elseif (meshPairing%spaceDime .eq. 2) then + sig = edgeProj(1)*edgeOrig(1)+ & + edgeProj(2)*edgeOrig(2) + else + ASSERT(ASTER_FALSE) + end if + +! --------- Sign of colinear product: direction of normal to edges + sp_ns_vsp = 0.d0 + sp_np_vsp = 0.d0 + if (meshPairing%spaceDime .eq. 3) then + sp_ns_vsp = normOrig(1)*vectProjOrig(1)+ & + normOrig(2)*vectProjOrig(2)+ & + normOrig(3)*vectProjOrig(3) + sp_np_vsp = normTarg(1)*vectProjOrig(1)+ & + normTarg(2)*vectProjOrig(2)+ & + normTarg(3)*vectProjOrig(3) + elseif (meshPairing%spaceDime .eq. 2) then + sp_ns_vsp = normOrig(1)*vectProjOrig(1)+ & + normOrig(2)*vectProjOrig(2) + sp_np_vsp = normTarg(1)*vectProjOrig(1)+ & + normTarg(2)*vectProjOrig(2) + else + ASSERT(ASTER_FALSE) + end if + +! --------- Check signs + if (sig .lt. (0.d0-meshPairing%pairTole)) then +! ------------- The two edges are opposite + inteIsEmpty = ASTER_TRUE + if (meshPairing%debug) then + WRITE (6, *) " Edge on original cell : ", edgeOrig + WRITE (6, *) " Edge on projected cell: ", edgeProj + WRITE (6, *) " Vector between edges : ", vectProjOrig + WRITE (6, *) " Normal to edge on origin cell : ", normOrig + WRITE (6, *) " Normal to edge on target cell : ", normTarg + WRITE (6, *) " Error: the two edges are opposite" + end if + exit + elseif (sp_ns_vsp .lt. (0.d0-meshPairing%pairTole) .and. & + sp_np_vsp .lt. (0.d0-meshPairing%pairTole)) then + inteIsEmpty = ASTER_TRUE + if (meshPairing%debug) then + WRITE (6, *) " Edge on original cell : ", edgeOrig + WRITE (6, *) " Edge on projected cell: ", edgeProj + WRITE (6, *) " Vector between edges : ", vectProjOrig + WRITE (6, *) " Normal to edge on original cell : ", normOrig + WRITE (6, *) " Normal to edge on target cell : ", normTarg + WRITE (6, *) " Error: les normales ne sont pas opposées" + end if + exit + elseif (sp_ns_vsp .gt. (0.d0+meshPairing%pairTole) .and. & + sp_np_vsp .gt. (0.d0+meshPairing%pairTole)) then + inteIsEmpty = ASTER_TRUE + if (meshPairing%debug) then + WRITE (6, *) " Edge on original cell : ", edgeOrig + WRITE (6, *) " Edge on projected cell: ", edgeProj + WRITE (6, *) " Vector between edges : ", vectProjOrig + WRITE (6, *) " Normal to edge on original cell : ", normOrig + WRITE (6, *) " Normal to edge on target cell : ", normTarg + WRITE (6, *) " Error: les normales ne sont pas opposées" + end if + exit + end if + end do + if (meshPairing%debug) then + if (inteIsEmpty) then + WRITE (6, *) " Empty intersection" + else + WRITE (6, *) " Not empty intersection" + end if + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellProjOnCell +! +! Project a cell to another one: cellOrig ===> cellProj +! +! In meshPairing : main datastructure for pairing +! In cellOrig : geometric properties of cell to project +! In cellOrigLine : geometric properties of cell to project (linearized) +! In cellTargLine : geometric properties of cell where to project (linearized) +! Out cellProj : geometric properties of projected cell +! Out nbNodeProj : number of projected nodes +! Out iret : return code error +! +! -------------------------------------------------------------------------------------------------- + subroutine cellProjOnCell(meshPairing, & + cellOrig, cellOrigLine, cellTargLine, & + cellProj, nbNodeProj, iret) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellOrig, cellOrigLine, cellTargLine + type(CELL_GEOM), intent(out) :: cellProj + integer, intent(out) :: nbNodeProj + integer, intent(out) :: iret +! ----- Local + real(kind=8) :: normOrig(3), normTarg(3) + real(kind=8) :: ps, distCell + aster_logical :: inteIsEmpty +! ------------------------------------------------------------------------------------------------ +! + ASSERT(cellTargLine%isSkin) + ASSERT(cellTargLine%isSkin) + ASSERT(cellTargLine%isLinear) + ASSERT(cellOrigLine%isLinear) + + iret = ERR_PAIR_NONE + nbNodeProj = 0 + if (meshPairing%debug) then + WRITE (6, *) " Compute projection of cell in another one" + WRITE (6, *) " =========================================" + end if + +! ----- Compute norms at barycenter + call cellCompNormAtBary(meshPairing%spaceDime, cellTargLine, normTarg) + call cellCompNormAtBary(meshPairing%spaceDime, cellOrigLine, normOrig) + if (meshPairing%debug) then + WRITE (6, *) " Barycenter normal (target): ", normTarg + WRITE (6, *) " Barycenter normal (origin): ", normOrig + end if + +! ----- If cells are orthogonal -> exit + ps = dot_product(normTarg(1:3), normOrig(1:3)) + if (abs(ps) <= meshPairing%pairTole) then + if (meshPairing%debug) then + WRITE (6, *) " Cells are normal (", abs(ps), ") => STOP" + end if + iret = ERR_CELL_ORTH + goto 99 + end if + +! ----- If distance between barycenter is too high -> exit + if (meshPairing%distRatio > 0) then + ASSERT(cellTargLine%diameter .ge. 0.d0) + ASSERT(cellOrig%diameter .ge. 0.d0) + distCell = norm2(cellTargLine%baryGlob-cellOrig%baryGlob) + if (distCell >= & + 2*meshPairing%distRatio*max(cellTargLine%diameter, cellOrig%diameter)) then + iret = ERR_CELL_OOR + if (meshPairing%debug) then + WRITE (6, *) " Cells are too far away (", distCell, ") => STOP" + end if + go to 99 + end if + end if + +! ----- Project nodes in target cell parametric space using raytracing + call nodeProjOnCell(meshPairing, & + cellOrig, cellOrigLine, cellTargLine, & + cellProj, nbNodeProj, iret) + ASSERT(cellProj%isLinear) + if (iret .eq. ERR_PAIR_PROJ) then + goto 99 + else + if (meshPairing%debug) then + WRITE (6, *) " Success of the projection of cell" + end if + end if + +! ----- Check if intersection is empty or not + call inteCellChck(meshPairing, & + cellProj, nbNodeProj, & + cellOrigLine, cellTargLine, & + normOrig, normTarg, & + inteIsEmpty) + if (inteIsEmpty) then + iret = ERR_INTE_VOID + end if + +99 continue +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! cellInteProj - prjint_ray +! +! Compute intersection and projection from cell to target cell +! +! In meshPairing : main datastructure for pairing +! In cellOrig : general geometric properties of origin cell +! In cellOrigLine : general geometric properties of linearized origin cell +! In cellTargLine : general geometric properties of linearized target cell +! Out iret : return code error +! Out nbPoinInte : number of intersection points +! Out poinInteOrig : coordinates of intersection points (in origin cell parametric space) +! +! -------------------------------------------------------------------------------------------------- + subroutine cellInteProj(meshPairing, & + cellOrig, cellOrigLine, cellTargLine, & + iret_, & + nbPoinInte_, poinInteOrig_, & + inteArea_, inteNeigh_) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellOrig, cellOrigLine, cellTargLine + integer, optional, intent(out) :: iret_ + integer, optional, intent(out) :: nbPoinInte_ + real(kind=8), optional, intent(out) :: poinInteOrig_(2, MAX_NB_INTE) + real(kind=8), optional, intent(out) :: inteArea_ + integer, optional, intent(out) :: inteNeigh_(MAX_NB_NEIGH) +! ----- Local + aster_logical, parameter :: debug = ASTER_FALSE + integer :: iret, inteNeigh(MAX_NB_NEIGH) + integer :: nbPoinInteI + real(kind=8) :: poinInteTargI(2, 2*MAX_NB_INTE), poinInteOrigI(2, 2*MAX_NB_INTE) + integer :: nbPoinInteS + real(kind=8) :: poinInteTargS(2, MAX_NB_INTE), poinInteOrigS(2, MAX_NB_INTE) + integer :: nbPoinInte + real(kind=8) :: poinInteOrig(2, MAX_NB_INTE) + real(kind=8) :: inteArea + aster_logical :: errorProj, errorInte + type(CELL_GEOM) :: cellProj + integer :: nbCmpPara, nbNodeProj +! ------------------------------------------------------------------------------------------------ +! + inteNeigh = 0 + nbPoinInte = 0 + poinInteOrig = 0.d0 + inteArea = 0.d0 + iret = ERR_PAIR_NONE + nbCmpPara = meshPairing%spaceDime-1 + +! ----- Compute projection of cell on target cell + errorProj = ASTER_FALSE + call cellProjOnCell(meshPairing, & + cellOrig, cellOrigLine, cellTargLine, & + cellProj, nbNodeProj, iret) + if (iret .ne. ERR_PAIR_NONE) then + errorProj = ASTER_TRUE + goto 100 + end if + if (meshPairing%debug) then + WRITE (6, *) " Intersection is OK" + end if + +! ----- Compute intersection in parametric space of target cell + nbPoinInteI = 0 + poinInteTargI = 0.d0 + poinInteOrigI = 0.d0 + if (meshPairing%spaceDime .eq. 2) then + ASSERT(nbNodeProj .eq. 2) + call addPoinInte2D(meshPairing, cellProj, & + nbPoinInteI, poinInteTargI, poinInteOrigI, & + inteNeigh) + elseif (meshPairing%spaceDime .eq. 3) then + call addPoinInte3D(meshPairing, cellProj, nbNodeProj, & + cellOrigLine, cellTargLine, & + nbPoinInteI, poinInteTargI, poinInteOrigI, & + inteNeigh, iret) + call addPoinOnEdge(meshPairing, cellProj, nbNodeProj, & + cellOrigLine, cellTargLine, & + nbPoinInteI, poinInteTargI, poinInteOrigI, & + inteNeigh) + else + ASSERT(ASTER_FALSE) + end if + ASSERT(nbPoinInteI .le. 2*MAX_NB_INTE) + +! ----- Error management + errorInte = ASTER_FALSE + if (nbPoinInteI == 0 .or. iret == ERR_PAIR_MAST) then + errorInte = ASTER_TRUE + goto 100 + end if + +! ----- Debug print + if (meshPairing%debug) then + WRITE (6, *) " Intersection (before re-ordering): ", nbPoinInteI, & + " points of intersection" + WRITE (6, *) " Target side : ", poinInteTargI(1:nbCmpPara, 1:nbPoinInteI) + WRITE (6, *) " Origin side : ", poinInteOrigI(1:nbCmpPara, 1:nbPoinInteI) + end if + +! ----- Sort list of intersection points + if ((nbPoinInteI .gt. 2 .and. meshPairing%spaceDime == 3) .or. & + (nbPoinInteI .ge. 2 .and. meshPairing%spaceDime == 2)) then + call intePoinSort(meshPairing, & + nbPoinInteI, poinInteTargI, poinInteOrigI, & + nbPoinInteS, poinInteTargS, poinInteOrigS) + else + ASSERT(nbPoinInteI .le. MAX_NB_INTE) + nbPoinInteS = nbPoinInteI + poinInteTargS(:, 1:nbPoinInteI) = poinInteTargI(:, 1:nbPoinInteI) + poinInteOrigS(:, 1:nbPoinInteI) = poinInteOrigI(:, 1:nbPoinInteI) + end if + +! ----- Error management + if (nbPoinInteS > MAX_NB_INTE) then + if (meshPairing%debug) then + WRITE (6, *) " Intersection (after re-ordering): ", nbPoinInteS, & + " points of intersection" + WRITE (6, *) " Too many points !" + end if + iret = ERR_PAIR_SLAV + go to 99 + end if + +! ----- Debug print + if (meshPairing%debug) then + WRITE (6, *) " Intersection (after re-ordering): ", nbPoinInteS, & + " points of intersection" + WRITE (6, *) " Target side : ", poinInteTargS(1:nbCmpPara, 1:nbPoinInteS) + WRITE (6, *) " Origin side : ", poinInteOrigS(1:nbCmpPara, 1:nbPoinInteS) + end if + +! ----- All nodes have to be inside original cell + call intePoinInCell(meshPairing, cellOrigLine, & + nbPoinInteS, poinInteOrigS, poinInteOrig) + nbPoinInte = nbPoinInteS + +! ----- Compute weight of intersection + call inteCellArea(meshPairing%spaceDime, nbPoinInte, poinInteOrig, & + inteArea) + if (meshPairing%debug) then + WRITE (6, *) " Area of intersection : ", inteArea + end if + +! ----- Error +100 continue + if (errorProj .or. errorInte) then + if (meshPairing%debug) then + WRITE (6, *) " Failure of intersection" + end if + nbPoinInte = 0 + poinInteOrig = 0.d0 + inteNeigh = 0 + inteArea = 0.d0 + else + if (meshPairing%debug) then + WRITE (6, *) " Success of intersection" + end if + end if + +! ----- Fatal error only in debug mode +99 continue + if (debug) then + ASSERT(iret .ne. ERR_PAIR_NONE) + end if + +! ----- Outputs + if (present(inteNeigh_)) then + inteNeigh_ = inteNeigh + end if + if (present(nbPoinInte_)) then + nbPoinInte_ = nbPoinInte + end if + if (present(inteArea_)) then + inteArea_ = inteArea + end if + if (present(poinInteOrig_)) then + poinInteOrig_ = poinInteOrig + end if + if (present(iret_)) then + iret_ = iret + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! addPoinInte2D +! +! Compute intersection in parametric space of target cell - For 2D case (only segments) +! +! In meshPairing : main datastructure for pairing +! In cellProj : geometric properties of original cell +! Out nbPoinInte : number of intersection points +! Out poinInteTarg : coordinates of intersection points in target cell +! Out poinInteOrig : coordinates of intersection points in original cell +! Out inteNeigh : active cell neighbours for each node of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine addPoinInte2D(meshPairing, cellProj, & + nbPoinInte, poinInteTarg, poinInteOrig, & + inteNeigh) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellProj + integer, intent(out) :: nbPoinInte + real(kind=8), intent(out) :: poinInteTarg(2, 2*MAX_NB_INTE), poinInteOrig(2, 2*MAX_NB_INTE) + integer, intent(out) :: inteNeigh(MAX_NB_NEIGH) +! ----- Local + integer :: iNode, nbNode + real(kind=8) :: ksi + real(kind=8), parameter :: coorSegPara(2) = (/-1.d0, +1.d0/) + real(kind=8) :: ksiMini, ksiMaxi, t1 +! ------------------------------------------------------------------------------------------------ +! + nbPoinInte = 0 + poinInteTarg = 0.d0 + poinInteOrig = 0.d0 + inteNeigh = 0 + nbNode = cellProj%nbNode + ASSERT(nbNode .eq. 2) + +! ----- Add projected nodes inside target cell + do iNode = 1, nbNode + ksi = cellProj%coorNodePara(1, iNode) + if (ksi > (-1.d0-meshPairing%pairTole) .and. & + ksi < (1.d0+meshPairing%pairTole)) then + nbPoinInte = nbPoinInte+1 + poinInteTarg(1, nbPoinInte) = ksi + poinInteOrig(1, nbPoinInte) = coorSegPara(iNode) + inteNeigh(iNode) = 1 + end if + end do + +! ----- Add target nodes if they are inside projected cell + ksiMini = min(cellProj%coorNodePara(1, 1), cellProj%coorNodePara(1, 2)) + ksiMaxi = max(cellProj%coorNodePara(1, 1), cellProj%coorNodePara(1, 2)) + if ((ksiMini-meshPairing%pairTole) <= -1.d0 .and. & + -1.d0 <= (ksiMaxi+meshPairing%pairTole)) then + nbPoinInte = nbPoinInte+1 + poinInteTarg(1, nbPoinInte) = coorSegPara(1) + if (abs(-1.d0-cellProj%coorNodePara(1, 1)) < meshPairing%pairTole) then + poinInteOrig(1, nbPoinInte) = coorSegPara(1) + else + t1 = (-1.d0-cellProj%coorNodePara(1, 1))/ & + (cellProj%coorNodePara(1, 2)-cellProj%coorNodePara(1, 1)) + poinInteOrig(1, nbPoinInte) = 2*t1-1 + end if + end if + if ((ksiMini-meshPairing%pairTole) <= 1.d0 .and. & + 1.d0 <= (ksiMaxi+meshPairing%pairTole)) then + nbPoinInte = nbPoinInte+1 + poinInteTarg(1, nbPoinInte) = coorSegPara(2) + if (abs(1.d0-cellProj%coorNodePara(1, 1)) .lt. meshPairing%pairTole) then + poinInteOrig(1, nbPoinInte) = coorSegPara(1) + else + t1 = (1.d0-cellProj%coorNodePara(1, 1))/ & + (cellProj%coorNodePara(1, 2)-cellProj%coorNodePara(1, 1)) + poinInteOrig(1, nbPoinInte) = 2*t1-1 + end if + end if + if (meshPairing%debug) then + WRITE (6, *) " Neighbours : ", inteNeigh + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! addPoinInte3D +! +! Compute intersection in parametric master space - For 3D case +! +! In meshPairing : main datastructure for pairing +! In cellProj : geometric properties of projected cell from slave cell +! In nbNodeProj : number of projected nodes +! In cellOrigLine : geometric properties of cell to project (linearized) +! In cellTargLine : geometric properties of cell where to project (linearized) +! Out nbPoinInte : number of intersection points +! Out poinInteTarg : coordinates of intersection points in target cell +! Out poinInteOrig : coordinates of intersection points in original cell +! Out inteNeigh : active cell neighbours for each node of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine addPoinInte3D(meshPairing, cellProj, nbNodeProj, & + cellOrigLine, cellTargLine, & + nbPoinInte, poinInteTarg, poinInteOrig, & + inteNeigh, iret) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellProj + integer, intent(in) :: nbNodeProj + type(CELL_GEOM), intent(in) :: cellOrigLine, cellTargLine + integer, intent(out) :: nbPoinInte + real(kind=8), intent(out) :: poinInteTarg(2, 2*MAX_NB_INTE), poinInteOrig(2, 2*MAX_NB_INTE) + integer, intent(out) :: inteNeigh(MAX_NB_NEIGH) + integer, intent(out) :: iret +! ----- Local + aster_logical :: pointIsInside + real(kind=8) :: nodeProjPara(2), origCoorPara(2) + integer :: listNodePrev(4) + integer :: iNodeTarg, iNodeProj, errorInside +! ------------------------------------------------------------------------------------------------ +! + inteNeigh = 0 + nbPoinInte = 0 + iret = ERR_PAIR_NONE + +! ----- Liste orientée des noeuds projetés de la cellule + ASSERT(nbNodeProj .le. 4) + listNodePrev = 0 + if (cellOrigLine%cellCode .eq. "TR3") then + listNodePrev(1:3) = nodePrevTRIA + elseif (cellOrigLine%cellCode .eq. "QU4") then + listNodePrev(1:4) = nodePrevQUAD + else + ASSERT(ASTER_FALSE) + end if + +! ----- Add projection of original nodes inside target cell (parametric space) + do iNodeProj = 1, nbNodeProj + nodeProjPara(1:2) = cellProj%coorNodePara(1:2, iNodeProj) + if (meshPairing%debug) then + WRITE (6, *) "Project original nodes inside target cell: ", & + iNodeProj, nodeProjPara(1:2) + WRITE (6, *) " on cell ", cellTargLine%cellCode + end if + pointIsInside = cellPoinInside(cellTargLine, meshPairing%pairTole, nodeProjPara) + if (meshPairing%debug) then + if (pointIsInside) then + WRITE (6, *) " => is inside" + else + WRITE (6, *) " => is NOT inside" + end if + end if + if (pointIsInside) then + nbPoinInte = nbPoinInte+1 + ASSERT(nbPoinInte .le. MAX_NB_INTE) + poinInteTarg(:, nbPoinInte) = nodeProjPara + poinInteOrig(:, nbPoinInte) = cellOrigLine%coorNodePara(1:2, iNodeProj) + if (meshPairing%debug) then + WRITE (6, *) " nbPoinInte :", nbPoinInte + WRITE (6, *) " Coor. targ.:", nodeProjPara + WRITE (6, *) " Coor. orig.:", cellOrigLine%coorNodePara(1:2, iNodeProj) + end if + inteNeigh(iNodeProj) = 1 + inteNeigh(listNodePrev(iNodeProj)) = 1 + end if + end do + +! ----- Add targeted nodes if they are inside projected original cell + do iNodeTarg = 1, cellTargLine%nbNode +! --------- Current parametric coordinates of targeted node + nodeProjPara = cellTargLine%coorNodePara(1:2, iNodeTarg) + if (meshPairing%debug) then + WRITE (6, *) "Project targeted nodes inside original cell: ", & + iNodeTarg, nodeProjPara(1:2) + WRITE (6, *) " on cell ", cellProj%cellCode + end if + +! --------- Test + call poinIsInsideOtherCell(meshPairing%pairTole, meshPairing%debug, & + nodeProjPara, cellProj, & + origCoorPara, pointIsInside, & + errorInside) + if (meshPairing%debug) then + if (pointIsInside) then + WRITE (6, *) " => is inside" + else + WRITE (6, *) " => is NOT inside" + end if + end if + + if (pointIsInside) then + nbPoinInte = nbPoinInte+1 + poinInteTarg(:, nbPoinInte) = nodeProjPara + poinInteOrig(:, nbPoinInte) = origCoorPara + if (meshPairing%debug) then + WRITE (6, *) " nbPoinInte :", nbPoinInte + WRITE (6, *) " Coor. targ.:", nodeProjPara + WRITE (6, *) " Coor. orig.:", origCoorPara + end if + end if + if (errorInside == ERR_CELL_DEGE) then + iret = ERR_PAIR_MAST + if (meshPairing%debug) then + WRITE (6, *) "Error during projection" + end if + end if + end do + if (meshPairing%debug) then + WRITE (6, *) " Neighbours after points intersection : ", inteNeigh + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! poinIsInsideOtherCell +! +! Detect if point is inside other cell +! +! In projTole : tolerance for projection +! In poinCoorPara : coordinates of point in parametric space +! In cellGeom : geometric properties of cell +! Out origCoorPara +! Out poinIsInside +! Out error +! +! -------------------------------------------------------------------------------------------------- + subroutine poinIsInsideOtherCell(projTole, debug, & + poinCoorPara, cellGeom, & + origCoorPara, poinIsInside, & + error) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + real(kind=8), intent(in) :: projTole + aster_logical, intent(in) :: debug + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), intent(in) :: poinCoorPara(2) + real(kind=8), intent(out) :: origCoorPara(2) + aster_logical, intent(out) :: poinIsInside + integer, intent(out) :: error +! ----- Local + character(len=8) :: cellCode + real(kind=8) :: cellCoorPara(2, MT_NNOMAX3D) + real(kind=8) :: v0(2), v1(2), v2(2), d00, d10, d11, m, u, v + real(kind=8) :: d02, d12 +! ------------------------------------------------------------------------------------------------ +! + poinIsInside = ASTER_FALSE + error = ERR_PAIR_NONE + cellCode = cellGeom%cellCode + cellCoorPara = cellGeom%coorNodePara(1:2, :) + ASSERT(celLGeom%isSkin) + ASSERT(cellGeom%isLinear) + ASSERT(cellGeom%nbNode .le. MT_NNOMAX2D) + origCoorPara = 0.d0 + +! ----- First detect with triangle + +! ----- Vectorial basis for element + v0 = cellCoorPara(:, 2)-cellCoorPara(:, 1) + v1 = cellCoorPara(:, 3)-cellCoorPara(:, 1) + d00 = v0(1)*v0(1)+v0(2)*v0(2) + d10 = v0(1)*v1(1)+v0(2)*v1(2) + d11 = v1(1)*v1(1)+v1(2)*v1(2) + m = (d00*d11-d10*d10) + if (debug) then + WRITE (6, *) "Base vectorielle: ", v0, v1, m + end if + +! ----- Degenerated vectorial basis for element (colinear vectors) => exit + if (abs(m) .le. projTole) then + poinIsInside = ASTER_FALSE + error = ERR_CELL_DEGE + goto 99 + end if + +! ----- Coordinates of point in element's basis + v2 = poinCoorPara(:)-cellCoorPara(:, 1) + d02 = v0(1)*v2(1)+v0(2)*v2(2) + d12 = v1(1)*v2(1)+v1(2)*v2(2) + if (debug) then + WRITE (6, *) "Base vectorielle 2: ", v2 + end if + +! ----- Point is in element => exit + if (sqrt(v2(1)**2+v2(2)**2) .le. 0.d0+projTole) then + poinIsInside = ASTER_TRUE + if (cellCode .eq. 'TR3') then + origCoorPara(1) = 0.d0 + origCoorPara(2) = 0.d0 + elseif (cellCode .eq. 'QU4') then + origCoorPara(1) = -1.d0 + origCoorPara(2) = -1.d0 + else + ASSERT(ASTER_FALSE) + end if + if (debug) then + WRITE (6, *) "Dedans sans extension" + end if + goto 99 + end if + +! ----- Extension with projTole + u = 1/m*(d11*d02-d10*d12) + v = 1/m*(d00*d12-d10*d02) + if (debug) then + WRITE (6, *) "Extension T3: ", u, v, projTole + end if + if (u .ge. (0.d0-projTole) .and. & + v .ge. (0.d0-projTole) .and. & + (u+v) .le. (1.d0+projTole)) then + poinIsInside = ASTER_TRUE + if (cellCode .eq. 'TR3') then + origCoorPara(1) = 0.d0+u + origCoorPara(2) = 0.d0+v + elseif (cellCode .eq. 'QU4') then + origCoorPara(1) = -1.d0+u*2+v*2 + origCoorPara(2) = -1.d0+v*2 + else + ASSERT(ASTER_FALSE) + end if + if (debug) then + WRITE (6, *) "Dedans avec extension" + end if + goto 99 + else + poinIsInside = ASTER_FALSE + end if + + if (cellCode .eq. 'QU4') then +! --------- Vectorial basis for element + v0(:) = cellCoorPara(:, 3)-cellCoorPara(:, 1) + v1(:) = cellCoorPara(:, 4)-cellCoorPara(:, 1) + d00 = v0(1)*v0(1)+v0(2)*v0(2) + d10 = v0(1)*v1(1)+v0(2)*v1(2) + d11 = v1(1)*v1(1)+v1(2)*v1(2) + m = (d00*d11-d10*d10) + if (debug) then + WRITE (6, *) "Base vectorielle Q4-1: ", v0, v1, m + end if + +! --------- Degenerated vectorial basis for element (colinear vectors) => exit + if (abs(m) .le. projTole) then + poinIsInside = ASTER_FALSE + error = ERR_CELL_DEGE + goto 99 + end if + +! --------- Coordinates of point in element's basis + v2(:) = poinCoorPara(:)-cellCoorPara(:, 1) + d02 = v0(1)*v2(1)+v0(2)*v2(2) + d12 = v1(1)*v2(1)+v1(2)*v2(2) + if (debug) then + WRITE (6, *) "Base vectorielle Q4-2: ", v2 + end if + +! --------- Point is in element => exit + if (sqrt(v2(1)**2+v2(2)**2) .le. 0.d0+projTole) then + poinIsInside = ASTER_TRUE + if (cellCode .eq. 'QU4') then + origCoorPara(1) = -1.d0 + origCoorPara(2) = -1.d0 + end if + if (debug) then + WRITE (6, *) "Dedans sans extension" + end if + goto 99 + end if + +! --------- Extension with projTole + u = 1/m*(d11*d02-d10*d12) + v = 1/m*(d00*d12-d10*d02) + if (debug) then + WRITE (6, *) "Extension Q4: ", u, v, projTole + end if + if (u .ge. (0.d0-projTole) .and. & + v .ge. (0.d0-projTole) .and. & + (u+v) .le. (1.d0+projTole)) then + poinIsInside = ASTER_TRUE + if (cellCode .eq. 'QU4') then + origCoorPara(1) = -1.d0+u*2 + origCoorPara(2) = -1.d0+v*2+u*2 + end if + if (debug) then + WRITE (6, *) "Dedans avec extension" + end if + goto 99 + else + poinIsInside = ASTER_FALSE + end if + end if +! +99 continue +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! inteCellSegm +! +! Compute intersection between segment and (linearized) cell +! +! In meshPairing : main datastructure for pairing +! In coorSegm : coordinates of segment +! In cellLine : general geometric properties of linearized cell +! IO nbPoinInte : number of intersection points +! IO poinInte : coordinates of intersection points +! +! -------------------------------------------------------------------------------------------------- + subroutine inteCellSegm(meshPairing, & + coorSegm, cellLine, & + nbPoinInte, poinInte) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + real(kind=8), intent(in) :: coorSegm(2, 2) + type(CELL_GEOM), intent(in) :: cellLine + integer, intent(inout) :: nbPoinInte + real(kind=8), intent(inout) :: poinInte(2, 2*MAX_NB_INTE) +! ----- Local + integer :: nbNode, iNode + real(kind=8) :: a, b, c, d + real(kind=8) :: t1, t2, det, aux(2), norm + real(kind=8) :: x1, y1, x2, y2 + integer :: listNodeNext(4) +! ------------------------------------------------------------------------------------------------ +! + ASSERT(cellLine%isLinear) + nbNode = cellLine%nbNode + +! ----- Set index of next nodes + ASSERT(nbNode .le. 4) + listNodeNext = 0 + if (cellLine%cellCode .eq. "SE2") then + listNodeNext(1:2) = nodeNextSEG + elseif (cellLine%cellCode .eq. "TR3") then + listNodeNext(1:3) = nodeNextTRIA + elseif (cellLine%cellCode .eq. "QU4") then + listNodeNext(1:4) = nodeNextQUAD + else + ASSERT(ASTER_FALSE) + end if + +! ----- Coefficients for parametric equation of segment + x1 = coorSegm(1, 1) + y1 = coorSegm(2, 1) + a = coorSegm(1, 2)-x1 + b = coorSegm(2, 2)-y1 + + if (meshPairing%debug) then + WRITE (6, *) " Intersection" + WRITE (6, *) " Segment 1: ", x1, y1 + WRITE (6, *) " Parametric equation: ", a, b + end if + +! ----- Loop on edges of element + do iNode = 1, nbNode +! --------- Current segment in cell + x2 = cellLine%coorNodePara(1, iNode) + y2 = cellLine%coorNodePara(2, iNode) + +! --------- Coefficients for parametric equation of segment in cell + c = cellLine%coorNodePara(1, listNodeNext(iNode))-x2 + d = cellLine%coorNodePara(2, listNodeNext(iNode))-y2 + +! --------- Compute intersection + det = b*c-a*d + if (meshPairing%debug) then + WRITE (6, *) " Segment : ", iNode, x2, y2 + WRITE (6, *) " Parametric equation: ", c, d + end if + + if (sqrt(det**2) .gt. meshPairing%pairTole) then + t1 = 1/det*(d*(x1-x2)-c*(y1-y2)) + t2 = 1/det*(b*(x1-x2)-a*(y1-y2)) + aux(1) = (-t1*a-t2*c)-(x1-x2) + aux(2) = (t1*b+t2*d)-(y1-y2) + norm = sqrt(aux(1)**2+aux(2)**2) + else + t1 = -1.d0 + t2 = -1.d0 + end if + +! --------- Test intersection + if (t1 .lt. 1.d0+meshPairing%pairTole .and. & + t1 .gt. 0.d0-meshPairing%pairTole .and. & + t2 .lt. 1.d0+meshPairing%pairTole .and. & + t2 .gt. 0.d0-meshPairing%pairTole) then + nbPoinInte = nbPoinInte+1 + ASSERT(nbPoinInte .le. 2*MAX_NB_INTE) + poinInte(1, nbPoinInte) = (t2*c+x2+t1*a+x1)/2.d0 + poinInte(2, nbPoinInte) = (t2*d+y2+t1*b+y1)/2.d0 + if (meshPairing%debug) then + WRITE (6, *) " -> intersection détectée: ", & + nbPoinInte, poinInte(:, nbPoinInte) + end if + end if + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! addPoinOnEdge +! +! Compute intersection of edges for 3D case +! +! In meshPairing : main datastructure for pairing +! In cellProj : geometric properties of projected cell from slave cell +! In nbNodeProj : number of projected nodes +! In cellOrigLine : general geometric properties of linearized origin cell +! In cellTargLine : general geometric properties of linearized target cell +! Out nbPoinInte : number of intersection points +! Out poinInteTarg : coordinates of intersection points on target cell +! Out poinInteOrig : coordinates of intersection points on origin cell +! IO inteNeigh : active cell neighbours for each node of cell +! +! -------------------------------------------------------------------------------------------------- + subroutine addPoinOnEdge(meshPairing, cellProj, nbNodeProj, & + cellOrigLine, cellTargLine, & + nbPoinInte, poinInteTarg, poinInteOrig, & + inteNeigh) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellProj + integer, intent(in) :: nbNodeProj + type(CELL_GEOM), intent(in) :: cellOrigLine, cellTargLine + integer, intent(inout) :: nbPoinInte + real(kind=8), intent(inout) :: poinInteTarg(2, 2*MAX_NB_INTE) + real(kind=8), intent(inout) :: poinInteOrig(2, 2*MAX_NB_INTE) + integer, intent(inout) :: inteNeigh(MAX_NB_NEIGH) +! ----- Local + real(kind=8) :: coorSegmProj(2, 2), t1, t2 + real(kind=8) :: coorSegmOrig(2, 2) + integer :: nbPoinAdd, nbPoinInteAv + integer :: iPoinAdd, listNodeNext(4), iNodeProj +! ------------------------------------------------------------------------------------------------ +! + ASSERT(nbNodeProj .le. 4) + +! ----- Set index of next nodes + listNodeNext = 0 + if (cellOrigLine%cellCode .eq. "SE2") then + listNodeNext(1:2) = nodeNextSEG + elseif (cellOrigLine%cellCode .eq. "TR3") then + listNodeNext(1:3) = nodeNextTRIA + elseif (cellOrigLine%cellCode .eq. "QU4") then + listNodeNext(1:4) = nodeNextQUAD + else + ASSERT(ASTER_FALSE) + end if + +! ----- Intersection of edges + do iNodeProj = 1, nbNodeProj + +! --------- Coordinates of segment from projected cell (in target cell reference frame) + coorSegmProj(1:2, 1) = cellProj%coorNodePara(1:2, iNodeProj) + coorSegmProj(1:2, 2) = cellProj%coorNodePara(1:2, listNodeNext(iNodeProj)) + +! --------- Coordinates of segment from original cell (in original cell reference frame) + coorSegmOrig(1:2, 1) = cellOrigLine%coorNodePara(1:2, iNodeProj) + coorSegmOrig(1:2, 2) = cellOrigLine%coorNodePara(1:2, listNodeNext(iNodeProj)) + + if (meshPairing%debug) then + WRITE (6, *) "Intersection of edges: ", & + iNodeProj, coorSegmProj + WRITE (6, *) " Intersection points before: ", & + nbPoinInte, poinInteTarg + end if + +! --------- Compute intersection between edge of master and projected slave cells + nbPoinInteAv = nbPoinInte + call inteCellSegm(meshPairing, & + coorSegmProj, cellTargLine, & + nbPoinInte, poinInteTarg) + if (meshPairing%debug) then + WRITE (6, *) " => intersection points: ", & + nbPoinInte, poinInteTarg + end if + +! --------- Number of intersection points to add + nbPoinAdd = nbPoinInte-nbPoinInteAv + if (nbPoinAdd .gt. 0) then + inteNeigh(iNodeProj) = 1 + do iPoinAdd = 1, nbPoinAdd + t1 = 0.d0 + t2 = 0.d0 + if (abs(poinInteTarg(1, nbPoinInteAv+iPoinAdd)-coorSegmProj(1, 1)) .gt. & + meshPairing%pairTole) then + t1 = (coorSegmProj(1, 2)-coorSegmProj(1, 1))/ & + (poinInteTarg(1, nbPoinInteAv+iPoinAdd)-coorSegmProj(1, 1)) + poinInteOrig(1, nbPoinInteAv+iPoinAdd) = & + (1.0/t1)*(coorSegmOrig(1, 2)-coorSegmOrig(1, 1))+coorSegmOrig(1, 1) + else + poinInteOrig(1, nbPoinInteAv+iPoinAdd) = & + coorSegmOrig(1, 1) + end if + if (abs(poinInteTarg(2, nbPoinInteAv+iPoinAdd)-coorSegmProj(2, 1)) .gt. & + meshPairing%pairTole) then + t2 = (coorSegmProj(2, 2)-coorSegmProj(2, 1))/ & + (poinInteTarg(2, nbPoinInteAv+iPoinAdd)-coorSegmProj(2, 1)) + poinInteOrig(2, nbPoinInteAv+iPoinAdd) = & + (1.0/t2)*(coorSegmOrig(2, 2)-coorSegmOrig(2, 1))+coorSegmOrig(2, 1) + poinInteOrig(1, nbPoinInteAv+iPoinAdd) = & + (1.0/t2)*(coorSegmOrig(1, 2)-coorSegmOrig(1, 1))+coorSegmOrig(1, 1) + else + if (t1 .lt. meshPairing%pairTole) then + poinInteOrig(2, nbPoinInteAv+iPoinAdd) = & + coorSegmOrig(2, 1) + else + poinInteOrig(2, nbPoinInteAv+iPoinAdd) = & + (1.0/t1)*(coorSegmOrig(2, 2)-coorSegmOrig(2, 1))+coorSegmOrig(2, 1) + end if + end if + end do + end if + end do + if (meshPairing%debug) then + WRITE (6, *) " Neighbours after segments intersection : ", inteNeigh + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! pairGetStartCells - ap_infast_n +! +! Get cell for starting search +! +! In meshPairing : main datastructure for pairing +! Ptr nodeCoor : updated coordinates of nodes of mesh +! Ptr meshTypeGeom : pointer to type of cells in mesh +! Ptr meshConx : pointers to connectivity of mesh +! meshConxCumu +! Ptr mastConxInv : pointers to inverse conenctivity of master cells +! mastConxInvCumu +! In nbCellSlav : number of slave cells +! In listCellSlav : list of slave cells +! In cellSlavFlag : flag for slave cell has been used in a pair +! 0 - Never used +! 1 - Used as starting point +! 2 - Used +! In nbCellMast : number of master cells +! In listCellMast : list of master cells +! In nbNodeMast : number of master nodes +! In listNodeMast : list of master nodes +! In nbMastStart : number of master cells used as a start cell +! In cellMastStart : list of master cells used as a start cell +! In nbSlavStart : number of slave cells used as a start cell +! In cellSlavStart : list of slave cells used as a start cell +! +! -------------------------------------------------------------------------------------------------- + subroutine pairGetStartCells(meshPairing, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + mastConxInv, mastConxInvCumu, & + nbCellSlav, listCellSlav, cellSlavFlag, & + nbCellMast, listCellMast, & + nbNodeMast, listNodeMast, & + nbMastStart, cellMastStart, & + nbSlavStart, cellSlavStart) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + real(kind=8), pointer :: nodeCoor(:) + integer, pointer :: meshTypeGeom(:) + integer, pointer :: meshConx(:), meshConxCumu(:) + integer, pointer :: mastConxInv(:), mastConxInvCumu(:) + integer, intent(in) :: nbCellSlav, listCellSlav(nbCellSlav) + integer, pointer :: cellSlavFlag(:) + integer, intent(in) :: nbCellMast, listCellMast(nbCellMast) + integer, intent(in) :: nbNodeMast, listNodeMast(nbNodeMast) + integer, intent(out) :: nbMastStart, cellMastStart(nbCellMast) + integer, intent(out) :: nbSlavStart, cellSlavStart(nbCellSlav) +! ----- Local + integer :: iCellSlav, iCellMast + integer :: cellSlavNume, cellSlavIndx + integer :: cellMastNume + type(CELL_GEOM) :: cellSlav, cellSlavLine + type(CELL_GEOM) :: cellMast, cellMastLine + integer :: nodeNumeClosest + integer :: slavIndxMini + integer :: nbCellToNode, cellToNode(nbCellMast) + real(kind=8) :: inteArea +! ------------------------------------------------------------------------------------------------ +! + slavIndxMini = minval(listCellSlav) + nbMastStart = 0 + cellMastStart = 0 + nbSlavStart = 0 + cellSlavStart = 0 + +! ----- Loop on slave elements + do iCellSlav = 1, nbCellSlav +! --------- Get current slave element + cellSlavNume = listCellSlav(iCellSlav) + cellSlavIndx = cellSlavNume+1-slavIndxMini + if (meshPairing%debug) then + WRITE (6, *) " Current slave cell : ", cellSlavNume + end if + +! --------- Already tracked ? + if (cellSlavFlag(cellSlavIndx) .eq. 0) then + if (meshPairing%debug) then + WRITE (6, *) " Current slave cell not yet tracked" + end if + +! ------------- Create slave cell + call cellCreate(cellSlavNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellSlav, cellSlavLine) + if (meshPairing%debug) then + WRITE (6, *) "Properties of slave cell" + WRITE (6, *) "========================" + call cellDebug(cellSlav) + end if + +! ------------- Find the closest master node from center of slave cell + if (meshPairing%debug) then + WRITE (6, *) " Seek for closest master node from center of slave cell" + end if + call getClosestNodesFromCell(cellSlav, nodeCoor, & + nbNodeMast, listNodeMast, & + nodeNumeClosest) + if (meshPairing%debug) then + WRITE (6, *) " => ", nodeNumeClosest + end if + +! ------------- Construct list of master cells attached to this node + if (meshPairing%debug) then + WRITE (6, *) " Get list of cells attached to this node" + end if + call getCellsFromNode(nodeNumeClosest, & + mastConxInv, mastConxInvCumu, & + nbCellMast, listCellMast, & + nbCellToNode, cellToNode) + if (meshPairing%debug) then + WRITE (6, *) " => Number of cells: ", nbCellToNode + WRITE (6, *) " => Cells connected: ", cellToNode(1:nbCellToNode) + end if + +! ------------- Loop on master elements linked to the closest master node + do iCellMast = 1, nbCellToNode + if (meshPairing%debug) then + WRITE (6, *) " Seek for closest master cell" + end if +! ----------------- Get current master cell + cellMastNume = cellToNode(iCellMast) + if (meshPairing%debug) then + WRITE (6, *) " Current master cell : ", cellMastNume + end if + +! ----------------- Create master cell + call cellCreate(cellMastNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellMast, cellMastLine) + if (meshPairing%debug) then + WRITE (6, *) "Properties of master cell" + WRITE (6, *) "========================" + call cellDebug(cellMast) + end if + +! ----------------- Projection/intersection of the two cells + if (meshPairing%debug) then + WRITE (6, *) " Compute intersection and projection in slave space" + end if + call cellInteProj(meshPairing, & + cellMast, cellMastLine, cellSlavLine, & + inteArea_=inteArea) + if (meshPairing%debug) then + WRITE (6, *) " Intersection area: ", inteArea + end if + +! ----------------- Set start elements + if (inteArea .gt. 100*meshPairing%pairTole) then + cellMastStart(1) = cellMastNume + nbMastStart = 1 + cellSlavStart(1) = cellSlavNume + nbSlavStart = 1 + cellSlavFlag(cellSlavIndx) = 1 + goto 100 + end if + end do + else + if (meshPairing%debug) then + WRITE (6, *) " Current slave cell is already tracked" + end if + end if + cellSlavFlag(cellSlavIndx) = 2 + end do +100 continue +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! intePoinSort +! +! Sort points of intersection +! +! In meshPairing : main datastructure for pairing +! In nbPoinInteIn : number of intersection points (input) +! In poinInteTargIn : intersection points on target cell (input) +! In poinInteOrigIn : intersection points on original cell (input) +! Out nbPoinInteOut : number of intersection points (output) +! Out poinInteTargOut : intersection points on target cell (output) +! Out poinInteOrigOut : intersection points on original cell (output) +! +! -------------------------------------------------------------------------------------------------- + subroutine intePoinSort(meshPairing, & + nbPoinInteIn, poinInteTargIn, poinInteOrigIn, & + nbPoinInteOut, poinInteTargOut, poinInteOrigOut) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + integer, intent(in) :: nbPoinInteIn + real(kind=8), intent(in) :: poinInteTargIn(2, 2*MAX_NB_INTE) + real(kind=8), intent(in) :: poinInteOrigIn(2, 2*MAX_NB_INTE) + integer, intent(out) :: nbPoinInteOut + real(kind=8), intent(out) :: poinInteTargOut(2, MAX_NB_INTE) + real(kind=8), intent(out) :: poinInteOrigOut(2, MAX_NB_INTE) +! ----- Local + real(kind=8) :: poinInteSort1(2, 2*MAX_NB_INTE), poinInteSort2(2, 2*MAX_NB_INTE) + real(kind=8) :: angle(2*MAX_NB_INTE) + real(kind=8) :: v(2), norm, bary(2) + integer :: iPoinInte, angle_sorted(2*MAX_NB_INTE), listPoinNext(2*MAX_NB_INTE) +! ------------------------------------------------------------------------------------------------ +! + bary = 0.d0 + v = 0.d0 + nbPoinInteOut = 0 + poinInteSort1 = 0.d0 + poinInteSort2 = 0.d0 + poinInteTargOut = 0.d0 + poinInteOrigOut = 0.d0 + +! ----- Set index of next points + do iPoinInte = 2, nbPoinInteIn + listPoinNext(iPoinInte-1) = iPoinInte + end do + listPoinNext(nbPoinInteIn) = 1 + + if (meshPairing%spaceDime .eq. 3) then +! --------- Coordinates of barycenter + do iPoinInte = 1, nbPoinInteIn + bary(:) = bary(:)+poinInteTargIn(:, iPoinInte)/real(nbPoinInteIn) + end do + +! --------- Compute angles + do iPoinInte = 1, nbPoinInteIn + v(:) = poinInteTargIn(:, iPoinInte)-bary(:) + angle(iPoinInte) = atan2(v(1), v(2)) + end do + +! --------- Sort angles + call ordr8(angle, nbPoinInteIn, angle_sorted) + +! --------- Sort + nbPoinInteOut = 0 + do iPoinInte = 1, nbPoinInteIn + norm = sqrt((angle(angle_sorted(iPoinInte))- & + angle(angle_sorted(listPoinNext(iPoinInte))))**2) + if (norm .gt. 10*meshPairing%pairTole) then + nbPoinInteOut = nbPoinInteOut+1 + poinInteSort1(1:2, nbPoinInteOut) = poinInteTargIn(1:2, angle_sorted(iPoinInte)) + poinInteSort2(1:2, nbPoinInteOut) = poinInteOrigIn(1:2, angle_sorted(iPoinInte)) + end if + end do + + elseif (meshPairing%spaceDime .eq. 2) then + poinInteSort1(1, 1) = poinInteTargIn(1, 1) + poinInteSort1(1, 2) = poinInteTargIn(1, 1) + poinInteSort2(1, 1) = poinInteOrigIn(1, 1) + poinInteSort2(1, 2) = poinInteOrigIn(1, 1) + + do iPoinInte = 2, nbPoinInteIn + if (poinInteTargIn(1, iPoinInte) .le. poinInteSort1(1, 1) .and. & + poinInteTargIn(1, iPoinInte) .ge. (-1.d0)) then + poinInteSort1(1, 1) = poinInteTargIn(1, iPoinInte) + poinInteSort2(1, 1) = poinInteOrigIn(1, iPoinInte) + + elseif (poinInteTargIn(1, iPoinInte) .ge. poinInteSort1(1, 2) .and. & + poinInteTargIn(1, iPoinInte) .le. (1.d0)) then + poinInteSort1(1, 2) = poinInteTargIn(1, iPoinInte) + poinInteSort2(1, 2) = poinInteOrigIn(1, iPoinInte) + + end if + end do + nbPoinInteOut = 2 + + else + ASSERT(ASTER_FALSE) + end if + +! ----- Copy + if (nbPoinInteOut .le. MAX_NB_INTE) then + do iPoinInte = 1, nbPoinInteOut + poinInteTargOut(1, iPoinInte) = poinInteSort1(1, iPoinInte) + poinInteOrigOut(1, iPoinInte) = poinInteSort2(1, iPoinInte) + if (meshPairing%spaceDime == 3) then + poinInteTargOut(2, iPoinInte) = poinInteSort1(2, iPoinInte) + poinInteOrigOut(2, iPoinInte) = poinInteSort2(2, iPoinInte) + end if + end do + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! intePoinInCell +! +! Check if intersection points are in cell and adjust them with tolerance +! +! In meshPairing : main datastructure for pairing +! In cellGeom : general geometric properties of cell +! In nbPoinInte : number of intersection points +! In poinInteIn : list of intersection points +! Out poinInteOut : list of intersection points after adjustements +! +! -------------------------------------------------------------------------------------------------- + subroutine intePoinInCell(meshPairing, cellGeom, & + nbPoinInte, poinInteIn, poinInteOut) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(in) :: meshPairing + type(CELL_GEOM), intent(in) :: cellGeom + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInteIn(2, MAX_NB_INTE) + real(kind=8), intent(out) :: poinInteOut(2, MAX_NB_INTE) +! ----- Local + integer :: iPoinInte + aster_logical :: pointIsInside +! ------------------------------------------------------------------------------------------------ +! + poinInteOut = 0.d0 + do iPoinInte = 1, nbPoinInte + poinInteOut(:, iPoinInte) = poinInteIn(:, iPoinInte) + +!---------- Adjust point inside element + call cellPoinAdjust(cellGeom, meshPairing%pairTole, poinInteOut) + +! --------- Test if point is inside element + pointIsInside = cellPoinInside(cellGeom, meshPairing%pairTole, poinInteOut) + ASSERT(pointIsInside) + + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! inteCellArea +! +! Compute area of intersection +! +! In spaceDime : dimension of space (2 or 3) +! In nbPoinInte : number of intersection points +! In poinInte : list of intersection points +! Out inteArea : area of intersection +! +! -------------------------------------------------------------------------------------------------- + subroutine inteCellArea(spaceDime, nbPoinInte, poinInte, & + inteArea) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: spaceDime, nbPoinInte + real(kind=8), intent(in) :: poinInte(2, MAX_NB_INTE) + real(kind=8), intent(out) :: inteArea +! ----- Local + integer :: listPoinNext(MAX_NB_INTE), iPoinInte +! ------------------------------------------------------------------------------------------------ +! + inteArea = 0.d0 + +! ----- Set index of next points + if (spaceDime .eq. 3) then + do iPoinInte = 2, nbPoinInte + listPoinNext(iPoinInte-1) = iPoinInte + end do + listPoinNext(nbPoinInte) = 1 + end if + +! ----- Compute area + if ((nbPoinInte .gt. 2 .and. spaceDime .eq. 3) .or. & + (nbPoinInte .ge. 2 .and. spaceDime .eq. 2)) then + if (spaceDime .eq. 3) then + do iPoinInte = 1, nbPoinInte + inteArea = inteArea+ & + poinInte(1, iPoinInte)* & + poinInte(2, listPoinNext(iPoinInte))- & + poinInte(1, listPoinNext(iPoinInte))* & + poinInte(2, iPoinInte) + end do + inteArea = 1.d0/2.d0*inteArea + inteArea = sqrt(inteArea**2) + elseif (spaceDime .eq. 2) then + inteArea = sqrt((poinInte(1, 2)-poinInte(1, 1))**2) + else + ASSERT(ASTER_FALSE) + end if + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! isFatalError +! +! Is the error is fatal ? +! +! -------------------------------------------------------------------------------------------------- + function isFatalError(errorPair) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + aster_logical :: isFatalError + integer, intent(in) :: errorPair +! ------------------------------------------------------------------------------------------------ +! + isFatalError = ASTER_TRUE + if (errorPair .eq. ERR_CELL_ORTH) then + isFatalError = ASTER_TRUE + elseif (errorPair .eq. ERR_CELL_OOR) then + isFatalError = ASTER_TRUE + elseif (errorPair .eq. ERR_PAIR_PROJ) then + isFatalError = ASTER_FALSE + elseif (errorPair .eq. ERR_INTE_VOID) then + isFatalError = ASTER_TRUE + elseif (errorPair .eq. ERR_PAIR_SLAV) then + isFatalError = ASTER_TRUE + elseif (errorPair .eq. ERR_PAIR_MAST) then + isFatalError = ASTER_TRUE + end if +! +! ------------------------------------------------------------------------------------------------ + end function +! -------------------------------------------------------------------------------------------------- +! +! pairAllocate +! +! Allocate objects for pairing +! +! -------------------------------------------------------------------------------------------------- + subroutine pairAllocate(pairDime, meshPairing) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: pairDime + type(MESH_PAIRING), intent(inout) :: meshPairing +! ------------------------------------------------------------------------------------------------ +! + AS_ALLOCATE(vi=meshPairing%pair, size=2*pairDime) + AS_ALLOCATE(vi=meshPairing%nbPoinInte, size=pairDime) + AS_ALLOCATE(vr=meshPairing%poinInte, size=2*pairDime*MAX_NB_INTE) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! pairDeallocate +! +! Deallocate objects for pairing +! +! -------------------------------------------------------------------------------------------------- + subroutine pairDeallocate(meshPairing) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(MESH_PAIRING), intent(inout) :: meshPairing +! ------------------------------------------------------------------------------------------------ +! + AS_DEALLOCATE(vi=meshPairing%pair) + AS_DEALLOCATE(vi=meshPairing%nbPoinInte) + AS_DEALLOCATE(vr=meshPairing%poinInte) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! pairAdd +! +! Add a pair +! +! -------------------------------------------------------------------------------------------------- + subroutine pairAdd(cellSlavNume, cellMastNume, & + nbPoinInte, poinInte, & + meshPairing) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: cellSlavNume, cellMastNume + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInte(2, MAX_NB_INTE) + type(MESH_PAIRING), intent(inout) :: meshPairing +! ----- Locals + integer :: iPoinInte, iPair +! ------------------------------------------------------------------------------------------------ +! + iPair = meshPairing%nbPair+1 + ASSERT(nbPoinInte .le. MAX_NB_INTE) + meshPairing%nbPair = meshPairing%nbPair+1 + meshPairing%pair(2*(meshPairing%nbPair-1)+1) = cellSlavNume + meshPairing%pair(2*(meshPairing%nbPair-1)+2) = cellMastNume + meshPairing%nbPoinInte(meshPairing%nbPair) = nbPoinInte + do iPoinInte = 1, MAX_NB_INTE + meshPairing%poinInte(2*MAX_NB_INTE*(iPair-1)+iPoinInte) = & + poinInte(1, iPoinInte) + meshPairing%poinInte(2*MAX_NB_INTE*(iPair-1)+MAX_NB_INTE+iPoinInte) = & + poinInte(2, iPoinInte) + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! intePoinCoor +! +! Compute coordinates of points in real space +! +! In cellGeom : general geometric properties of cell +! In nbPoinInte : number of intersection points +! In poinInte : list of intersection points (parametric space of cellGeom) +! Out poinInteReal : list of intersection points after transformation (global space) +! +! -------------------------------------------------------------------------------------------------- + subroutine intePoinCoor(cellGeom, nbPoinInte, poinInte, poinInteReal) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + integer, intent(in) :: nbPoinInte + real(kind=8), intent(in) :: poinInte(2, MAX_NB_INTE) + real(kind=8), intent(out) :: poinInteReal(3, MAX_NB_INTE) +! ----- Local + integer :: iPoinInte +! ------------------------------------------------------------------------------------------------ +! + ASSERT(nbPoinInte .le. MAX_NB_INTE) + poinInteReal = 0.d0 + do iPoinInte = 1, nbPoinInte + call cellPoinParaToGlob(cellGeom, & + poinInte(:, iPoinInte), poinInteReal(:, iPoinInte)) + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! quadPoinCoor +! +! Compute coordinates of quadrature points in real space +! +! In cellGeom : general geometric properties of cell +! In nbPoinQuad : number of quadrature points +! In quadPoinSlav : list of quadrature points (parametric space of cellGeom) +! Out quadPoinReal : list of quadrature points after transformation (global space) +! +! -------------------------------------------------------------------------------------------------- + subroutine quadPoinCoor(cellSlav, nbPoinQuad, quadPoinSlav, quadPoinReal) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellSlav + integer, intent(in) :: nbPoinQuad + real(kind=8), intent(in) :: quadPoinSlav(2, MAX_NB_QUAD) + real(kind=8), intent(out) :: quadPoinReal(3, MAX_NB_QUAD) +! ----- Local + integer :: iPoinQuad +! ------------------------------------------------------------------------------------------------ +! + ASSERT(nbPoinQuad .le. MAX_NB_QUAD) + quadPoinReal = 0.d0 + do iPoinQuad = 1, nbPoinQuad + call cellPoinParaToGlob(cellSlav, & + quadPoinSlav(:, iPoinQuad), quadPoinReal(:, iPoinQuad)) + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! getClosestNodesFromCell +! +! Get the closest node in a list from given cell +! +! In cellGeom : geometric properties of cell +! Ptr nodeCoor : pointer to coordinates of nodes +! In nbNode : number of nodes +! In listNode : list of nodes +! Out nodeNumeClosest : index of the closest node (index in mesh) +! +! -------------------------------------------------------------------------------------------------- + subroutine getClosestNodesFromCell(cellGeom, nodeCoor, & + nbNode, listNode, & + nodeNumeClosest) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + type(CELL_GEOM), intent(in) :: cellGeom + real(kind=8), pointer :: nodeCoor(:) + integer, intent(in) :: nbNode, listNode(nbNode) + integer, intent(out) :: nodeNumeClosest +! ----- Local + real(kind=8) :: cellCentGlob(3) + integer :: iDime, iNode, nodeNume + real(kind=8) :: vect_pm(3), distMini, dist +! ------------------------------------------------------------------------------------------------ +! + nodeNumeClosest = 0 + +! ----- Get center of cell in global space + call cellCompCenterGlob(cellGeom, cellCentGlob) + +! ----- Find closest node + distMini = 0.d0 + do iNode = 1, nbNode + nodeNume = listNode(iNode) + do iDime = 1, 3 + vect_pm(iDime) = nodeCoor(3*(nodeNume-1)+iDime)-cellCentGlob(iDime) + end do + dist = sqrt(vect_pm(1)**2+vect_pm(2)**2+vect_pm(3)**2) + if (dist .lt. distMini .or. iNode .eq. 1) then + distMini = dist + nodeNumeClosest = nodeNume + end if + end do + ASSERT(nodeNumeClosest .ne. 0) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! getCellsFromNode +! +! Get list of cells attached to a node +! +! In nodeNume : index in mesh of reference node +! Ptr meshConxInve : pointers to inverse connectivity +! meshConxInveCumu +! In nbCell : length of list of cells +! In listCell : list of cells +! Out nbCellToNode : length of list of cells attached to node +! Out cellToNode : list of cells attached to node +! +! -------------------------------------------------------------------------------------------------- + subroutine getCellsFromNode(nodeNume, & + meshConxInve, meshConxInveCumu, & + nbCell, listCell, & + nbCellToNode, cellToNode) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + integer, intent(in) :: nodeNume + integer, pointer :: meshConxInve(:), meshConxInveCumu(:) + integer, intent(in) :: nbCell + integer, intent(in) :: listCell(nbCell) + integer, intent(out) :: nbCellToNode + integer, intent(out) :: cellToNode(nbCell) +! ----- Local + integer :: iCell +! ------------------------------------------------------------------------------------------------ +! + cellToNode = 0 + nbCellToNode = meshConxInveCumu(nodeNume+1)-meshConxInveCumu(nodeNume) + do iCell = 1, nbCellToNode + cellToNode(iCell) = listCell(meshConxInve(meshConxInveCumu(nodeNume)-1+iCell)) + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! getPairJV +! +! Get pair from JEVEUX object +! +! In mesh : mesh +! In baseName : JEVEUX base name for output objects +! Ptr nodeCoor : pointer to coordinates of nodes +! In iPair : index of pair +! Out cellSlav : slave cell +! Out cellMast : master cell +! +! -------------------------------------------------------------------------------------------------- + subroutine getPairJV(mesh, baseName, nodeCoor, iPair, cellSlav_, cellMast_) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: baseName + integer, intent(in) :: iPair + real(kind=8), pointer :: nodeCoor(:) + type(CELL_GEOM), optional, intent(out) :: cellSlav_, cellMast_ +! ----- Local + integer :: jvData + type(CELL_GEOM) :: cellSlav, cellMast + character(len=24) :: zonePair + integer, pointer :: meshTypeGeom(:) => null() + integer, pointer :: meshConx(:) => null(), meshConxCumu(:) => null() + integer :: nbPair, cellSlavNume, cellMastNume +! ------------------------------------------------------------------------------------------------ +! +! ----- Access to mesh + call jeveuo(mesh(1:8)//'.TYPMAIL', 'L', vi=meshTypeGeom) + call jeveuo(mesh(1:8)//'.CONNEX', 'L', vi=meshConx) + call jeveuo(jexatr(mesh(1:8)//'.CONNEX', 'LONCUM'), 'L', vi=meshConxCumu) + +! ----- Access to pair objects + zonePair = baseName(1:8)//".LISTPAIRS" + call jeexin(zonePair, jvData) + if (jvData == 0) then + call utmess("F", "MESH4_4") + end if + call jeveuo(zonePair, 'L', jvData) + call jelira(zonePair, 'LONMAX', nbPair) + if (iPair .le. 0 .or. iPair .gt. nbPair) then + call utmess("F", "MESH4_5") + end if + +! ----- Get current cells in pair + cellSlavNume = zi(jvData+2*(iPair-1)-1+1) + call cellCreate(cellSlavNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellSlav) + + !call cellSetType(meshTypeGeom, cellSlavNume, cellSlav) + cellMastNume = zi(jvData+2*(iPair-1)-1+2) + !call cellSetType(meshTypeGeom, cellMastNume, cellMast) + call cellCreate(cellMastNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellMast) + +! ----- Outputs + if (present(cellSlav_)) then + cellSlav_ = cellSlav + end if + if (present(cellMast_)) then + cellMast_ = cellMast + end if +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! getInteJV +! +! Get integration points from JEVEUX object +! +! In baseName : JEVEUX base name for output objects +! In iPair : index of pair +! Out nbPoinInte : number of intersection points +! Out poinInte : coordinates of intersection points (parametric slave coordinates) +! +! -------------------------------------------------------------------------------------------------- + subroutine getInteJV(baseName, iPair, nbPoinInte, poinInte) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + character(len=24), intent(in) :: baseName + integer, intent(in) :: iPair + integer, intent(out) :: nbPoinInte + real(kind=8), intent(out) :: poinInte(2, MAX_NB_INTE) +! ----- Local + integer :: jvData, iPoinInte + character(len=24) :: zonePair, zoneNbPoinInte, zonePoinInte + integer :: nbPair +! ------------------------------------------------------------------------------------------------ +! + nbPoinInte = 0 + poinInte = 0.d0 + +! ----- Access to pair objects + zonePair = baseName(1:8)//".LISTPAIRS" + call jeexin(zonePair, jvData) + if (jvData == 0) then + call utmess("F", "MESH4_4") + end if + call jeveuo(zonePair, 'L', jvData) + call jelira(zonePair, 'LONMAX', nbPair) + if (iPair .le. 0 .or. iPair .gt. nbPair) then + call utmess("F", "MESH4_5") + end if + +! ----- Get intersection points + zoneNbPoinInte = baseName(1:8)//".NBPOIN" + zonePoinInte = baseName(1:8)//".INTERSLPTS" + call jeveuo(zoneNbPoinInte, 'L', jvData) + nbPoinInte = zi(jvData-1+iPair) + call jeveuo(zonePoinInte, 'L', jvData) + do iPoinInte = 1, MAX_NB_INTE + poinInte(1, iPoinInte) = zr(jvData-1+2*MAX_NB_INTE*(iPair-1)+iPoinInte) + poinInte(2, iPoinInte) = zr(jvData-1+2*MAX_NB_INTE*(iPair-1)+MAX_NB_INTE+iPoinInte) + end do +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! -------------------------------------------------------------------------------------------------- +! +! robustPair +! +! Robust pairing on zone +! +! In mesh : mesh +! In newgeo : updated coordinates of nodes +! In nbCellSlav : number of slave cells +! In nbCellMast : number of master cells +! In listCellSlav : list of slave cells +! In listCellMast : list of master cells +! IO meshPairing : main datastructure for pairing +! +! -------------------------------------------------------------------------------------------------- + subroutine robustPair(mesh, newgeo, & + nbCellSlav, nbCellMast, & + listCellSlav, listCellMast, & + meshPairing) +! ------------------------------------------------------------------------------------------------ +! ----- Parameters + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: newgeo + integer, intent(in) :: nbCellSlav, nbCellMast + integer, intent(in) :: listCellMast(nbCellMast), listCellSlav(nbCellSlav) + type(MESH_PAIRING), intent(inout) :: meshPairing +! ----- Local + ! aster_logical :: pair_exist, isFatal, l_recup + aster_logical :: isFatal + ! integer :: nbSlavStart, nbMastStart + ! integer, pointer :: cellSlavStart(:) => null() + ! integer, pointer :: cellMastStart(:) => null() + ! integer, pointer :: cellMastFlag(:) => null() + ! integer, pointer :: cellSlavFlag(:) => null(), cellMastPaired(:) => null() + ! integer :: slavIndxMini, slavIndxMaxi + ! integer :: mastIndxMini, mastIndxMaxi + ! integer :: iCell, iMastNeigh, iSlavNeigh + integer :: iCellSlav, cellSlavNume, iCellMast, cellMastNume + real(kind=8), pointer :: nodeCoor(:) => null() + integer, pointer :: meshTypeGeom(:) => null() + integer, pointer :: meshConx(:) => null(), meshConxCumu(:) => null() + ! integer, pointer :: mastConxInv(:) => null(), mastConxInvCumu(:) => null() + type(CELL_GEOM) :: cellSlav, cellMast + type(CELL_GEOM) :: cellSlavLine, cellMastLine + ! integer :: nbSlavNeigh, nbMastPaired, inteNeigh(MAX_NB_NEIGH), nbMastNeigh + ! integer :: cellNeigh(MAX_NB_NEIGH), iret + integer :: iret + real(kind=8) :: inteArea + ! integer :: mastFindIndx, cellMastNume, cellMastIndx, cellSlavIndx, cellSlavNume + integer :: nbPoinInte + real(kind=8) :: poinInte(2, MAX_NB_INTE), poinInteReal(3, MAX_NB_INTE) + ! integer :: cellNeighNume, cellNeighIndx + ! integer, pointer :: meshMastNeigh(:) => null(), meshSlavNeigh(:) => null() +! ------------------------------------------------------------------------------------------------ +! + if (meshPairing%debug) then + write (6, *) "==================" + write (6, *) "= Robust pairing =" + write (6, *) "==================" + write (6, *) " " + end if + +! ----- Access to updated geometry + call jeveuo(newgeo(1:19)//'.VALE', 'L', vr=nodeCoor) + +! ----- Access to mesh + call jeveuo(mesh(1:8)//'.TYPMAIL', 'L', vi=meshTypeGeom) + call jeveuo(mesh(1:8)//'.CONNEX', 'L', vi=meshConx) + call jeveuo(jexatr(mesh(1:8)//'.CONNEX', 'LONCUM'), 'L', vi=meshConxCumu) + +! ----- Protection + if (nbCellSlav .eq. 0 .or. nbCellMast .eq. 0) then + call utmess('F', 'MESH4_1') + end if + +! ----- Loop on slave cells + do iCellSlav = 1, nbCellSlav +! --------- Get slave element + cellSlavNume = listCellSlav(iCellSlav) + +! --------- Create slave cell + call cellCreate(cellSlavNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellSlav, cellSlavLine) + + if (meshPairing%debug) then + write (6, *) "Current slave element : ", cellSlavNume + write (6, *) " Coordinates (global frame): ", & + cellSlav%coorNodeGlob(1:meshPairing%spaceDime, 1:cellSlav%nbNode) + end if + +! --------- Loop on master cells + do iCellMast = 1, nbCellMast +! ------------- Get master element + cellMastNume = listCellMast(iCellMast) + +! ------------- Create master cell + call cellCreate(cellMastNume, nodeCoor, & + meshTypeGeom, meshConx, meshConxCumu, & + cellMast, cellMastLine) + if (meshPairing%debug) then + write (6, *) "Current master element: ", cellMastNume + write (6, *) " Coordinates (global frame): ", & + cellMast%coorNodeGlob(1:meshPairing%spaceDime, 1:cellMast%nbNode) + end if + +! ------------- Compute intersection of the two cells + inteArea = 0.d0 + nbPoinInte = 0 + poinInte = 0.d0 + poinInteReal = 0.d0 + if (meshPairing%debug) then + WRITE (6, *) "Compute intersection and projection in master space" + end if + call cellInteProj(meshPairing, & + cellSlav, cellSlavLine, cellMastLine, & + iret, & + nbPoinInte, poinInte, & + inteArea) + isFatal = isFatalError(iret) + if (.not. isFatal .and. iret .ne. ERR_PAIR_NONE) then + call utmess('A', 'MESH4_3') + inteArea = 0.d0 + nbPoinInte = 0 + end if + ASSERT(nbPoinInte .le. MAX_NB_INTE) + if (meshPairing%debug) then + WRITE (6, *) "Intersection area: ", inteArea + end if + +! ------------- Add pair + if (inteArea > meshPairing%pairTole .and. iret == ERR_PAIR_NONE) then + if (meshPairing%debug) then + call intePoinCoor(cellSlav, nbPoinInte, poinInte, poinInteReal) + WRITE (6, *) "Add pair: ", meshPairing%nbPair+1, & + "(", cellSlavNume, "-", cellMastNume, ")" + WRITE (6, *) "Nb points integrations : ", & + nbPoinInte + WRITE (6, *) "Coor. points integrations (parametric): ", & + poinInte(:, 1:nbPoinInte) + WRITE (6, *) "Coef. points integrations (global) : ", & + poinInteReal(:, 1:nbPoinInte) + WRITE (6, *) "Area of intersection : ", & + inteArea + end if + call pairAdd(cellSlavNume, cellMastNume, & + nbPoinInte, poinInte, & + meshPairing) + end if + end do + end do + +! ----- Clean memory + ! AS_DEALLOCATE(vi=cellSlavStart) + ! AS_DEALLOCATE(vi=cellMastStart) + ! AS_DEALLOCATE(vi=cellSlavFlag) + ! AS_DEALLOCATE(vi=cellMastFlag) + ! AS_DEALLOCATE(vi=cellMastPaired) +! +! ------------------------------------------------------------------------------------------------ + end subroutine +! +end module diff --git a/bibfor/mesh/mesh_pairing_type.F90 b/bibfor/mesh/mesh_pairing_type.F90 new file mode 100644 index 00000000000..86d182a6ff5 --- /dev/null +++ b/bibfor/mesh/mesh_pairing_type.F90 @@ -0,0 +1,27 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! aslint: disable=W1403 +module mesh_pairing_type +! + implicit none +! +#include "asterf_types.h" +! +! false module required because of error in aslint (E1009) +! +end module mesh_pairing_type diff --git a/bibfor/mesh/mesh_type.F90 b/bibfor/mesh/mesh_type.F90 new file mode 100644 index 00000000000..3847b5bb79e --- /dev/null +++ b/bibfor/mesh/mesh_type.F90 @@ -0,0 +1,83 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +! ================================================================================================== +! +! Module for types of mesh +! +! ================================================================================================== +module mesh_type +! ================================================================================================== +! ================================================================================================== + implicit none +! ================================================================================================== + private +#include "asterf_types.h" +#include "MeshTypes_type.h" +! ================================================================================================== +! Global variables +! ================================================================================================== +! - None +! ================================================================================================== +! Define types +! ================================================================================================== +! -------------------------------------------------------------------------------------------------- +! Geometry of a cell +! -------------------------------------------------------------------------------------------------- + type CELL_GEOM +! ----- String for type of cell + character(len=8) :: cellCode = " " + aster_logical :: isLinear = ASTER_TRUE + aster_logical :: isSkin = ASTER_FALSE +! ----- Topological dimension of cell (-1, 0, 1 or 2) + integer :: cellDime = 0 +! ----- Number of nodes + integer :: nbNode = 0 +! ----- Number of neighbours + integer :: nbNeigh = 0 +! ----- Diameter of cell + real(kind=8) :: diameter = -1.d0 +! ----- Barycenter of cell in global basis (X,Y,Z) + real(kind=8) :: baryGlob(3) = 0.d0 +! ----- Barycenter of cell in parametric basis (ksi, eta, zeta) + real(kind=8) :: baryPara(3) = 0.d0 +! ----- Coordinates of cell in global basis (X,Y,Z) + real(kind=8), dimension(3, MT_NNOMAX3D) :: coorNodeGlob = 0.d0 +! ----- Coordinates of cell in parametric basis (ksi, eta, zeta) + real(kind=8), dimension(3, MT_NNOMAX3D) :: coorNodePara = 0.d0 + end type CELL_GEOM +! -------------------------------------------------------------------------------------------------- +! Base for skin cell +! -------------------------------------------------------------------------------------------------- + type CELL_SKIN_BASE +! ----- Dimension of space + integer :: spaceDime = 0 +! ----- Flag for _external_ normal + aster_logical :: normIsExte = ASTER_TRUE +! ----- Normal + real(kind=8) :: norm(3) = 0.d0 +! ----- Tangents + real(kind=8) :: tau(3, 2) = 0.d0 + end type CELL_SKIN_BASE +!=================================================================================================== +!=================================================================================================== + public :: CELL_GEOM, CELL_SKIN_BASE +contains +!=================================================================================================== +!=================================================================================================== +end module mesh_type diff --git a/bibfor/mesh/pairWrap.F90 b/bibfor/mesh/pairWrap.F90 new file mode 100644 index 00000000000..d917f9a72e9 --- /dev/null +++ b/bibfor/mesh/pairWrap.F90 @@ -0,0 +1,168 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +subroutine pairWrap(method, & + mesh, newgeo, mastConxInvName, & + mastNeighName, slavNeighName, & + pairTole, distRatio, verbosity, & + nbCellMast, listCellMast, & + nbCellSlav, listCellSlav, & + nbNodeMast, listNodeMast, & + nbPairZone, baseName) +! + use MeshPairing_module +! + implicit none +! +#include "asterf_types.h" +#include "asterfort/aplcpgn.h" +#include "asterfort/assert.h" +#include "asterfort/dismoi.h" +#include "asterfort/jedetr.h" +#include "asterfort/mesh_pairing_type.h" +#include "asterfort/utmess.h" +#include "asterfort/wkvect.h" +#include "jeveux.h" +! + integer, intent(in) :: method + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: newgeo, mastConxInvName + character(len=24), intent(in) :: mastNeighName, slavNeighName + real(kind=8), intent(in) :: pairTole, distRatio + integer, intent(in) :: verbosity + integer, intent(in) :: nbCellMast, listCellMast(nbCellMast) + integer, intent(in) :: nbCellSlav, listCellSlav(nbCellSlav) + integer, intent(in) :: nbNodeMast, listNodeMast(nbNodeMast) + integer, intent(out) :: nbPairZone + character(len=8), intent(in) :: baseName +! +! -------------------------------------------------------------------------------------------------- +! +! Pairing segment to segment +! +! Building a list of paired cells by PANG method +! +! -------------------------------------------------------------------------------------------------- +! +! In method : method of pairing +! In mesh : mesh +! In newgeo : updated coordinates of nodes +! In mastConxInvName : name of object for inverse connectivity of master cells on current zone +! In mastNeighName : name of object for neighbours of master cells +! In slavNeighName : name of object for neighbours of slave cells +! In pairTole : tolerance for projection (all operations ! ) +! In distRatio : tolerance from DIST_RATIO +! In verbosity : level of verbosity +! In nbCellSlav : number of slave cells +! In listCellSlav : list of slave cells +! In nbCellMast : number of master cells +! In listCellMast : list of master cells +! In nbNodeMast : number of master nodes +! In listNodeMast : list of master nodes +! Out nbPairZone : number of paired cells +! In baseName : JEVEUX base name for output objects +! In zonePair : name of datastructure for list of paired cells +! In zoneNbPoinInte : name of datastructure for number of integration points on slave cell +! In zonePoinInte : name of datastructure for coordinates of integration points on slave cell +! +! -------------------------------------------------------------------------------------------------- +! + integer :: pairDime, jvData, spaceDime + type(MESH_PAIRING) :: meshPairing + character(len=24) :: zonePair, zoneNbPoinInte, zonePoinInte +! +! -------------------------------------------------------------------------------------------------- +! + nbPairZone = 0 + +! - Protection + if (nbCellSlav .eq. 0 .or. nbCellMast .eq. 0) then + call utmess('F', 'MESH4_1') + end if + +! - Flags for debug + meshPairing%debug = verbosity .ge. 2 + +! - Create main object for pairing + pairDime = nbCellMast*nbCellSlav + call pairAllocate(pairDime, meshPairing) + +! - Tolerances + meshPairing%distRatio = distRatio + meshPairing%pairTole = pairTole + +! - Name of output objects + zonePair = baseName(1:8)//".LISTPAIRS" + zoneNbPoinInte = baseName(1:8)//".NBPOIN" + zonePoinInte = baseName(1:8)//".INTERSLPTS" + call jedetr(zonePair) + call jedetr(zoneNbPoinInte) + call jedetr(zonePoinInte) + +! - Get space dimension + call dismoi('DIM_GEOM', mesh, 'MAILLAGE', repi=spaceDime) + spaceDime = spaceDime + if (spaceDime .eq. 2) then + spaceDime = 2 + else + spaceDime = 3 + end if + meshPairing%spaceDime = spaceDime + +! - Pairing (fast version) + if (method == PAIR_FAST) then + call fastPair(mesh, newgeo, mastConxInvName, & + mastNeighName, slavNeighName, & + nbCellSlav, nbCellMast, nbNodeMast, & + listCellSlav, listCellMast, listNodeMast, & + meshPairing) + elseif (method == PAIR_OLD) then + call aplcpgn(mesh, newgeo, & + mastConxInvName, mastNeighName, slavNeighName, & + pairTole, distRatio, & + nbCellMast, listCellMast, & + nbCellSlav, listCellSlav, & + listNodeMast, nbNodeMast, & + meshPairing) + elseif (method == PAIR_ROBUST) then + call robustPair(mesh, newgeo, & + nbCellSlav, nbCellMast, & + listCellSlav, listCellMast, & + meshPairing) + else + ASSERT(ASTER_FALSE) + end if + +! - Save results for this zone + nbPairZone = meshPairing%nbPair + if (nbPairZone > 0) then + call wkvect(zonePair, 'G V I', 2*nbPairZone, jvData) + zi(jvData-1+1:jvData-1+2*nbPairZone) = & + meshPairing%Pair(1:2*nbPairZone) + call wkvect(zoneNbPoinInte, 'G V I', nbPairZone, jvData) + zi(jvData-1+1:jvData-1+nbPairZone) = & + meshPairing%nbPoinInte(1:nbPairZone) + call wkvect(zonePoinInte, 'G V R', 2*MAX_NB_INTE*nbPairZone, jvData) + zr(jvData-1+1:jvData-1+2*MAX_NB_INTE*nbPairZone) = & + meshPairing%poinInte(1:2*MAX_NB_INTE*nbPairZone) + end if + +! - Clean memory + call pairDeallocate(meshPairing) +! +end subroutine diff --git a/bibfor/mesh/quadPoinCoorWrap.F90 b/bibfor/mesh/quadPoinCoorWrap.F90 new file mode 100644 index 00000000000..b7524b53698 --- /dev/null +++ b/bibfor/mesh/quadPoinCoorWrap.F90 @@ -0,0 +1,92 @@ +! -------------------------------------------------------------------- +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +! This file is part of code_aster. +! +! code_aster is free software: you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation, either version 3 of the License, or +! (at your option) any later version. +! +! code_aster is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with code_aster. If not, see . +! -------------------------------------------------------------------- +! +subroutine quadPoinCoorWrap(mesh, nodeCoorName, baseName, iPair, & + nbPoinQuad, poinQuad) +! + use MeshPairing_module + use mesh_type + use mesh_cell_module +! + implicit none +! +#include "asterf_types.h" +#include "asterfort/assert.h" +#include "asterfort/getQuadCont.h" +#include "asterfort/jeveuo.h" +#include "asterfort/mesh_pairing_type.h" +#include "Contact_type.h" +#include "jeveux.h" +! + character(len=8), intent(in) :: mesh + character(len=24), intent(in) :: nodeCoorName, baseName + integer, intent(in) :: iPair + integer, intent(out) :: nbPoinQuad + real(kind=8), intent(out) :: poinQuad(3, MAX_NB_QUAD) +! +! -------------------------------------------------------------------------------------------------- +! +! Pairing segment to segment +! +! Get coordinates of Gauss point in intersection +! +! -------------------------------------------------------------------------------------------------- +! +! In mesh : mesh +! In baseName : JEVEUX base name for output objects +! In nodeCoorName : JEVEUX name for coordinates of nodes +! In iPair : index of pair +! Out nbPoinQuad : number of quadrature points +! Out poinQuad : coordinates of quadrature points en global space +! +! -------------------------------------------------------------------------------------------------- +! + integer:: nbPoinInte + real(kind=8) :: poinInteSlav(2, MAX_NB_INTE) + real(kind=8) :: poinQuadSlav(2, MAX_NB_QUAD) + integer :: modelDime + type(CELL_GEOM) :: cellSlav, cellMast + real(kind=8), pointer :: nodeCoor(:) => null() +! +! -------------------------------------------------------------------------------------------------- +! + nbPoinQuad = 0 + poinQuad = 0.d0 + +! - Access to updated geometry + call jeveuo(nodeCoorName(1:19)//'.VALE', 'L', vr=nodeCoor) + +! - Access to pair objects + call getPairJV(mesh, baseName, nodeCoor, iPair+1, & + cellSlav_=cellSlav, cellMast_=cellMast) + ASSERT(cellMast%cellDime .eq. cellSlav%cellDime) + modelDime = cellMast%cellDime+1 + +! - Get coordinates of intersection points in slave parametric space + call getInteJV(baseName, iPair+1, nbPoinInte, poinInteSlav) + +! - Get quadrature points + call getQuadCont(modelDime, & + cellSlav%cellCode, cellMast%cellCode, & + nbPoinInte, poinInteSlav, & + nbPoinQuad, poinQuadSlav) + +! - Project coordinates + call quadPoinCoor(cellSlav, nbPoinQuad, poinQuadSlav, poinQuad) +! +end subroutine diff --git a/bibfor/op/op0176.F90 b/bibfor/op/op0176.F90 index a0a8ea68289..bee03aa160c 100644 --- a/bibfor/op/op0176.F90 +++ b/bibfor/op/op0176.F90 @@ -1,5 +1,5 @@ ! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +! Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org ! This file is part of code_aster. ! ! code_aster is free software: you can redistribute it and/or modify @@ -26,7 +26,6 @@ subroutine op0176() #include "asterc/getres.h" #include "asterfort/assert.h" #include "asterfort/dyarc0.h" -#include "asterfort/extrs1.h" #include "asterfort/extrs2.h" #include "asterfort/getvid.h" #include "asterfort/infmaj.h" @@ -140,15 +139,9 @@ subroutine op0176() call rscrsd('G', resultOutName, typcon, nbarch) end if ! - if (resultInName .eq. resultOutName) then - if (lrest) call utmess('F', 'PREPOST2_5') - call extrs1(resultInName, storeNb, storeIndx, paraNb, paraName, & - nbarch, archi, nbexcl, zk16(jexcl), nbnosy) - else - call extrs2(resultInName, resultOutName, typcon, lrest, noma, & - nomo, nocara, nochmat, storeNb, storeIndx, paraNb, paraName, & - nbarch, archi, nbexcl, zk16(jexcl), nbnosy) - end if + call extrs2(resultInName, resultOutName, typcon, lrest, noma, & + nomo, nocara, nochmat, storeNb, storeIndx, paraNb, paraName, & + nbarch, archi, nbexcl, zk16(jexcl), nbnosy) AS_DEALLOCATE(vi=storeIndx) ! @@ -173,12 +166,9 @@ subroutine op0176() ! 999 continue ! -! -! ! -- CREATION DE L'OBJET .REFD SI NECESSAIRE: ! ------------------------------------------- call refdcp(resultInName, resultOutName) -! ! call jedema() ! diff --git a/bibfor/prepost/extrs1.F90 b/bibfor/prepost/extrs1.F90 deleted file mode 100644 index cd7f7d5e695..00000000000 --- a/bibfor/prepost/extrs1.F90 +++ /dev/null @@ -1,215 +0,0 @@ -! -------------------------------------------------------------------- -! Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org -! This file is part of code_aster. -! -! code_aster is free software: you can redistribute it and/or modify -! it under the terms of the GNU General Public License as published by -! the Free Software Foundation, either version 3 of the License, or -! (at your option) any later version. -! -! code_aster is distributed in the hope that it will be useful, -! but WITHOUT ANY WARRANTY; without even the implied warranty of -! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -! GNU General Public License for more details. -! -! You should have received a copy of the GNU General Public License -! along with code_aster. If not, see . -! -------------------------------------------------------------------- -! -subroutine extrs1(resu0, nbrang, nuordr, nbpara, nompar, & - nbarch, nuarch, nbexcl, chexcl, nbnosy) - implicit none -#include "jeveux.h" -#include "asterc/isnnem.h" -#include "asterc/r8vide.h" -#include "asterfort/assert.h" -#include "asterfort/copisd.h" -#include "asterfort/detrsd.h" -#include "asterfort/extrs3.h" -#include "asterfort/jedema.h" -#include "asterfort/jeecra.h" -#include "asterfort/jemarq.h" -#include "asterfort/jenuno.h" -#include "asterfort/jeveuo.h" -#include "asterfort/jexnum.h" -#include "asterfort/rsadpa.h" -#include "asterfort/rsexch.h" -#include "asterfort/rsmena.h" -#include "asterfort/rsutch.h" -! - integer :: nbrang, nuordr(*), nbarch, nbpara, nuarch(*), nbexcl, nbnosy - character(len=16) :: nompar(*), chexcl(*) - character(len=*) :: resu0 -! ------------------------------------------------------------------ -! person_in_charge: jacques.pellet at edf.fr -! EXTR_RESU / ARCHIVAGE + REUSE -! ---------------------------------------------------------------------- -! -! -! 0.3. ==> VARIABLES LOCALES -! -! - integer :: irang, i, j, k, jtach, iadin, iadou, ire1 - integer :: iundf, iordr - real(kind=8) :: rundf - character(len=3) :: type - character(len=16) :: nomsym - character(len=16) :: nopara - character(len=19) :: nomsdr - character(len=19) :: chamin, nomch1, nomch2 - integer, pointer :: ordr(:) => null() -! ------------------------------------------------------------------ -! - call jemarq() - rundf = r8vide() - iundf = isnnem() -! - nomsdr = resu0 -! -! -! 1. -- ON COMPACTE LES CHAMPS ARCHIVES : -! ------------------------------------------------------- - do i = 1, nbnosy - call jenuno(jexnum(nomsdr//'.DESC', i), nomsym) - call jeveuo(jexnum(nomsdr//'.TACH', i), 'E', jtach) - do j = 1, nbexcl - if (chexcl(j) .eq. nomsym) then - do k = 1, nbrang - if (zk24(jtach+k-1) (1:1) .eq. ' ') goto 10 - call rsexch('F', nomsdr, nomsym, nuordr(k), chamin, & - ire1) - call detrsd('CHAMP_GD', chamin) - zk24(jtach+k-1) = ' ' -10 continue - end do - goto 50 -! - end if - end do -! - irang = 0 - do j = 1, nbrang - if (zk24(jtach+j-1) (1:1) .eq. ' ') goto 30 - call rsexch('F', nomsdr, nomsym, nuordr(j), chamin, & - ire1) - if (nuarch(j) .eq. 0) then - call detrsd('CHAMP_GD', chamin) - else - irang = irang+1 - zk24(jtach+irang-1) = chamin - end if -30 continue - end do -! - do k = irang+1, nbrang - zk24(jtach+k-1) = ' ' - end do -50 continue - end do -! -! -! 2. -- ON COMPACTE LES PARAMETRES ARCHIVES : -! ------------------------------------------- - irang = 0 - do i = 1, nbrang - if (nuarch(i) .eq. 0) goto 70 - irang = irang+1 - do j = 1, nbpara - nopara = nompar(j) - call rsadpa(nomsdr, 'L', 1, nopara, nuordr(i), & - 1, sjv=iadin, styp=type, istop=0) - call extrs3(nomsdr, nopara, irang, 'E', 1, & - type, iadou) - if (type(1:1) .eq. 'I') then - zi(iadou) = zi(iadin) - else if (type(1:1) .eq. 'R') then - zr(iadou) = zr(iadin) - else if (type(1:1) .eq. 'C') then - zc(iadou) = zc(iadin) - else if (type(1:3) .eq. 'K80') then - zk80(iadou) = zk80(iadin) - else if (type(1:3) .eq. 'K32') then - zk32(iadou) = zk32(iadin) - else if (type(1:3) .eq. 'K24') then - zk24(iadou) = zk24(iadin) - else if (type(1:3) .eq. 'K16') then - zk16(iadou) = zk16(iadin) - else if (type(1:2) .eq. 'K8') then - zk8(iadou) = zk8(iadin) - end if - end do -70 continue - end do - ASSERT(irang .eq. nbarch) -! -! -! 3. -- ON COMPACTE LES NUME_ORDRE ARCHIVES : -! ------------------------------------------- - call jeecra(nomsdr//'.ORDR', 'LONUTI', nbarch) - call jeveuo(nomsdr//'.ORDR', 'E', vi=ordr) - irang = 0 - do i = 1, nbrang - if (nuarch(i) .eq. 0) goto 80 - irang = irang+1 - ordr(irang) = nuordr(i) -80 continue - end do - ASSERT(irang .eq. nbarch) -! -! -! 4. -- ON MET A "ZERO" LES IRANG INUTILISES : -! ------------------------------------------------- - do irang = nbarch+1, nbrang - ordr(irang) = iundf - do j = 1, nbpara - nopara = nompar(j) - call extrs3(nomsdr, nopara, irang, 'E', 1, & - type, iadou) - if (type(1:1) .eq. 'I') then - zi(iadou) = iundf - else if (type(1:1) .eq. 'R') then - zr(iadou) = rundf - else if (type(1:1) .eq. 'C') then - zc(iadou) = dcmplx(rundf, rundf) - else if (type(1:3) .eq. 'K80') then - zk80(iadou) = ' ' - else if (type(1:3) .eq. 'K32') then - zk32(iadou) = ' ' - else if (type(1:3) .eq. 'K24') then - zk24(iadou) = ' ' - else if (type(1:3) .eq. 'K16') then - zk16(iadou) = ' ' - else if (type(1:2) .eq. 'K8') then - zk8(iadou) = ' ' - end if - end do - end do -! -! -! 5. -- IL FAUT RENOMMER LES CHAMPS POUR QU'ILS RESPECTENT -! LA REGLE DE NOMMAGE DE RSUTCH.F : -! --------------------------------------------------------- - do i = 1, nbnosy - call jenuno(jexnum(nomsdr//'.DESC', i), nomsym) - call jeveuo(jexnum(nomsdr//'.TACH', i), 'E', jtach) - do j = 1, nbarch - iordr = ordr(j) - nomch1 = zk24(jtach-1+j) - if (nomch1 .eq. ' ') goto 41 - call rsutch(nomsdr, nomsym, iordr, nomch2, .false._1) - if (nomch1 .ne. nomch2) then - call copisd('CHAMP', 'G', nomch1, nomch2) - call detrsd('CHAMP', nomch1) - zk24(jtach-1+j) = nomch2 - end if -41 continue - end do - end do -! -! -! 6. -- IL FAUT ENCORE DETRUIRE LES SCORIES INUTILES : -! ---------------------------------------------------- - call rsmena(nomsdr) -! - call jedema() -end subroutine diff --git a/code_aster/Behaviours/BETON_AGEINGMFront.py b/code_aster/Behaviours/BETON_AGEINGMFront.py new file mode 100644 index 00000000000..abce9080722 --- /dev/null +++ b/code_aster/Behaviours/BETON_AGEINGMFront.py @@ -0,0 +1,41 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +# person_in_charge: goustan.bacquaert at edf.fr + +from .cata_comportement import LoiComportementMFront + +loi = LoiComportementMFront( + nom="BETON_AGEING", + lc_type=("MECANIQUE",), + doc="""To complete ...""", + num_lc=58, + nb_vari=0, + nom_vari=None, + mc_mater=None, + modelisation=("3D", "AXIS", "D_PLAN"), + deformation=("PETIT", "PETIT_REAC", "GDEF_LOG"), + algo_inte=("NEWTON", "NEWTON_PERT"), + type_matr_tang=("PERTURBATION", "VERIFICATION"), + proprietes=None, + syme_matr_tang=("Yes",), + exte_vari=None, + deform_ldc=("MECANIQUE",), + regu_visc=("No",), +) diff --git a/code_aster/Cata/Commands/defi_materiau.py b/code_aster/Cata/Commands/defi_materiau.py index 62d8e685990..6af86ff82d8 100644 --- a/code_aster/Cata/Commands/defi_materiau.py +++ b/code_aster/Cata/Commands/defi_materiau.py @@ -98,6 +98,7 @@ EXCLUS("MohrCoulombAS", "MohrCoulombAS_FO"), EXCLUS("NLH_CSRM", "NLH_CSRM_FO"), EXCLUS("MCC", "MCC_FO"), + EXCLUS("BETON_AGEING", "BETON_AGEING_FO"), EXCLUS("BETON_BURGER", "BETON_BURGER_FO"), EXCLUS("MetaAcierEPIL_PT", "MetaAcierEPIL_PT_FO"), PRESENT_PRESENT("BPEL_ACIER", "ELAS"), @@ -345,6 +346,8 @@ "Barcelone_FO", "CSSM", "CSSM_FO", + "BETON_AGEING", + "BETON_AGEING_FO", ), ), reuse=SIMP(statut="c", typ=CO), @@ -5734,6 +5737,38 @@ FlowCorrection=SIMP(statut="o", typ=fonction_sdaster), InitVoidsRatio=SIMP(statut="o", typ=fonction_sdaster), ), + BETON_AGEING=FACT( + statut="f", + YoungModulus=SIMP(statut="o", typ="R"), + PoissonRatio=SIMP(statut="o", typ="R"), + VoigtSphModulus=SIMP(statut="o", typ="R"), + VoigtDevModulus=SIMP(statut="o", typ="R"), + VoigtSphViscosity=SIMP(statut="o", typ="R"), + VoigtDevViscosity=SIMP(statut="o", typ="R"), + MaxwellSphModulus=SIMP(statut="o", typ="R"), + MaxwellDevModulus=SIMP(statut="o", typ="R"), + ConcreteInitTime=SIMP(statut="o", typ="R"), + DessiccationModulus=SIMP(statut="o", typ="R"), + ArrheniusIndex=SIMP(statut="o", typ="R"), + ReferenceTemperature=SIMP(statut="o", typ="R"), + KelvinIndex=SIMP(statut="o", typ="R"), + ), + BETON_AGEING_FO=FACT( + statut="f", + YoungModulus=SIMP(statut="o", typ=fonction_sdaster), + PoissonRatio=SIMP(statut="o", typ=fonction_sdaster), + VoigtSphModulus=SIMP(statut="o", typ=fonction_sdaster), + VoigtDevModulus=SIMP(statut="o", typ=fonction_sdaster), + VoigtSphViscosity=SIMP(statut="o", typ=fonction_sdaster), + VoigtDevViscosity=SIMP(statut="o", typ=fonction_sdaster), + MaxwellSphModulus=SIMP(statut="o", typ=fonction_sdaster), + MaxwellDevModulus=SIMP(statut="o", typ=fonction_sdaster), + ConcreteInitTime=SIMP(statut="o", typ=fonction_sdaster), + DessiccationModulus=SIMP(statut="o", typ=fonction_sdaster), + ArrheniusIndex=SIMP(statut="o", typ=fonction_sdaster), + ReferenceTemperature=SIMP(statut="o", typ=fonction_sdaster), + KelvinIndex=SIMP(statut="o", typ=fonction_sdaster), + ), NLH_CSRM=FACT( statut="f", YoungModulus=SIMP(statut="o", typ="R", val_min=0.000001), diff --git a/code_aster/Cata/Commands/extr_resu.py b/code_aster/Cata/Commands/extr_resu.py index 66e6c0d386c..67960ff6439 100644 --- a/code_aster/Cata/Commands/extr_resu.py +++ b/code_aster/Cata/Commands/extr_resu.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2022 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ from ..Commons import * from ..Language.DataStructure import * from ..Language.Syntax import * +from ..Language.SyntaxUtils import deprecate def extr_resu_prod(RESULTAT, **args): @@ -44,13 +45,20 @@ def extr_resu_prod(RESULTAT, **args): return AsType(RESULTAT) +def compat_syntax(keywords): + """Compatibility. + - reuse is not supported anymore. + """ + if keywords.pop("reuse", None): + deprecate("EXTR_RESU/reuse", case=2) + + EXTR_RESU = OPER( nom="EXTR_RESU", op=176, sd_prod=extr_resu_prod, - reentrant="f:RESULTAT", fr=tr("Extraire des champs au sein d'une SD Résultat"), - reuse=SIMP(statut="c", typ=CO), + compat_syntax=compat_syntax, RESULTAT=SIMP( statut="o", typ=( diff --git a/code_aster/Cata/Commons/c_comportement.py b/code_aster/Cata/Commons/c_comportement.py index defe0f6b5f4..16544bd908f 100644 --- a/code_aster/Cata/Commons/c_comportement.py +++ b/code_aster/Cata/Commons/c_comportement.py @@ -316,6 +316,7 @@ def C_COMPORTEMENT(command): "JOINT_BANDIS", "NLH_CSRM", "MCC", + "BETON_AGEING", "Barcelone", "CSSM", "LAIGLE", diff --git a/code_aster/Cata/Commons/c_relation.py b/code_aster/Cata/Commons/c_relation.py index 76b64fd5700..d2b0ad13f71 100644 --- a/code_aster/Cata/Commons/c_relation.py +++ b/code_aster/Cata/Commons/c_relation.py @@ -227,4 +227,5 @@ def C_RELATION(command): "Barcelone", "CSSM", "ELAS_HYPER_VISC", + "BETON_AGEING", ) diff --git a/code_aster/Cata/Language/SyntaxUtils.py b/code_aster/Cata/Language/SyntaxUtils.py index 35aaca6d973..6e9012e737b 100644 --- a/code_aster/Cata/Language/SyntaxUtils.py +++ b/code_aster/Cata/Language/SyntaxUtils.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -58,15 +58,15 @@ def deprecate(feature, case=1, help=None, level=6): level (int): Level of the caller in the stack. """ if case == 1: - msg = "This feature is obsoleted, {0!r} will be removed in the future." + msg = "This feature is obsolete, {0!r} will be removed in the future." elif case == 2: - msg = "This feature is obsoleted, {0!r} has been removed." + msg = "This feature is obsolete, {0!r} has been removed." elif case == 3: msg = "This feature has a new implementation, {0!r} will be removed in the future." elif case == 4: msg = "This feature has a new implementation, {0!r} has been removed." else: - msg = "This feature is obsoleted: {0!r}" + msg = "This feature is obsolete: {0!r}" if help: msg += " " + help warn(msg.format(feature), DeprecationWarning, stacklevel=level) diff --git a/code_aster/CodeCommands/__init__.py b/code_aster/CodeCommands/__init__.py index 161d22fb43d..f8f7902a9fd 100644 --- a/code_aster/CodeCommands/__init__.py +++ b/code_aster/CodeCommands/__init__.py @@ -148,8 +148,6 @@ from .modi_repere import MODI_REPERE from .norm_mode import NORM_MODE from .nume_ddl_gene import NUME_DDL_GENE - -# other commands are automatically added just using their catalog from .operator import define_operators from .post_cham_xfem import POST_CHAM_XFEM from .post_champ import POST_CHAMP @@ -189,5 +187,6 @@ from .ther_non_line_mo import THER_NON_LINE_MO from .variable import VARIABLE +# other commands are automatically added just using their catalog define_operators(globals()) del define_operators diff --git a/code_aster/CodeCommands/calc_champ.py b/code_aster/CodeCommands/calc_champ.py index 6fb95cf6a99..751c6e55478 100644 --- a/code_aster/CodeCommands/calc_champ.py +++ b/code_aster/CodeCommands/calc_champ.py @@ -46,28 +46,24 @@ def post_exec(self, keywords): Arguments: keywords (dict): User's keywords. """ - if "reuse" not in keywords: - modele = keywords.get("MODELE") - if modele is None: - try: - modele = keywords["RESULTAT"].getModel() - except: - modele = None - if modele is None: - try: - modele = keywords["RESULTAT"].getDOFNumbering().getModel() - except: - modele = None - if modele is not None: - self._result.setModel(modele) + new_model = keywords.get("MODELE") + if not new_model: + previous = keywords["RESULTAT"].getModels() + new_model = previous[-1] if previous else None + if not new_model: + try: + new_model = keywords["RESULTAT"].getDOFNumbering().getModel() + except AttributeError: + pass + if new_model: + self._result.setModel(new_model, exists_ok=True) + if "reuse" not in keywords: try: dofNume = keywords["RESULTAT"].getDOFNumbering() - except: - dofNume = None - - if dofNume is not None: self._result.setDOFNumbering(dofNume) + except AttributeError: + pass for rank in self._result.getIndexes(): if keywords["RESULTAT"].hasListOfLoads(rank): @@ -79,19 +75,8 @@ def post_exec(self, keywords): for fOND in keywords["RESULTAT"].getEquationNumberings(): self._result.addEquationNumbering(fOND) mesh = keywords["RESULTAT"].getMesh() - if mesh is not None: + if mesh: self._result.setMesh(mesh) - else: - try: - modele = self._result.getModel() - except: - modele = None - - if modele is None: - modele = keywords.get("MODELE") - - if modele is not None: - self._result.setModel(modele) self._result.build() @@ -105,27 +90,25 @@ def add_dependencies(self, keywords): """ super().add_dependencies(keywords) self.remove_dependencies(keywords, "RESULTAT") + self.remove_dependencies(keywords, "CHAM_UTIL", "FORMULE") if "reuse" not in keywords: # only if there is only one model, fieldmat... try: models = keywords["RESULTAT"].getModels() for model in models: - if model: - self._result.addDependency(model) + self._result.addDependency(model) except RuntimeError: pass try: fieldmats = keywords["RESULTAT"].getMaterialFields() for fieldmat in fieldmats: - if fieldmat: - self._result.addDependency(fieldmat) + self._result.addDependency(fieldmat) except RuntimeError: pass try: elems = keywords["RESULTAT"].getAllElementaryCharacteristics() for elem in elems: - if elem: - self._result.addDependency(elem) + self._result.addDependency(elem) except RuntimeError: pass diff --git a/code_aster/CodeCommands/calc_erreur.py b/code_aster/CodeCommands/calc_erreur.py index 4cea8a12686..4032e819f0f 100644 --- a/code_aster/CodeCommands/calc_erreur.py +++ b/code_aster/CodeCommands/calc_erreur.py @@ -1,6 +1,6 @@ # coding: utf-8 -# Copyright (C) 1991 - 2022 EDF R&D www.code-aster.org +# Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org # # This file is part of Code_Aster. # @@ -45,11 +45,12 @@ def post_exec(self, keywords): Arguments: keywords (dict): User's keywords. """ - modele = keywords.get("MODELE") - if modele is None: - modele = keywords["RESULTAT"].getModel() - if modele is not None: - self._result.setModel(modele) + new_model = keywords.get("MODELE") + if not new_model: + previous = keywords["RESULTAT"].getModels() + new_model = previous[-1] if previous else None + if new_model: + self._result.setModel(new_model, exists_ok=True) self._result.build() diff --git a/code_aster/CodeCommands/calc_meta.py b/code_aster/CodeCommands/calc_meta.py index 5cb39906778..34fa87269ba 100644 --- a/code_aster/CodeCommands/calc_meta.py +++ b/code_aster/CodeCommands/calc_meta.py @@ -1,6 +1,6 @@ # coding: utf-8 -# Copyright (C) 1991 - 2022 EDF R&D www.code-aster.org +# Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org # # This file is part of Code_Aster. # @@ -47,12 +47,13 @@ def post_exec(self, keywords): Arguments: keywords (dict): User's keywords. """ - modele = keywords["RESULTAT"].getModel() - if modele is None: - modele = keywords.get("MODELE") - if modele is not None: - self._result.setModel(modele) - self._result.build() + new_model = keywords.get("MODELE") + if not new_model: + previous = keywords["RESULTAT"].getModels() + new_model = previous[-1] if previous else None + if new_model: + self._result.setModel(new_model, exists_ok=True) + self._result.build() CALC_META = CalcMeta.run diff --git a/code_aster/CodeCommands/crea_resu.py b/code_aster/CodeCommands/crea_resu.py index 30c0b7c6f97..2895340889d 100644 --- a/code_aster/CodeCommands/crea_resu.py +++ b/code_aster/CodeCommands/crea_resu.py @@ -21,24 +21,23 @@ from ..Helpers import adapt_for_mgis_behaviour from ..Objects import ( - LoadResult, - ThermalResult, - FieldOnNodesComplex, - FieldOnNodesReal, - FieldOnNodesChar8, + ElasticFourierResult, + ElasticResult, + ExternalStateVariablesResult, FieldOnCellsComplex, - FieldOnCellsReal, FieldOnCellsLong, - ElasticFourierResult, - ThermalFourierResult, + FieldOnCellsReal, + FieldOnNodesChar8, + FieldOnNodesComplex, + FieldOnNodesReal, FullHarmonicResult, FullTransientResult, - ExternalStateVariablesResult, - ElasticResult, - ModeResultComplex, + LoadResult, ModeResult, + ModeResultComplex, MultipleElasticResult, NonLinearResult, + ThermalResult, ) from ..Supervis import ExecuteCommand from ..Utilities import force_list @@ -89,69 +88,100 @@ def create_result(self, keywords): raise NotImplementedError("Type of result {0!r} not yet " "implemented".format(typ)) def post_exec(self, keywords): - """Execute the command. + """Hook called after the execution of the command. Arguments: keywords (dict): User's keywords. """ - fkw = force_list(keywords.get("AFFE", [])) - - for occ in fkw: - if occ.get("MODELE"): - self._result.setModel(occ["MODELE"]) - break - chamGd = occ.get("CHAM_GD") - if chamGd is not None: - if isinstance(chamGd, (FieldOnNodesReal, FieldOnNodesComplex, FieldOnNodesChar8)): - mesh = chamGd.getMesh() - if mesh is not None: - self._result.setMesh(mesh) - break - - # find caraelem - for occ in fkw: - if occ.get("CARA_ELEM"): - self._result.setElementaryCharacteristics(occ["CARA_ELEM"]) - break + result = self._result + get_ = keywords.get + + new_model = None + new_mater = None + new_elemcara = None + for kw in ( + "AFFE", + "ASSE", + "PERM_CHAM", + "PROL_RTZ", + "PREP_VARC", + "KUCV", + "CONV_CHAR", + "CONV_RESU", + ): + if kw in keywords: + fkw = force_list(keywords[kw]) + + if "ASSE" in keywords: + src = fkw[0]["RESULTAT"] + new_model = src.getModel() + new_mater = src.getMaterialField() + new_elemcara = src.getElementaryCharacteristics() + + # Model, MaterialField... can not change between occurrences, + # the first found is used. + if not new_model: + new_model = [occ["MODELE"] for occ in fkw if occ.get("MODELE")] + new_model = new_model and new_model[0] + if not new_mater: + new_mater = [occ["CHAM_MATER"] for occ in fkw if occ.get("CHAM_MATER")] + new_mater = new_mater and new_mater[0] + if not new_elemcara: + new_elemcara = [occ["CARA_ELEM"] for occ in fkw if occ.get("CARA_ELEM")] + new_elemcara = new_elemcara and new_elemcara[0] + + matr = get_("MATR_RIGI", get_("MATR_MASS")) + if matr: + result.setDOFNumbering(matr.getDOFNumbering()) + if not new_model: + new_model = matr.getDOFNumbering().getModel() + if not new_model and get_("ECLA_PG"): + new_model = keywords["ECLA_PG"]["MODELE_INIT"] + if not new_model and get_("CONV_CHAR"): + matr_rigi = keywords["CONV_CHAR"]["MATR_RIGI"] + new_model = matr_rigi.getDOFNumbering().getModel() + if not new_model and get_("CONV_RESU"): + new_model = keywords["CONV_RESU"]["RESU_INIT"].getModel() + if not new_model and get_("KUCV"): + new_model = keywords["KUCV"]["RESU_INIT"].getModel() + + if new_model: + result.setModel(new_model, exists_ok=True) + elif "reuse" not in keywords: + # not reuse, at least set the mesh support from AFFE/CHAM_GD or PROL_RTZ + if get_("PROL_RTZ"): + result.setMesh(keywords["PROL_RTZ"]["MAILLAGE_FINAL"]) + elif fkw[0].get("CHAM_GD"): + mesh = fkw[0]["CHAM_GD"].getMesh() + result.setMesh(mesh) + if new_elemcara: + result.setElementaryCharacteristics(new_elemcara, exists_ok=True) + if new_mater: + result.setMaterialField(new_mater, exists_ok=True) # find ligrel and nume_equa feds = [] fnds = [] for occ in fkw: - chamGd = occ.get("CHAM_GD") - if chamGd is not None: - if isinstance(chamGd, (FieldOnNodesReal, FieldOnNodesComplex, FieldOnNodesChar8)): - fnd = chamGd.getDescription() - if fnd is not None: - fnds.append(fnd) - elif isinstance(chamGd, (FieldOnCellsReal, FieldOnCellsComplex, FieldOnCellsLong)): - fed = chamGd.getDescription() - if fed is not None: - feds.append(fed) - - if keywords.get("MATR_RIGI"): - self._result.setModel(keywords["MATR_RIGI"].getDOFNumbering().getModel()) - self._result.setMesh(keywords["MATR_RIGI"].getMesh()) - self._result.setDOFNumbering(keywords["MATR_RIGI"].getDOFNumbering()) - elif keywords.get("MATR_MASS"): - self._result.setModel(keywords["MATR_MASS"].getDOFNumbering().getModel()) - self._result.setMesh(keywords["MATR_MASS"].getMesh()) - self._result.setDOFNumbering(keywords["MATR_MASS"].getDOFNumbering()) - - if keywords.get("ECLA_PG"): - self._result.setModel(keywords["ECLA_PG"]["MODELE_INIT"]) - if keywords.get("CONV_CHAR"): + chamGd = occ["CHAM_GD"] + if isinstance(chamGd, (FieldOnNodesReal, FieldOnNodesComplex, FieldOnNodesChar8)): + fnd = chamGd.getDescription() + if fnd is not None: + fnds.append(fnd) + elif isinstance(chamGd, (FieldOnCellsReal, FieldOnCellsComplex, FieldOnCellsLong)): + fed = chamGd.getDescription() + if fed is not None: + feds.append(fed) + + if get_("CONV_CHAR"): matr_rigi = keywords["CONV_CHAR"]["MATR_RIGI"] - self._result.setModel(matr_rigi.getDOFNumbering().getModel()) - self._result.setMesh(matr_rigi.getMesh()) dofNum = matr_rigi.getDOFNumbering() if dofNum: if keywords["TYPE_RESU"] == "DYNA_TRANS": - self._result.setDOFNumbering(dofNum) + result.setDOFNumbering(dofNum) else: fnds.append(dofNum.getEquationNumbering()) - if keywords.get("CONV_RESU"): - self._result.setModel(keywords["CONV_RESU"]["RESU_INIT"].getModel()) + if get_("CONV_RESU"): matr_rigi = keywords["CONV_RESU"].get("MATR_RIGI") if matr_rigi is not None: dofNum = matr_rigi.getDOFNumbering() @@ -159,45 +189,13 @@ def post_exec(self, keywords): dofNum = keywords["CONV_RESU"]["NUME_DDL"] if dofNum: if keywords["TYPE_RESU"] == "DYNA_TRANS": - self._result.setDOFNumbering(dofNum) + result.setDOFNumbering(dofNum) else: fnds.append(dofNum.getEquationNumbering()) - if keywords.get("KUCV"): - self._result.setModel(keywords["KUCV"]["RESU_INIT"].getModel()) + if get_("KUCV"): dofNum = keywords["KUCV"]["MATR_AMOR"].getDOFNumbering() if dofNum: fnds.append(dofNum.getEquationNumbering()) - if keywords.get("PROL_RTZ"): - self._result.setMesh(keywords["PROL_RTZ"]["MAILLAGE_FINAL"]) - - if not fkw: - fkw = keywords.get("ASSE") - if not fkw: - fkw = keywords.get("PREP_VARC") - - if fkw: - chamMater = fkw[0].get("CHAM_MATER") - if chamMater is not None: - self._result.setMaterialField(chamMater) - - model = fkw[0].get("MODELE") - chamGd = fkw[0].get("CHAM_GD") - result = fkw[0].get("RESULTAT") - - if model is not None: - self._result.setModel(model) - elif result is not None: - model = result.getModel() - if model is not None: - self._result.setModel(model) - - mesh = result.getMesh() - if mesh is not None: - self._result.setMesh(mesh) - elif chamGd is not None: - mesh = chamGd.getMesh() - if mesh is not None: - self._result.setMesh(mesh) self._result.build(feds, fnds) diff --git a/code_aster/CodeCommands/lire_resu.py b/code_aster/CodeCommands/lire_resu.py index 06ec1ff7430..d4a50ded441 100644 --- a/code_aster/CodeCommands/lire_resu.py +++ b/code_aster/CodeCommands/lire_resu.py @@ -1,6 +1,6 @@ # coding: utf-8 -# Copyright (C) 1991 - 2023 EDF R&D www.code-aster.org +# Copyright (C) 1991 - 2024 EDF R&D www.code-aster.org # # This file is part of Code_Aster. # @@ -82,16 +82,15 @@ def post_exec(self, keywords): keywords (dict): User's keywords. """ if "MODELE" in keywords: - self._result.setModel(keywords["MODELE"]) - self._result.setMesh(keywords["MODELE"].getMesh()) + self._result.setModel(keywords["MODELE"], exists_ok=True) elif "MAILLAGE" in keywords: self._result.setMesh(keywords["MAILLAGE"]) if "CHAM_MATER" in keywords: - self._result.setMaterialField(keywords["CHAM_MATER"]) + self._result.setMaterialField(keywords["CHAM_MATER"], exists_ok=True) if "CARA_ELEM" in keywords: - self._result.setElementaryCharacteristics(keywords["CARA_ELEM"]) + self._result.setElementaryCharacteristics(keywords["CARA_ELEM"], exists_ok=True) if "MATR_RIGI" in keywords: dofNum = keywords["MATR_RIGI"].getDOFNumbering() diff --git a/code_aster/CodeCommands/rest_gene_phys.py b/code_aster/CodeCommands/rest_gene_phys.py index 32803006285..7b2ef54f030 100644 --- a/code_aster/CodeCommands/rest_gene_phys.py +++ b/code_aster/CodeCommands/rest_gene_phys.py @@ -79,57 +79,55 @@ def post_exec(self, keywords): for fED in resu_gene.getFiniteElementDescriptors(): self._result.addFiniteElementDescriptor(fED) - if dofNum is not None: + if dofNum: self._result.setDOFNumbering(dofNum) - modele = dofNum.getModel() - if modele is not None: - self._result.setModel(modele) + model = dofNum.getModel() + if model: + self._result.setModel(model) for i in dofNum.getFiniteElementDescriptors(): self._result.addFiniteElementDescriptor(i) - self._result.setModel(dofNum.getModel()) else: geneDofNum = resu_gene.getGeneralizedDOFNumbering() mesh = None - if geneDofNum is not None: + if geneDofNum: basis = geneDofNum.getModalBasis() - if basis is not None: + if basis: dofNum = basis.getDOFNumbering() if mesh is None: mesh = basis.getMesh() - if dofNum is not None: + if dofNum: self._result.setDOFNumbering(dofNum) - modele = dofNum.getModel() - if modele is not None: - self._result.setModel(modele) - elif mesh is None: + model = dofNum.getModel() + if model: + self._result.setModel(model) + elif not mesh: mesh = dofNum.getMesh() for i in dofNum.getFiniteElementDescriptors(): self._result.addFiniteElementDescriptor(i) - if mesh is None: + if not mesh: if "MODE_MECA" in keywords: mesh = keywords["MODE_MECA"].getMesh() - - if mesh is not None: + if mesh: self._result.setMesh(mesh) elif isinstance(resu_gene, GeneralizedModeResult): self._result.setMesh(resu_gene.getMesh()) matrRigi = resu_gene.getStiffnessMatrix() - if matrRigi is not None: + if matrRigi: modalBasis = matrRigi.getModalBasis() if modalBasis is None: dofNum = matrRigi.getGeneralizedDOFNumbering() if dofNum: modalBasis = dofNum.getModalBasis() - if modalBasis is not None: + if modalBasis: dofNum = modalBasis.getDOFNumbering() - if dofNum is not None: + if dofNum: self._result.setDOFNumbering(dofNum) else: # resultat issue de proj_mesu_modal dofNum = resu_gene.getDOFNumbering() - if dofNum is not None: + if dofNum: self._result.setDOFNumbering(dofNum) elif isinstance(resu_gene, ModeResult): matrRigiElim = resu_gene.getDependencies()[0] @@ -145,9 +143,10 @@ def post_exec(self, keywords): else: raise Exception("Unknown result type") - if self._result.getMesh() is None: + if not self._result.getMesh(): for fed in feds: self._result.setMesh(fed.getMesh()) + break if self._result.getMesh(): self._result.build(feds, fnds) diff --git a/code_aster/CodeCommands/stat_non_line.py b/code_aster/CodeCommands/stat_non_line.py index f418508cd05..5821a30425b 100644 --- a/code_aster/CodeCommands/stat_non_line.py +++ b/code_aster/CodeCommands/stat_non_line.py @@ -55,7 +55,7 @@ def create_result(self, keywords): Arguments: keywords (dict): Keywords arguments of user's keywords. """ - if keywords.get("reuse") is not None: + if keywords.get("reuse"): self._result = keywords["reuse"] incr = keywords["INCREMENT"][0] index = incr.get("NUME_INST_INIT") @@ -73,15 +73,15 @@ def post_exec(self, keywords): Arguments: keywords (dict): User's keywords. """ - self._result.setModel(keywords["MODELE"]) - self._result.setMaterialField(keywords["CHAM_MATER"]) + result = self._result caraElem = keywords.get("CARA_ELEM") - if caraElem is not None: - self._result.setElementaryCharacteristics(caraElem) - contact = keywords.get("CONTACT") - if contact is not None: - self._result.setContact(contact) + result.setModel(keywords["MODELE"], exists_ok=True) + result.setMaterialField(keywords["CHAM_MATER"], exists_ok=True) + if caraElem: + result.setElementaryCharacteristics(caraElem, exists_ok=True) + if contact: + result.setContact(contact) if self.exception and self.exception.id_message in ("MECANONLINE5_2",): return @@ -107,7 +107,7 @@ def post_exec(self, keywords): feds += etat["EVOL_NOLI"].getFiniteElementDescriptors() fnds += etat["EVOL_NOLI"].getEquationNumberings() - self._result.build(feds, fnds) + result.build(feds, fnds) def add_dependencies(self, keywords): """Register input *DataStructure* objects as dependencies. diff --git a/code_aster/Coupling/med_coupler.py b/code_aster/Coupling/med_coupler.py index 50b145fd821..8aa480e358d 100644 --- a/code_aster/Coupling/med_coupler.py +++ b/code_aster/Coupling/med_coupler.py @@ -21,10 +21,10 @@ Definition of a convenient object to synchronize MEDCoupling fields. """ -from ..Objects import LoadResult, SimpleFieldOnNodesReal, SimpleFieldOnCellsReal +from ..Objects import LoadResult, SimpleFieldOnCellsReal, SimpleFieldOnNodesReal +from ..Utilities import ParaMEDMEM as PMM from ..Utilities import logger, no_new_attributes from ..Utilities import medcoupling as MEDC -from ..Utilities import ParaMEDMEM as PMM class CoupledField(PMM.ParaFIELD): diff --git a/code_aster/MacroCommands/CalcEssai/ce_calcul_expansion.py b/code_aster/MacroCommands/CalcEssai/ce_calcul_expansion.py index 48244c78bbb..7885b07a2ee 100644 --- a/code_aster/MacroCommands/CalcEssai/ce_calcul_expansion.py +++ b/code_aster/MacroCommands/CalcEssai/ce_calcul_expansion.py @@ -52,7 +52,7 @@ def extract_mac_array(mac_mode, nom_table="MAC"): - """!Reconstruit un tableau numpy de modes MAC + """Reconstruit un tableau numpy de modes MAC /param mac_mode concept Table aster """ @@ -69,8 +69,7 @@ def extract_mac_array(mac_mode, nom_table="MAC"): class CalcEssaiExpansion: - - """!Classe qui s'occupe des calculs de l'interface correlation + """Classe qui s'occupe des calculs de l'interface correlation Cette classe un peu fourre-tout a pour but de separer les calculs specifique aster de l'interface graphique. L'objectif etant de pouvoir @@ -79,7 +78,7 @@ class CalcEssaiExpansion: """ def __init__(self, macro, mess, objects): - """!Constructeur + """Constructeur macro: le self de l'objet macro provenant de calc_essai_ops """ @@ -96,7 +95,7 @@ def __init__(self, macro, mess, objects): self.mess = mess def __setitem__(self, n, val): - """!Emulation d'un dictionnaire + """Emulation d'un dictionnaire On implemente __setitem__ pour faire croire au superviseur qu'on cree @@ -104,7 +103,7 @@ def __setitem__(self, n, val): self.concepts[n] = val def __getitem__(self, n): - """!Emulation d'un dictionnaire + """Emulation d'un dictionnaire On implemente __getitem__ pour les meme raison, et pour faire de l'allocation dynamique de numero de concept @@ -124,7 +123,6 @@ def calc_proj_resu(self): 4 resultats sont crees, nommes basename + suffix, ou suffix = ['_NX','_EX','_ET','_RD']""" self.mess.disp_mess("Debut de MACRO_EXPANS") - mdo = self.ce_objects # Preparation des donnees de mesure nume = None @@ -178,7 +176,7 @@ def calc_proj_resu(self): return result def calc_mac_mode(self, resu1, resu2, norme): - """!Calcul de MAC entre deux bases modales compatibles""" + """Calcul de MAC entre deux bases modales compatibles""" try: __MAC = MAC_MODES(BASE_1=resu1, BASE_2=resu2, MATR_ASSE=norme, INFO=1) except AsterError as err: diff --git a/code_aster/MacroCommands/CalcEssai/ce_test.py b/code_aster/MacroCommands/CalcEssai/ce_test.py index a4cf60786f6..86a1562a6c4 100644 --- a/code_aster/MacroCommands/CalcEssai/ce_test.py +++ b/code_aster/MacroCommands/CalcEssai/ce_test.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -22,15 +22,11 @@ # Fichier comprenant une procédure de test de CALC_ESSAI avec les différentes # options de calcul. -from numpy import take - -import aster from .ce_calcul_modifstruct import CalcEssaiModifStruct from ...Cata.Syntax import _F -from ...Messages import UTMESS from .ce_calcul_expansion import CalcEssaiExpansion -from .ce_calcul_identification import CalcEssaiIdentification, CalculInverse +from .ce_calcul_identification import CalcEssaiIdentification def TestCalcEssai( @@ -134,7 +130,6 @@ def TestCalcEssai( class MessageBox: - """!Classe qui permet d'ecrire dans un .mess separe""" def __init__(self, unite): diff --git a/code_aster/MacroCommands/Mac3Coeur/mac3coeur_calcul.py b/code_aster/MacroCommands/Mac3Coeur/mac3coeur_calcul.py index 85292766c10..4cd4e72ef77 100644 --- a/code_aster/MacroCommands/Mac3Coeur/mac3coeur_calcul.py +++ b/code_aster/MacroCommands/Mac3Coeur/mac3coeur_calcul.py @@ -80,7 +80,6 @@ def wrapper(inst): class Mac3CoeurCalcul: - """Base class of an analysis, intended to be inherited Its factory builds the proper object according to the passed keywords. @@ -755,7 +754,6 @@ def evaluate_contacts_prediction(self, initial_state_kws, current_load, type_cal class Mac3CoeurDeformation(Mac3CoeurCalcul): - """Compute the strain of the assemblies""" mcfact = "DEFORMATION" @@ -1192,11 +1190,16 @@ def _run(self, **kwargs): ) logger.debug(": Finish vessel opening using prediction.") + logger.debug( + "%s (%s), %s", + self.cham_mater_free, + self.cham_mater_free.getName(), + __RESULT.getMaterialField(__RESULT.getLastIndex()), + ) return __RESULT class Mac3CoeurLame(Mac3CoeurCalcul): - """Compute the thinkness of water from deformed assemblies""" mcfact = "LAME" @@ -1431,7 +1434,6 @@ def _run(self, **kwargs): class Mac3CoeurEtatInitial(Mac3CoeurLame): - """Compute Initial State""" mcfact = "LAME" diff --git a/code_aster/Messages/contact1.py b/code_aster/Messages/contact1.py index bea1081b063..4029c825859 100644 --- a/code_aster/Messages/contact1.py +++ b/code_aster/Messages/contact1.py @@ -29,15 +29,6 @@ 2: _( """ Le modèle n'est pas de type mécanique, ce n'est pas possible. -""" - ), - 3: _( - """ -Il existe des noeuds communs aux surfaces esclaves entre les zones de contact : c'est interdit. -Conseil : - - changez vos surfaces de contact, - - définissez alternativement les zones possédant un noeud commun comme maître et esclave, - - A MODIFIER pour la méthode LAC, il faut désactiver le lissage. """ ), 4: _( diff --git a/code_aster/Messages/mesh4.py b/code_aster/Messages/mesh4.py new file mode 100644 index 00000000000..ed66e57e6c9 --- /dev/null +++ b/code_aster/Messages/mesh4.py @@ -0,0 +1,37 @@ +# coding=utf-8 +# -------------------------------------------------------------------- +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org +# This file is part of code_aster. +# +# code_aster is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# code_aster is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with code_aster. If not, see . +# -------------------------------------------------------------------- + +from ..Utilities import _ + +cata_msg = { + 1: _("""Les surfaces à apparier n'ont pas de cellules."""), + # 2: _("""Les cellules de la surface ne sont pas toutes des mailles de peau."""), + 3: _( + """ + Une erreur non fatale est détectée lors de l'appariement de deux cellules. + Ce couple est ignoré, il y a potentiellement interpénétration entre ces deux cellules. + Conseil : + Vérifiez la qualité de l'appariement visuellement . +""" + ), + 4: _( + """On ne trouve pas les objets de l'appariement. Vérifiez que vous avez bien effectué le calcul.""" + ), + 5: _("""La paire demandée n'existe pas à cet index."""), +} diff --git a/code_aster/Messages/prepost2.py b/code_aster/Messages/prepost2.py index edd2263c8f6..5a1ceade193 100644 --- a/code_aster/Messages/prepost2.py +++ b/code_aster/Messages/prepost2.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -20,11 +20,6 @@ from ..Utilities import _ cata_msg = { - 5: _( - """ - Le mot-clé RESTREINT n'est pas autorisé dans EXTR_RESU en reuse. -""" - ), 6: _( """ Aucune maille n'a été trouvée avec le critère donné. diff --git a/code_aster/Messages/result2.py b/code_aster/Messages/result2.py index faa9382a55f..12e13d69ac2 100644 --- a/code_aster/Messages/result2.py +++ b/code_aster/Messages/result2.py @@ -1,6 +1,6 @@ # coding=utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2023 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -27,6 +27,28 @@ 5: _( """le numéro d'archivage est inférieur au numéro précédent. Il doit être strictement croissant.""" ), + 6: _( + """Cette opération n'est pas possible si le modèle varie. + +Risques & Conseils : + Limiter le traitement sur des numéros d'ordre où le modèle ne change pas. + """ + ), + 7: _( + """Cette opération n'est pas possible si le champ de matériau varie. + +Risques & Conseils : + Limiter le traitement sur des numéros d'ordre où le champ de matériau ne change pas. + """ + ), + 8: _( + """Cette opération n'est pas possible si les caractéristiques élémentaires varient. + +Risques & Conseils : + Limiter le traitement sur des numéros d'ordre où les caractéristiques élémentaires + ne changent pas. + """ + ), 14: _("""Le NUME_DDL a été déterminé à partir de la matrice de rigidité %(k1)s."""), 15: _("""Les NUME_DDL associés aux matrices MATR_RIGI et MATR_MASS sont différents."""), 16: _( diff --git a/code_aster/Supervis/ExecuteCommand.py b/code_aster/Supervis/ExecuteCommand.py index 45d34e58af7..cce16a77124 100644 --- a/code_aster/Supervis/ExecuteCommand.py +++ b/code_aster/Supervis/ExecuteCommand.py @@ -55,9 +55,7 @@ ============ """ -# aslint: disable=C4009 -# because of HELP_LEGACY_MODE string - +import gc import inspect import linecache import re @@ -81,6 +79,7 @@ Options, config, deprecated, + haveMPI, import_object, logger, no_new_attributes, @@ -89,7 +88,7 @@ from .code_file import track_coverage from .CommandSyntax import CommandSyntax from .ctopy import check_ds_object -from .Serializer import saveObjectsFromContext +from .Serializer import FinalizeOptions, saveObjectsFromContext @contextmanager @@ -535,6 +534,7 @@ def post_exec_(self, keywords): if self.hook: self.hook(keywords) finally: + self.cleanup() self.print_result() def post_exec(self, keywords): @@ -549,6 +549,9 @@ def post_exec(self, keywords): keywords (dict): Keywords arguments of user's keywords. """ + def cleanup(self): + """Clean-up function.""" + def check_ds(self): """Check a result created by the command. @@ -619,12 +622,6 @@ def check_jeveux(): ) -HELP_LEGACY_MODE = """ - from code_aster.Utilities import ExecutionParameter, Options - ExecutionParameter().enable(Options.UseLegacyMode) -""" - - class ExecuteMacro(ExecuteCommand): """This implements an executor of *legacy* macro-commands. @@ -650,6 +647,9 @@ class ExecuteMacro(ExecuteCommand): _add_results (dict): Dict of additional results. """ + # class attributes + _last_cleanup = 0 + _sdprods = _result_names = _add_results = None def __init__(self): @@ -690,6 +690,18 @@ def print_result(self): logger.info(command_result(self._counter, self.name, self._add_results.get(name))) self._print_stats() + def cleanup(self): + """Clean-up function.""" + if ExecuteCommand.level > 1: + if self._counter < ExecuteMacro._last_cleanup + 250: + return + ExecuteMacro._last_cleanup = self._counter + # wrapper to collect after each macro-command + timer = ExecutionParameter().timer + timer.Start(" . cleanup", num=1.9e6) + gc.collect() + timer.Stop(" . cleanup") + def exec_(self, keywords): """Execute the command and fill the *_result* attribute. @@ -1022,13 +1034,19 @@ def excepthook(cls, type, value, traceb): except AssertionError: pass if cls._current_cmd: + opt = ExecutionParameter().option + options = FinalizeOptions.Set + if haveMPI() and not opt & Options.HPCMode: + options |= FinalizeOptions.OnlyProc0 + if opt & Options.SaveBase: + options |= FinalizeOptions.SaveBase print("\nException: Trying to close the database after an uncaught exception...\n") print( f"\nPublishing the result of the current command {cls._current_cmd.name}...\n", flush=True, ) cls._current_cmd.publish_result() - saveObjectsFromContext(cls._current_cmd.caller_context) + saveObjectsFromContext(cls._current_cmd.caller_context, options=options) else: sys.__excepthook__(type, value, traceb) diff --git a/code_aster/Supervis/Serializer.py b/code_aster/Supervis/Serializer.py index 23a777d97c1..6439a7b9f70 100644 --- a/code_aster/Supervis/Serializer.py +++ b/code_aster/Supervis/Serializer.py @@ -314,7 +314,7 @@ def saveObjectsFromContext(context, delete=True, options=0): saved = pickler.save() else: saved = [] - logger.info("Objects not saved on processor #%d", rank) + logger.info("No database in results, objects not saved on processor #%d", rank) # close Jeveux files (should not be done before pickling) libaster.jeveux_finalize(options) diff --git a/code_aster/Utilities/compatibility.py b/code_aster/Utilities/compatibility.py index 6a4f1b2f3f1..0d4d734bc45 100644 --- a/code_aster/Utilities/compatibility.py +++ b/code_aster/Utilities/compatibility.py @@ -1,6 +1,6 @@ # coding: utf-8 # -------------------------------------------------------------------- -# Copyright (C) 1991 - 2022 - EDF R&D - www.code-aster.org +# Copyright (C) 1991 - 2024 - EDF R&D - www.code-aster.org # This file is part of code_aster. # # code_aster is free software: you can redistribute it and/or modify @@ -57,15 +57,15 @@ def deprecate(feature, case=1, help=None, level=4): level (int): Level of the caller in the stack. """ if case == 1: - msg = "This feature is obsoleted, {0!r} will be " "removed in the future." + msg = "This feature is obsolete, {0!r} will be removed in the future." elif case == 2: - msg = "This feature is obsoleted, {0!r} has been removed." + msg = "This feature is obsolete, {0!r} has been removed." elif case == 3: - msg = "This feature has a new implementation, {0!r} will be " "removed in the future." + msg = "This feature has a new implementation, {0!r} will be removed in the future." elif case == 4: - msg = "This feature has a new implementation, {0!r} has been " "removed." + msg = "This feature has a new implementation, {0!r} has been removed." else: - msg = "This feature is obsoleted: {0!r}" + msg = "This feature is obsolete: {0!r}" if help: msg += " " + help warn(msg.format(feature), DeprecationWarning, stacklevel=level) @@ -200,7 +200,7 @@ def remove_keyword(keywords, factor_keyword, simple_keyword, warning=False): def _warn(container, key): if not warning: return - msg = "This keyword is not yet supported and are currently " "removed: {0}{1}{2}" + msg = "This keyword is not yet supported and are currently removed: {0}{1}{2}" sep = "/" if factor_keyword.strip() and simple_keyword.strip() else "" warn(msg.format(factor_keyword, sep, simple_keyword)) del container[key] diff --git a/doc/_automatic_/libaster.py b/doc/_automatic_/libaster.py index 0045d45d283..98005f24a34 100644 --- a/doc/_automatic_/libaster.py +++ b/doc/_automatic_/libaster.py @@ -6226,28 +6226,28 @@ def getFiniteElementDescriptor(self): """Return the finite element descriptor to define virtual cells for Lagrange multipliers Returns: - FiniteElementDescriptor: fed. + FiniteElementDescriptor: finite element descriptor """ def getMesh(self): """Return the mesh used in the contact definition Returns: - Mesh: mesh. + BaseMesh: mesh. """ def getModel(self): """Return the model used in the contact definition Returns: - Model: model. + Model: model """ def getNumberOfContactZones(self): """Return the number of contact zones used Returns: - inter: number of contact zones. + int: number of contact zones. """ def getVerbosity(self): @@ -6310,7 +6310,7 @@ def __init__(self, *args, **kwargs): class ContactZone(DataStructure): - pass + """Object to define a zone of contact.""" # Method resolution order: # ContactZone @@ -6329,20 +6329,17 @@ def __init__(self, *args, **kwargs): """ def build(self): - """Build and check internal objects""" - - def getContactParameter(self): - """Get contact parameters defining method, coefficient... + """Build and check internal objects Returns: - ContactParameter: contact parameters + bool: success or failure """ - def getExcludedSlaveCells(self): - """Get excluded groups of cells on slave side + def getContactParameter(self): + """Get contact parameters defining method, coefficient... Returns: - str: excluded groups' names + ContactParameter: contact parameters """ def getFrictionParameter(self): @@ -6352,32 +6349,25 @@ def getFrictionParameter(self): FrictionParameter: friction parameters """ - def getMasterCellNeighbors(self, cell_number): - """Get the master cells in the neighbor of a given master cell number + def getMesh(self): + """Return the mesh used in the contact zone definition - Arguments: - int: master cell number + Returns: + BaseMesh: mesh """ - def getMasterCellsFromNode(self, node_number): - """Get the master cells associtaed with a node number - - Arguments: - int: node number - """ - - def getMesh(self): - """Return the mesh used in the contact zone definition + def getMeshPairing(self): + """Get pairing of surface meshes Returns: - BaseMesh: mesh. + MeshPairing: mesh pairing """ def getModel(self): """Return the model used in the contact zone definition Returns: - Model: model. + Model: model """ def getPairingParameter(self): @@ -6387,13 +6377,6 @@ def getPairingParameter(self): PairingParameter: pairing parameters """ - def getSlaveCellNeighbors(self, cell_number): - """Get the slave cells in the neighbor of a given slave cell number - - Arguments: - int: slave cell number - """ - def getSlaveCells(self): """Get slave's cells index @@ -6401,13 +6384,6 @@ def getSlaveCells(self): list[int]: slave's cells index """ - def getSlaveCellsFromNode(self, node_number): - """Get the slave cells associtaed with a node number - - Arguments: - int: node number - """ - def getSlaveNodes(self): """Get slave's nodes index @@ -6416,72 +6392,72 @@ def getSlaveNodes(self): """ def getVerbosity(self): - """Get level of verbosity: - 0- without - 1- normal - 2- detailled + """Get level of verbosity + 0- without + 1- normal + 2- detailled Returns: - integer: level of verbosity + int: level of verbosity """ - def setContactParameter(self, contact): + def setContactParameter(self, contParam): """Set contact parameters defining method, coefficient... Arguments: - ContactParameter: contact parameters + contParam (ContactParameter) : contact parameters """ - def setExcludedSlaveGroupOfCells(self, groups): + def setExcludedSlaveGroupOfCells(self, cellGroupsName): """Set excluded groups of cells on slave side Arguments: - str: excluded groups' names + cellGroupsName (str) : excluded groups' names """ - def setExcludedSlaveGroupOfNodes(self, groups): + def setExcludedSlaveGroupOfNodes(self, nodeGroupsName): """Set excluded groups of nodes on slave side Arguments: - str: excluded groups' names + nodeGroupsName (str) : excluded groups' names """ - def setFrictionParameter(self, friction): + def setFrictionParameter(self, fricParam): """Set friction parameters defining method, coefficient... Arguments: - FrictionParameter: friction parameters + fricParam (FrictionParameter) : friction parameters """ def setMasterGroupOfCells(self, master_name): """Set master's name of group of cells Arguments: - str: master's name + master_name (str) : name of group for master cells """ - def setPairingParameter(self, pairing): + def setPairingParameter(self, pairParam): """Set pairing parameters defining algorithm, distance... Arguments: - PairingParameter: pairing parameters + pairParam (PairingParameter) : pairing parameters """ def setSlaveGroupOfCells(self, slave_name): """Set slave's name of group of cells Arguments: - str: slave's name + slave_name (str) : name of group for slave cells """ def setVerbosity(self, level): - """Set level of verbosity: - 0- without - 1- normal (default) - 2- detailled + """Set level of verbosity + 0- without + 1- normal (default) + 2- detailled Arguments: - integer: level of verbosity + level (int) : level of verbosity """ # ---------------------------------------------------------------------- @@ -6489,22 +6465,391 @@ def setVerbosity(self, level): @property def checkNormals(self): - """bool: Attribute that holds the checking of outwards normals.""" + """bool: attribute that holds the checking of outwards normals.""" @property def hasFriction(self): - """bool: enable or disable the use of friction.""" + """Get status of friction + + Returns: + bool: friction or not + """ @property def hasSmoothing(self): - """bool: enable or disable the use of smoothing.""" + """Smoothing of normals + + Returns: + bool: smoothing or not + """ + + +# class MeshPairing in libaster + + +class MeshPairing(DataStructure): + """Object to create a pairing operator between two meshed surfaces.""" + + # Method resolution order: + # MeshPairing + # DataStructure + # pybind11_builtins.pybind11_object + # builtins.object + + # Methods defined here: + + def __init__(self, *args, **kwargs): + """Overloaded function. + + 1. __init__(self: libaster.MeshPairing, arg0: str, arg1: libaster.BaseMesh) -> None + + 2. __init__(self: libaster.MeshPairing, arg0: libaster.BaseMesh) -> None + """ + + def checkNormals(self, model): + """Check orientation of normals + + Arguments: + ModelPtr: a pointer to the model + + Returns: + nothing + """ + + def compute(self, dist_pairing=-1.0, pair_tole=1e-08): + """Compute pairing + + Arguments: + dist_pairing (real): tolerance from DIST_RATIO (projection outside cell) + pair_tole (real): tolerance for pairing + """ + + def getIntersectionArea(self, *args, **kwargs): + """Overloaded function. + + 1. getIntersectionArea(self: libaster.MeshPairing, indexPair: int) -> float + + + Compute intersection of area + + Arguments: + indexPair (integer): index of pair + + Returns: + double: area of intersection + + + 2. getIntersectionArea(self: libaster.MeshPairing, indexPair: int) -> float + + + Get area of intersection for a given pair + + Arguments: + indexPair (integer): index of pair + + Returns: + real: area of intersection + """ + + def getIntersectionPoints(self, indexPair, CoordinatesSpace=1): + """Get coordinates of intersection points for a given pair + + Arguments: + indexPair (integer): index of pair + CoordinatesSpace (CoordinatesSpace): space to describe coordinates + + Returns: + list[list]: coordinates in given space + """ + + def getListOfPairs(self): + """Get pairs + + Returns: + list: pairs (slave-master) + """ + + def getMasterCellNeighbors(self, cell_number): + """Get the master cells in the neighbor of a given master cell number + + Arguments: + int: master cell number + + Returns: + list: master neighbors cells + """ + + def getMasterCellsFromNode(self, node_number): + """Get the master cells associated with a node number + + Arguments: + int: node number + + Returns: + list: master cells associated + """ + + def getMesh(self): + """Return the mesh + + Returns: + Mesh: mesh. + """ + + def getNumberOfIntersectionPoints(self, *args, **kwargs): + """Overloaded function. + + 1. getNumberOfIntersectionPoints(self: libaster.MeshPairing, indexPair: int) -> int + + + Get number of intersection points + + Arguments: + indexPair (integer): index of pair + + Returns: + integer: number of intersection points + + + 2. getNumberOfIntersectionPoints(self: libaster.MeshPairing) -> list[int] + + + Get number of intersection points of all pairs + + Returns: + list: number of intersection points + """ + + def getNumberOfPairs(self): + """Get number of pairs + + Returns: + integer: number of pairs + """ + + def getQuadraturePoints(self, indexPair): + """Get coordinates of quadrature points for a given pair in global space + + Arguments: + indexPair (integer): index of pair + + Returns: + list: quadrature points + """ + + def getSlaveCellNeighbors(self, cell_number): + """Get the slave cells in the neighbor of a given slave cell number + + Arguments: + int: slave cell number + + Returns: + list: slave neighbors cells + """ + + def getSlaveCellsFromNode(self, node_number): + """Get the slave cells associated with a node number + + Arguments: + int: node number + + Returns: + list: slave cells associated + """ + + def getVerbosity(self): + """Get level of verbosity + + Returns: + integer: level of verbosity + """ + + def setExcludedSlaveGroupOfCells(self, groups): + """Set excluded groups of cells on slave side + + Arguments: + str: excluded groups' names + """ + + def setExcludedSlaveGroupOfNodes(self, groups): + """Set excluded groups of nodes on slave side + + Arguments: + str: excluded groups' names + """ + + def setMethod(self, method): + """Set method of pairing + + Arguments: + method (PairingMethod): method ("OLD", "Fast", "Robust) + """ + + def setPair(self, groupNameSlav, groupNameMast): + """Set pair of meshed surfaces + + Arguments: + groupNameSlav (str): slave's name + groupNameMast (str): master's name + """ + + def setVerbosity(self, level): + """Set level of verbosity + 0 - without + 1 - normal (default) + 2 - detailled (text) + + Arguments: + level (integer): level of verbosity + """ + + def updateCoordinates(self, disp): + """Update coordinates of nodes + + Arguments: + disp (FieldOnNodesReal): nodal field of displacement + """ + + +# class CoordinatesSpace in libaster + + +class CoordinatesSpace: + """Type of coordinates: Slave or Global.""" + + # Method resolution order: + # CoordinatesSpace + # pybind11_builtins.pybind11_object + # builtins.object + + # Methods defined here: + + def __eq__(self, other): + pass + + def __getstate__(self): + pass + + def __hash__(self): + pass + + def __index__(self): + pass + + def __init__(self, value): + pass + + def __int__(self): + pass + + def __ne__(self, other): + pass + + def __repr__(self): + pass + + def __setstate__(self, state): + pass + + def __str__(self): + pass + + # ---------------------------------------------------------------------- + # Data descriptors defined here: + + @property + def __members__(self): + pass + + @property + def name(self): + """name(self: object) -> str""" + + @property + def value(self): + pass + + # ---------------------------------------------------------------------- + # Data and other attributes defined here: + + Global = 1 + + Slave = 0 + + +# class PairingMethod in libaster + + +class PairingMethod: + """Type of pairing: Fast, BrutForce and Legacy.""" + + # Method resolution order: + # PairingMethod + # pybind11_builtins.pybind11_object + # builtins.object + + # Methods defined here: + + def __eq__(self, other): + pass + + def __getstate__(self): + pass + + def __hash__(self): + pass + + def __index__(self): + pass + + def __init__(self, value): + pass + + def __int__(self): + pass + + def __ne__(self, other): + pass + + def __repr__(self): + pass + + def __setstate__(self, state): + pass + + def __str__(self): + pass + + # ---------------------------------------------------------------------- + # Data descriptors defined here: + + @property + def __members__(self): + pass + + @property + def name(self): + """name(self: object) -> str""" + + @property + def value(self): + pass + + # ---------------------------------------------------------------------- + # Data and other attributes defined here: + + BrutForce = 2 + + Fast = 0 + + Legacy = 1 # class ContactPairing in libaster class ContactPairing(DataStructure): - pass + """Object to create contact pairing.""" # Method resolution order: # ContactPairing @@ -6522,31 +6867,50 @@ def __init__(self, *args, **kwargs): 2. __init__(self: libaster.ContactPairing, arg0: libaster.ContactNew) -> None """ - def clear(self): - """clean all the paring quantities of all zones + def clearPairing(self, *args, **kwargs): + """Overloaded function. + + 1. clearPairing(self: libaster.ContactPairing) -> None + + + Clean pairing for all zones + Returns: bool: true if the pairing quantities are cleared - """ - def clearZone(self, zone_index): - """clean all the paring quantities of zone zonde_index + + 2. clearPairing(self: libaster.ContactPairing, zone_index: int) -> None + + + Clean pairing for a zone + Arguments: - zone_index(int) + zone_index(int) : index of zone + Returns: bool: true if the pairing quantities are cleared """ - def compute(self): - """Compute the pairing quantities associated with the zones + def compute(self, *args, **kwargs): + """Overloaded function. + + 1. compute(self: libaster.ContactPairing) -> bool + + + Compute the pairing quantities on all zones Returns: bool: True if the pairing quantities are updated appropriately - """ - def computeZone(self, zone_index): - """Compute the pairing quantities associated with the zone zone_index + + 2. compute(self: libaster.ContactPairing, zone_index: int) -> bool + + + Compute the pairing quantities on a zone + Arguments: zone_index(int) + Returns: bool: True if the pairing quantities are updated appropriately """ @@ -6555,7 +6919,7 @@ def getCoordinates(self): """Coordinates of nodes used for pairing (almost always different from the intial mesh). Returns: - MeshCoordinatesFieldPtr: the coordinates field + MeshCoordinatesField: the coordinates field """ def getFiniteElementDescriptor(self): @@ -6565,37 +6929,93 @@ def getFiniteElementDescriptor(self): FiniteElementDescriptor: finite element for virtual cells """ - def getListOfPairsOfZone(self, zone_index): - """return list of pairs associated with the zone izone + def getIntersectionPoints(self, zone_index, CoordinatesSpace=1): + """Get the intersection points between master and slave cells + + Arguments: + zone_index(int) : index of zone + CoordinatesSpace (CoordinatesSpace): space to describe coordinates + + Returns: + list[pair]: list of pair of coordinates of intersection points + """ + + def getListOfPairs(self, *args, **kwargs): + """Overloaded function. + + 1. getListOfPairs(self: libaster.ContactPairing, zone_index: int) -> list[tuple[int, int]] + + + Get list of contact pairs for a contact zone + Arguments: zone_index(int) + + Returns: + list[tuple[int, int]]: list of contact pairs + + + 2. getListOfPairs(self: libaster.ContactPairing) -> list[tuple[int, int]] + + + Get list of contact pairs on all zones + Returns: - List[List[int]]: List of pairs + list[tuple[int, int]]: list of contact pairs """ - def getNumberOfPairs(self): - """return the total number of pairs + def getMesh(self): + """Mesh + Returns: - int: Total number of pairs + BaseMesh: the mesh """ - def getNumberOfPairsOfZone(self, zone_index): - """return number of pairs associated with the zone zone_index + def getNumberOfIntersectionPoints(self, zone_index): + """Get list of the number of intersection points beetween a master and slave cells. + + Arguments: + zone_index(int) : index of zone + + Returns: + list: list of number of intersection points + """ + + def getNumberOfPairs(self, *args, **kwargs): + """Overloaded function. + + 1. getNumberOfPairs(self: libaster.ContactPairing) -> int + + + Return number of pairs on all zones + + Returns: + int: number of pairs + + + 2. getNumberOfPairs(self: libaster.ContactPairing, zone_index: int) -> int + + + Return the number of pairs on a zone + Arguments: zone_index(int) Returns: int: number of pairs """ - def getSlaveIntersectionPoints(self, zone_index): - """Get the intersection points beetween a master and slave cells in the parametric - slave space. The maximum number of points is 8. + def getNumberOfZones(self): + """Return the number of zones - Arguments: - zone_index(int) : index of zone + Returns: + int: number of zones + """ + + def getVerbosity(self): + """Get level of verbosity Returns: - list[list]: list of list of intersection points (each intersection is of size 16) + integer: level of verbosity """ def setCoordinates(self, coordinates): @@ -6605,8 +7025,22 @@ def setCoordinates(self, coordinates): coordinates (MeshCoordinatesField) : coordinates to use for pairing """ + def setVerbosity(self, verbosity): + """Set level of verbosity + 0 - without + 1 - normal (default) + 2 - detailled (text) + + Arguments: + level (integer): level of verbosity + """ + def updateCoordinates(self, disp): - """Update the mesh coordinates given a displacement field""" + """Update the mesh coordinates given a displacement field + + Arguments: + disp (FieldOnNodes) : field for displacement + """ # class ContactComputation in libaster @@ -6632,16 +7066,15 @@ def __setstate__(self, arg0): pass def contactCoefficient(self): - """Compute contact coefficient at the nodes of the slave surface based on values of COEF_CONT + """Compute contact coefficients at the nodes of the slave surface based on values of COEF_CONT and COEF_FROT Returns: - FieldOnNodesReal: contact coefficient (= COEF_CONT) - FieldOnNodesReal: friction coefficient (= COEF_FROT) + list[FieldOnNodesReal]: coefficients (COEF_CONT and COEF_FROT) """ def contactData(self, pairing, material, initial_contact): - """Compute contact data (cf. MMCHML) as input to compute contact forces and matrices. + """Compute contact data as input to compute contact forces and matrices. Arguments: pairing (ContactPairing): pairing object @@ -6652,6 +7085,26 @@ def contactData(self, pairing, material, initial_contact): FieldOnCellsReal: contact data """ + def getVerbosity(self): + """Get level of verbosity + 0- without + 1- normal + 2- detailled + + Returns: + int: level of verbosity + """ + + def setVerbosity(self, level): + """Set level of verbosity + 0- without + 1- normal (default) + 2- detailled + + Arguments: + level (int) : level of verbosity + """ + # class BaseAssemblyMatrix in libaster diff --git a/doc/_automatic_/objects_DataStructure.rst b/doc/_automatic_/objects_DataStructure.rst index 72d135be857..a133823afac 100644 --- a/doc/_automatic_/objects_DataStructure.rst +++ b/doc/_automatic_/objects_DataStructure.rst @@ -1081,6 +1081,15 @@ Subclasses of :py:class:`~code_aster.Objects.DataStructure` :members: +******************************************************************************** +:py:class:`~code_aster.Objects.MeshPairing` object +******************************************************************************** + +.. autoclass:: code_aster.Objects.MeshPairing + :show-inheritance: + :members: + + ******************************************************************************** :py:class:`~code_aster.Objects.MeshesMapping` object ******************************************************************************** diff --git a/doc/_automatic_/objects_Others.rst b/doc/_automatic_/objects_Others.rst index b399e64437c..5f6d4d25c29 100644 --- a/doc/_automatic_/objects_Others.rst +++ b/doc/_automatic_/objects_Others.rst @@ -83,6 +83,15 @@ Documentation of all other types. :members: +******************************************************************************** +:py:class:`~code_aster.Objects.CoordinatesSpace` object +******************************************************************************** + +.. autoclass:: code_aster.Objects.CoordinatesSpace + :show-inheritance: + :members: + + ******************************************************************************** :py:class:`~code_aster.Objects.CrackShape` object ******************************************************************************** @@ -438,6 +447,15 @@ Documentation of all other types. :members: +******************************************************************************** +:py:class:`~code_aster.Objects.PairingMethod` object +******************************************************************************** + +.. autoclass:: code_aster.Objects.PairingMethod + :show-inheritance: + :members: + + ******************************************************************************** :py:class:`~code_aster.Objects.PairingParameter` object ******************************************************************************** diff --git a/doc/_automatic_/table_DataStructure.rst b/doc/_automatic_/table_DataStructure.rst index 2fd1aedc968..06e1636a366 100644 --- a/doc/_automatic_/table_DataStructure.rst +++ b/doc/_automatic_/table_DataStructure.rst @@ -249,6 +249,8 @@ - ``maillage_sdaster`` * - :py:class:`~code_aster.Objects.MeshCoordinatesField` - + * - :py:class:`~code_aster.Objects.MeshPairing` + - * - :py:class:`~code_aster.Objects.MeshesMapping` - ``corresp_2_mailla`` * - :py:class:`~code_aster.Objects.ModeResult` diff --git a/doc/_automatic_/table_Others.rst b/doc/_automatic_/table_Others.rst index 3d54b5eb621..9c4e68def0b 100644 --- a/doc/_automatic_/table_Others.rst +++ b/doc/_automatic_/table_Others.rst @@ -18,6 +18,7 @@ * - :py:class:`~code_aster.Objects.ContactParameter` * - :py:class:`~code_aster.Objects.ContactType` * - :py:class:`~code_aster.Objects.ContactVariant` + * - :py:class:`~code_aster.Objects.CoordinatesSpace` * - :py:class:`~code_aster.Objects.CrackShape` * - :py:class:`~code_aster.Objects.DiscreteComputation` * - :py:class:`~code_aster.Objects.DisplacementReal` @@ -58,6 +59,7 @@ * - :py:class:`~code_aster.Objects.NormalSpeedReal` * - :py:class:`~code_aster.Objects.ObjectBalancer` * - :py:class:`~code_aster.Objects.PairingAlgo` + * - :py:class:`~code_aster.Objects.PairingMethod` * - :py:class:`~code_aster.Objects.PairingParameter` * - :py:class:`~code_aster.Objects.ParMetisPartitioner` * - :py:class:`~code_aster.Objects.PartOfMaterialField` diff --git a/mfront/BETON_AGEING.mfront b/mfront/BETON_AGEING.mfront new file mode 100644 index 00000000000..d51477c7183 --- /dev/null +++ b/mfront/BETON_AGEING.mfront @@ -0,0 +1,150 @@ +@Parser Default; +@Behaviour BETON_AGEING; +@Author Goustan Bacquaert; +@Date 06/11/2024; + +/// >>>>>>>>>>>>>>>>>>> +/// Material properties +/// <<<<<<<<<<<<<<<<<<< + +@MaterialProperty stress young; // Young modulus [Pa] +@MaterialProperty stress nu; // Poisson coefficient [-] +@MaterialProperty stress Kv_vt; // Volumetric stiffness in the Voigt element [Pa] +@MaterialProperty stress Kd_vt; // Deviatoric stiffness in the Voigt element [Pa] +@MaterialProperty real Etav_vt; // Volumetric viscosity in the Voigt element [Pa.s] +@MaterialProperty real Etad_vt; // Deviatoric viscosity in the Voigt element [Pa.s] +@MaterialProperty stress Kv_mx; // Stress slope of the time-dependent volumetric viscosity in the Maxwell element [Pa] +@MaterialProperty stress Kd_mx; // Stress slope of the time-dependent deviatoric viscosity in the Maxwell element [Pa] +@MaterialProperty real t0; // Concrete pouring instant [s] +@MaterialProperty real Ea_R; // Molar activation energy / universal gas constant [K] +@MaterialProperty real M_RhoR; // Steam molar mass / (water mass density x universal gas constant) [Pa^-1] +@MaterialProperty real Tref; // Reference temperature [K] +@MaterialProperty real K_fd; // Modulus of the dessiccation creep [Pa] + +young.setGlossaryName("YoungModulus"); +nu.setGlossaryName("PoissonRatio"); +Kv_vt.setEntryName("VoigtSphModulus"); +Kd_vt.setEntryName("VoigtDevModulus"); +Etav_vt.setEntryName("VoigtSphViscosity"); +Etad_vt.setEntryName("VoigtDevViscosity"); +Kv_mx.setEntryName("MaxwellSphModulus"); +Kd_mx.setEntryName("MaxwellDevModulus"); +t0.setEntryName("ConcreteInitTime"); +K_fd.setEntryName("DessiccationModulus"); +Tref.setEntryName("ReferenceTemperature"); +Ea_R.setEntryName("ArrheniusIndex"); +M_RhoR.setEntryName("KelvinIndex"); + +/// >>>>>>>>>>>>>>> +/// Local variables +/// <<<<<<<<<<<<<<< + +@LocalVariable Stensor4 id4; // Identity or order 4 +@LocalVariable Stensor4 k4; // Deviatoric projector of order 4 +@LocalVariable Stensor4 j4; // Spheric projector of order 4 +@LocalVariable Stensor4 C_el; // Elastic stiffness +@LocalVariable Stensor4 C_vt; // Stiffness in the Voigt element +@LocalVariable Stensor4 V_vt; // Viscosity in the Voigt element +@LocalVariable Stensor4 V_mx; // Viscosity tensor in the Maxwell element +@LocalVariable real rH; // Relative humidity +@LocalVariable real drH; // Relative humidity increment +@LocalVariable real VrH; // = -drH iff drH < 0 and rH < rHmin+1 + +/// >>>>>>>>>>>>>>>>>>>>>>>> +/// External state variables +/// <<<<<<<<<<<<<<<<<<<<<<<< + +@ExternalStateVariable real PCAP; // Capillary pressure at !!previous!! time-step +@ExternalStateVariable real TIME; // Time at !!current!! time-step + +PCAP.setEntryName("CapillaryPressure"); +TIME.setEntryName("Time"); + +/// >>>>>>>>>>>>>>>>>>>>>>>>> +/// Auxiliary state variables +/// <<<<<<<<<<<<<<<<<<<<<<<<< + +@AuxiliaryStateVariable Stensor efr; // Reversible creep strain +@AuxiliaryStateVariable Stensor efi; // Irreversible creep strain +@AuxiliaryStateVariable Stensor efd; // Dessiccation creep strain +@AuxiliaryStateVariable real rHmin; // Shifted historical minimum relative humidity + +efr.setEntryName("RevCreepStrain"); +efi.setEntryName("IrrCreepStrain"); +efd.setEntryName("DesCreepStrain"); +rHmin.setEntryName("ShiftMiniRelaHumi"); + +/// >>>>>>>>>>>>>>>>>>>> +/// Init local variables +/// <<<<<<<<<<<<<<<<<<<< + +@InitLocalVariables{ + // Initialize invariant projection tensors + k4 = Stensor4::K(); + j4 = Stensor4::J(); + id4 = Stensor4::Id(); + + // Initialize the Arrhenius coefficient + const real expT = exp(Ea_R*((1./(T+dT/2.)-1./(Tref)))); + + // Initialize the relative humiditidy + rH = exp(-(PCAP+0.5*dPCAP)*M_RhoR/(T+dT/2.)); + drH = exp(-(PCAP+dPCAP)*M_RhoR/(T+dT))-exp(-PCAP*M_RhoR/T); + + // Compute the dessiccation creep strain source term + if ((drH <= 0.) && (rH <= rHmin+1.)){ + VrH = -drH; + rHmin = rH-1.; + } + else{ + VrH = 0.; + } + + // Initialize the elastic stiffness + C_el = young/(1.-2.*nu)*j4+young/(1.+nu)*k4; + + // Initialize the stiffness and the viscosity in the Voigt element, taken into account the temperature and relative humidity influence + C_vt = expT*(3.*Kv_vt*j4+2.*Kd_vt*k4)/rH; + V_vt = expT*(3.*Etav_vt*j4+2.*Etad_vt*k4)/rH; + + // Initialize viscosity in the Maxwell element, taken into account the temperature and relative humidity influence + V_mx = expT*(3.*Kv_mx*j4+2.*Kd_mx*k4)/rH*max(TIME-0.5*dt-t0,0.); +} + +/// >>>>>>>>>>>>>>>>>> +/// Elastic prediction +/// <<<<<<<<<<<<<<<<<< + +@PredictionOperator{ + Dt = C_el; +} + +/// >>>>>>>>>>> +/// Integration +/// <<<<<<<<<<< + +@Integrator{ + // Compute the tangent compliance + const Stensor4 St = invert(C_el)+dt*invert(dt*C_vt+V_vt)+dt*invert(V_mx)+VrH/K_fd*id4; + + // Compute the stress + sig = invert(St)*(eto+deto-invert(dt*C_vt+V_vt)*V_vt*efr-efi-efd); +} + +/// <<<<<<<<<<<<<<<< +/// Tangent operator +/// >>>>>>>>>>>>>>>> + +@TangentOperator{ + Dt = invert(invert(C_el)+dt*invert(dt*C_vt+V_vt)+dt*invert(V_mx)+VrH/K_fd*id4); +} + +/// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +/// Update auxiliary state variables +/// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +@UpdateAuxiliaryStateVariables { + efr += dt*invert(dt*C_vt+V_vt)*(sig-C_vt*efr); + efi += dt*invert(V_mx)*sig; + efd += VrH/K_fd*sig; +}