From 023d6a13b28f97630aef84fa7a432ea2f962fce5 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 8 Mar 2016 17:07:22 +0100 Subject: [PATCH 01/46] test that fails on distributed channel --- test/codes_tests/test_c_implementation.py | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/codes_tests/test_c_implementation.py b/test/codes_tests/test_c_implementation.py index 5c075e843..75f8d9a3d 100644 --- a/test/codes_tests/test_c_implementation.py +++ b/test/codes_tests/test_c_implementation.py @@ -607,6 +607,36 @@ def test7(self): self.assertEquals(out[0], "abc") self.assertEquals(out[1], "def") + def test7b(self): + instance = ForTestingInterface(self.exefile) + + out, error = instance.echo_int(numpy.arange(2000000)) + + self.assertEquals(error, [0]*2000000) + self.assertEquals(out, numpy.arange(2000000)) + + instance.stop() + + def test7c(self): + instance = ForTestingInterface(self.exefile) + + out, error = instance.echo_string(["abc"]*10) + + self.assertEquals(error, [0]*10) + self.assertEquals(out, ["abc"]*10) + + instance.stop() + + def test7d(self): + instance = ForTestingInterface(self.exefile) + + out, error = instance.echo_string(["abc"]*100) + + self.assertEquals(error, [0]*100) + self.assertEquals(out, ["abc"]*100) + + instance.stop() + def test8(self): instance = ForTestingInterface(self.exefile) out1, out2, error = instance.echo_strings("abc","def") From 38a01a7286f384adf86973803ec4f809234c752a Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 5 Apr 2016 11:16:14 +0200 Subject: [PATCH 02/46] add fortran tests for (distributed) string error --- .../test_fortran_implementation.py | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/test/codes_tests/test_fortran_implementation.py b/test/codes_tests/test_fortran_implementation.py index 6a84d350f..437782d82 100644 --- a/test/codes_tests/test_fortran_implementation.py +++ b/test/codes_tests/test_fortran_implementation.py @@ -79,7 +79,7 @@ function hello_string(string_out) implicit none - character(len=30) :: string_out + character(len=*) :: string_out integer :: hello_string string_out = 'hello' @@ -157,6 +157,12 @@ echo_logical = 0 end function +function get_element_status(ind,x) result(ret) + integer :: ind,ret + character(len=*) :: x + x="dry" + ret=0 +end function """ class ForTestingInterface(CodeInterface): @@ -286,6 +292,15 @@ def print_error_string(): function.result_type = 'int32' function.can_handle_array = True return function + + @legacy_function + def get_element_status(): + function = LegacyFunctionSpecification() + function.addParameter('index', dtype='i', direction=function.IN) + function.addParameter('status', dtype='string', direction=function.OUT) + function.result_type = 'int32' + function.can_handle_array = True + return function class ForTesting(InCodeComponentImplementation): @@ -720,3 +735,25 @@ def test31(self): t2=time.time() print "2 time:",t2-t1,(t2-t1)/N instance.stop() + + def test32(self): + instance = ForTestingInterface(self.exefile) + out, error = instance.get_element_status(numpy.arange(10)) + del instance + + self.assertEquals(out, ["dry"]*10) + + def test33(self): + instance = ForTestingInterface(self.exefile) + out, error = instance.get_element_status(numpy.arange(100)) + del instance + + self.assertEquals(out, ["dry"]*100) + + def test34(self): + instance = ForTestingInterface(self.exefile) + out, error = instance.echo_string(["abc"]*14) + del instance + + self.assertEquals(out, ["abc"]*14) + self.assertEquals(error, [0]*14) From 5b267f139123b6ed06d9d2a11c5272b2573e94cc Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Fri, 15 Apr 2016 12:25:59 +0200 Subject: [PATCH 03/46] increase test size to break test on more machines --- test/codes_tests/test_c_implementation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/codes_tests/test_c_implementation.py b/test/codes_tests/test_c_implementation.py index 7553b2246..ea97ae2da 100644 --- a/test/codes_tests/test_c_implementation.py +++ b/test/codes_tests/test_c_implementation.py @@ -636,10 +636,10 @@ def test7c(self): def test7d(self): instance = ForTestingInterface(self.exefile) - out, error = instance.echo_string(["abc"]*100) + out, error = instance.echo_string(["abc"]*100000) - self.assertEquals(error, [0]*100) - self.assertEquals(out, ["abc"]*100) + self.assertEquals(error, [0]*100000) + self.assertEquals(out, ["abc"]*100000) instance.stop() From ebbe29167e2277924b9505c855cfd604c1af1dde Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 11 Sep 2018 17:34:29 +0200 Subject: [PATCH 04/46] fix socket channel memory leak for strings and changes to make string sending/ receiving similar on mpi and sockets channel --- src/amuse/rfi/channel.py | 53 ++++++------- src/amuse/rfi/tools/create_c.py | 101 +++++++++++++++++++------ src/amuse/rfi/tools/create_fortran.py | 102 +++++++++++++++++--------- 3 files changed, 168 insertions(+), 88 deletions(-) diff --git a/src/amuse/rfi/channel.py b/src/amuse/rfi/channel.py index d4629dd7f..fc1eeb3b2 100644 --- a/src/amuse/rfi/channel.py +++ b/src/amuse/rfi/channel.py @@ -748,28 +748,22 @@ def send_strings(self, comm, array): if len(array) == 0: return - lengths = self.string_lengths(array) - self.mpi_send(comm, [lengths, MPI.INT]) + lengths = numpy.array( [len(s) for s in array] ,dtype='i') chars=(chr(0).join(array)+chr(0)).encode("utf-8") chars = numpy.fromstring(chars, dtype='uint8') + + if len(chars) != lengths.sum()+len(lengths): + raise Exception("send_strings size mismatch {0} vs {1}".format( len(chars) , lengths.sum()+len(lengths) )) + + self.mpi_send(comm, [lengths, MPI.INT]) self.mpi_send(comm, [chars, MPI.CHARACTER]) def send_booleans(self, comm, array): if len(array) > 0: sendbuffer = numpy.array(array, dtype='int32') self.mpi_send(comm, [sendbuffer, MPI.LOGICAL]) - - def string_lengths(self, array): - lengths = numpy.zeros(len(array), dtype='i') - index = 0 - for string in array: - lengths[index] = len(string) - index += 1 - - return lengths - def set_error(self, message): self.strings = [message] self.error = True @@ -2058,12 +2052,16 @@ def receive_strings(self, socket, count): if count > 0: lengths = self.receive_ints(socket, count) + total = lengths.sum() + len(lengths) + + data_bytes = self._receive_all(total, socket) + strings = [] - - for i in range(count): - data_bytes = self._receive_all(lengths[i], socket) - strings.append(str(data_bytes.decode('utf-8'))) - + begin = 0 + for size in lengths: + strings.append(data_bytes[begin:begin + size].decode('utf-8')) + begin = begin + size + 1 + return strings else: return [] @@ -2122,21 +2120,16 @@ def send_floats(self, socket, array): socket.sendall(data_buffer.tostring()) def send_strings(self, socket, array): - header = [] - data_bytes = [] - - for i in range(len(array)): + if len(array) > 0: - #logger.debug("sending string %s", array[i]) + lengths = numpy.array( [len(s) for s in array] ,dtype='int32') + chars=(chr(0).join(array)+chr(0)).encode("utf-8") - utf8_string = array[i].encode('utf-8') - header.append(len(utf8_string)) - data_bytes.append(utf8_string) - - self.send_ints(socket, header); - - for i in range(len(data_bytes)): - socket.sendall(data_bytes[i]) + if len(chars) != lengths.sum()+len(lengths): + raise Exception("send_strings size mismatch {0} vs {1}".format( len(chars) , lengths.sum()+len(lengths) )) + + self.send_ints(socket, lengths); + socket.sendall(chars) def send_booleans(self, socket, array): if len(array) > 0: diff --git a/src/amuse/rfi/tools/create_c.py b/src/amuse/rfi/tools/create_c.py index a4996841a..78ab3e9c5 100644 --- a/src/amuse/rfi/tools/create_c.py +++ b/src/amuse/rfi/tools/create_c.py @@ -652,12 +652,21 @@ if(header_in[HEADER_STRING_COUNT] > 0) { receive_array_sockets(string_sizes_in, header_in[HEADER_STRING_COUNT] * sizeof(int), socketfd, rank); MPI_Bcast(string_sizes_in, header_in[HEADER_STRING_COUNT], MPI_INT, 0, MPI_COMM_WORLD); - for (int i = 0; i < header_in[HEADER_STRING_COUNT]; i++) { - strings_in[i] = new char[string_sizes_in[i] + 1]; - receive_array_sockets(strings_in[i], string_sizes_in[i], socketfd, rank); - MPI_Bcast(strings_in[i], string_sizes_in[i], MPI_CHARACTER, 0, MPI_COMM_WORLD); - strings_in[i][string_sizes_in[i]] = '\\0'; + + int total_string_size = 0; + for (int i = 0; i < header_in[HEADER_STRING_COUNT];i++) { + total_string_size += string_sizes_in[i] + 1; } + + characters_in = new char[total_string_size]; + receive_array_sockets(characters_in, total_string_size, socketfd, rank); + MPI_Bcast(characters_in, total_string_size, MPI_CHARACTER, 0, MPI_COMM_WORLD); + + int offset = 0; + for (int i = 0 ; i < header_in[HEADER_STRING_COUNT];i++) { + strings_in[i] = characters_in + offset; + offset += string_sizes_in[i] + 1; + } } header_out[HEADER_FLAGS] = 0; @@ -711,19 +720,36 @@ } if(header_out[HEADER_STRING_COUNT] > 0) { - for (int i = 0; i < header_out[HEADER_STRING_COUNT]; i++) { - string_sizes_out[i] = strlen(strings_out[i]); + int offset = 0; + for( int i = 0; i < header_out[HEADER_STRING_COUNT] ; i++) { + int length = strlen(strings_out[i]); + string_sizes_out[i] = length; + offset += length + 1; } - send_array_sockets(string_sizes_out, header_out[HEADER_STRING_COUNT] * sizeof(int), socketfd, 0); - - for (int i = 0; i < header_out[HEADER_STRING_COUNT]; i++) { - send_array_sockets(strings_out[i], string_sizes_out[i] * sizeof(char), socketfd, 0); + + characters_out = new char[offset + 1]; + offset = 0; + + for( int i = 0; i < header_out[HEADER_STRING_COUNT] ; i++) { + strcpy(characters_out+offset, strings_out[i]); + offset += string_sizes_out[i] + 1; } + + send_array_sockets(string_sizes_out, header_out[HEADER_STRING_COUNT] * sizeof(int), socketfd, 0); + send_array_sockets(characters_out, offset * sizeof(char), socketfd, 0); } //fprintf(stderr, "sockets_mpicall done\\n"); } - + if (characters_in) { + delete[] characters_in; + characters_in = 0; + } + + if (characters_out) { + delete[] characters_out; + characters_out = 0; + } } delete_arrays(); @@ -841,11 +867,20 @@ if(header_in[HEADER_STRING_COUNT] > 0) { receive_array_sockets(string_sizes_in, header_in[HEADER_STRING_COUNT] * sizeof(int), socketfd, 0); - for (int i = 0; i < header_in[HEADER_STRING_COUNT]; i++) { - strings_in[i] = new char[string_sizes_in[i] + 1]; - receive_array_sockets(strings_in[i], string_sizes_in[i], socketfd, 0); - strings_in[i][string_sizes_in[i]] = '\\0'; + + int total_string_size = 0; + for (int i = 0; i < header_in[HEADER_STRING_COUNT];i++) { + total_string_size += string_sizes_in[i] + 1; } + + characters_in = new char[total_string_size]; + receive_array_sockets(characters_in, total_string_size, socketfd, 0); + + int offset = 0; + for (int i = 0 ; i < header_in[HEADER_STRING_COUNT];i++) { + strings_in[i] = characters_in + offset; + offset += string_sizes_in[i] + 1; + } } header_out[HEADER_FLAGS] = 0; @@ -896,16 +931,34 @@ } if(header_out[HEADER_STRING_COUNT] > 0) { - for (int i = 0; i < header_out[HEADER_STRING_COUNT]; i++) { - string_sizes_out[i] = strlen(strings_out[i]); - } - send_array_sockets(string_sizes_out, header_out[HEADER_STRING_COUNT] * sizeof(int), socketfd, 0); - - for (int i = 0; i < header_out[HEADER_STRING_COUNT]; i++) { - send_array_sockets(strings_out[i], string_sizes_out[i] * sizeof(char), socketfd, 0); - } + int offset = 0; + for( int i = 0; i < header_out[HEADER_STRING_COUNT] ; i++) { + int length = strlen(strings_out[i]); + string_sizes_out[i] = length; + offset += length + 1; + } + + characters_out = new char[offset + 1]; + offset = 0; + + for( int i = 0; i < header_out[HEADER_STRING_COUNT] ; i++) { + strcpy(characters_out+offset, strings_out[i]); + offset += string_sizes_out[i] + 1; + } + + send_array_sockets(string_sizes_out, header_out[HEADER_STRING_COUNT] * sizeof(int), socketfd, 0); + send_array_sockets(characters_out, offset * sizeof(char), socketfd, 0); } + if (characters_in) { + delete[] characters_in; + characters_in = 0; + } + + if (characters_out) { + delete[] characters_out; + characters_out = 0; + } //fprintf(stderr, "call done\\n"); } delete_arrays(); diff --git a/src/amuse/rfi/tools/create_fortran.py b/src/amuse/rfi/tools/create_fortran.py index 08e08f2ec..d29be3e70 100644 --- a/src/amuse/rfi/tools/create_fortran.py +++ b/src/amuse/rfi/tools/create_fortran.py @@ -444,7 +444,6 @@ offset = offset + string_sizes_in(i) + 1 !print*, 'fortran: strings_in(i) ', i, strings_in(i) , ' of length ', string_sizes_in(i), & !' actually of size ', len_trim(strings_in(i)) - end do end if @@ -532,8 +531,8 @@ implicit none integer :: max_call_count = 255 - integer :: must_run_loop - integer i, call_count, port + integer :: must_run_loop, maximum_size, total_string_length + integer :: i, offset, call_count, port character(len=32) :: port_string character(kind=c_char, len=64) :: host logical (c_bool), allocatable, target :: c_booleans_in(:) @@ -637,11 +636,27 @@ strings_in = ' ' call receive_integers(c_loc(string_sizes_in), header_in(HEADER_STRING_COUNT)) + maximum_size = 0 + total_string_length = 0 do i = 1, header_in(HEADER_STRING_COUNT), 1 - strings_in(i) = ' ' - call receive_string(c_loc(strings_in(i)), string_sizes_in(i)) + total_string_length = total_string_length + string_sizes_in(i) + 1 + if (string_sizes_in(i) .gt. maximum_size) then + maximum_size = string_sizes_in(i) + end if end do + call receive_string(c_loc(characters_in), total_string_length) + + offset = 1 + do i = 1, header_in(HEADER_STRING_COUNT), 1 + strings_in(i) = ' ' + strings_in(i) = characters_in(offset : (offset + string_sizes_in(i))) + strings_in(i)((string_sizes_in(i) + 1):(string_sizes_in(i) + 1)) = ' ' + offset = offset + string_sizes_in(i) + 1 + !print*, 'fortran: strings_in(i) ', i, strings_in(i) , ' of length ', string_sizes_in(i), & + !' actually of size ', len_trim(strings_in(i)) + end do + end if header_out = 0 @@ -678,19 +693,21 @@ end if if (header_out(HEADER_STRING_COUNT) .gt. 0) then - + offset = 1 do i = 1, header_out(HEADER_STRING_COUNT),1 + string_sizes_out(i) = len_trim(strings_out(i)) - - !print*, 'fortran: sending strings, strings_out(i) ', i, strings_out(i) , ' of length ', string_sizes_out(i), & - !'actually of size ', len_trim(strings_out(i)) + + !print*, 'fortran: sending strings, strings_out(i) ', i, strings_out(i) , ' of length ', string_sizes_out(i), & + !' actually of size ', len_trim(strings_out(i)) + + characters_out(offset:offset+string_sizes_out(i)) = strings_out(i) + offset = offset + string_sizes_out(i) + 1 + characters_out(offset-1:offset-1) = char(0) end do - + call send_integers(c_loc(string_sizes_out), header_out(HEADER_STRING_COUNT)) - - do i = 1, header_out(HEADER_STRING_COUNT),1 - call send_string(c_loc(strings_out(i)), string_sizes_out(i)) - end do + call send_integers(c_loc(characters_out), offset-1 ) end if end do @@ -736,8 +753,8 @@ integer :: provided integer :: max_call_count = 255 - integer :: must_run_loop - integer i, call_count, port, rank, ioerror + integer :: must_run_loop, maximum_size, total_string_length + integer :: i, offset, call_count, port, rank, ioerror character(len=32) :: port_string character(kind=c_char, len=64) :: host logical (c_bool), allocatable, target :: c_booleans_in(:) @@ -865,22 +882,37 @@ end if if (header_in(HEADER_STRING_COUNT) .gt. 0) then - strings_in = ' ' - + if (rank .eq. 0) then call receive_integers(c_loc(string_sizes_in), header_in(HEADER_STRING_COUNT)) end if - call MPI_BCast(string_sizes_in, header_in(HEADER_STRING_COUNT), MPI_INTEGER, 0, MPI_COMM_WORLD, ioError); + maximum_size = 0 + total_string_length = 0 + do i = 1, header_in(HEADER_STRING_COUNT), 1 + total_string_length = total_string_length + string_sizes_in(i) + 1 + if (string_sizes_in(i) .gt. maximum_size) then + maximum_size = string_sizes_in(i) + end if + end do + + if (rank .eq. 0) then + call receive_string(c_loc(characters_in), total_string_length) + endif + call MPI_BCast(characters_in, total_string_length, MPI_CHARACTER, 0, MPI_COMM_WORLD, ioError); + + offset = 1 do i = 1, header_in(HEADER_STRING_COUNT), 1 - strings_in(i) = ' ' - if (rank .eq. 0) then - call receive_string(c_loc(strings_in(i)), string_sizes_in(i)) - end if - call MPI_BCast(strings_in(i), string_sizes_in(i), MPI_CHARACTER, 0, MPI_COMM_WORLD, ioError); + strings_in(i) = ' ' + strings_in(i) = characters_in(offset : (offset + string_sizes_in(i))) + strings_in(i)((string_sizes_in(i) + 1):(string_sizes_in(i) + 1)) = ' ' + offset = offset + string_sizes_in(i) + 1 + !print*, 'fortran: strings_in(i) ', i, strings_in(i) , ' of length ', string_sizes_in(i), & + !' actually of size ', len_trim(strings_in(i)) end do + end if header_out = 0 @@ -922,20 +954,22 @@ end if if (header_out(HEADER_STRING_COUNT) .gt. 0) then - + offset = 1 do i = 1, header_out(HEADER_STRING_COUNT),1 + string_sizes_out(i) = len_trim(strings_out(i)) - - !print*, 'fortran: sending strings, strings_out(i) ', i, strings_out(i) , ' of length ', string_sizes_out(i), & - !'actually of size ', len_trim(strings_out(i)) + + !print*, 'fortran: sending strings, strings_out(i) ', i, strings_out(i) , ' of length ', string_sizes_out(i), & + !' actually of size ', len_trim(strings_out(i)) + + characters_out(offset:offset+string_sizes_out(i)) = strings_out(i) + offset = offset + string_sizes_out(i) + 1 + characters_out(offset-1:offset-1) = char(0) end do - + call send_integers(c_loc(string_sizes_out), header_out(HEADER_STRING_COUNT)) - - do i = 1, header_out(HEADER_STRING_COUNT),1 - call send_string(c_loc(strings_out(i)), string_sizes_out(i)) - end do - end if + call send_integers(c_loc(characters_out), offset-1 ) + end if end if end do From 33cca3580d7b9f9a3cdebb80fd7eeb8d9d8f0084 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 11 Sep 2018 20:55:09 +0200 Subject: [PATCH 05/46] fix send string error --- src/amuse/rfi/tools/create_fortran.py | 4 ++-- test/compile_tests/test_fortran_sockets_implementation.py | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/amuse/rfi/tools/create_fortran.py b/src/amuse/rfi/tools/create_fortran.py index d29be3e70..da719eae3 100644 --- a/src/amuse/rfi/tools/create_fortran.py +++ b/src/amuse/rfi/tools/create_fortran.py @@ -707,7 +707,7 @@ end do call send_integers(c_loc(string_sizes_out), header_out(HEADER_STRING_COUNT)) - call send_integers(c_loc(characters_out), offset-1 ) + call send_string(c_loc(characters_out), offset-1 ) end if end do @@ -968,7 +968,7 @@ end do call send_integers(c_loc(string_sizes_out), header_out(HEADER_STRING_COUNT)) - call send_integers(c_loc(characters_out), offset-1 ) + call send_string(c_loc(characters_out), offset-1 ) end if end if end do diff --git a/test/compile_tests/test_fortran_sockets_implementation.py b/test/compile_tests/test_fortran_sockets_implementation.py index d000d8126..0314178f6 100644 --- a/test/compile_tests/test_fortran_sockets_implementation.py +++ b/test/compile_tests/test_fortran_sockets_implementation.py @@ -404,10 +404,13 @@ def test9(self): def test10(self): instance = ForTestingInterface(self.exefile, channel_type="sockets") - out = instance.return_string("abc") + out = instance.return_string("qwerty") + out = instance.return_string("abcdefghi") + + instance.stop() del instance - self.assertEquals(out, "abc") + self.assertEquals(out, "abcdefghi") def test11(self): instance = ForTestingInterface(self.exefile, channel_type="sockets") From ce2587ff354932e555c69465231005d1040810d0 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 12 Sep 2018 11:36:38 +0200 Subject: [PATCH 06/46] update create_java + easy optimization of capacity check --- src/amuse/rfi/tools/create_java.py | 58 ++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/amuse/rfi/tools/create_java.py b/src/amuse/rfi/tools/create_java.py index 56faaf9b3..29ff6ebb8 100644 --- a/src/amuse/rfi/tools/create_java.py +++ b/src/amuse/rfi/tools/create_java.py @@ -286,10 +286,11 @@ stringHeader.put(0, bytes.length); - ensureStringsCapacity(); + ensureStringsCapacity(0); stringBytes[0].clear(); stringBytes[0].put(bytes); + stringBytes[0].put( (byte) 0); // add extra zero } catch (UnsupportedEncodingException e) { System.err.println("could not set error: " + e); stringHeader.put(0, 0); @@ -330,10 +331,11 @@ stringHeader.put(position, bytes.length); // make sure there is space for the string - ensureStringsCapacity(); + ensureStringsCapacity(position); stringBytes[position].clear(); stringBytes[position].put(bytes); + stringBytes[position].put( (byte) 0); // add extra zero } catch (UnsupportedEncodingException e) { System.err.println("ERROR! UTF-8 not supported by the JVM!"); @@ -356,10 +358,11 @@ stringHeader.put(index, bytes.length); // make sure there is space for the string - ensureStringsCapacity(); + ensureStringsCapacity(index); stringBytes[index].clear(); stringBytes[index].put(bytes); + stringBytes[index].put( (byte) 0); // add extra zero } catch (UnsupportedEncodingException e) { System.err.println("ERROR! UTF-8 not supported by the JVM!"); @@ -431,7 +434,7 @@ } byte[] bytes = new byte[utf8length]; stringBytes[index].position(0); - stringBytes[index].limit(utf8length); + stringBytes[index].limit(utf8length+1); // account for extra zero stringBytes[index].get(bytes); return new String(bytes, 0, utf8length, "UTF-8"); @@ -488,7 +491,7 @@ for (int i = 0; i < getStringCount(); i++) { int utf8Length = stringHeader.get(i); - stringBytes[i].clear().limit(utf8Length); + stringBytes[i].clear().limit(utf8Length + 1); // account for extra zero } // set the limit of the rest of the string bytes to 0 @@ -611,7 +614,7 @@ } for (int i = 0; i < getStringCount(); i++) { - int stringLength = stringHeader.get(i); + int stringLength = stringHeader.get(i) +1; // account for extra zero if (stringBytes[i] == null || stringLength > stringBytes[i].capacity()) { stringBytes[i] = ByteBuffer.allocateDirect(stringLength); @@ -637,6 +640,49 @@ return buffersUpdated; } + public boolean ensureStringsCapacity(int index) { + // checking if the string header is big enough is checked above, so + // we + // only check if all strings listed in the header + boolean buffersUpdated = false; + + if (stringBytes.length < getStringCount()) { + ByteBuffer[] oldStringBytes = stringBytes; + stringBytes = new ByteBuffer[getStringCount()]; + for (int i = 0; i < oldStringBytes.length; i++) { + stringBytes[i] = oldStringBytes[i]; + } + buffersUpdated = true; + } + + if (buffersUpdated) { + // update byte buffers array + ByteBuffer[] newByteBuffers = new ByteBuffer[allButStringByteBuffers.length + stringBytes.length]; + for (int i = 0; i < allButStringByteBuffers.length; i++) { + newByteBuffers[i] = allButStringByteBuffers[i]; + } + for (int i = 0; i < stringBytes.length; i++) { + newByteBuffers[allButStringByteBuffers.length + i] = stringBytes[i]; + } + byteBuffers = newByteBuffers; + + + //System.err.println("ensureStringsCapacity() Updated buffers to " + Arrays.toString(byteBuffers)); + } + + { + int stringLength = stringHeader.get(index) +1; // account for extra zero + if (stringBytes[index] == null || stringLength > stringBytes[index].capacity()) { + + stringBytes[index] = ByteBuffer.allocateDirect(stringLength); + byteBuffers[allButStringByteBuffers.length + index] = stringBytes[index]; + } + } + + + return buffersUpdated; + } + boolean readFrom(SocketChannel channel) throws IOException { boolean updatedBuffers = false; From eefe8830dfd8933897736f1c1233766621cd5196 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 12 Sep 2018 16:14:36 +0200 Subject: [PATCH 07/46] make distributed amuse message consistent with current socket messages --- .../amuse/distributed/AmuseMessage.java | 103 +++++++++++++++--- 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/src/amuse/community/distributed/src/src/nl/esciencecenter/amuse/distributed/AmuseMessage.java b/src/amuse/community/distributed/src/src/nl/esciencecenter/amuse/distributed/AmuseMessage.java index df6a3444c..ef744f497 100644 --- a/src/amuse/community/distributed/src/src/nl/esciencecenter/amuse/distributed/AmuseMessage.java +++ b/src/amuse/community/distributed/src/src/nl/esciencecenter/amuse/distributed/AmuseMessage.java @@ -133,8 +133,8 @@ public AmuseMessage() { stringHeaderBytes = ByteBuffer.allocateDirect(0); stringBytes = new ByteBuffer[0]; - allButStringByteBuffers = new ByteBuffer[] { headerBytes, intBytes, longBytes, floatBytes, doubleBytes, booleanBytes, - stringHeaderBytes }; + allButStringByteBuffers = new ByteBuffer[] { headerBytes, intBytes, longBytes, floatBytes, doubleBytes, + booleanBytes, stringHeaderBytes }; // no string buffers yet byteBuffers = allButStringByteBuffers; @@ -189,7 +189,7 @@ public long getDataSize() { result += getBooleanCount() * SIZEOF_BOOLEAN; for (int i = 0; i < getStringCount(); i++) { - result += stringHeader.get(i); + result += stringHeader.get(i)+1 ; // account for zero } return result; @@ -302,10 +302,11 @@ public void setError(String error) { stringHeader.put(0, bytes.length); - ensureStringsCapacity(); + ensureStringsCapacity(0); stringBytes[0].clear(); stringBytes[0].put(bytes); + stringBytes[0].put( (byte) 0); // add extra zero } catch (UnsupportedEncodingException e) { System.err.println("could not set error: " + e); stringHeader.put(0, 0); @@ -335,17 +336,22 @@ public void addString(String value) { byte[] bytes; try { - bytes = value.getBytes("UTF-8"); + if (value == null) { + //set null values to an empty string + bytes = new String().getBytes("UTF-8"); + } else { + bytes = value.getBytes("UTF-8"); + } // set length of string in header stringHeader.put(position, bytes.length); // make sure there is space for the string - ensureStringsCapacity(); + ensureStringsCapacity(position); stringBytes[position].clear(); stringBytes[position].put(bytes); - + stringBytes[position].put( (byte) 0); // add extra zero } catch (UnsupportedEncodingException e) { System.err.println("ERROR! UTF-8 not supported by the JVM!"); } @@ -356,17 +362,22 @@ public void setString(int index, String value) { byte[] bytes; try { - bytes = value.getBytes("UTF-8"); - + if (value == null) { + //set null values to an empty string + bytes = new String().getBytes("UTF-8"); + } else { + bytes = value.getBytes("UTF-8"); + } + // set length of string in header stringHeader.put(index, bytes.length); // make sure there is space for the string - ensureStringsCapacity(); + ensureStringsCapacity(index); stringBytes[index].clear(); stringBytes[index].put(bytes); - + stringBytes[index].put( (byte) 0); // add extra zero } catch (UnsupportedEncodingException e) { System.err.println("ERROR! UTF-8 not supported by the JVM!"); } @@ -434,7 +445,8 @@ public String getString(int index) throws IOException { } if (stringBytes.length <= index) { - throw new IOException("cannot get string at index " + index + " in call" + this + " header does not match content!"); + throw new IOException("cannot get string at index " + index + " in call" + this + + " header does not match content!"); } @@ -445,7 +457,7 @@ public String getString(int index) throws IOException { } byte[] bytes = new byte[utf8length]; stringBytes[index].position(0); - stringBytes[index].limit(utf8length); + stringBytes[index].limit(utf8length +1 ); // account for extra zero stringBytes[index].get(bytes); return new String(bytes, 0, utf8length, "UTF-8"); @@ -497,9 +509,9 @@ private void setStringLimitsFromHeader() throws IOException { } for (int i = 0; i < getStringCount(); i++) { - int utf8Length = stringHeader.get(i); + int utf8Length = stringHeader.get(i) +1; // account for extra zero - stringBytes[i].clear().limit(utf8Length); + stringBytes[i].clear().limit(utf8Length ); } // set the limit of the rest of the string bytes to 0 @@ -517,7 +529,21 @@ public void writeTo(SocketChannel channel) throws IOException { setStringLimitsFromHeader(); // write to channel - channel.write(byteBuffers); + // channel.write(byteBuffers); + + // write all bufferd to channel + boolean done = false; + + while(!done) { + channel.write(byteBuffers); + + done = true; + for (ByteBuffer buffer : byteBuffers) { + if (buffer.hasRemaining()) { + done = false; + } + } + } // alternative, debugging version of writing buffers // for (ByteBuffer buffer : byteBuffers) { @@ -627,7 +653,7 @@ public boolean ensureStringsCapacity() { } for (int i = 0; i < getStringCount(); i++) { - int stringLength = stringHeader.get(i); + int stringLength = stringHeader.get(i) +1 ; // account for extra zero if (stringBytes[i] == null || stringLength > stringBytes[i].capacity()) { stringBytes[i] = ByteBuffer.allocateDirect(stringLength); @@ -652,6 +678,49 @@ public boolean ensureStringsCapacity() { return buffersUpdated; } + public boolean ensureStringsCapacity(int index) { + // checking if the string header is big enough is checked above, so + // we + // only check if all strings listed in the header + boolean buffersUpdated = false; + + if (stringBytes.length < getStringCount()) { + ByteBuffer[] oldStringBytes = stringBytes; + stringBytes = new ByteBuffer[getStringCount()]; + for (int i = 0; i < oldStringBytes.length; i++) { + stringBytes[i] = oldStringBytes[i]; + } + buffersUpdated = true; + } + + if (buffersUpdated) { + // update byte buffers array + ByteBuffer[] newByteBuffers = new ByteBuffer[allButStringByteBuffers.length + stringBytes.length]; + for (int i = 0; i < allButStringByteBuffers.length; i++) { + newByteBuffers[i] = allButStringByteBuffers[i]; + } + for (int i = 0; i < stringBytes.length; i++) { + newByteBuffers[allButStringByteBuffers.length + i] = stringBytes[i]; + } + byteBuffers = newByteBuffers; + + + //System.err.println("ensureStringsCapacity() Updated buffers to " + Arrays.toString(byteBuffers)); + } + + { + int stringLength = stringHeader.get(index) +1; // account for extra zero + if (stringBytes[index] == null || stringLength > stringBytes[index].capacity()) { + + stringBytes[index] = ByteBuffer.allocateDirect(stringLength); + byteBuffers[allButStringByteBuffers.length + index] = stringBytes[index]; + } + } + + + return buffersUpdated; + } + public boolean readFrom(SocketChannel channel) throws IOException { boolean updatedBuffers = false; From 20fedfd19cc71c21f47b4011addbfe720f81d39f Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 12 Sep 2018 16:47:43 +0200 Subject: [PATCH 08/46] trivial change to trigger stale workers on this branch (make sure they get rebuild) --- src/amuse/rfi/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/amuse/rfi/core.py b/src/amuse/rfi/core.py index a02a78971..c6182c261 100644 --- a/src/amuse/rfi/core.py +++ b/src/amuse/rfi/core.py @@ -12,7 +12,7 @@ import inspect import functools -#from collections import OrderedDict +# from collections import OrderedDict from subprocess import Popen, PIPE From 7c50fd5e06f08010efd957584c1077b005215382 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Fri, 14 Sep 2018 14:14:04 +0200 Subject: [PATCH 09/46] fix for older gfortran versions ~<4.9 --- src/amuse/rfi/tools/create_fortran.py | 36 +++++++++++++++---- .../test_fortran_implementation.py | 19 ++++++++++ .../test_fortran_sockets_implementation.py | 17 +++++++++ 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/src/amuse/rfi/tools/create_fortran.py b/src/amuse/rfi/tools/create_fortran.py index da719eae3..858171b3c 100644 --- a/src/amuse/rfi/tools/create_fortran.py +++ b/src/amuse/rfi/tools/create_fortran.py @@ -88,9 +88,12 @@ character (c_char), allocatable, target :: strings_in(:) * 256 character (c_char), allocatable, target :: strings_out(:) * 256 + + character (len=1000000) :: characters_in + character (len=1000000) :: characters_out - character (kind=c_char, len=1000000), target :: characters_in - character (kind=c_char, len=1000000), target :: characters_out + character (kind=c_char), target :: c_characters_in(1000000) + character (kind=c_char), target :: c_characters_out(1000000) """ MODULE_GLOBALS_STRING = """ @@ -645,7 +648,13 @@ end if end do - call receive_string(c_loc(characters_in), total_string_length) + call receive_string(c_loc(c_characters_in), total_string_length) + + ! this trick is necessary on older gfortran compilers (~<4.9) + ! as c_loc needs character(len=1) + do i=1, total_string_length + characters_in(i:i)=c_characters_in(i) + enddo offset = 1 do i = 1, header_in(HEADER_STRING_COUNT), 1 @@ -706,8 +715,13 @@ characters_out(offset-1:offset-1) = char(0) end do + total_string_length=offset-1 + do i=1, total_string_length + c_characters_out(i)=characters_out(i:i) + enddo + call send_integers(c_loc(string_sizes_out), header_out(HEADER_STRING_COUNT)) - call send_string(c_loc(characters_out), offset-1 ) + call send_string(c_loc(c_characters_out), offset-1 ) end if end do @@ -899,8 +913,13 @@ end do if (rank .eq. 0) then - call receive_string(c_loc(characters_in), total_string_length) + call receive_string(c_loc(c_characters_in), total_string_length) endif + + do i=1, total_string_length + characters_in(i:i)=c_characters_in(i) + enddo + call MPI_BCast(characters_in, total_string_length, MPI_CHARACTER, 0, MPI_COMM_WORLD, ioError); offset = 1 @@ -967,8 +986,13 @@ characters_out(offset-1:offset-1) = char(0) end do + total_string_length=offset-1 + do i=1, total_string_length + c_characters_out(i)=characters_out(i:i) + enddo + call send_integers(c_loc(string_sizes_out), header_out(HEADER_STRING_COUNT)) - call send_string(c_loc(characters_out), offset-1 ) + call send_string(c_loc(c_characters_out), offset-1 ) end if end if end do diff --git a/test/compile_tests/test_fortran_implementation.py b/test/compile_tests/test_fortran_implementation.py index 3e547c57d..fdbf33be6 100644 --- a/test/compile_tests/test_fortran_implementation.py +++ b/test/compile_tests/test_fortran_implementation.py @@ -656,3 +656,22 @@ def test34(self): self.assertEquals(out, ["abc"]*14) self.assertEquals(error, [0]*14) + + def test35(self): + instance = ForTestingInterface(self.exefile) + out, error = instance.echo_string(["abc","def"]*100000) + del instance + + self.assertEquals(error[0], 0) + self.assertEquals(error[1], 0) + self.assertEquals(out[-2], "abc") + self.assertEquals(out[-1], "def") + + def test36(self): + instance = ForTestingInterface(self.exefile) + N=255 + out, error = instance.echo_string("a"*N) + del instance + + self.assertEquals(error, 0) + self.assertEquals(out, "a"*N) diff --git a/test/compile_tests/test_fortran_sockets_implementation.py b/test/compile_tests/test_fortran_sockets_implementation.py index 0314178f6..60be87dba 100644 --- a/test/compile_tests/test_fortran_sockets_implementation.py +++ b/test/compile_tests/test_fortran_sockets_implementation.py @@ -522,4 +522,21 @@ def xtest20(self): content = f.read() self.assertEquals(content.strip(), "exex\n exex") + def test35(self): + instance = ForTestingInterface(self.exefile, channel_type="sockets") + out, error = instance.echo_string(["abc","def"]*100000) + del instance + + self.assertEquals(error[0], 0) + self.assertEquals(error[1], 0) + self.assertEquals(out[-2], "abc") + self.assertEquals(out[-1], "def") + def test36(self): + instance = ForTestingInterface(self.exefile, channel_type="sockets") + N=255 + out, error = instance.echo_string("a"*N) + del instance + + self.assertEquals(error, 0) + self.assertEquals(out, "a"*N) From 51fc270fae8e15bef522eddbfad0c7fa0a6d9cc6 Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Fri, 14 Sep 2018 14:01:16 +0100 Subject: [PATCH 10/46] Use quantities.arange in example to fix #302 (#303) Use quantities.arange in examples (fixes #302) --- examples/textbook/gravity_drifter.py | 4 ++-- examples/textbook/gravity_gravity.py | 3 ++- examples/textbook/gravity_potential.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/textbook/gravity_drifter.py b/examples/textbook/gravity_drifter.py index 751439c3c..99190d69d 100644 --- a/examples/textbook/gravity_drifter.py +++ b/examples/textbook/gravity_drifter.py @@ -1,7 +1,7 @@ -from amuse.lab import * import numpy from amuse.lab import * from amuse.units import units +from amuse.units import quantities from amuse.units import constants from amuse.units import nbody_system from amuse.ext.bridge import bridge @@ -146,7 +146,7 @@ def evolve_cluster_in_galaxy(N, W0, Rinit, tend, timestep, M, R): system = bridge(verbose=False) system.add_system(cluster_code, (galaxy_code,)) - times = numpy.arange(0|units.Myr, tend, 100*timestep) + times = quantities.arange(0|units.Myr, tend, 100*timestep) for i,t in enumerate(times): print "Time=", t.in_(units.Myr) system.evolve_model(t, timestep=timestep) diff --git a/examples/textbook/gravity_gravity.py b/examples/textbook/gravity_gravity.py index 5d08e01c6..ba8050bb4 100644 --- a/examples/textbook/gravity_gravity.py +++ b/examples/textbook/gravity_gravity.py @@ -1,6 +1,7 @@ #from __future__ import print_function import numpy from amuse.units import units +from amuse.units import quantities from amuse.units import constants from amuse.units import nbody_system from amuse.ext.bridge import bridge @@ -97,7 +98,7 @@ def evolve_cluster_in_galaxy(N, W0, Rinit, tend, timestep, M, R): system.add_system(galaxy_code, (cluster_code,)) system.timestep = 0.1*timestep - times=numpy.arange(0|units.Myr, tend, timestep) + times = quantities.arange(0|units.Myr, tend, timestep) for i,t in enumerate(times): print "Time=", t.in_(units.Myr) channe_to_galaxy.copy() diff --git a/examples/textbook/gravity_potential.py b/examples/textbook/gravity_potential.py index 473adce02..b780b60f3 100644 --- a/examples/textbook/gravity_potential.py +++ b/examples/textbook/gravity_potential.py @@ -1,6 +1,7 @@ #from __future__ import print_function import numpy from amuse.units import units +from amuse.units import quantities from amuse.units import constants from amuse.units import nbody_system from amuse.ext.bridge import bridge @@ -97,7 +98,7 @@ def evolve_cluster_in_galaxy(N, W0, Rinit, tend, timestep, M, R): system = bridge(verbose=False) system.add_system(cluster_code, (galaxy_code,)) - times = numpy.arange(0|units.Myr, tend, timestep) + times = quantities.arange(0|units.Myr, tend, timestep) for i,t in enumerate(times): system.evolve_model(t,timestep=timestep) From ea54a77798f71395aad1c2ce18457b367508985e Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Fri, 14 Sep 2018 15:43:04 +0200 Subject: [PATCH 11/46] move build_worker fortran to compile tools --- src/amuse/test/compile_tools.py | 18 ++++++++++++++++++ .../test_fortran_implementation.py | 19 +------------------ .../test_fortran_sockets_implementation.py | 18 +----------------- 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/amuse/test/compile_tools.py b/src/amuse/test/compile_tools.py index 258f81782..09cfc9d4a 100644 --- a/src/amuse/test/compile_tools.py +++ b/src/amuse/test/compile_tools.py @@ -7,6 +7,7 @@ from amuse.rfi.tools import create_java from amuse.rfi.tools import create_c +from amuse.rfi.tools import create_fortran from amuse.rfi.core import config from amuse.test.amusetest import get_amuse_root_dir @@ -499,3 +500,20 @@ def build_java_worker(codestring, path_to_results, specification_class): os.chmod(exefile, 0777) return exefile + +def build_fortran_worker(codestring, path_to_results, interface): + + path = os.path.abspath(path_to_results) + codefile = os.path.join(path,"code.o") + interfacefile = os.path.join(path,"interface.o") + exefile = os.path.join(path,"fortran_worker") + + fortran_compile(codefile, codestring) + + uc = create_fortran.GenerateAFortranSourcecodeStringFromASpecificationClass() + uc.specification_class = interface + uc.needs_mpi = True + string = uc.result + fortran_compile(interfacefile, string) + fortran_build(exefile, [interfacefile, codefile] ) + return exefile diff --git a/test/compile_tests/test_fortran_implementation.py b/test/compile_tests/test_fortran_implementation.py index fdbf33be6..8c2256445 100644 --- a/test/compile_tests/test_fortran_implementation.py +++ b/test/compile_tests/test_fortran_implementation.py @@ -10,7 +10,6 @@ from amuse.units import nbody_system from amuse.units import units from amuse import datamodel -from amuse.rfi.tools import create_fortran from amuse.rfi import channel from amuse.rfi.core import * @@ -332,28 +331,12 @@ def skip_if_fortran_does_not_support_mpi(self): return else: self.skip("cannot run test as fortran does not support iso c bindings") - - def build_worker(self): - - path = os.path.abspath(self.get_path_to_results()) - codefile = os.path.join(path,"code.o") - interfacefile = os.path.join(path,"interface.o") - self.exefile = os.path.join(path,"fortran_worker") - - compile_tools.fortran_compile(codefile, codestring) - - uc = create_fortran.GenerateAFortranSourcecodeStringFromASpecificationClass() - uc.specification_class = ForTestingInterface - uc.needs_mpi = True - string = uc.result - compile_tools.fortran_compile(interfacefile, string) - compile_tools.fortran_build(self.exefile, [interfacefile, codefile] ) def setUp(self): super(TestInterface, self).setUp() print "building" self.check_can_compile_modules() - self.build_worker() + self.exefile=compile_tools.build_fortran_worker(codestring, self.get_path_to_results(), ForTestingInterface) def test1(self): instance = ForTestingInterface(self.exefile) diff --git a/test/compile_tests/test_fortran_sockets_implementation.py b/test/compile_tests/test_fortran_sockets_implementation.py index 60be87dba..7a9c89b73 100644 --- a/test/compile_tests/test_fortran_sockets_implementation.py +++ b/test/compile_tests/test_fortran_sockets_implementation.py @@ -7,7 +7,6 @@ from amuse.units import nbody_system from amuse.units import units from amuse import datamodel -from amuse.rfi.tools import create_fortran from amuse.rfi import channel from amuse.rfi.core import * @@ -281,29 +280,14 @@ def print_error_string(): class TestInterface(TestWithMPI): - - def build_worker(self): - - path = os.path.abspath(self.get_path_to_results()) - codefile = os.path.join(path,"code-sockets.o") - interfacefile = os.path.join(path,"interface-sockets.o") - self.exefile = os.path.join(path,"fortran_worker") - compile_tools.fortran_compile(codefile, codestring) - - uc = create_fortran.GenerateAFortranSourcecodeStringFromASpecificationClass() - uc.specification_class = ForTestingInterface - string = uc.result - compile_tools.fortran_compile(interfacefile, string) - compile_tools.fortran_build(self.exefile, [interfacefile, codefile] ) - def setUp(self): super(TestInterface, self).setUp() print "building" self.check_can_compile_modules() self.check_fortran_version() self.check_not_in_mpiexec() - self.build_worker() + self.exefile=compile_tools.build_fortran_worker(codestring, self.get_path_to_results(), ForTestingInterface) def check_fortran_version(self): pass From 842b1eae8fbd54d63146609474d0867dd003c3cc Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Fri, 14 Sep 2018 15:59:52 +0200 Subject: [PATCH 12/46] check fortran string limits --- src/amuse/rfi/tools/create_fortran.py | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/amuse/rfi/tools/create_fortran.py b/src/amuse/rfi/tools/create_fortran.py index 858171b3c..3c2e1f942 100644 --- a/src/amuse/rfi/tools/create_fortran.py +++ b/src/amuse/rfi/tools/create_fortran.py @@ -436,6 +436,16 @@ maximum_size = string_sizes_in(i) end if end do + + if(maximum_size.GT.256) then + print*, "fortran_worker reports too large string" + stop + endif + + if(total_string_length.GT.1000000) then + print*, "fortran_worker reports too large string message" + stop + endif call MPI_BCast(characters_in, total_string_length, MPI_CHARACTER, 0, parent, ioError); @@ -496,6 +506,12 @@ offset = offset + string_sizes_out(i) + 1 characters_out(offset-1:offset-1) = char(0) end do + + total_string_length=offset-1 + if(total_string_length.GT.1000000) then + print*, "fortran_worker reports too large string message" + stop + endif call MPI_SEND(string_sizes_out, header_out(HEADER_STRING_COUNT), MPI_INTEGER, 0, 999, parent, ioerror) call MPI_SEND(characters_out, offset -1, MPI_CHARACTER, 0, 999, parent, ioerror) @@ -647,6 +663,16 @@ maximum_size = string_sizes_in(i) end if end do + + if(maximum_size.GT.256) then + print*, "fortran_worker reports too large string" + stop + endif + + if(total_string_length.GT.1000000) then + print*, "fortran_worker reports too large string message" + stop + endif call receive_string(c_loc(c_characters_in), total_string_length) @@ -716,6 +742,12 @@ end do total_string_length=offset-1 + + if(total_string_length.GT.1000000) then + print*, "fortran_worker reports too large string message" + stop + endif + do i=1, total_string_length c_characters_out(i)=characters_out(i:i) enddo @@ -912,6 +944,16 @@ end if end do + if(maximum_size.GT.256) then + print*, "fortran_worker reports too large string" + stop + endif + + if(total_string_length.GT.1000000) then + print*, "fortran_worker reports too large string message" + stop + endif + if (rank .eq. 0) then call receive_string(c_loc(c_characters_in), total_string_length) endif @@ -987,6 +1029,12 @@ end do total_string_length=offset-1 + + if(total_string_length.GT.1000000) then + print*, "fortran_Worker reports too large string message" + stop + endif + do i=1, total_string_length c_characters_out(i)=characters_out(i:i) enddo From 9fc8e787f1b9d8d732d5a11f649774b63da9b793 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Sun, 16 Sep 2018 15:53:07 +0200 Subject: [PATCH 13/46] cython test compile fix --- test/compile_tests/test_cython_implementation.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/compile_tests/test_cython_implementation.py b/test/compile_tests/test_cython_implementation.py index 452b2034c..ca998e4b5 100644 --- a/test/compile_tests/test_cython_implementation.py +++ b/test/compile_tests/test_cython_implementation.py @@ -215,7 +215,12 @@ def build_worker(self): os.chmod(self.exefile, 0777) - process, stdout, stderr = compile_tools.open_subprocess([config.compilers.cython, sourcename, '-o', cname]) + import mpi4py + process, stdout, stderr = compile_tools.open_subprocess([config.compilers.cython, + '-I', + mpi4py.get_include(), + sourcename, '-o', cname]) + if process.returncode == 0: compile_tools.wait_for_file(cname) From 0f3d9fbac4bdc1ec2c66b2290ac32b5e62594fac Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 17 Sep 2018 10:39:12 +0200 Subject: [PATCH 14/46] fix missing header --- lib/forsockets/forsockets.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/forsockets/forsockets.c b/lib/forsockets/forsockets.c index 3b08831fb..6ac6c5ec9 100644 --- a/lib/forsockets/forsockets.c +++ b/lib/forsockets/forsockets.c @@ -11,6 +11,7 @@ #include #include #include + #include #endif int32_t socketfd; From 8511f5cc2482080b4949fec43547554ea40e2f64 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 17 Sep 2018 10:40:43 +0200 Subject: [PATCH 15/46] deduplicate, add arguments for test compiles --- src/amuse/test/compile_tools.py | 53 ++++--------------- .../compile_tests/test_stopping_conditions.py | 24 ++------- 2 files changed, 15 insertions(+), 62 deletions(-) diff --git a/src/amuse/test/compile_tools.py b/src/amuse/test/compile_tools.py index 09cfc9d4a..66b549d4e 100644 --- a/src/amuse/test/compile_tools.py +++ b/src/amuse/test/compile_tools.py @@ -194,7 +194,7 @@ def c_build(exename, objectnames, extra_args=[]): def build_worker(codestring, path_to_results, specification_class, write_header=True, - extra_args=[]): + extra_args=[], needs_mpi = False): path = os.path.abspath(path_to_results) codefile = os.path.join(path, "code.o") headerfile = os.path.join(path, "worker_code.h") @@ -205,7 +205,7 @@ def build_worker(codestring, path_to_results, specification_class, write_header= uc = create_c.GenerateACHeaderStringFromASpecificationClass() uc.specification_class = specification_class - uc.needs_mpi = False + uc.needs_mpi = needs_mpi header = uc.result if write_header: @@ -215,7 +215,7 @@ def build_worker(codestring, path_to_results, specification_class, write_header= uc = create_c.GenerateACSourcecodeStringFromASpecificationClass() uc.specification_class = specification_class - uc.needs_mpi = False + uc.needs_mpi = needs_mpi code = uc.result cxx_compile(interfacefile, code if write_header else header+"\n\n"+code, @@ -363,7 +363,7 @@ def fortran_compile(objectname, string, extra_args=[]): raise Exception("Could not compile {0}\nstdout:\n{1}\nstderr:\n{2}\narguments:\n{3}".format(objectname, stdout, stderr, ' '.join(arguments))) -def fortran_build(exename, objectnames): +def fortran_build(exename, objectnames, extra_args=[]): if os.path.exists(exename): os.remove(exename) @@ -373,6 +373,7 @@ def fortran_build(exename, objectnames): arguments.append("-L{0}/lib/forsockets".format(get_amuse_root_dir())) arguments.append("-Wall") arguments.append("-lforsockets") + arguments.extend(extra_args) arguments.append("-o") arguments.append(exename) @@ -387,39 +388,6 @@ def fortran_build(exename, objectnames): if process.returncode != 0 or not os.path.exists(exename): raise Exception("Could not build {0}\nstdout:\n{1}\nstderr:\n{2}\narguments:\n{3}".format(exename, stdout, stderr, ' '.join(arguments))) - -def f90_compile(objectname, string, mpidir): - root, ext = os.path.splitext(objectname) - sourcename = root + '.f90' - if os.path.exists(objectname): - os.remove(objectname) - with open(sourcename, "w") as f: - f.write(string) - - rootdir = get_amuse_root_dir() - arguments = get_mpif90_arguments() - arguments.extend(["-I", "{0}/lib/stopcond".format(rootdir, mpidir), "-I", rootdir + "/lib/forsockets", "-c", "-o", objectname, sourcename]) - process, stderr, stdout = open_subprocess(arguments) - if not os.path.exists(objectname): # or process.poll() == 1: - raise Exception("Could not compile {0}\nstdout:\n{1}\nstderr:\n{2}\narguments:\n{3}".format(objectname, stdout, stderr, ' '.join(arguments))) - - -def f90_build(exename, objectnames, libname): - rootdir = get_amuse_root_dir() - - arguments = get_mpif90_arguments() - arguments.extend(objectnames) - arguments.append("-o") - arguments.append(exename) - arguments.extend(["-L{0}/lib/stopcond".format(rootdir), "-l"+libname]) - arguments.extend(["-L" + rootdir + "/lib/forsockets","-lforsockets"]) - arguments.extend(get_ld_flags().split()) - print 'build command:' - print ' '.join(arguments) - process, stderr, stdout = open_subprocess(arguments) - if process.returncode != 0: - raise Exception("Could not build {0}\nstdout:\n{1}\nstderr:\n{2}\narguments:\n{3}".format(exename, stdout, stderr, ' '.join(arguments))) - def build_java_worker(codestring, path_to_results, specification_class): path = os.path.abspath(path_to_results) exefile = os.path.join(path,"java_worker") @@ -501,19 +469,20 @@ def build_java_worker(codestring, path_to_results, specification_class): return exefile -def build_fortran_worker(codestring, path_to_results, interface): +def build_fortran_worker(codestring, path_to_results, interface, needs_mpi = True, + extra_fflags=[], extra_ldflags=[]): path = os.path.abspath(path_to_results) codefile = os.path.join(path,"code.o") interfacefile = os.path.join(path,"interface.o") exefile = os.path.join(path,"fortran_worker") - fortran_compile(codefile, codestring) + fortran_compile(codefile, codestring, extra_args=extra_fflags) uc = create_fortran.GenerateAFortranSourcecodeStringFromASpecificationClass() uc.specification_class = interface - uc.needs_mpi = True + uc.needs_mpi = needs_mpi string = uc.result - fortran_compile(interfacefile, string) - fortran_build(exefile, [interfacefile, codefile] ) + fortran_compile(interfacefile, string, extra_args=extra_fflags) + fortran_build(exefile, [interfacefile, codefile], extra_args=extra_ldflags ) return exefile diff --git a/test/compile_tests/test_stopping_conditions.py b/test/compile_tests/test_stopping_conditions.py index ec61f9fdd..751c58075 100644 --- a/test/compile_tests/test_stopping_conditions.py +++ b/test/compile_tests/test_stopping_conditions.py @@ -573,31 +573,15 @@ def get_interface_class(self): def get_number_of_workers(self): return 1 - - def build_worker(self): - path = os.path.abspath(self.get_path_to_results()) - codefile = os.path.join(path,"codef90.o") - interfacefile = os.path.join(path,"interfacef90.o") - self.exefile = os.path.join(path,"fortran_worker") - - compile_tools.f90_compile(codefile, self.get_codestring(), - self.get_mpidir()) - uf = create_fortran.GenerateAFortranSourcecodeStringFromASpecificationClass() - uf.needs_mpi = True - uf.specification_class = self.get_interface_class() - string = uf.result - - compile_tools.f90_compile(interfacefile, string, - self.get_mpidir()) - compile_tools.f90_build(self.exefile, [interfacefile, codefile], - self.get_libname()) - def setUp(self): super(_AbstractTestInterfaceFortran, self).setUp() print "building" self.check_can_compile_modules() - self.build_worker() + self.exefile=compile_tools.build_fortran_worker(self.get_codestring(), + self.get_path_to_results(), self.get_interface_class(), needs_mpi= True, + extra_fflags = ["-I","{0}/lib/stopcond".format( get_amuse_root_dir())], + extra_ldflags = ["-L{0}/lib/stopcond".format(get_amuse_root_dir()), "-l"+self.get_libname()] ) class _TestInterfaceFortranSingleProcess(_AbstractTestInterfaceFortran): From 31ba8217c31e3a63b3a1d50207c8105a0f07f5b8 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 17 Sep 2018 11:01:05 +0200 Subject: [PATCH 16/46] also use compile_tools function to build for simplified test --- .../test_c_implementation_simplified.py | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/test/compile_tests/test_c_implementation_simplified.py b/test/compile_tests/test_c_implementation_simplified.py index 57e2bc48d..2985fd02b 100644 --- a/test/compile_tests/test_c_implementation_simplified.py +++ b/test/compile_tests/test_c_implementation_simplified.py @@ -242,35 +242,13 @@ def define_methods(self, object): class TestCImplementationInterface(TestWithMPI): - def build_worker(self): - path = os.path.abspath(self.get_path_to_results()) - codefile = os.path.join(path, "code.o") - interfacefile = os.path.join(path, "interface.o") - self.exefile = os.path.join(path, "c_worker") - - compile_tools.c_compile(codefile, codestring) - - uc = create_c.GenerateACHeaderStringFromASpecificationClass() - uc.specification_class = ForTestingInterface - uc.needs_mpi = False - header = uc.result - - uc = create_c.GenerateACSourcecodeStringFromASpecificationClass() - uc.specification_class = ForTestingInterface - uc.needs_mpi = False - code = uc.result - - string = '\n\n'.join([header, code]) - - compile_tools.cxx_compile(interfacefile, string) - compile_tools.c_build(self.exefile, [interfacefile, codefile]) - def setUp(self): super(TestCImplementationInterface, self).setUp() print "building...", self.check_can_compile_modules() try: - self.build_worker() + self.exefile = compile_tools.build_worker(codestring, self.get_path_to_results(), + ForTestingInterface, write_header=False) except Exception as ex: print ex raise From f038a23d0edf9d33ed4641b0f5912a54a6c66c28 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Sat, 22 Sep 2018 17:57:38 +0200 Subject: [PATCH 17/46] allow new rectilinear grid also with specified cell centers --- src/amuse/datamodel/grids.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/amuse/datamodel/grids.py b/src/amuse/datamodel/grids.py index a17692223..edf3b4043 100644 --- a/src/amuse/datamodel/grids.py +++ b/src/amuse/datamodel/grids.py @@ -318,16 +318,25 @@ def positions(indices, length, n): return result -def new_rectilinear_grid(shape, axes_cell_boundaries, axes_names = "xyz",offset=None): +def new_rectilinear_grid(shape, axes_cell_boundaries=None, cell_centers=None, axes_names = "xyz",offset=None): """Returns a rectilinear grid with cells at positions midway given cell boundaries. """ if len(axes_names) Date: Mon, 24 Sep 2018 20:16:46 +0200 Subject: [PATCH 18/46] allow multiple parameter sets for codes by specifying the parameter_set keyword, the the add_method_parameter etc methods one can add the parameter definition to a different set (instead of parameters) --- src/amuse/support/interface.py | 57 +++++++++++--------- test/core_tests/test_parameters.py | 85 +++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 25 deletions(-) diff --git a/src/amuse/support/interface.py b/src/amuse/support/interface.py index 3ee1fbece..1fc9fab0a 100644 --- a/src/amuse/support/interface.py +++ b/src/amuse/support/interface.py @@ -22,6 +22,7 @@ from amuse.datamodel import incode_storage import itertools +from collections import defaultdict class ConvertArgumentsException(core.IncompatibleUnitsException): formatstring = "{0}" @@ -859,22 +860,25 @@ class HandleParameters(HandleCodeInterfaceAttributeAccess): def __init__(self, interface): self.property_definitions = {} self.interface = interface - self.definitions = [] - self.parameters = None + self.definitions = defaultdict(list,parameters=[]) + self.parameters = {} def supports(self, name, was_found): - return name == 'parameters' + return name in self.definitions.keys() def get_attribute(self, name, value): if not self.parameters: - self.parameters = parameters.new_parameters_instance_with_docs(self.definitions, self.interface) + for n,d in self.definitions.iteritems(): + self.parameters[n] = parameters.new_parameters_instance_with_docs(d, self.interface) - return self.parameters + return self.parameters[name or 'parameters'] def attribute_names(self): - return set(['parameters']) + return set(self.definitions.keys()) - def add_method_parameter(self, get_method, set_method, name, description, default_value = None,must_set_before_get = False, is_vector = False): + def add_method_parameter(self, get_method, set_method, name, description, + default_value = None,must_set_before_get = False, is_vector = False, + parameter_set='parameters'): if is_vector: definition = parameters.ModuleVectorMethodParameterDefinition( get_method, @@ -893,18 +897,18 @@ def add_method_parameter(self, get_method, set_method, name, description, defaul default_value, must_set_before_get = must_set_before_get ) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) - def add_alias_parameter(self, name, aliased_name, description): + def add_alias_parameter(self, name, aliased_name, description,parameter_set='parameters'): definition = parameters.AliasParameterDefinition( name, aliased_name, description ) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) - def add_caching_parameter(self, function_name, parameter_name, name, description, default_value = None): + def add_caching_parameter(self, function_name, parameter_name, name, description, default_value = None,parameter_set='parameters'): definition = parameters.ModuleCachingParameterDefinition( function_name, parameter_name, @@ -912,9 +916,9 @@ def add_caching_parameter(self, function_name, parameter_name, name, description description, default_value ) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) - def add_boolean_parameter(self, get_method, set_method, name, description, default_value = None): + def add_boolean_parameter(self, get_method, set_method, name, description, default_value = None,parameter_set='parameters'): definition = parameters.ModuleBooleanParameterDefinition( get_method, set_method, @@ -922,15 +926,15 @@ def add_boolean_parameter(self, get_method, set_method, name, description, defau description, default_value ) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) - def add_default_form_parameter(self,name,description,default): + def add_default_form_parameter(self,name,description,default,parameter_set='parameters'): if isinstance(default,bool): - self.add_boolean_parameter("get_"+name,"set_"+name,name,description,default) + self.add_boolean_parameter("get_"+name,"set_"+name,name,description,default,parameter_set='parameters') else: - self.add_method_parameter("get_"+name,"set_"+name,name,description,default) + self.add_method_parameter("get_"+name,"set_"+name,name,description,default,parameter_set='parameters') - def add_array_parameter(self, get_method, set_method, range_method, name, description): + def add_array_parameter(self, get_method, set_method, range_method, name, description,parameter_set='parameters'): definition = parameters.ModuleArrayParameterDefinition( get_method, set_method, @@ -938,7 +942,7 @@ def add_array_parameter(self, get_method, set_method, range_method, name, descri name, description ) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) def has_name(self, name): return name == 'PARAMETER' @@ -948,10 +952,10 @@ def setup(self, object): - def add_vector_parameter(self, name, description, parameter_names): + def add_vector_parameter(self, name, description, parameter_names,parameter_set='parameters'): default_value = None for parameter_name in parameter_names: - for defined_parameter in self.definitions: + for defined_parameter in self.definitions[parameter_set]: if defined_parameter.name == parameter_name: if default_value is None: if not is_quantity(defined_parameter.default_value): @@ -965,11 +969,11 @@ def add_vector_parameter(self, name, description, parameter_names): parameter_names, default_value ) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) - def add_interface_parameter(self, name, description, default_value,state_guard=None): + def add_interface_parameter(self, name, description, default_value,state_guard=None,parameter_set='parameters'): definition=parameters.InterfaceParameterDefinition(name,description,default_value,state_guard=state_guard) - self.definitions.append(definition) + self.definitions[parameter_set].append(definition) class HandleErrorCodes(HandleCodeInterfaceAttributeAccess): def __init__(self, interface): @@ -1521,6 +1525,11 @@ def __setstate__(self, state): def data_store_names(self): self.before_get_data_store_names() return self.get_handler('PARTICLES').mapping_from_name_to_set_definition.keys() + + def parameter_set_names(self): + #~ self.before_get_data_store_names() + return self.get_handler('PARAMETER').definitions.keys() + class IncorrectMethodDefinition(IncorrectWrappedMethodException): formatstring = "Incorrect definition of method '{0}' of class '{1}', the number of {4} do not match, expected {2}, actual {3}." diff --git a/test/core_tests/test_parameters.py b/test/core_tests/test_parameters.py index 8f6bb3a49..83e3aedc5 100644 --- a/test/core_tests/test_parameters.py +++ b/test/core_tests/test_parameters.py @@ -6,6 +6,8 @@ from amuse.units import units from amuse.datamodel import parameters from amuse.support.interface import HandleParameters +from amuse.support.interface import InCodeComponentImplementation + class BaseTestModule(object): def before_get_parameter(self): @@ -1129,7 +1131,7 @@ def range(self): x = parameters_handler.get_attribute(None, None) self.assertTrue("length" in str(x)) self.assertTrue("[1.0, 2.0, 3.0] length" in str(x)) - + def test18(self): print "Testing array parameters" definitions = [] @@ -1157,3 +1159,84 @@ def range(self): self.assertEqual(x.param, [1.,2.,3.] | generic_unit_system.length) x.param*=2 self.assertEqual(x.param, [2.,4.,6.] | generic_unit_system.length) + + def test19(self): + print "Testing multiple parameter sets" + + class TestModule(BaseTestModule): + x = 123.0 | generic_unit_system.length + y = 456.0 | generic_unit_system.length + z = 789.0 | generic_unit_system.length + + def get_length_x(self): + return self.x + def set_length_x(self, value): + self.x = value + def get_length_y(self): + return self.y + def set_length_y(self, value): + self.y = value + def get_length_z(self): + return self.z + def set_length_z(self, value): + self.z = value + + o = TestModule() + parameters_handler = HandleParameters(o) + for par_name in ["length_x", "length_y", "length_z"]: + parameters_handler.add_method_parameter( + "get_"+par_name, + "set_"+par_name, + par_name, + "a test parameter", + default_value = 10.0 | generic_unit_system.length, + parameter_set = par_name+"_set" + ) + + for i,par_name in enumerate(["length_x", "length_y", "length_z"]): + x = parameters_handler.get_attribute(par_name+"_set", None) + self.assertTrue([123.0, 456.0, 789.0][i] == getattr(x,par_name).number) + + def test20(self): + print "Testing multiple parameter sets 2" + + class TestInterface(BaseTestModule): + x = 123.0 + y = 456.0 + + def get_x(self): + return self.x + def set_x(self, value): + self.x = value + def get_y(self): + return self.y + def set_y(self, value): + self.y = value + + + class Testing(InCodeComponentImplementation): + + def __init__(self, **options): + InCodeComponentImplementation.__init__(self, TestInterface(), **options) + + def define_parameters(self,object): + object.add_method_parameter( + "get_x", "set_x", "x", "test parameter", 123. + ) + object.add_method_parameter( + "get_y", "set_y", "y", "test parameter 2", 456., + parameter_set="parameters2" + ) + object.add_alias_parameter( + "y_alias","y", " new y", parameter_set="parameters2" + ) + + t=Testing() + + self.assertEqual(set(t.parameter_set_names()), set(('parameters','parameters2'))) + + self.assertEqual(t.parameters.x,123.) + self.assertEqual(t.parameters2.y,456.) + t.parameters2.y=789. + self.assertEqual(t.parameters2.y,789.) + self.assertEqual(t.parameters2.y_alias,789.) From a159fb9a1e6c6b5dd3148f77fc65beae81125f3c Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 24 Sep 2018 20:28:04 +0200 Subject: [PATCH 19/46] allow codes w/o a parameter set named parameters --- src/amuse/support/interface.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/amuse/support/interface.py b/src/amuse/support/interface.py index 1fc9fab0a..79bf40f55 100644 --- a/src/amuse/support/interface.py +++ b/src/amuse/support/interface.py @@ -860,7 +860,7 @@ class HandleParameters(HandleCodeInterfaceAttributeAccess): def __init__(self, interface): self.property_definitions = {} self.interface = interface - self.definitions = defaultdict(list,parameters=[]) + self.definitions = defaultdict(list) self.parameters = {} def supports(self, name, was_found): @@ -868,8 +868,8 @@ def supports(self, name, was_found): def get_attribute(self, name, value): if not self.parameters: - for n,d in self.definitions.iteritems(): - self.parameters[n] = parameters.new_parameters_instance_with_docs(d, self.interface) + for n in self.definitions or ['parameters']: + self.parameters[n] = parameters.new_parameters_instance_with_docs(self.definitions[n], self.interface) return self.parameters[name or 'parameters'] From a506149f5c4bdfe2d2c69dc6e0776e14d37e4764 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 25 Sep 2018 14:18:26 +0200 Subject: [PATCH 20/46] Revert "allow codes w/o a parameter set named parameters" This reverts commit a159fb9a1e6c6b5dd3148f77fc65beae81125f3c. all codes are expected to have the parameters parameter set.. --- src/amuse/support/interface.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/amuse/support/interface.py b/src/amuse/support/interface.py index 79bf40f55..1fc9fab0a 100644 --- a/src/amuse/support/interface.py +++ b/src/amuse/support/interface.py @@ -860,7 +860,7 @@ class HandleParameters(HandleCodeInterfaceAttributeAccess): def __init__(self, interface): self.property_definitions = {} self.interface = interface - self.definitions = defaultdict(list) + self.definitions = defaultdict(list,parameters=[]) self.parameters = {} def supports(self, name, was_found): @@ -868,8 +868,8 @@ def supports(self, name, was_found): def get_attribute(self, name, value): if not self.parameters: - for n in self.definitions or ['parameters']: - self.parameters[n] = parameters.new_parameters_instance_with_docs(self.definitions[n], self.interface) + for n,d in self.definitions.iteritems(): + self.parameters[n] = parameters.new_parameters_instance_with_docs(d, self.interface) return self.parameters[name or 'parameters'] From db7b76d33c7ecf8aaef90e9bd55445187318fbb7 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 25 Sep 2018 15:16:35 +0200 Subject: [PATCH 21/46] add parameter tools module with as yet 1 class to allow initialization of parameter from namelist + a descrptive dict... --- src/amuse/support/parameter_tools.py | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/amuse/support/parameter_tools.py diff --git a/src/amuse/support/parameter_tools.py b/src/amuse/support/parameter_tools.py new file mode 100644 index 000000000..649f0345d --- /dev/null +++ b/src/amuse/support/parameter_tools.py @@ -0,0 +1,58 @@ +import f90nml +from collections import defaultdict +from omuse.units.quantities import new_quantity, to_quantity, is_quantity + + +# CodeWithNamelistParameters +# +# namelist_parameters=dict( +# parametername = dict(group_name="name", short="codename", dtype="int32", default=64, description="description", ptype="nml" [, set_name="name"]), +# ) + +class CodeWithNamelistParameters(object): + def __init__(self, namelist_parameters): + self._namelist_parameters=namelist_parameters + + def define_parameters(self,object): + for name,p in self._namelist_parameters.iteritems(): + if p["ptype"] in ["nml", "nml+normal"]: + parameter_set_name=p.get("set_name", "parameters_"+p["group_name"]) + object.add_interface_parameter( name, p["description"], p["default"], "before_set_interface_parameter", parameter_set=parameter_set_name) + + def read_namelist_parameters(self, inputfile): + + self._nml_file=inputfile + self._nml_params = f90nml.read(inputfile) + + for group, d in self._nml_params.iteritems(): + for name, val in d.iteritems(): + if name in self._namelist_parameters: + group_name=self._namelist_parameters[name]["group_name"] + parameter_set_name=self._namelist_parameters[name].get("set_name", "parameters_"+group_name) + parameter_set=getattr(self, parameter_set_name) + if is_quantity(self._namelist_parameters[name]["default"]): + setattr(parameter_set, name, new_quantity(val, to_quantity(self._namelist_parameters[name]["default"]).unit) ) + else: + setattr(parameter_set, name, val ) + else: + print "'%s' of group '%s' not in the namelist_parameters"%(name, group) + + def write_namelist_parameters(self, outputfile, do_patch=False, nml_file=None): + patch=defaultdict( dict ) + for name, v in self._namelist_parameters.iteritems(): + group_name=v["group_name"] + group=patch[group_name] + short=v["short"] + parameter_set_name=v.get("set_name", "parameters_"+group_name) + parameter_set=getattr(self, parameter_set_name) + if getattr(parameter_set, name) is None: # omit if value is None + continue + if is_quantity(self._namelist_parameters[name]["default"]): + group[short]=to_quantity(getattr(parameter_set, name)).value_in(self._namelist_parameters[name]["default"].unit) + else: + group[short]=getattr(parameter_set, name) + + if do_patch: + f90nml.patch(nml_file or self._nml_file,patch,outputfile) + else: + f90nml.write(patch, outputfile, force=True) From 02caac4614841257654353cc5968430371381628 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Tue, 25 Sep 2018 20:01:26 +0200 Subject: [PATCH 22/46] rework namelist parameter tool format to allow duplicate parameter names (in different groups) --- src/amuse/support/parameter_tools.py | 41 +++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/amuse/support/parameter_tools.py b/src/amuse/support/parameter_tools.py index 649f0345d..ae1d851b8 100644 --- a/src/amuse/support/parameter_tools.py +++ b/src/amuse/support/parameter_tools.py @@ -5,19 +5,19 @@ # CodeWithNamelistParameters # -# namelist_parameters=dict( -# parametername = dict(group_name="name", short="codename", dtype="int32", default=64, description="description", ptype="nml" [, set_name="name"]), +# namelist_parameters=( +# dict(name="name", group_name="name", short="codename", dtype="int32", default=64, description="description", ptype="nml" [, set_name="name"]), ... # ) class CodeWithNamelistParameters(object): def __init__(self, namelist_parameters): - self._namelist_parameters=namelist_parameters + self._namelist_parameters=dict([((x["short"],x["group_name"]),x) for x in namelist_parameters]) def define_parameters(self,object): - for name,p in self._namelist_parameters.iteritems(): + for p in self._namelist_parameters.values(): if p["ptype"] in ["nml", "nml+normal"]: parameter_set_name=p.get("set_name", "parameters_"+p["group_name"]) - object.add_interface_parameter( name, p["description"], p["default"], "before_set_interface_parameter", parameter_set=parameter_set_name) + object.add_interface_parameter( p["name"], p["description"], p["default"], "before_set_interface_parameter", parameter_set=parameter_set_name) def read_namelist_parameters(self, inputfile): @@ -25,34 +25,37 @@ def read_namelist_parameters(self, inputfile): self._nml_params = f90nml.read(inputfile) for group, d in self._nml_params.iteritems(): - for name, val in d.iteritems(): - if name in self._namelist_parameters: - group_name=self._namelist_parameters[name]["group_name"] - parameter_set_name=self._namelist_parameters[name].get("set_name", "parameters_"+group_name) + for short, val in d.iteritems(): + key=(short,group.upper()) + if key in self._namelist_parameters: + group_name=self._namelist_parameters[key]["group_name"] + name=self._namelist_parameters[key]["name"] + parameter_set_name=self._namelist_parameters[key].get("set_name", "parameters_"+group_name) parameter_set=getattr(self, parameter_set_name) - if is_quantity(self._namelist_parameters[name]["default"]): - setattr(parameter_set, name, new_quantity(val, to_quantity(self._namelist_parameters[name]["default"]).unit) ) + if is_quantity(self._namelist_parameters[key]["default"]): + setattr(parameter_set, name, new_quantity(val, to_quantity(self._namelist_parameters[key]["default"]).unit) ) else: setattr(parameter_set, name, val ) else: - print "'%s' of group '%s' not in the namelist_parameters"%(name, group) + print "'%s' of group '%s' not in the namelist_parameters"%(short, group) def write_namelist_parameters(self, outputfile, do_patch=False, nml_file=None): patch=defaultdict( dict ) - for name, v in self._namelist_parameters.iteritems(): - group_name=v["group_name"] + for p in self._namelist_parameters.values(): + name=p["name"] + group_name=p["group_name"] group=patch[group_name] - short=v["short"] - parameter_set_name=v.get("set_name", "parameters_"+group_name) + short=p["short"] + parameter_set_name=p.get("set_name", "parameters_"+group_name) parameter_set=getattr(self, parameter_set_name) if getattr(parameter_set, name) is None: # omit if value is None continue - if is_quantity(self._namelist_parameters[name]["default"]): - group[short]=to_quantity(getattr(parameter_set, name)).value_in(self._namelist_parameters[name]["default"].unit) + if is_quantity(p["default"]): + group[short]=to_quantity(getattr(parameter_set, name)).value_in(p["default"].unit) else: group[short]=getattr(parameter_set, name) if do_patch: f90nml.patch(nml_file or self._nml_file,patch,outputfile) else: - f90nml.write(patch, outputfile, force=True) + f90nml.write(patch, outputfile, force=True) From 25a9140ecece9222de89e6eafd3bfd6f9f52c37a Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 26 Sep 2018 10:59:26 +0200 Subject: [PATCH 23/46] import from omuse fixed --- src/amuse/support/parameter_tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/amuse/support/parameter_tools.py b/src/amuse/support/parameter_tools.py index ae1d851b8..7d5f7b0f8 100644 --- a/src/amuse/support/parameter_tools.py +++ b/src/amuse/support/parameter_tools.py @@ -1,6 +1,6 @@ import f90nml from collections import defaultdict -from omuse.units.quantities import new_quantity, to_quantity, is_quantity +from amuse.units.quantities import new_quantity, to_quantity, is_quantity # CodeWithNamelistParameters From e686c1e9f1c8168c9cc3b464d49de8dbc51b92cb Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 26 Sep 2018 14:18:23 +0200 Subject: [PATCH 24/46] add possibility of aliasing a parameter from different set --- src/amuse/datamodel/parameters.py | 15 ++++++++++++--- src/amuse/support/interface.py | 5 +++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/amuse/datamodel/parameters.py b/src/amuse/datamodel/parameters.py index 0aeffd907..b68a2f16e 100644 --- a/src/amuse/datamodel/parameters.py +++ b/src/amuse/datamodel/parameters.py @@ -382,19 +382,28 @@ def must_set_to_default_if_not_set(self): class AliasParameterDefinition(AbstractParameterDefinition): - def __init__(self, name, aliased_name, description): + def __init__(self, name, aliased_name, description, alias_set=None): AbstractParameterDefinition.__init__(self, name, description) self.aliased_name = aliased_name + self.alias_set = alias_set self.default_value = None def get_default_value(self, parameter_set): return parameter_set.get_parameter(self.aliased_name).definition.get_default_value(parameter_set) def get_value(self, parameter, object): - return getattr(parameter.parameter_set, self.aliased_name) + if self.alias_set: + parameter_set=getattr(object, self.alias_set) + else: + parameter_set=parameter.parameter_set + return getattr(parameter_set, self.aliased_name) def set_value(self, parameter, object, quantity): - return setattr(parameter.parameter_set, self.aliased_name, quantity) + if self.alias_set: + parameter_set=getattr(object, self.alias_set) + else: + parameter_set=parameter.parameter_set + return setattr(parameter_set, self.aliased_name, quantity) def set_default_value(self, parameter, object): pass diff --git a/src/amuse/support/interface.py b/src/amuse/support/interface.py index 1fc9fab0a..206f72f7e 100644 --- a/src/amuse/support/interface.py +++ b/src/amuse/support/interface.py @@ -899,11 +899,12 @@ def add_method_parameter(self, get_method, set_method, name, description, ) self.definitions[parameter_set].append(definition) - def add_alias_parameter(self, name, aliased_name, description,parameter_set='parameters'): + def add_alias_parameter(self, name, aliased_name, description,parameter_set='parameters',alias_set=None): definition = parameters.AliasParameterDefinition( name, aliased_name, - description + description, + alias_set=alias_set ) self.definitions[parameter_set].append(definition) From 005c8ef7cd7b8b26852c1fcbfdb5f1dfe03a61a4 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 26 Sep 2018 15:41:45 +0200 Subject: [PATCH 25/46] fix to reraise exception, fixes case where attribute setting with wrongly sized arrays was silently ignored --- src/amuse/datamodel/memory_storage.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/amuse/datamodel/memory_storage.py b/src/amuse/datamodel/memory_storage.py index c237ce133..8fa649418 100644 --- a/src/amuse/datamodel/memory_storage.py +++ b/src/amuse/datamodel/memory_storage.py @@ -142,8 +142,8 @@ def set_values_in_store(self, indices, attributes, list_of_values_to_set): #~ storage.set_values(indices, units.none.new_quantity(values_to_set)) #~ else: #~ raise AttributeError("exception in setting attribute '{0}', error was '{1}'".format(attribute, ex)) - #~ else: - #~ raise AttributeError("exception in setting attribute '{0}', error was '{1}'".format(attribute, ex)) + else: + raise AttributeError("exception in setting attribute '{0}', error was '{1}'".format(attribute, ex)) def set_values_in_store_async(self, indices, attributes, list_of_values_to_set): from amuse.rfi.channel import FakeASyncRequest @@ -292,6 +292,9 @@ def set_values_in_store(self, indices, attributes, list_of_values_to_set): storage.set_values(indices, values_to_set.value_in(units.none)) else: raise AttributeError("exception in setting attribute '{0}', error was '{1}'".format(attribute, ex)) + else: + raise AttributeError("exception in setting attribute '{0}', error was '{1}'".format(attribute, ex)) + def has_key_in_store(self, key): return key in self.mapping_from_particle_to_index From ef65cfbb84cd94d36308ec81a62af310a77e1cfc Mon Sep 17 00:00:00 2001 From: "Jurriaan H. Spaaks" Date: Thu, 27 Sep 2018 10:56:40 +0200 Subject: [PATCH 26/46] added citation metadata --- .zenodo.json | 45 ++++++++++++++++++++++++++++++++++++ CITATION.cff | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 .zenodo.json create mode 100644 CITATION.cff diff --git a/.zenodo.json b/.zenodo.json new file mode 100644 index 000000000..a1cd0d449 --- /dev/null +++ b/.zenodo.json @@ -0,0 +1,45 @@ +{ + "creators": [ + { + "affiliation": "Netherlands eScience Center", + "name": "Pelupessy, Inti" + }, + { + "affiliation": "Leiden University", + "name": "van Elteren, Arjen" + }, + { + "affiliation": "Drexel University", + "name": "McMillan, Steve" + }, + { + "affiliation": "Leiden University", + "name": "Portegies Zwart, Simon", + "orcid": "0000-0001-5839-0302" + }, + { + "name": "Rieder, Steven", + "orcid": "0000-0003-3688-5798" + }, + { + "affiliation": "Netherlands eScience Center", + "name": "Bos, Patrick" + }, + { + "affiliation": "Netherlands eScience Center", + "name": "Drost, Niels", + "orcid": "0000-0001-9795-7981" + } + ], + "description": "

Astrophysical Multipurpose Software Environment

Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.

What AMUSE can do for you:

  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • couples different simulation codes in a Python environment to be run locally or distributed
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • used for more than 40 scientific papers and PhD theses
", + "keywords": [ + "astronomy", + "multi-model simulation", + "model coupling", + "physics" + ], + "license": { + "id": "Apache-2.0" + }, + "title": "AMUSE" +} diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..36ca85b07 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,64 @@ +# YAML 1.2 +--- +abstract: | + "

+ Astrophysical Multipurpose Software Environment +

+

+ Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies. +

+

+ What AMUSE can do for you: +

+
    +
  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • +
  • couples different simulation codes in a Python environment to be run locally or distributed
  • +
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • +
  • used for more than 40 scientific papers and PhD theses
  • +
" +authors: + - + affiliation: "Netherlands eScience Center" + family-names: Pelupessy + given-names: Inti + - + affiliation: "Leiden University" + family-names: Elteren + given-names: Arjen + name-particle: van + - + affiliation: "Drexel University" + family-names: McMillan + given-names: Steve + - + affiliation: "Leiden University" + family-names: "Portegies Zwart" + given-names: Simon + orcid: "https://orcid.org/0000-0001-5839-0302" + - + family-names: Rieder + given-names: Steven + orcid: "https://orcid.org/0000-0003-3688-5798" + - + affiliation: "Netherlands eScience Center" + family-names: Bos + given-names: Patrick + - + affiliation: "Netherlands eScience Center" + family-names: Drost + given-names: Niels + orcid: "https://orcid.org/0000-0001-9795-7981" +cff-version: "1.0.3" +date-released: 2018-09-27 +doi: "10.5281/zenodo.1435860" +keywords: + - astronomy + - "multi-model simulation" + - "model coupling" + - physics +license: "Apache-2.0" +message: "If you use this software, please cite it using these metadata." +repository-code: "https://github.com/amusecode/amuse" +title: AMUSE +version: "11.3" +... \ No newline at end of file From c2697977fa8ae14d5264131b61436b5a57cd246f Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Thu, 27 Sep 2018 10:14:48 +0100 Subject: [PATCH 27/46] Update CITATION.cff --- CITATION.cff | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index 36ca85b07..f8fee55b4 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -36,6 +36,7 @@ authors: given-names: Simon orcid: "https://orcid.org/0000-0001-5839-0302" - + affiliation: "University of Exeter" family-names: Rieder given-names: Steven orcid: "https://orcid.org/0000-0003-3688-5798" @@ -61,4 +62,4 @@ message: "If you use this software, please cite it using these metadata." repository-code: "https://github.com/amusecode/amuse" title: AMUSE version: "11.3" -... \ No newline at end of file +... From 43e279fd5387e26e2d6bb12e826280216adc440c Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Thu, 27 Sep 2018 10:15:26 +0100 Subject: [PATCH 28/46] Update .zenodo.json --- .zenodo.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.zenodo.json b/.zenodo.json index a1cd0d449..9304cd9fb 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -18,6 +18,7 @@ "orcid": "0000-0001-5839-0302" }, { + "affiliation": "University of Exeter", "name": "Rieder, Steven", "orcid": "0000-0003-3688-5798" }, From f164bf52ab5dbfef38d230342229f0240b2b598b Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Thu, 27 Sep 2018 15:00:42 +0200 Subject: [PATCH 29/46] add and reorder authors may not be complete yet --- CITATION.cff | 64 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index f8fee55b4..96f38c8b6 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -18,37 +18,76 @@ abstract: | " authors: - - affiliation: "Netherlands eScience Center" - family-names: Pelupessy - given-names: Inti + affiliation: "Leiden University" + family-names: "Portegies Zwart" + given-names: Simon + orcid: "https://orcid.org/0000-0001-5839-0302" - affiliation: "Leiden University" family-names: Elteren given-names: Arjen name-particle: van + - + affiliation: "Netherlands eScience Center" + family-names: Pelupessy + given-names: Inti - affiliation: "Drexel University" family-names: McMillan given-names: Steve - - - affiliation: "Leiden University" - family-names: "Portegies Zwart" - given-names: Simon - orcid: "https://orcid.org/0000-0001-5839-0302" - affiliation: "University of Exeter" family-names: Rieder given-names: Steven orcid: "https://orcid.org/0000-0003-3688-5798" - - affiliation: "Netherlands eScience Center" - family-names: Bos - given-names: Patrick + affiliation: "Leiden University" + family-names: de Vries + given-names: Nathan + - + affiliation: "Leiden University" + family-names: Marosvolgyi + given-names: Marcell + - + affiliation: "Drexel University" + family-names: Whitehead + given-names: Alfred + - + affiliation: "Drexel University" + family-names: Wall + given-names: Joshua - affiliation: "Netherlands eScience Center" family-names: Drost given-names: Niels orcid: "https://orcid.org/0000-0001-9795-7981" + - + affiliation: "Leiden University" + family-names: Jilkova + given-names: Lucie + - + affiliation: "Leiden University" + family-names: Martinez Barbosa + given-names: Barbosa + - + affiliation: "Leiden University" + family-names: Beedorf + given-names: Jeroen + - + affiliation: "Leiden University" + family-names: Boekholt + given-names: Tjarda + - + affiliation: "Netherlands eScience Center" + family-names: Bos + given-names: Patrick + - + affiliation: "Netherlands eScience Center" + family-names: Werkhoven + given-names: Ben + name-particle: van + + cff-version: "1.0.3" date-released: 2018-09-27 doi: "10.5281/zenodo.1435860" @@ -58,7 +97,8 @@ keywords: - "model coupling" - physics license: "Apache-2.0" -message: "If you use this software, please cite it using these metadata." +message: "This is the software citation for the framework code. If you publish work +with AMUSE please cite also the code papers of the components used." repository-code: "https://github.com/amusecode/amuse" title: AMUSE version: "11.3" From 9a32b30096dd4af8b5ea5f8ec3212cf01955490b Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Thu, 27 Sep 2018 15:03:01 +0200 Subject: [PATCH 30/46] fix typo --- CITATION.cff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index 96f38c8b6..1677991e2 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -68,7 +68,7 @@ authors: - affiliation: "Leiden University" family-names: Martinez Barbosa - given-names: Barbosa + given-names: Carmen - affiliation: "Leiden University" family-names: Beedorf From d781ecb8efa789d6fb0052cefcb634decc903a7a Mon Sep 17 00:00:00 2001 From: Steven Rieder Date: Thu, 27 Sep 2018 17:18:33 +0100 Subject: [PATCH 31/46] fix typo --- examples/textbook/two_body_bridge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/textbook/two_body_bridge.py b/examples/textbook/two_body_bridge.py index aff3c8393..03f203e5e 100644 --- a/examples/textbook/two_body_bridge.py +++ b/examples/textbook/two_body_bridge.py @@ -24,7 +24,7 @@ def main(): gravity.add_system(planet_gravity, (star_gravity,) ) ###BOOKLISTSTOP### - write_set_to_file(ss, filename, 'hdf5', append_to_file=Fale) + write_set_to_file(ss, filename, 'hdf5', append_to_file=False) Etot_init = gravity.kinetic_energy + gravity.potential_energy Etot_prev = Etot_init From 5d832c399ea3059b12ff190fbc3868eb8e4d0a2b Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Thu, 27 Sep 2018 20:14:49 +0200 Subject: [PATCH 32/46] update zenodo.json --- .zenodo.json | 95 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 28 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 9304cd9fb..67a1c6a1f 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,46 +1,85 @@ { "creators": [ { - "affiliation": "Netherlands eScience Center", - "name": "Pelupessy, Inti" - }, + "affiliation": "Leiden University", + "name": "Portegies Zwart, Simon", + "orcid": "0000-0001-5839-0302" + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "van Elteren, Arjen" - }, + }, { - "affiliation": "Drexel University", - "name": "McMillan, Steve" - }, + "affiliation": "Netherlands eScience Center", + "name": "Pelupessy, Inti" + }, { - "affiliation": "Leiden University", - "name": "Portegies Zwart, Simon", - "orcid": "0000-0001-5839-0302" - }, + "affiliation": "Drexel University", + "name": "McMillan, Steve" + }, { - "affiliation": "University of Exeter", - "name": "Rieder, Steven", + "affiliation": "University of Exeter", + "name": "Rieder, Steven", "orcid": "0000-0003-3688-5798" - }, + }, { - "affiliation": "Netherlands eScience Center", - "name": "Bos, Patrick" - }, + "affiliation": "Leiden University", + "name": "de Vries, Nathan" + }, + { + "affiliation": "Leiden University", + "name": "Marosvolgyi, Marcell" + }, + { + "affiliation": "Drexel University", + "name": "Whitehead, Alfred" + }, { - "affiliation": "Netherlands eScience Center", - "name": "Drost, Niels", + "affiliation": "Drexel University", + "name": "Wall, Joshua" + }, + { + "affiliation": "Netherlands eScience Center", + "name": "Drost, Niels", "orcid": "0000-0001-9795-7981" + }, + { + "affiliation": "Leiden University", + "name": "Jilkova, Lucie" + }, + { + "affiliation": "Leiden University", + "name": "Martinez Barbosa, Carmen" + }, + { + "affiliation": "Leiden University", + "name": "Beedorf, Jeroen" + }, + { + "affiliation": "Leiden University", + "name": "Boekholt, Tjarda" + }, + { + "affiliation": "Netherlands eScience Center", + "name": "Bos, Patrick" + }, + { + "affiliation": "Netherlands eScience Center", + "name": "van Werkhoven, Ben" } - ], - "description": "

Astrophysical Multipurpose Software Environment

Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.

What AMUSE can do for you:

  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • couples different simulation codes in a Python environment to be run locally or distributed
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • used for more than 40 scientific papers and PhD theses
", + ], + "description": "\"

\nAstrophysical Multipurpose Software Environment\n

\n

\nCombine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.\n

\n

\nWhat AMUSE can do for you:\n

\n
    \n
  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • \n
  • couples different simulation codes in a Python environment to be run locally or distributed
  • \n
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • \n
  • used for more than 40 scientific papers and PhD theses
  • \n
\"\n", + "doi": "10.5281/zenodo.1435860", "keywords": [ - "astronomy", - "multi-model simulation", - "model coupling", + "astronomy", + "multi-model simulation", + "model coupling", "physics" - ], + ], "license": { "id": "Apache-2.0" - }, - "title": "AMUSE" + }, + "publication_date": "2018-09-27", + "title": "AMUSE", + "version": "11.3" } From 3c49488dd7e09102d766e43046534e7b44b9767e Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Fri, 28 Sep 2018 10:30:49 +0200 Subject: [PATCH 33/46] add more authors to citation --- .zenodo.json | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- CITATION.cff | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 67a1c6a1f..e1e9b1c32 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -53,19 +53,63 @@ }, { "affiliation": "Leiden University", - "name": "Beedorf, Jeroen" + "name": "van der Helm, Edwin" }, { "affiliation": "Leiden University", - "name": "Boekholt, Tjarda" + "name": "Beedorf, Jeroen" }, { "affiliation": "Netherlands eScience Center", "name": "Bos, Patrick" }, + { + "affiliation": "Leiden University", + "name": "Boekholt, Tjarda" + }, { "affiliation": "Netherlands eScience Center", "name": "van Werkhoven, Ben" + }, + { + "affiliation": "Leiden University", + "name": "Wijnen, Thomas" + }, + { + "affiliation": "Institute for Advanced Study", + "name": "Hamers, Adrian" + }, + { + "affiliation": "Booking.com", + "name": "Caputo, Daniel" + }, + { + "affiliation": "Leiden University", + "name": "Ferrari, Guilherme" + }, + { + "affiliation": "University of Amsterdam", + "name": "Toonen, Silvia" + }, + { + "affiliation": "Nvidia", + "name": "Gaburov, Evghenii" + }, + { + "affiliation": "TNO", + "name": "Paardekooper, Jan-Pieter" + }, + { + "affiliation": "University of Cambridge", + "name": "Janes, Jurgen" + }, + { + "affiliation": "Quintel Intellegence", + "name": "Kruip, Chael" + }, + { + "affiliation": "Georgia Institute of Technology", + "name": "Altay, Gabriel" } ], "description": "\"

\nAstrophysical Multipurpose Software Environment\n

\n

\nCombine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.\n

\n

\nWhat AMUSE can do for you:\n

\n
    \n
  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • \n
  • couples different simulation codes in a Python environment to be run locally or distributed
  • \n
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • \n
  • used for more than 40 scientific papers and PhD theses
  • \n
\"\n", diff --git a/CITATION.cff b/CITATION.cff index 1677991e2..78fa39edd 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -71,21 +71,65 @@ authors: given-names: Carmen - affiliation: "Leiden University" - family-names: Beedorf - given-names: Jeroen + family-names: van der Helm + given-names: Edwin - affiliation: "Leiden University" - family-names: Boekholt - given-names: Tjarda + family-names: Beedorf + given-names: Jeroen - affiliation: "Netherlands eScience Center" family-names: Bos given-names: Patrick + - + affiliation: "Leiden University" + family-names: Boekholt + given-names: Tjarda - affiliation: "Netherlands eScience Center" family-names: Werkhoven given-names: Ben name-particle: van + - + affiliation: "Leiden University" + family-names: Wijnen + given-names: Thomas + - + affiliation: "Institute for Advanced Study" + family-names: Hamers + given-names: Adrian + - + affiliation: "Booking.com" + family-names: Caputo + given-names: Daniel + - + affiliation: "Leiden University" + family-names: Ferrari + given-names: Guilherme + - + affiliation: "University of Amsterdam" + family-names: Toonen + given-names: Silvia + - + affiliation: "Nvidia" + family-names: Gaburov + given-names: Evghenii + - + affiliation: "TNO" + family-names: Paardekooper + given-names: Jan-Pieter + - + affiliation: "University of Cambridge" + family-names: Janes + given-names: Jurgen + - + affiliation: "Quintel Intellegence" + family-names: Kruip + given-names: Chael + - + affiliation: "Georgia Institute of Technology" + family-names: Altay + given-names: Gabriel cff-version: "1.0.3" From 5dbd52e225d53af921939e575618ba3e1e81eaf1 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Fri, 28 Sep 2018 10:59:28 +0200 Subject: [PATCH 34/46] add author --- .zenodo.json | 4 ++++ CITATION.cff | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.zenodo.json b/.zenodo.json index e1e9b1c32..933da00f0 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -103,6 +103,10 @@ "affiliation": "University of Cambridge", "name": "Janes, Jurgen" }, + { + "affiliation": "University of Groningen", + "name": "Punzo, Davide" + }, { "affiliation": "Quintel Intellegence", "name": "Kruip, Chael" diff --git a/CITATION.cff b/CITATION.cff index 78fa39edd..2370b91df 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -122,6 +122,10 @@ authors: affiliation: "University of Cambridge" family-names: Janes given-names: Jurgen + - + affiliation: "University of Groningen" + family-names: Punzo + given-names: Davide - affiliation: "Quintel Intellegence" family-names: Kruip From d171d468351b6f21915f94483f631cb9af8bd3a6 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Sun, 30 Sep 2018 17:42:31 +0200 Subject: [PATCH 35/46] provisional fix for grid_remapping test tests of spherical remapper should move to omuse --- test/ext_tests/test_grid_remappers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/ext_tests/test_grid_remappers.py b/test/ext_tests/test_grid_remappers.py index 10761d59d..ee8ef288e 100644 --- a/test/ext_tests/test_grid_remappers.py +++ b/test/ext_tests/test_grid_remappers.py @@ -3,7 +3,11 @@ from amuse.support.exceptions import AmuseException from amuse.test.amusetest import TestCase -from amuse.ext import grid_remappers +try: + from omuse.ext import grid_remappers +except: + from amuse.ext import grid_remappers + import numpy from amuse.datamodel.grids import * From eaaec66cf5da7f05ef792ce7769f44c7c754a55a Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Sun, 30 Sep 2018 17:46:59 +0200 Subject: [PATCH 36/46] make f90nml import fail not raise exception (optional) --- src/amuse/support/parameter_tools.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/amuse/support/parameter_tools.py b/src/amuse/support/parameter_tools.py index 7d5f7b0f8..254a81505 100644 --- a/src/amuse/support/parameter_tools.py +++ b/src/amuse/support/parameter_tools.py @@ -1,4 +1,8 @@ -import f90nml +try: + import f90nml + HAS_F90NML=True +except: + HAS_F90NML=False from collections import defaultdict from amuse.units.quantities import new_quantity, to_quantity, is_quantity From 16a1b5355a14fa63abd0cb618a9c22a9b8353aec Mon Sep 17 00:00:00 2001 From: "Jurriaan H. Spaaks" Date: Mon, 1 Oct 2018 12:55:53 +0200 Subject: [PATCH 37/46] corrected overenthusiastic escaping of cahracters...hopefully the zenodo-github integration works now --- .zenodo.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zenodo.json b/.zenodo.json index 933da00f0..1b182081f 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -116,7 +116,7 @@ "name": "Altay, Gabriel" } ], - "description": "\"

\nAstrophysical Multipurpose Software Environment\n

\n

\nCombine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.\n

\n

\nWhat AMUSE can do for you:\n

\n
    \n
  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • \n
  • couples different simulation codes in a Python environment to be run locally or distributed
  • \n
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • \n
  • used for more than 40 scientific papers and PhD theses
  • \n
\"\n", + "description": "

Astrophysical Multipurpose Software Environment

Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.

What AMUSE can do for you:

  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • couples different simulation codes in a Python environment to be run locally or distributed
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • used for more than 40 scientific papers and PhD theses
", "doi": "10.5281/zenodo.1435860", "keywords": [ "astronomy", From 66bceb8c5df4fd7d18c407b535fe9c0b210739a2 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 1 Oct 2018 14:28:23 +0200 Subject: [PATCH 38/46] simplify zenode json some more. hopefully works now --- .zenodo.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.zenodo.json b/.zenodo.json index 1b182081f..85c076bb7 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -116,7 +116,9 @@ "name": "Altay, Gabriel" } ], - "description": "

Astrophysical Multipurpose Software Environment

Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.

What AMUSE can do for you:

  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • couples different simulation codes in a Python environment to be run locally or distributed
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • used for more than 40 scientific papers and PhD theses
", + + "description": "

Astrophysical Multipurpose Software Environment

Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.

", + "doi": "10.5281/zenodo.1435860", "keywords": [ "astronomy", From a05f205a9eeccb6d41f472af3c5dfd762f09de92 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 1 Oct 2018 14:49:27 +0200 Subject: [PATCH 39/46] simplify zenodo json some more... --- .zenodo.json | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 85c076bb7..9704dee5a 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -116,8 +116,8 @@ "name": "Altay, Gabriel" } ], - - "description": "

Astrophysical Multipurpose Software Environment

Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.

", + + "description": "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.", "doi": "10.5281/zenodo.1435860", "keywords": [ @@ -126,10 +126,8 @@ "model coupling", "physics" ], - "license": { - "id": "Apache-2.0" - }, + "license": "Apache-2.0", "publication_date": "2018-09-27", - "title": "AMUSE", + "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", "version": "11.3" } From 9e64042a2f5d792a2d0c529098e9252635508197 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 1 Oct 2018 15:21:25 +0200 Subject: [PATCH 40/46] update zenodo and citation again... --- .zenodo.json | 8 ++++---- CITATION.cff | 22 +++------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 9704dee5a..da030bb1c 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -116,9 +116,7 @@ "name": "Altay, Gabriel" } ], - - "description": "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.", - + "description": "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.", "doi": "10.5281/zenodo.1435860", "keywords": [ "astronomy", @@ -126,7 +124,9 @@ "model coupling", "physics" ], - "license": "Apache-2.0", + "license": { + "id": "Apache-2.0" + }, "publication_date": "2018-09-27", "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", "version": "11.3" diff --git a/CITATION.cff b/CITATION.cff index 2370b91df..a623114cf 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,21 +1,6 @@ # YAML 1.2 --- -abstract: | - "

- Astrophysical Multipurpose Software Environment -

-

- Combine existing numerical codes in an easy to use Python framework. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies. -

-

- What AMUSE can do for you: -

-
    -
  • provides a homogeneous environment to design astrophysical simulations used by students and researchers
  • -
  • couples different simulation codes in a Python environment to be run locally or distributed
  • -
  • provides a very easy way to solve astronomical problems that involve complicated physical interactions
  • -
  • used for more than 40 scientific papers and PhD theses
  • -
" +abstract: "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies." authors: - affiliation: "Leiden University" @@ -145,9 +130,8 @@ keywords: - "model coupling" - physics license: "Apache-2.0" -message: "This is the software citation for the framework code. If you publish work -with AMUSE please cite also the code papers of the components used." +message: "This is the software citation for the framework code. If you publish work with AMUSE please cite also the code papers of the components used." repository-code: "https://github.com/amusecode/amuse" -title: AMUSE +title: "the Astrophysical Multipurpose Software Environment (AMUSE)" version: "11.3" ... From 185696551089d8ce6ce00c3335907a92e63e5c14 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 1 Oct 2018 15:41:16 +0200 Subject: [PATCH 41/46] try zenodo file generated by python3... --- .zenodo.json | 136 +++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index da030bb1c..49524c174 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,133 +1,133 @@ { "creators": [ { - "affiliation": "Leiden University", - "name": "Portegies Zwart, Simon", + "affiliation": "Leiden University", + "name": "Portegies Zwart, Simon", "orcid": "0000-0001-5839-0302" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "van Elteren, Arjen" - }, + }, { - "affiliation": "Netherlands eScience Center", + "affiliation": "Netherlands eScience Center", "name": "Pelupessy, Inti" - }, + }, { - "affiliation": "Drexel University", + "affiliation": "Drexel University", "name": "McMillan, Steve" - }, + }, { - "affiliation": "University of Exeter", - "name": "Rieder, Steven", + "affiliation": "University of Exeter", + "name": "Rieder, Steven", "orcid": "0000-0003-3688-5798" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "de Vries, Nathan" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Marosvolgyi, Marcell" - }, + }, { - "affiliation": "Drexel University", + "affiliation": "Drexel University", "name": "Whitehead, Alfred" - }, + }, { - "affiliation": "Drexel University", + "affiliation": "Drexel University", "name": "Wall, Joshua" - }, + }, { - "affiliation": "Netherlands eScience Center", - "name": "Drost, Niels", + "affiliation": "Netherlands eScience Center", + "name": "Drost, Niels", "orcid": "0000-0001-9795-7981" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Jilkova, Lucie" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Martinez Barbosa, Carmen" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "van der Helm, Edwin" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Beedorf, Jeroen" - }, + }, { - "affiliation": "Netherlands eScience Center", + "affiliation": "Netherlands eScience Center", "name": "Bos, Patrick" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Boekholt, Tjarda" - }, + }, { - "affiliation": "Netherlands eScience Center", + "affiliation": "Netherlands eScience Center", "name": "van Werkhoven, Ben" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Wijnen, Thomas" - }, + }, { - "affiliation": "Institute for Advanced Study", + "affiliation": "Institute for Advanced Study", "name": "Hamers, Adrian" - }, + }, { - "affiliation": "Booking.com", + "affiliation": "Booking.com", "name": "Caputo, Daniel" - }, + }, { - "affiliation": "Leiden University", + "affiliation": "Leiden University", "name": "Ferrari, Guilherme" - }, + }, { - "affiliation": "University of Amsterdam", + "affiliation": "University of Amsterdam", "name": "Toonen, Silvia" - }, + }, { - "affiliation": "Nvidia", + "affiliation": "Nvidia", "name": "Gaburov, Evghenii" - }, + }, { - "affiliation": "TNO", + "affiliation": "TNO", "name": "Paardekooper, Jan-Pieter" - }, + }, { - "affiliation": "University of Cambridge", + "affiliation": "University of Cambridge", "name": "Janes, Jurgen" - }, + }, { - "affiliation": "University of Groningen", + "affiliation": "University of Groningen", "name": "Punzo, Davide" - }, + }, { - "affiliation": "Quintel Intellegence", + "affiliation": "Quintel Intellegence", "name": "Kruip, Chael" - }, + }, { - "affiliation": "Georgia Institute of Technology", + "affiliation": "Georgia Institute of Technology", "name": "Altay, Gabriel" } - ], - "description": "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.", - "doi": "10.5281/zenodo.1435860", + ], + "description": "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.", + "doi": "10.5281/zenodo.1435860", "keywords": [ - "astronomy", - "multi-model simulation", - "model coupling", + "astronomy", + "multi-model simulation", + "model coupling", "physics" - ], + ], "license": { "id": "Apache-2.0" - }, - "publication_date": "2018-09-27", - "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", + }, + "publication_date": "2018-09-27", + "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", "version": "11.3" } From 9c6fd431245f156c3fb917a3a6a4f645bf237dbe Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 1 Oct 2018 16:09:37 +0200 Subject: [PATCH 42/46] add keywords to zenodo json --- .zenodo.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 49524c174..da82ab927 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -124,10 +124,10 @@ "model coupling", "physics" ], - "license": { - "id": "Apache-2.0" - }, + "upload_type": "software", + "license": "id": "Apache-2.0", "publication_date": "2018-09-27", "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", - "version": "11.3" + "version": "11.3", + "access_right": "open" } From 6291e0e33bde1a029fb7545765cb6635755605ef Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Mon, 1 Oct 2018 16:12:46 +0200 Subject: [PATCH 43/46] fix typo --- .zenodo.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.zenodo.json b/.zenodo.json index da82ab927..c2547ec35 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -125,7 +125,7 @@ "physics" ], "upload_type": "software", - "license": "id": "Apache-2.0", + "license": "Apache-2.0", "publication_date": "2018-09-27", "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", "version": "11.3", From e1664e58b7bb15e798d5f9051250f776154e34f3 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 3 Oct 2018 10:59:27 +0200 Subject: [PATCH 44/46] retry zenodo with updated version --- .zenodo.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index c2547ec35..7b903d314 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -126,8 +126,8 @@ ], "upload_type": "software", "license": "Apache-2.0", - "publication_date": "2018-09-27", + "publication_date": "2018-10-03", "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", - "version": "11.3", + "version": "11.4", "access_right": "open" } From de842e9ddd6612af70d838277a8fa55767d4c215 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 3 Oct 2018 11:31:12 +0200 Subject: [PATCH 45/46] working zenodo and citation --- .zenodo.json | 11 ++++------- CITATION.cff | 4 +--- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/.zenodo.json b/.zenodo.json index 7b903d314..bd6a105f8 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -117,17 +117,14 @@ } ], "description": "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies.", - "doi": "10.5281/zenodo.1435860", "keywords": [ "astronomy", "multi-model simulation", "model coupling", "physics" ], - "upload_type": "software", - "license": "Apache-2.0", - "publication_date": "2018-10-03", - "title": "the Astrophysical Multipurpose Software Environment (AMUSE)", - "version": "11.4", - "access_right": "open" + "license": { + "id": "Apache-2.0" + }, + "title": "AMUSE: the Astrophysical Multipurpose Software Environment" } diff --git a/CITATION.cff b/CITATION.cff index a623114cf..bfa9e212e 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -122,7 +122,6 @@ authors: cff-version: "1.0.3" -date-released: 2018-09-27 doi: "10.5281/zenodo.1435860" keywords: - astronomy @@ -132,6 +131,5 @@ keywords: license: "Apache-2.0" message: "This is the software citation for the framework code. If you publish work with AMUSE please cite also the code papers of the components used." repository-code: "https://github.com/amusecode/amuse" -title: "the Astrophysical Multipurpose Software Environment (AMUSE)" -version: "11.3" +title: "AMUSE: the Astrophysical Multipurpose Software Environment" ... From 91a6f784b076b294f65da2a279486b0c50df6e47 Mon Sep 17 00:00:00 2001 From: ipelupessy Date: Wed, 3 Oct 2018 11:33:38 +0200 Subject: [PATCH 46/46] add comment with command to generate .zenodo --- CITATION.cff | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CITATION.cff b/CITATION.cff index bfa9e212e..f6ad6824d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,4 +1,6 @@ # YAML 1.2 +# to generate .zenodo json: cffconvert -ig -f zenodo -of .zenodo.json +# note we have omitted date released & version --- abstract: "A Python framework to combine existing astrophysical simulation codes in numerical experiments. With AMUSE you can simulate objects such as star clusters, proto-planetary disks and galaxies." authors: