1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import glob
import os
from spack import *
class Camx(MakefilePackage):
'''Comprehensive Air Quality Model with Extensions.'''
homepage = 'http://www.camx.com'
# Upstream obfuscates their download URL to get you to fill out their
# registration form and accept their license agreement.
version('6.50',
url='http://www.camx.com/getmedia/caaf7983-616b-4207-bd10-c2b404bda78d/CAMx_v6-50-src-180430.tgz',
sha256='4a53f78e0722d85a9c7d8ed6732aff55163a4ce06f69b6bbc9e00a3bf36a756c')
resource(when='@6.50',
name='user_manual',
url='http://www.camx.com/files/camxusersguide_v6-50.pdf',
sha256='b02d9826d59f22f9daa5955bb7b9fd3e0ca86eb73017c5845896d40391c64588',
expand=False,
placement='doc')
resource(when='@6.50',
name='input_data',
url='http://www.camx.com/getmedia/77ad8028-9388-4f5d-bcab-a418e15dde68/v6-50-specific-inputs-180430.tgz',
sha256='89b58283e37b8e2bd550a8ec62208f241be72c78dc26da9c42ad63c34f54ebfb',
placement='data')
variant('mpi', default=True, description='Enable MPI')
variant(
'threads', default='pthread', description='Multithreading support',
values=('pthread', 'openmp'), multi=False
)
depends_on('mpi', when='+mpi')
parallel = False
def patch(self):
# Relax values in parameter file to fix fun errors like this:
#
# ERROR in STARTUP:
# A parameter in the camx.prm is not sufficiently large.
# Please change the value for parameter: MXCELLS
# It should be set to a value of at least: 396
with working_dir('Includes'):
duplicate = 'camx.prm'
os.remove(duplicate)
orig = 'camx.prm.v{0}'.format(self.spec.version)
prm = FileFilter(orig)
prm.filter(r'MXCELLS = [^)]+', 'MXCELLS = 400 ')
prm.filter(r'MXPTSRC = [^)]+', 'MXPTSRC = 1355961 ')
prm.filter(r'MXLAYER = [^)]+', 'MXLAYER = 40 ')
prm.filter(r'MXPIG = [^)]+', 'MXPIG = 100000 ')
def edit(self, spec, prefix):
makefile = FileFilter('Makefile')
# Support Intel MPI.
if spec['mpi'].name == 'intel-mpi':
makefile.filter(
'else ifneq (, $(findstring $(MPI),openmpi openMPI OPENMPI))',
'''else ifneq (, $(findstring $(MPI),intel-mpi intel impi))
MPI_ECHO = "* MPI will be built in using Intel MPI"
MPI_INC = $(MPI_INST)/include
MPI_LIBS = -L$(CAMX_MPI)/util -lutil -lparlib ''' +
spec['mpi'].libs.ld_flags +
'''
MPI_STRING = IntelMPI
FC = $(MPI_INST)/bin64/mpifort
CC = $(MPI_INST)/bin64/mpicc
else ifneq (, $(findstring $(MPI),openmpi openMPI OPENMPI))''',
string=True)
makefile.filter('OPENMPI MVAPICH',
'OPENMPI MVAPICH IntelMPI',
string=True)
if '+mpi' in spec:
# Substitute CC, FC.
makefile.filter('CC = .*', 'CC = ' + spec['mpi'].mpicc)
makefile.filter('FC = .*', 'FC = ' + spec['mpi'].mpifc)
# Fix parlib not being compiled.
makefile.filter('all: comp_$(COMPILER)',
# Yes, flake8, Makefile rules needs tabs!
'''all: parlib comp_$(COMPILER)
parlib :
$(MAKE) -C $(CAMX_MPI)/util # noqa: E101,W191
''',
string=True) # noqa: E101
makefile_parlib = FileFilter('MPI/util/Makefile')
makefile_parlib.filter('CC = .*',
'CC = ' + spec['mpi'].mpicc)
makefile_parlib.filter('LIBS = .*',
'LIBS = ' + spec['mpi'].libs.ld_flags)
makefile_parlib.filter('MPI_INST = .*',
'MPI_INST = ' + spec['mpi'].prefix)
else:
# Substitute CC, FC.
makefile.filter('CC = .*', 'CC = ' + env['CC'])
makefile.filter('FC = .*', 'FC = ' + env['FC'])
@property
def build_targets(self):
# Set compiler.
omp = ['', 'omp'][self.spec.satisfies('threads=openmp')]
compiler = os.path.basename(env['FC']) + omp
args = ['COMPILER={0}'.format(compiler)]
# Set MPI.
if '+mpi' in self.spec:
mpi = self.spec['mpi']
args += [
'MPI={0}'.format(mpi.name),
'MPI_INST={0}'.format(mpi.prefix),
]
return args
def install(self, spec, prefix):
exe = glob.glob('CAMx.*')[0]
mkdir(prefix.bin)
install(exe, prefix.bin.camx)
mkdirp(prefix.share.doc)
install_tree('doc', prefix.share.doc, symlinks=False)
mkdir(prefix.share.data)
install_tree('data', prefix.share.data)
|