#!/mnt/c/Users/moiki/bash/env/bin/python
H,W      = list(map(int, input().split()))
S        =  [ list(input()) for _ in range(H)]
NUM_GRID = [ [-1] * W for _ in range(H) ]


united_count = [ ]
# [ (黒1個、白2個) ,... k 個] 

directions = [(1,0), (0,1), (-1,0), (0,-1)] # y,x の順番
def dfs(pos, c, now_k):
    # pos : (1,2)
    # 引数は現在の連結成分の番号
    # 座標と、現在の1,0 が渡される
    # 渡されたnow_kで塗りつぶす
    y,x = pos
    for d in directions:
        if y+d[0] < 0 or x+d[1] < 0:
            continue
        try:
            content = S[y+d[0]][x+d[1]] 

            if c != content and NUM_GRID[y+d[0]][x+d[1]] == -1:

                NUM_GRID[y+d[0]] [x+d[1]] = now_k  # 塗る
                inplace_tuple     = united_count[now_k]
                united_count[now_k]     = ( inplace_tuple[0] + 1, inplace_tuple[1]) if content == "#" else \
                                    ( inplace_tuple[0]    , inplace_tuple[1]+1) # タプルなので新しく作る

                dfs( (y+d[0], x+d[1]),  content,  now_k)  # DFSかける
            else:
                continue

        except IndexError: # はじっこに来た
            continue


now_k = 0
for y in range(H):
    for x in range(W):
        c = S[y][x]  
        if NUM_GRID[y][x] == -1:

            united_count.append( (1,0) if  c == "#" else (0,1) ) # now_k番目
            NUM_GRID[y][x] = now_k  # cの値は黒だったら、1 を入れてdfsに投げる

            pos = (y,x)
            dfs(pos, c, now_k)
            now_k         += 1

        else:
            continue # もう数字が入っている場合は、パス

# for y in range(H):
#     for x in range(W):
#         print(NUM_GRID[y][x], end="")
#     print("")


answer = 0
mod    = int(1e9)+7
for uni in united_count:
    answer = ((uni[0]*uni[1])%mod + answer) % mod

print(answer)




### FIXED CODE ###

#!/mnt/c/Users/moiki/bash/env/bin/python
H,W      = list(map(int, input().split()))
S        =  [ list(input()) for _ in range(H)]

import sys
sys.setrecursionlimit(2600000)

united_count = [ ]
# [ (黒1個、白2個) ,... k 個] 

directions = [(1,0), (0,1), (-1,0), (0,-1)] # y,x の順番


def dfs(pos, c, now_k):
    # pos : (1,2)
    # 引数は現在の連結成分の番号
    # 座標と、現在の1,0 が渡される
    # 渡されたnow_kで塗りつぶす
    y,x = pos
    for d in directions:
        try:
            if y+d[0] < 0 or x+d[1] < 0:
                continue
            content = S[y+d[0]][x+d[1]] 

            if c != content and (content == "#" or content == ".") :
                S[y+d[0]][x+d[1]] = now_k
                inplace_tuple     = united_count[now_k]
                united_count[now_k]     = ( inplace_tuple[0] + 1, inplace_tuple[1]) if content == "#" else \
                                    ( inplace_tuple[0]    , inplace_tuple[1]+1) # タプルなので新しく作る

                dfs( (y+d[0], x+d[1]),  content,  now_k)  # DFSかける

            else:
                continue
        except:
            continue



now_k = 0
for y in range(H):
    for x in range(W):
        c = S[y][x]  
        if c == "#" or c == "." :
            united_count.append( (1,0) if  c == "#" else (0,1) ) # now_k番目
            S[y][x] = now_k  # cの値は黒だったら、1 を入れてdfsに投げる

            pos = (y,x)
            dfs(pos, c, now_k)
            now_k         += 1

        else:
            continue # もう数字が入っている場合は、パス


answer = 0
for uni in united_count:
    answer = ((uni[0]*uni[1]) + answer) 

print(answer)