# Compare the signs - 3dec fish

**URL:** <https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404>\
**Category:** 3DEC\
**Tags:** fish\
**Created:** [March 31, 2022, 9:25am UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404 "2022-03-31T09:25:21Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mattia\_S\_ITA](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@Mattia\_S\_ITA](https://forum.itascainternational.com/u/Mattia_S_ITA)\
**Post date:** [March 31, 2022, 9:25am UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/1 "2022-03-31T09:25:21Z")

</div>

Hi,  
I would like to see the sign (in terms of velocity) of some blocks (after applying the input) and compare it with the sign (in terms of acceleration) of the input.

My idea is as follows:  
sgn (vbk) = sgn (a)  
And depending on the situation create two scenarios  
If sgn (vbk) is equal to sgn (a) → scenario 1  
If sgn (vbk) is not equal to sgn (a) → scenario 2

Can you tell me how to do it?  
Thanks in advance

---

<div class="post-metadata">

**Author:** ![jhazzard](https://avatars.discourse-cdn.com/v4/letter/j/4af34b/32.png) [@jhazzard](https://forum.itascainternational.com/u/jhazzard)\
**Post date:** [March 31, 2022, 2:22pm UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/2 "2022-03-31T14:22:04Z")

</div>

You can use the math.sgn function. See here: [math.sgn — 3DEC 7.0 documentation (itascacg.com)](http://docs.itascacg.com/3dec700/common/fish/doc/fish_manual/fish_fish/math_utilities/fish_math.sgn.html#math.sgn)

---

<div class="post-metadata">

**Author:** ![Mattia\_S\_ITA](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@Mattia\_S\_ITA](https://forum.itascainternational.com/u/Mattia_S_ITA)\
**Post date:** [March 31, 2022, 4:29pm UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/3 "2022-03-31T16:29:23Z")

</div>

instead, for obtain the sum in terms of mass of all the blocks in the model?

---

<div class="post-metadata">

**Author:** ![itsmoho\_sen](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.itascainternational.com/itsmoho_sen/32/421_2.png) [@itsmoho\_sen](https://forum.itascainternational.com/u/itsmoho_sen)\
**Post date:** [August 4, 2022, 1:30pm UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/4 "2022-08-04T13:30:19Z")

</div>

I am trying to convert this function from 3DEC 5.0 to 3DEC 7 and I get the following error, any idea how to modify this?

def b\_sa\_min(index\_)  
if b\_type(index\_) = 1 then ; rigid  
bf = b\_face(index\_)  
else ; deformable  
bf = b\_face2(index\_)  
endif

The converted version suggests the following

fish define b\_sa\_min(index\_)  
if %%block.rigid%%(index\_) = 1 then ; rigid  
;%%- Not an exact analology to b\_type  
bf = %%block.facelist%%(index\_)  
;%%- Use foreach to loop through faces  
else ; deformable  
bf = %%block.facelist%%(index\_)  
;%%- Use foreach to loop through faces. Set second parameter to true for original block faces  
endif

---

<div class="post-metadata">

**Author:** ![Theophile](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.itascainternational.com/theophile/32/299_2.png) [@Theophile](https://forum.itascainternational.com/u/Theophile)\
**Post date:** [August 11, 2022, 8:25am UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/5 "2022-08-11T08:25:10Z")

</div>

Hi.

The suggestion is right.  
However, notice that in 3DEC5.20, bf would be a block face index.  
In 3DEC7.00, bf is the list of all the block faces, as mentioned in [official documentation](http://docs.itascacg.com/3dec700/3dec/block/doc/manual/block_manual/block_fish/block/fish_block.facelist.html?highlight=block%20facelist)

So, if you wish to loop through your blocks, the complete function would be:

```auto
fish define b_sa_min(index_)
    local use_deformable = true
    local use_rigid = false
    if block.rigid(index_) = 1
        bf = block.facelist(index_, use_rigid)
    else
        bf = block.facelist(index_, use_deformable )
    end_if
    ; Now, to loop through the block faces:
    loop foreach local bfpnt bf
        ; Do stuff considering that bfpnt is a block face pointer
    end_loop
end

```

Cheers

---

<div class="post-metadata">

**Author:** ![itsmoho\_sen](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.itascainternational.com/itsmoho_sen/32/421_2.png) [@itsmoho\_sen](https://forum.itascainternational.com/u/itsmoho_sen)\
**Post date:** [August 11, 2022, 11:17am UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/6 "2022-08-11T11:17:28Z")

</div>

Thank you very much, Theophile,

I used a longer version for my code where it is very important to find the bad blocks.

;  
fish define b\_sa\_min(index\_)  
local use\_deformable = true  
local use\_rigid = false  
if block.rigid(index\_) = 1  
bf = block.facelist(index\_, use\_rigid)  
else  
bf = block.facelist(index\_, use\_deformable )  
end\_if  
; Now, to loop through the block faces:  
loop foreach local bfpnt bf  
; Do stuff considering that bfpnt is a block face pointer  
end\_loop  
end  
;  
fish define sa\_bad  
;  
;------- FISH range to find blocks with small face surface area -------

;INPUT: sa\_min: minimum face area. Block is selected if any face area is below this value

```
argument ;(position)
argument ;(object)
    b = range.isin(r,a)

if b_sa_min(object) < sa_min then
	sa_bad = 1
else
	sa_bad = 0
endif

```

end

fish define findBadBlock()

```
loop foreach local bPnt block.list()

    loop foreach local fPnt block.facelist(bPnt,~block.rigid(bPnt))

        if block.face.area(fPnt)<b_sa_min

            block.group(bPnt,'bad') ="yes"

            exit loop

        endif

    endloop

endloop

```

end  
;  
;  
fish define b\_edge\_min(index\_)  
;  
; ----- Function to determine minimum edge length for a given block  
;  
; INPUT: index\_ - index of block to be tested  
;

```
if block.rigid(index_) = 1 then ; rigid
	bf = block.facelist(index_)
else ; deformable
	bf = block.facelist(index_)
endif

local ret = 1.0e24

loop while bf # 0
	local block.gp.num = block.face.ngp(bf)
	local next = 2
	loop n (1,block.gp.num)
		if n = block.gp.num then
			next = 1
		endif

		local v1 = block.gp.pos(block.face.gp(bf, n)) ;vector of gridpoint 1
		local v2 = block.gp.pos(block.face.gp(bf, next)) ;vector of gridpoint 2
		local edge = math.mag(v1-v2) ;magnitude of vector difference

		ret = math.min(ret,edge)
		next = next + 1
	endloop
	bf = block.face.next(bf)
endloop
b_edge_min = ret

```

end  
;  
fish define edge\_bad  
;  
; -------- FISH range to find blocks with small edge lengths -------------  
;  
; INPUT: e\_min - minimum edge length. Block is selected if any edge length is below this value  
;  
argument position  
argument object

```
if b_edge_min(object) < e_min then
	edge_bad = 1
else
	edge_bad = 0
endif

```

end  
;  
fish define b\_aspect\_max(index\_)  
;  
; ----- Function to calculate maximum aspect ratio for input block  
;  
; INPUT: index\_ - index of block to be tested  
;  
if block.rigid(index\_) = 1 then ; rigid  
bf = block.facelist(index\_)  
else ; deformable  
bf = block.facelist(index\_)  
endif

```
local ret = 0.0

loop while bf # 0
	local block.gp.num = block.face.ngp(bf)
	local next = 2
	loop n (1,block.gp.num)

		if n = block.gp.num then
			next = 1
		endif

		local v1 = block.gp.pos(block.face.gp(bf, n)) ;vector of gridpoint 1
		local v2 = block.gp.pos(block.face.gp(bf, next)) ;vector of gridpoint 2
		local edgel = math.mag(v1-v2) ;magnitude of vector difference

		local aspect = edgel/(block.vol(index_)^(1.0/3.0)) ;aspect ratio

		ret = math.max(ret,aspect)

		next = next + 1

	endloop

	bf = block.face.next(bf)
endloop

b_aspect_max = ret

```

end  
;  
fish define aspect\_bad  
;  
; ----- FISH range to find blocks with large aspect ratios ----------  
;  
; INPUT: a\_max - maximum aspect ratio. Block is selected if aspect ratio is greater than this value  
;  
argument position  
argument object

```
if b_aspect_max(object) > a_max then
	aspect_bad = 1
else
	aspect_bad = 0
endif

```

end  
;  
fish define b\_max\_fa(index\_)  
;  
; Function to get maximum angle between faces on a given block  
;  
; NOTE 1: This assume block is convex. Will not return angles \> 180 degrees  
; NOTE 2: If maximum angle is less than 90 degrees, this function will return 0  
;  
; INPUT: index\_ - index of block to be tested  
;  
if block.rigid(index\_) = 1 then ; rigid  
bf = block.facelist(index\_)  
else ; deformable  
bf = block.facelist(index\_)  
endif

```
local ret = 0.0

loop while bf # 0
  local n1 = block.face.normal(bf)
  local bf2 = block.face.next(bf)
  loop while bf2 # 0
    local n2 = block.face.normal(bf2)
    local dot_product = math.dot(n1,n2)
    if dot_product > 0 ; ensure pointing in the same direction
      if dot_product > 0.99999 ; coincident - 180 degrees
        ret = math.pi
      else
        ret = math.max(ret,math.pi-math.acos(dot_product))
      end_if
    end_if
    bf2 = block.face.next(bf2)
  end_loop

  bf = block.face.next(bf)
endloop

b_max_fa = ret/math.degrad

```

end  
;  
fish define fa\_bad  
;  
; ----- FISH range to find blocks with large face angles  
;  
; INPUT: fa\_max - maximum face angle in degrees. Block is slected if 2 faces have an angle greater than this  
;  
argument position  
argument object

```
if b_max_fa(object) > fa_max then
	fa_bad = 1
else
	fa_bad = 0
endif

```

end  
;  
fish define get\_worst\_blocks  
;  
; Function to loop through all blocks and get worst ones  
;

local min\_vol\_allblocks = 1.0e12  
local min\_vol\_bi = 0  
local min\_edge\_allblocks = 1.0e12  
local min\_edge\_bi = 0  
local min\_area\_allblocks = 1.0e12  
local min\_area\_bi = 0  
local max\_aratio\_allblocks = 0.0  
local max\_aratio\_bi = 0  
local max\_angle\_allblocks = 0.0  
local max\_angle\_bi = 0

local bi = block.head  
loop while bi # 0  
if block.vol(bi) \< min\_vol\_allblocks  
min\_vol\_allblocks = block.vol(bi)  
min\_vol\_bi = bi  
end\_if  
if b\_edge\_min(bi) \< min\_edge\_allblocks  
min\_edge\_allblocks = b\_edge\_min(bi)  
min\_edge\_bi = bi  
end\_if  
if b\_sa\_min(bi) \< min\_area\_allblocks  
min\_area\_allblocks = b\_sa\_min(bi)  
min\_area\_bi = bi  
end\_if  
if b\_aspect\_max(bi) \> max\_aratio\_allblocks  
max\_aratio\_allblocks = b\_aspect\_max(bi)  
max\_aratio\_bi = bi  
end\_if  
if b\_max\_fa(bi) \> max\_angle\_allblocks  
max\_angle\_allblocks = b\_max\_fa(bi)  
max\_angle\_bi = bi  
end\_if

```
bi = block.next(bi)

```

end\_loop

end  
;  
; — find and group bad blocks —  
;  
fish set @b\_sa\_min 0.00003  
block group ‘bad\_face’ range fish ‘sa\_bad’  
fish set @edge\_min = 0.00020

---

<div class="post-metadata">

**Author:** ![jhazzard](https://avatars.discourse-cdn.com/v4/letter/j/4af34b/32.png) [@jhazzard](https://forum.itascainternational.com/u/jhazzard)\
**Post date:** [August 12, 2022, 1:33am UTC](https://forum.itascainternational.com/t/compare-the-signs-3dec-fish/404/7 "2022-08-12T01:33:31Z")

</div>

Note that you probably don’t need those functions anymore. These are now built in ranges. See EDGE-LENGTH, ASPECT-RATIO and FACE-AREA here: [Range Phrase Keyword Reference — 3DEC 7.0 documentation](http://docs.itascacg.com/3dec700/common/module/doc/manual/range_manual/range_commands/rangephrasereference.html?node1944)
