Compare the signs - 3dec fish

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

1 Like

You can use the math.sgn function. See here: math.sgn β€” 3DEC 7.0 documentation (itascacg.com)

1 Like

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

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

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

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

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

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

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